siv-rb 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []