siv-rb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,89 @@
1
+ /* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */
2
+ /* ====================================================================
3
+ * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions
7
+ * are met:
8
+ *
9
+ * 1. Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ *
12
+ * 2. Redistributions in binary form must reproduce the above copyright
13
+ * notice, this list of conditions and the following disclaimer in
14
+ * the documentation and/or other materials provided with the
15
+ * distribution.
16
+ *
17
+ * 3. All advertising materials mentioning features or use of this
18
+ * software must display the following acknowledgment:
19
+ * "This product includes software developed by the OpenSSL Project
20
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
21
+ *
22
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23
+ * endorse or promote products derived from this software without
24
+ * prior written permission. For written permission, please contact
25
+ * openssl-core@openssl.org.
26
+ *
27
+ * 5. Products derived from this software may not be called "OpenSSL"
28
+ * nor may "OpenSSL" appear in their names without prior written
29
+ * permission of the OpenSSL Project.
30
+ *
31
+ * 6. Redistributions of any form whatsoever must retain the following
32
+ * acknowledgment:
33
+ * "This product includes software developed by the OpenSSL Project
34
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
35
+ *
36
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
40
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
48
+ * ====================================================================
49
+ *
50
+ */
51
+
52
+ #ifndef HEADER_AES_LOCL_H
53
+ #define HEADER_AES_LOCL_H
54
+
55
+ #include <openssl/e_os2.h>
56
+
57
+ #ifdef OPENSSL_NO_AES
58
+ #error AES is disabled.
59
+ #endif
60
+
61
+ #include <stdio.h>
62
+ #include <stdlib.h>
63
+ #include <string.h>
64
+
65
+ #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
66
+ # define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
67
+ # define GETU32(p) SWAP(*((u32 *)(p)))
68
+ # define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
69
+ #else
70
+ # define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3]))
71
+ # define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); }
72
+ #endif
73
+
74
+ #ifdef AES_LONG
75
+ typedef unsigned long u32;
76
+ #else
77
+ typedef unsigned int u32;
78
+ #endif
79
+ typedef unsigned short u16;
80
+ typedef unsigned char u8;
81
+
82
+ #define MAXKC (256/32)
83
+ #define MAXKB (256/8)
84
+ #define MAXNR 14
85
+
86
+ /* This controls loop-unrolling in aes_core.c */
87
+ #undef FULL_UNROLL
88
+
89
+ #endif /* !HEADER_AES_LOCL_H */
@@ -0,0 +1,6 @@
1
+ require 'mkmf'
2
+
3
+ dir_config('openssl')
4
+ have_header("openssl/ssl.h")
5
+ have_library("ssl", "SSLv23_method")
6
+ create_makefile('siv/wrapper')
@@ -0,0 +1,364 @@
1
+ /*
2
+ * Copyright (c) The Industrial Lounge, 2007
3
+ *
4
+ * Copyright holder grants permission for redistribution and use in source
5
+ * and binary forms, with or without modification, provided that the
6
+ * following conditions are met:
7
+ * 1. Redistribution of source code must retain the above copyright
8
+ * notice, this list of conditions, and the following disclaimer
9
+ * in all source files.
10
+ * 2. Redistribution in binary form must retain the above copyright
11
+ * notice, this list of conditions, and the following disclaimer
12
+ * in the documentation and/or other materials provided with the
13
+ * distribution.
14
+ * 3. All advertising materials and documentation mentioning features
15
+ * or use of this software must display the following acknowledgement:
16
+ *
17
+ * "This product includes software written by
18
+ * Dan Harkins (dharkins at lounge dot org)"
19
+ *
20
+ * "DISCLAIMER OF LIABILITY
21
+ *
22
+ * THIS SOFTWARE IS PROVIDED BY THE INDUSTRIAL LOUNGE ``AS IS''
23
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INDUSTRIAL LOUNGE BE LIABLE
26
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
+ * SUCH DAMAGE."
33
+ *
34
+ * This license and distribution terms cannot be changed. In other words,
35
+ * this code cannot simply be copied and put under another distribution
36
+ * license (including the GNU public license).
37
+ */
38
+ #include <stdio.h>
39
+ #include <string.h>
40
+ #include <openssl/crypto.h>
41
+ #include <openssl/evp.h>
42
+ #include <openssl/aes.h>
43
+ #include "siv.h"
44
+ #include "aes_locl.h"
45
+
46
+ #define Rb 0x87
47
+
48
+ static void
49
+ xor (unsigned char *output, const unsigned char *input)
50
+ {
51
+ int i;
52
+
53
+ i = AES_BLOCK_SIZE - 1;
54
+ do {
55
+ output[i] ^= input[i];
56
+ i--;
57
+ } while (i >= 0);
58
+ return;
59
+ }
60
+
61
+ static void
62
+ times_two (unsigned char *output, unsigned char *input)
63
+ {
64
+ int i;
65
+ unsigned char *out = output, *in = input;
66
+ unsigned char carry = 0;
67
+
68
+ out = output + AES_BLOCK_SIZE - 1;
69
+ in = input + AES_BLOCK_SIZE - 1;
70
+ for (i = 0; i < AES_BLOCK_SIZE; i++) {
71
+ *(out--) = (*in << 1) | carry;
72
+ carry = (*(in--) & 0x80) ? 1 : 0;
73
+ }
74
+
75
+ if (carry) {
76
+ output[AES_BLOCK_SIZE-1] ^= Rb;
77
+ }
78
+ return;
79
+ }
80
+
81
+ static void
82
+ pad (unsigned char *buf, int len)
83
+ {
84
+ int i;
85
+
86
+ i = len;
87
+ buf[i++] = 0x80;
88
+ if (i < AES_BLOCK_SIZE) {
89
+ memset(buf + i, 0, AES_BLOCK_SIZE - i);
90
+ }
91
+ }
92
+
93
+ void
94
+ aes_cmac (siv_ctx *ctx, const unsigned char *msg, int mlen, unsigned char *C)
95
+ {
96
+ int n, i, slop;
97
+ unsigned char Mn[AES_BLOCK_SIZE], *ptr;
98
+
99
+ // NOTE(jacobsa): For some reason, weird things happen when when `zero` is
100
+ // a global, as in the original program.
101
+ unsigned char zero[AES_BLOCK_SIZE] = {
102
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
104
+ };
105
+
106
+ memcpy(C, zero, AES_BLOCK_SIZE);
107
+
108
+ n = (mlen+(AES_BLOCK_SIZE-1))/AES_BLOCK_SIZE;
109
+
110
+ ptr = (unsigned char *)msg;
111
+ for (i = 0; i < (n-1); i++) {
112
+ xor(C, ptr);
113
+ AES_ecb_encrypt(C, C, &ctx->s2v_sched, AES_ENCRYPT);
114
+ ptr += AES_BLOCK_SIZE;
115
+ }
116
+
117
+ memset(Mn, 0, AES_BLOCK_SIZE);
118
+ if ((slop = (mlen % AES_BLOCK_SIZE)) != 0) {
119
+ memcpy(Mn, ptr, slop);
120
+ pad(Mn, slop);
121
+ xor(Mn, ctx->K2);
122
+ } else {
123
+ if (msg != NULL && mlen != 0) {
124
+ memcpy(Mn, ptr, AES_BLOCK_SIZE);
125
+ xor(Mn, ctx->K1);
126
+ } else {
127
+ pad(Mn, 0);
128
+ xor(Mn, ctx->K2);
129
+ }
130
+ }
131
+ xor(C, Mn);
132
+ AES_ecb_encrypt(C, C, &ctx->s2v_sched, AES_ENCRYPT);
133
+ return;
134
+ }
135
+
136
+ int
137
+ s2v_final (siv_ctx *ctx, const unsigned char *X, int xlen, unsigned char *digest)
138
+ {
139
+ unsigned char T[AES_BLOCK_SIZE], C[AES_BLOCK_SIZE];
140
+ unsigned char padX[AES_BLOCK_SIZE], *ptr;
141
+ int blocks, i, slop;
142
+
143
+ // NOTE(jacobsa): For some reason, weird things happen when when `zero` is
144
+ // a global, as in the original program.
145
+ unsigned char zero[AES_BLOCK_SIZE] = {
146
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
148
+ };
149
+
150
+ if (xlen < AES_BLOCK_SIZE) {
151
+ memcpy(padX, X, xlen);
152
+ pad(padX, xlen);
153
+
154
+ times_two(T, ctx->T);
155
+ xor(T, padX);
156
+ aes_cmac(ctx, T, AES_BLOCK_SIZE, digest);
157
+ } else {
158
+ if (xlen == AES_BLOCK_SIZE) {
159
+ memcpy(T, X, AES_BLOCK_SIZE);
160
+ xor(T, ctx->T);
161
+ aes_cmac(ctx, T, AES_BLOCK_SIZE, digest);
162
+ } else {
163
+ blocks = (xlen+(AES_BLOCK_SIZE-1))/AES_BLOCK_SIZE - 1;
164
+ ptr = (unsigned char *)X;
165
+ memcpy(C, zero, AES_BLOCK_SIZE);
166
+ if (blocks > 1) {
167
+ for (i = 0; i < (blocks-1); i++) {
168
+ xor(C, ptr);
169
+ AES_ecb_encrypt(C, C, &ctx->s2v_sched, AES_ENCRYPT);
170
+ ptr += AES_BLOCK_SIZE;
171
+ }
172
+ }
173
+ memcpy(T, ptr, AES_BLOCK_SIZE);
174
+ slop = xlen % AES_BLOCK_SIZE;
175
+ if (slop) {
176
+ for (i = 0; i < AES_BLOCK_SIZE - slop; i++) {
177
+ T[i + slop] ^= ctx->T[i];
178
+ }
179
+ xor(C, T);
180
+ AES_ecb_encrypt(C, C, &ctx->s2v_sched, AES_ENCRYPT);
181
+ ptr += AES_BLOCK_SIZE;
182
+ memset(T, 0, AES_BLOCK_SIZE);
183
+ memcpy(T, ptr, slop);
184
+ for (i = 0; i < slop; i++) {
185
+ T[i] ^= ctx->T[(AES_BLOCK_SIZE-slop)+i];
186
+ }
187
+ pad(T, slop);
188
+ xor(T, ctx->K2);
189
+ } else {
190
+ xor(C, ptr);
191
+ AES_ecb_encrypt(C, C, &ctx->s2v_sched, AES_ENCRYPT);
192
+ ptr += AES_BLOCK_SIZE;
193
+ memcpy(T, ptr, AES_BLOCK_SIZE);
194
+ xor(T, ctx->T);
195
+ xor(T, ctx->K1);
196
+ }
197
+ xor(C, T);
198
+ AES_ecb_encrypt(C, digest, &ctx->s2v_sched, AES_ENCRYPT);
199
+ }
200
+
201
+ }
202
+ return 0;
203
+ }
204
+
205
+ void
206
+ s2v_add (siv_ctx *ctx, const unsigned char *Y)
207
+ {
208
+ unsigned char T[AES_BLOCK_SIZE];
209
+
210
+ memcpy(T, ctx->T, AES_BLOCK_SIZE);
211
+ times_two(ctx->T, T);
212
+ xor(ctx->T, Y);
213
+ }
214
+
215
+ void
216
+ s2v_update (siv_ctx *ctx, const unsigned char *X, int xlen)
217
+ {
218
+ unsigned char Y[AES_BLOCK_SIZE];
219
+
220
+ aes_cmac(ctx, X, xlen, Y);
221
+ s2v_add(ctx, Y);
222
+ }
223
+
224
+ int
225
+ siv_init (siv_ctx *ctx, const unsigned char *key, int keylen)
226
+ {
227
+ unsigned char L[AES_BLOCK_SIZE];
228
+
229
+ // NOTE(jacobsa): For some reason, weird things happen when when `zero` is
230
+ // a global, as in the original program.
231
+ unsigned char zero[AES_BLOCK_SIZE] = {
232
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
234
+ };
235
+
236
+ memset((char *)ctx, 0, sizeof(siv_ctx));
237
+ switch (keylen) {
238
+ case SIV_512:
239
+ AES_set_encrypt_key(key, 256, &ctx->s2v_sched);
240
+ AES_set_encrypt_key(key+AES_256_BYTES, 256, &ctx->ctr_sched);
241
+ break;
242
+ case SIV_384:
243
+ AES_set_encrypt_key(key, 192, &ctx->s2v_sched);
244
+ AES_set_encrypt_key(key+AES_192_BYTES, 192, &ctx->ctr_sched);
245
+ break;
246
+ case SIV_256:
247
+ AES_set_encrypt_key(key, 128, &ctx->s2v_sched);
248
+ AES_set_encrypt_key(key+AES_128_BYTES, 128, &ctx->ctr_sched);
249
+ break;
250
+ default:
251
+ return -1;
252
+ }
253
+
254
+ AES_ecb_encrypt(zero, L, &ctx->s2v_sched, AES_ENCRYPT);
255
+ times_two(ctx->K1, L);
256
+ times_two(ctx->K2, ctx->K1);
257
+
258
+ memset(ctx->benchmark, 0, AES_BLOCK_SIZE);
259
+ aes_cmac(ctx, zero, AES_BLOCK_SIZE, ctx->T);
260
+ return 1;
261
+ }
262
+
263
+ void
264
+ siv_restart (siv_ctx *ctx)
265
+ {
266
+ // NOTE(jacobsa): For some reason, weird things happen when when `zero` is
267
+ // a global, as in the original program.
268
+ unsigned char zero[AES_BLOCK_SIZE] = {
269
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
271
+ };
272
+
273
+ memset(ctx->benchmark, 0, AES_BLOCK_SIZE);
274
+ memset(ctx->T, 0, AES_BLOCK_SIZE);
275
+ aes_cmac(ctx, zero, AES_BLOCK_SIZE, ctx->T);
276
+ }
277
+
278
+ void
279
+ s2v_benchmark (siv_ctx *ctx)
280
+ {
281
+ memcpy(ctx->benchmark, ctx->T, AES_BLOCK_SIZE);
282
+ }
283
+
284
+ void
285
+ s2v_reset (siv_ctx *ctx)
286
+ {
287
+ memcpy(ctx->T, ctx->benchmark, AES_BLOCK_SIZE);
288
+ }
289
+
290
+ void
291
+ siv_aes_ctr (siv_ctx *ctx, const unsigned char *p, const int lenp,
292
+ unsigned char *c, const unsigned char *iv)
293
+ {
294
+ int i, j;
295
+ unsigned char ctr[AES_BLOCK_SIZE], ecr[AES_BLOCK_SIZE];
296
+ unsigned long inc;
297
+
298
+ memcpy(ctr, iv, AES_BLOCK_SIZE);
299
+ ctr[12] &= 0x7f; ctr[8] &= 0x7f;
300
+ inc = GETU32(ctr + 12);
301
+ for (i = 0; i < lenp; i+=AES_BLOCK_SIZE) {
302
+ AES_ecb_encrypt(ctr, ecr, &ctx->ctr_sched, AES_ENCRYPT);
303
+ for (j = 0; j < AES_BLOCK_SIZE; j++) {
304
+ if ((i + j) == lenp) {
305
+ return;
306
+ }
307
+ c[i+j] = p[i+j] ^ ecr[j];
308
+ }
309
+ inc++; inc &= 0xffffffff;
310
+ PUTU32(ctr + 12, inc);
311
+ }
312
+ }
313
+
314
+ int
315
+ siv_encrypt (siv_ctx *ctx, const unsigned char *p, unsigned char *c,
316
+ const int len, unsigned char *counter,
317
+ const int nad, const int* adlens, const unsigned char** ads)
318
+ {
319
+ const unsigned char *ad;
320
+ int adlen;
321
+ int i;
322
+ unsigned char ctr[AES_BLOCK_SIZE];
323
+
324
+ for (i = 0; i < nad; ++i) {
325
+ ad = ads[i];
326
+ adlen = adlens[i];
327
+ s2v_update(ctx, ad, adlen);
328
+ }
329
+
330
+ s2v_final(ctx, p, len, ctr);
331
+ memcpy(counter, ctr, AES_BLOCK_SIZE);
332
+ siv_aes_ctr(ctx, p, len, c, ctr);
333
+ siv_restart(ctx);
334
+ return 1;
335
+ }
336
+
337
+ int
338
+ siv_decrypt (siv_ctx *ctx, const unsigned char *c, unsigned char *p,
339
+ const int len, unsigned char *counter,
340
+ const int nad, const int* adlens, const unsigned char** ads)
341
+ {
342
+ va_list ap;
343
+ const unsigned char *ad;
344
+ int adlen;
345
+ int i;
346
+ unsigned char ctr[AES_BLOCK_SIZE];
347
+
348
+ memcpy(ctr, counter, AES_BLOCK_SIZE);
349
+ siv_aes_ctr(ctx, c, len, p, ctr);
350
+ for (i = 0; i < nad; ++i) {
351
+ ad = ads[i];
352
+ adlen = adlens[i];
353
+ s2v_update(ctx, ad, adlen);
354
+ }
355
+ s2v_final(ctx, p, len, ctr);
356
+
357
+ siv_restart(ctx);
358
+ if (memcmp(ctr, counter, AES_BLOCK_SIZE)) {
359
+ memset(p, 0, len);
360
+ return -1;
361
+ } else {
362
+ return 1;
363
+ }
364
+ }
@@ -0,0 +1,79 @@
1
+ /*
2
+ * Copyright (c) The Industrial Lounge, 2007
3
+ *
4
+ * Copyright holder grants permission for redistribution and use in source
5
+ * and binary forms, with or without modification, provided that the
6
+ * following conditions are met:
7
+ * 1. Redistribution of source code must retain the above copyright
8
+ * notice, this list of conditions, and the following disclaimer
9
+ * in all source files.
10
+ * 2. Redistribution in binary form must retain the above copyright
11
+ * notice, this list of conditions, and the following disclaimer
12
+ * in the documentation and/or other materials provided with the
13
+ * distribution.
14
+ * 3. All advertising materials and documentation mentioning features
15
+ * or use of this software must display the following acknowledgement:
16
+ *
17
+ * "This product includes software written by
18
+ * Dan Harkins (dharkins at lounge dot org)"
19
+ *
20
+ * "DISCLAIMER OF LIABILITY
21
+ *
22
+ * THIS SOFTWARE IS PROVIDED BY THE INDUSTRIAL LOUNGE ``AS IS''
23
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INDUSTRIAL LOUNGE BE LIABLE
26
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
+ * SUCH DAMAGE."
33
+ *
34
+ * This license and distribution terms cannot be changed. In other words,
35
+ * this code cannot simply be copied and put under another distribution
36
+ * license (including the GNU public license).
37
+ */
38
+ #ifndef _SIV_H_
39
+ #define _SIV_H_
40
+
41
+ #include <openssl/aes.h>
42
+
43
+ #define AES_128_BYTES 16
44
+ #define AES_192_BYTES 24
45
+ #define AES_256_BYTES 32
46
+ #define SIV_256 256
47
+ #define SIV_384 384
48
+ #define SIV_512 512
49
+
50
+ typedef struct _siv_ctx {
51
+ unsigned char K1[AES_BLOCK_SIZE];
52
+ unsigned char K2[AES_BLOCK_SIZE];
53
+ unsigned char T[AES_BLOCK_SIZE];
54
+ unsigned char benchmark[AES_BLOCK_SIZE];
55
+ AES_KEY ctr_sched;
56
+ AES_KEY s2v_sched;
57
+ } siv_ctx;
58
+
59
+ /*
60
+ * exported APIs
61
+ */
62
+ void aes_cmac (siv_ctx *, const unsigned char *, int, unsigned char *);
63
+ int siv_init(siv_ctx *, const unsigned char *, int);
64
+ void siv_reset(siv_ctx *);
65
+ void s2v_benchmark(siv_ctx *);
66
+ void s2v_add(siv_ctx *, const unsigned char *);
67
+ void s2v_update(siv_ctx *, const unsigned char *, int);
68
+ int s2v_final(siv_ctx *, const unsigned char *, int, unsigned char *);
69
+ void siv_restart(siv_ctx *);
70
+ void siv_aes_ctr(siv_ctx *, const unsigned char *, const int, unsigned char *,
71
+ const unsigned char *);
72
+ int siv_encrypt (siv_ctx *ctx, const unsigned char *p, unsigned char *c,
73
+ const int len, unsigned char *counter,
74
+ const int nad, const int* adlens, const unsigned char** ads);
75
+ int siv_decrypt(siv_ctx *, const unsigned char *, unsigned char *,
76
+ const int, unsigned char *,
77
+ const int nad, const int* adlens, const unsigned char** ads);
78
+
79
+ #endif /* _SIV_H_ */
@@ -0,0 +1,302 @@
1
+ #include <ruby.h>
2
+ #include "siv.h"
3
+
4
+ // Convenience constant for unsigned char size
5
+ const int SIV_UCHAR_SIZE = sizeof(unsigned char);
6
+
7
+ // Top-level objects for the native extension
8
+ static VALUE siv_rb;
9
+ static VALUE siv_rb_cipher;
10
+
11
+ /*
12
+ * Initialize an SIV::Cipher object with a key.
13
+ * Performs basic length validation on the key.
14
+ */
15
+ static VALUE siv_rb_initialize(VALUE self, VALUE key) {
16
+
17
+ int keyLen;
18
+
19
+ // Replace key value with key.to_str
20
+ StringValue(key);
21
+
22
+ // Get the key length as an int.
23
+ keyLen = RSTRING_LEN(key);
24
+
25
+ // Make sure key is not empty
26
+ if (keyLen == 0) {
27
+ rb_raise(rb_eArgError, "Key must be non-empty.");
28
+ }
29
+
30
+ // Make sure key is acceptable size
31
+ if (keyLen * 8 != SIV_256 &&
32
+ keyLen * 8 != SIV_384 &&
33
+ keyLen * 8 != SIV_512) {
34
+ rb_raise(rb_eArgError, "Supported key sizes are 256, 384 and 512 bits.");
35
+ }
36
+
37
+ // Set key as instance variable
38
+ rb_iv_set(self, "@key", key);
39
+
40
+ return self;
41
+
42
+ }
43
+
44
+ /*
45
+ * Get an siv_ctx object for the current instance
46
+ * by fetching the @key instance variable, converting
47
+ * it to a byte array and feeding it into siv_init.
48
+ * Called by siv_rb_encrypt and siv_rb_decrypt.
49
+ *
50
+ * Returns 1 upon success, 0 upon failure.
51
+ */
52
+ static int siv_rb_get_ctx(VALUE self, siv_ctx* ctx) {
53
+
54
+ VALUE key; unsigned char* cKey; int cKeyLen;
55
+
56
+ // Get the key instance variable
57
+ key = rb_iv_get(self, "@key");
58
+
59
+ // Convert the key to a byte array
60
+ cKey = (unsigned char*) RSTRING_PTR(key);
61
+ cKeyLen = RSTRING_LEN(key);
62
+
63
+ // Initialize the context with the key
64
+ if (siv_init(ctx, cKey, cKeyLen * 8) < 0) {
65
+ return 0;
66
+ }
67
+
68
+ // Return 1 upon successful initialization
69
+ return 1;
70
+
71
+ }
72
+
73
+ /*
74
+ * Get the associated data as an array of integer lengths
75
+ * and an array of unsigned char arrays representing data.
76
+ */
77
+ static int siv_rb_get_associated(VALUE associated, int* cAdLensIn, unsigned char** cAdsIn) {
78
+
79
+ // Reference to arguments
80
+ int cAdNum; int* cAdLens;
81
+ unsigned char** cAds;
82
+
83
+ // Values for iterator
84
+ int i; VALUE adElement;
85
+ unsigned char* cAdElement;
86
+ int cAdElementLen;
87
+
88
+ // Set the references to arguments.
89
+ cAdLens = cAdLensIn; cAds = cAdsIn;
90
+
91
+ // Get the number of associated data items
92
+ cAdNum = (int) RARRAY_LEN(associated);
93
+
94
+ // Iterate over each associated data
95
+ for (i = 0; i < cAdNum; i++) {
96
+
97
+ // Get an element in the Ruby array
98
+ adElement = rb_ary_entry(associated, (long) i);
99
+
100
+ // Convert the Ruby string to bytes
101
+ StringValue(adElement);
102
+ cAdElement = (unsigned char*) RSTRING_PTR(adElement);
103
+ cAdElementLen = RSTRING_LEN(adElement);
104
+
105
+ // Set the element length
106
+ cAdLens[i] = cAdElementLen;
107
+
108
+ // Set the element data
109
+ if (cAdElementLen > 0) {
110
+
111
+ cAds[i] = (unsigned char*) malloc(SIV_UCHAR_SIZE * cAdElementLen);
112
+ cAds[i] = cAdElement;
113
+
114
+ }
115
+
116
+ }
117
+
118
+ // Return 1 to indicate success;
119
+ return 1;
120
+
121
+ }
122
+
123
+ /*
124
+ * Encrypt a plaintext and some associated data
125
+ */
126
+ static VALUE siv_rb_encrypt(VALUE self, VALUE plaintext, VALUE associated) {
127
+
128
+ // Holds the SIV context object.
129
+ siv_ctx ctx;
130
+
131
+ // Input plaintext as byte array.
132
+ const unsigned char* cPlaintext;
133
+
134
+ // Length of the input plaintext.
135
+ int cPlaintextLen;
136
+
137
+ // Holds the SIV counter object.
138
+ unsigned char cCounter[AES_BLOCK_SIZE];
139
+
140
+ // Holds the SIV ciphertext object.
141
+ unsigned char* cCiphertext;
142
+
143
+ // Hold the parsed associated data.
144
+ int cAdNum; int* cAdLens; unsigned char** cAds;
145
+
146
+ // For concatenation of IV with data.
147
+ unsigned char* cOutput;
148
+ int cOutputLen; int outputInd;
149
+
150
+ // Get the SIV context based on the instance's key.
151
+ if (!siv_rb_get_ctx(self, &ctx)) {
152
+ rb_raise(rb_eRuntimeError, "Could not get SIV context");
153
+ }
154
+
155
+ // Replace the plaintext with plaintext.to_str
156
+ StringValue(plaintext);
157
+
158
+ // Convert the plaintext to a byte array.
159
+ cPlaintext = (const unsigned char*) RSTRING_PTR(plaintext);
160
+
161
+ // Get the length of the plaintext as an int.
162
+ cPlaintextLen = RSTRING_LEN(plaintext);
163
+
164
+ cAdNum = (int) RARRAY_LEN(associated);
165
+ cAdLens = (int *) malloc(sizeof(int) * cAdNum);
166
+ cAds = (unsigned char **) malloc(sizeof(unsigned char*) * cAdNum);
167
+
168
+ // Get the parsed associated data values.
169
+ if (!siv_rb_get_associated(associated, cAdLens, cAds)) {
170
+ rb_raise(rb_eRuntimeError, "Could not get associated data");
171
+ }
172
+
173
+ // Allocate space for the ciphertext.
174
+ cCiphertext = (unsigned char*) malloc(SIV_UCHAR_SIZE * cPlaintextLen);
175
+
176
+ // Call siv_encrypt with all parameters.
177
+ if (siv_encrypt( &ctx, cPlaintext, cCiphertext,
178
+ (const int) cPlaintextLen, cCounter,
179
+ (const int) cAdNum, cAdLens, cAds) < 0) {
180
+ rb_raise(rb_eRuntimeError, "SIV encryption failed");
181
+ }
182
+
183
+ // Prepend the IV (counter) to the ciphertext.
184
+ cOutputLen = cPlaintextLen + AES_BLOCK_SIZE;
185
+ cOutput = (unsigned char*) malloc(SIV_UCHAR_SIZE * cOutputLen);
186
+
187
+ // Iterate through the output to prepend the iv.
188
+ for (outputInd = 0; outputInd < cOutputLen; ++outputInd) {
189
+ cOutput[outputInd] = (outputInd < AES_BLOCK_SIZE) ?
190
+ cCounter[outputInd] : cCiphertext[outputInd - AES_BLOCK_SIZE];
191
+ }
192
+
193
+ // Free up dynamically allocated memory.
194
+ free(cAdLens); free(cAds); free(cCiphertext);
195
+
196
+ // Return a new Ruby string with the resulting value.
197
+ return rb_str_new((const char*) cOutput, cOutputLen);
198
+
199
+ }
200
+
201
+ static VALUE siv_rb_decrypt(VALUE self, VALUE ciphertext, VALUE associated) {
202
+
203
+ siv_ctx ctx;
204
+
205
+ // Holds the counter object bytes
206
+ unsigned char cCounter[AES_BLOCK_SIZE];
207
+
208
+ // Holds the iv + ciphertext bytes
209
+ const unsigned char* cCiphertext;
210
+ int cCiphertextLen;
211
+
212
+ // Holds the ciphertext-only bytes
213
+ unsigned char* cCiphertextTrunc;
214
+ int j; int cCiphertextTruncLen;
215
+
216
+ // Receives the plaintext bytes
217
+ const unsigned char* cPlaintext;
218
+
219
+ // Holds associated-data
220
+ int cAdNum; int* cAdLens;
221
+ unsigned char** cAds;
222
+
223
+ // Get the SIV context with the key
224
+ if (!siv_rb_get_ctx(self, &ctx)) {
225
+ rb_raise(rb_eRuntimeError, "Could not get SIV context");
226
+ }
227
+
228
+ // Get the ciphertext bytes and length
229
+ StringValue(ciphertext);
230
+ cCiphertext = (unsigned char*) RSTRING_PTR(ciphertext);
231
+ cCiphertextLen = RSTRING_LEN(ciphertext);
232
+
233
+ // Truncate the IV (counter) off the ciphertext
234
+ cCiphertextTrunc = (unsigned char*) malloc(
235
+ SIV_UCHAR_SIZE * (cCiphertextLen - AES_BLOCK_SIZE));
236
+ cCiphertextTruncLen = cCiphertextLen - AES_BLOCK_SIZE;
237
+
238
+ // Iterate through the ciphertext to truncate
239
+ for (j = 0; j < cCiphertextLen; j++) {
240
+ if (j < AES_BLOCK_SIZE) cCounter[j] = cCiphertext[j];
241
+ else cCiphertextTrunc[j - AES_BLOCK_SIZE] = cCiphertext[j];
242
+ }
243
+
244
+ // Get the number of associated data items in the array.
245
+ cAdNum = (int) RARRAY_LEN(associated);
246
+ cAdLens = (int *) malloc(sizeof(int) * cAdNum);
247
+ cAds = (unsigned char **) malloc(sizeof(unsigned char*) * cAdNum);
248
+
249
+ // Get the associated data lengths and data arrays
250
+ if (!siv_rb_get_associated(associated, cAdLens, cAds)) {
251
+ rb_raise(rb_eRuntimeError, "Could not get associated data");
252
+ }
253
+
254
+ // Allocate space to receive the plaintext.
255
+ cPlaintext = (unsigned char*) malloc(SIV_UCHAR_SIZE * cCiphertextTruncLen);
256
+
257
+ // Decrypt the ciphertext using SIV.
258
+ if (siv_decrypt(&ctx, cCiphertextTrunc, cPlaintext,
259
+ (const int) cCiphertextTruncLen, cCounter,
260
+ (const int) cAdNum, cAdLens, cAds) < 0) {
261
+ rb_raise(rb_eRuntimeError, "SIV decryption failed");
262
+ }
263
+
264
+ // Free up dynamically allocated memory.
265
+ free(cAdLens); free(cAds); free(cCiphertextTrunc);
266
+
267
+ // Build and return a Ruby string object with the plaintext
268
+ return rb_str_new((const char*) cPlaintext, cCiphertextTruncLen);
269
+
270
+ }
271
+
272
+ /*
273
+ * Main wrapper for the SIV Ruby native extension.
274
+ */
275
+ void Init_wrapper(void) {
276
+
277
+ // Define the top-level module
278
+ siv_rb = rb_define_module("SIV");
279
+
280
+ // Define the cipher class
281
+ siv_rb_cipher = rb_define_class_under(siv_rb, "Cipher", rb_cObject);
282
+
283
+ // Define the implemented methods.
284
+ rb_define_method(siv_rb_cipher, "initialize", siv_rb_initialize, 1);
285
+ rb_define_method(siv_rb_cipher, "encrypt_native", siv_rb_encrypt, 2);
286
+ rb_define_method(siv_rb_cipher, "decrypt_native", siv_rb_decrypt, 2);
287
+
288
+ return;
289
+
290
+ }
291
+
292
+ /*
293
+ Debug helper method to print byte arrays in hex format.
294
+
295
+ void print_hex(const char* header, const unsigned char *bytes, int len) {
296
+
297
+ int i = 0; printf("\n%s (%d): ", header, len);
298
+ for (i = 0; i < len; ++i) printf("%x", bytes[i]);
299
+ printf("\n");
300
+
301
+ }
302
+ */
@@ -0,0 +1,18 @@
1
+ require 'siv-rb/wrapper'
2
+ require 'siv-rb/version'
3
+
4
+ module SIV
5
+
6
+ class Cipher
7
+
8
+ def encrypt(pt, ad = [])
9
+ encrypt_native(pt, ad)
10
+ end
11
+
12
+ def decrypt(ct, ad = [])
13
+ decrypt_native(ct, ad)
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,3 @@
1
+ module SIV
2
+ VERSION = '0.0.1'
3
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: siv-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Louis Mullie
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-04-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.12.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 2.12.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: ! ' Ruby C extension for the AES-SIV deterministic authenticated encryption
47
+ mode. '
48
+ email:
49
+ - louis.mullie@gmail.com
50
+ executables: []
51
+ extensions:
52
+ - ext/siv/extconf.rb
53
+ extra_rdoc_files: []
54
+ files:
55
+ - lib/siv-rb/version.rb
56
+ - lib/siv-rb.rb
57
+ - ext/siv/siv.c
58
+ - ext/siv/wrapper.c
59
+ - ext/siv/aes_locl.h
60
+ - ext/siv/siv.h
61
+ - ext/siv/extconf.rb
62
+ homepage: https://github.com/cryodex/siv-rb
63
+ licenses: []
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ! '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubyforge_project:
82
+ rubygems_version: 1.8.25
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: Ruby C extension for the AES-SIV deterministic authenticated encryption mode.
86
+ test_files: []