ruby_clang_fpe 0.1.0

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,334 @@
1
+ #include <stdint.h>
2
+ #include <string.h>
3
+ #include <math.h>
4
+ #include <assert.h>
5
+ #include <openssl/aes.h>
6
+ #include <openssl/bn.h>
7
+ #include <openssl/crypto.h>
8
+ #include "fpe.h"
9
+ #include "fpe_locl.h"
10
+
11
+ void rev_bytes(unsigned char X[], int len)
12
+ {
13
+ int hlen = len >> 1;
14
+ for (int i = 0; i < hlen; ++i) {
15
+ unsigned char tmp = X[i];
16
+ X[i] = X[len - i - 1];
17
+ X[len - i - 1] = tmp;
18
+ }
19
+ return;
20
+ }
21
+
22
+ // convert numeral string in reverse order to number
23
+ void str2num_rev(BIGNUM *Y, const unsigned int *X, unsigned int radix, unsigned int len, BN_CTX *ctx)
24
+ {
25
+ BN_CTX_start(ctx);
26
+ BIGNUM *r = BN_CTX_get(ctx),
27
+ *x = BN_CTX_get(ctx);
28
+
29
+ BN_set_word(Y, 0);
30
+ BN_set_word(r, radix);
31
+ for (int i = len - 1; i >= 0; --i) {
32
+ // Y = Y * radix + X[i]
33
+ BN_set_word(x, X[i]);
34
+ BN_mul(Y, Y, r, ctx);
35
+ BN_add(Y, Y, x);
36
+ }
37
+
38
+ BN_CTX_end(ctx);
39
+ return;
40
+ }
41
+
42
+ // convert number to numeral string in reverse order
43
+ void num2str_rev(const BIGNUM *X, unsigned int *Y, unsigned int radix, int len, BN_CTX *ctx)
44
+ {
45
+ BN_CTX_start(ctx);
46
+ BIGNUM *dv = BN_CTX_get(ctx),
47
+ *rem = BN_CTX_get(ctx),
48
+ *r = BN_CTX_get(ctx),
49
+ *XX = BN_CTX_get(ctx);
50
+
51
+ BN_copy(XX, X);
52
+ BN_set_word(r, radix);
53
+ memset(Y, 0, len << 2);
54
+
55
+ for (int i = 0; i < len; ++i) {
56
+ // XX / r = dv ... rem
57
+ BN_div(dv, rem, XX, r, ctx);
58
+ // Y[i] = XX % r
59
+ Y[i] = BN_get_word(rem);
60
+ // XX = XX / r
61
+ BN_copy(XX, dv);
62
+ }
63
+
64
+ BN_CTX_end(ctx);
65
+ return;
66
+ }
67
+
68
+ void FF3_encrypt(unsigned int *plaintext, unsigned int *ciphertext, FPE_KEY *key, const unsigned char *tweak, unsigned int txtlen)
69
+ {
70
+ BIGNUM *bnum = BN_new(),
71
+ *y = BN_new(),
72
+ *c = BN_new(),
73
+ *anum = BN_new(),
74
+ *qpow_u = BN_new(),
75
+ *qpow_v = BN_new();
76
+ BN_CTX *ctx = BN_CTX_new();
77
+
78
+
79
+ // Calculate split point
80
+ int u = ceil2(txtlen, 1);
81
+ int v = txtlen - u;
82
+
83
+ // Split the message
84
+ memcpy(ciphertext, plaintext, txtlen << 2);
85
+ unsigned int *A = ciphertext;
86
+ unsigned int *B = ciphertext + u;
87
+
88
+ pow_uv(qpow_u, qpow_v, key->radix, u, v, ctx);
89
+ unsigned int temp = (unsigned int)ceil(u * log2(key->radix));
90
+ const int b = ceil2(temp, 3);
91
+
92
+ unsigned char S[16], P[16];
93
+ unsigned char *Bytes = (unsigned char *)OPENSSL_malloc(b);
94
+
95
+ for (int i = 0; i < FF3_ROUNDS; ++i) {
96
+ // i
97
+ unsigned int m;
98
+ if (i & 1) {
99
+ m = v;
100
+ memcpy(P, tweak, 4);
101
+ } else {
102
+ m = u;
103
+ memcpy(P, tweak + 4, 4);
104
+ }
105
+ P[3] ^= i & 0xff;
106
+
107
+ str2num_rev(bnum, B, key->radix, txtlen - m, ctx);
108
+ memset(Bytes, 0x00, b);
109
+ int BytesLen = BN_bn2bin(bnum, Bytes);
110
+ BytesLen = BytesLen > 12? 12: BytesLen;
111
+ memset(P + 4, 0x00, 12);
112
+ memcpy(P + 16 - BytesLen, Bytes, BytesLen);
113
+
114
+ // iii
115
+ rev_bytes(P, 16);
116
+ AES_encrypt(P, S, &key->aes_enc_ctx);
117
+ rev_bytes(S, 16);
118
+
119
+ // iv
120
+ BN_bin2bn(S, 16, y);
121
+
122
+ // v
123
+ str2num_rev(anum, A, key->radix, m, ctx);
124
+ if (i & 1) BN_mod_add(c, anum, y, qpow_v, ctx);
125
+ else BN_mod_add(c, anum, y, qpow_u, ctx);
126
+
127
+ assert(A != B);
128
+ A = (unsigned int *)( (uintptr_t)A ^ (uintptr_t)B );
129
+ B = (unsigned int *)( (uintptr_t)B ^ (uintptr_t)A );
130
+ A = (unsigned int *)( (uintptr_t)A ^ (uintptr_t)B );
131
+
132
+ num2str_rev(c, B, key->radix, m, ctx);
133
+
134
+ }
135
+
136
+ // free the space
137
+ BN_clear_free(anum);
138
+ BN_clear_free(bnum);
139
+ BN_clear_free(c);
140
+ BN_clear_free(y);
141
+ BN_clear_free(qpow_u);
142
+ BN_clear_free(qpow_v);
143
+ BN_CTX_free(ctx);
144
+ OPENSSL_free(Bytes);
145
+ return;
146
+ }
147
+
148
+ void FF3_decrypt(unsigned int *ciphertext, unsigned int *plaintext, FPE_KEY *key, const unsigned char *tweak, unsigned int txtlen)
149
+ {
150
+ BIGNUM *bnum = BN_new(),
151
+ *y = BN_new(),
152
+ *c = BN_new(),
153
+ *anum = BN_new(),
154
+ *qpow_u = BN_new(),
155
+ *qpow_v = BN_new();
156
+ BN_CTX *ctx = BN_CTX_new();
157
+
158
+ memcpy(plaintext, ciphertext, txtlen << 2);
159
+
160
+ // Calculate split point
161
+ int u = ceil2(txtlen, 1);
162
+ int v = txtlen - u;
163
+
164
+ // Split the message
165
+ unsigned int *A = plaintext;
166
+ unsigned int *B = plaintext + u;
167
+
168
+ pow_uv(qpow_u, qpow_v, key->radix, u, v, ctx);
169
+ unsigned int temp = (unsigned int)ceil(u * log2(key->radix));
170
+ const int b = ceil2(temp, 3);
171
+
172
+ unsigned char S[16], P[16];
173
+ unsigned char *Bytes = (unsigned char *)OPENSSL_malloc(b);
174
+ for (int i = FF3_ROUNDS - 1; i >= 0; --i) {
175
+ // i
176
+ int m;
177
+ if (i & 1) {
178
+ m = v;
179
+ memcpy(P, tweak, 4);
180
+ } else {
181
+ m = u;
182
+ memcpy(P, tweak + 4, 4);
183
+ }
184
+ P[3] ^= i & 0xff;
185
+
186
+ // ii
187
+
188
+ str2num_rev(anum, A, key->radix, txtlen - m, ctx);
189
+ memset(Bytes, 0x00, b);
190
+ int BytesLen = BN_bn2bin(anum, Bytes);
191
+ BytesLen = BytesLen > 12? 12: BytesLen;
192
+ memset(P + 4, 0x00, 12);
193
+ memcpy(P + 16 - BytesLen, Bytes, BytesLen);
194
+
195
+ // iii
196
+ rev_bytes(P, 16);
197
+ memset(S, 0x00, sizeof(S));
198
+ AES_encrypt(P, S, &key->aes_enc_ctx);
199
+ rev_bytes(S, 16);
200
+
201
+ // iv
202
+ BN_bin2bn(S, 16, y);
203
+
204
+ // v
205
+ str2num_rev(bnum, B, key->radix, m, ctx);
206
+ if (i & 1) BN_mod_sub(c, bnum, y, qpow_v, ctx);
207
+ else BN_mod_sub(c, bnum, y, qpow_u, ctx);
208
+
209
+ assert(A != B);
210
+ A = (unsigned int *)( (uintptr_t)A ^ (uintptr_t)B );
211
+ B = (unsigned int *)( (uintptr_t)B ^ (uintptr_t)A );
212
+ A = (unsigned int *)( (uintptr_t)A ^ (uintptr_t)B );
213
+
214
+ num2str_rev(c, A, key->radix, m, ctx);
215
+
216
+ }
217
+
218
+ // free the space
219
+ BN_clear_free(anum);
220
+ BN_clear_free(bnum);
221
+ BN_clear_free(c);
222
+ BN_clear_free(y);
223
+ BN_clear_free(qpow_u);
224
+ BN_clear_free(qpow_v);
225
+ BN_CTX_free(ctx);
226
+ OPENSSL_free(Bytes);
227
+ return;
228
+ }
229
+
230
+ int create_ff3_key(const unsigned char *userKey, const int bits, const unsigned char *tweak, unsigned int radix, FPE_KEY *key)
231
+ {
232
+ int ret;
233
+ if (bits != 128 && bits != 192 && bits != 256) {
234
+ ret = -1;
235
+ return ret;
236
+ }
237
+ key->tweaklen = 64;
238
+ key->tweak = (unsigned char *)OPENSSL_malloc(8);
239
+ memcpy(key->tweak, tweak, 8);
240
+ key->radix = radix;
241
+
242
+ unsigned char tmp[32];
243
+ memcpy(tmp, userKey, bits >> 3);
244
+ rev_bytes(tmp, bits >> 3);
245
+ ret = AES_set_encrypt_key(tmp, bits, &key->aes_enc_ctx);
246
+ return ret;
247
+ }
248
+
249
+ FPE_KEY* FPE_ff3_create_key(const char *key, const char *tweak, unsigned int radix)
250
+ {
251
+ unsigned char k[100],
252
+ t[100];
253
+ int klen = strlen(key) / 2;
254
+
255
+ hex2chars(key, k);
256
+ hex2chars(tweak, t);
257
+
258
+ FPE_KEY *keystruct = (FPE_KEY *)OPENSSL_malloc(sizeof(FPE_KEY));
259
+ create_ff3_key(k,klen*8,t,radix,keystruct);
260
+ return keystruct;
261
+ }
262
+
263
+
264
+ int create_ff3_1_key(const unsigned char *userKey, const int bits, const unsigned char *tweak, unsigned int radix, FPE_KEY *key)
265
+ {
266
+ int ret;
267
+ if (bits != 128 && bits != 192 && bits != 256) {
268
+ ret = -1;
269
+ return ret;
270
+ }
271
+ key->tweaklen = 56;
272
+ key->tweak = (unsigned char *)OPENSSL_malloc(7);
273
+ memcpy(key->tweak, tweak, 7);
274
+ key->radix = radix;
275
+
276
+ // FF3-1: transform 56-bit to 64-bit tweak
277
+ unsigned char byte = tweak[3];
278
+ key->tweak[3] = (byte & 0xF0);
279
+ key->tweak[7] = (byte & 0x0F) << 4;
280
+
281
+ unsigned char tmp[32];
282
+ memcpy(tmp, userKey, bits >> 3);
283
+ rev_bytes(tmp, bits >> 3);
284
+ ret = AES_set_encrypt_key(tmp, bits, &key->aes_enc_ctx);
285
+ return ret;
286
+ }
287
+
288
+ FPE_KEY* FPE_ff3_1_create_key(const char *key, const char *tweak, unsigned int radix)
289
+ {
290
+ unsigned char k[100],
291
+ t[100];
292
+ int klen = strlen(key) / 2;
293
+
294
+ hex2chars(key, k);
295
+ hex2chars(tweak, t);
296
+
297
+ //display_as_hex("key", k, klen);
298
+ //display_as_hex("tweak", t, 56);
299
+
300
+ FPE_KEY *keystruct = (FPE_KEY *)OPENSSL_malloc(sizeof(FPE_KEY));
301
+ create_ff3_1_key(k,klen*8,t,radix,keystruct);
302
+ return keystruct;
303
+ }
304
+
305
+ void FPE_ff3_delete_key(FPE_KEY *key)
306
+ {
307
+ // zero out and then free the tweak and key values
308
+ OPENSSL_clear_free(key->tweak,key->tweaklen/8);
309
+ OPENSSL_clear_free(key,sizeof(key));
310
+ }
311
+
312
+ void FPE_ff3_encrypt(char *plaintext, char *ciphertext, FPE_KEY *key)
313
+ {
314
+ int txtlen = strlen(plaintext);
315
+ unsigned int x[100],
316
+ y[txtlen];
317
+ map_chars(plaintext, x);
318
+
319
+ FF3_encrypt(x, y, key, key->tweak, txtlen);
320
+
321
+ inverse_map_chars(y, ciphertext, txtlen);
322
+ }
323
+
324
+ void FPE_ff3_decrypt(char *ciphertext, char *plaintext, FPE_KEY *key)
325
+ {
326
+ int txtlen = strlen(ciphertext);
327
+ unsigned int x[100],
328
+ y[txtlen];
329
+ map_chars(ciphertext, x);
330
+
331
+ FF3_decrypt(x, y, key, key->tweak, txtlen);
332
+
333
+ inverse_map_chars(y, plaintext, txtlen);
334
+ }
@@ -0,0 +1,47 @@
1
+ #ifndef HEADER_FPE_H
2
+ # define HEADER_FPE_H
3
+
4
+ # include <openssl/aes.h>
5
+
6
+ # ifdef __cplusplus
7
+ extern "C" {
8
+ # endif
9
+
10
+ # define FF1_ROUNDS 10
11
+ # define FF3_ROUNDS 8
12
+ # define FF3_TWEAK_SIZE 8
13
+
14
+ struct fpe_key_st {
15
+ unsigned int tweaklen;
16
+ unsigned char *tweak;
17
+ unsigned int radix;
18
+ AES_KEY aes_enc_ctx;
19
+ };
20
+
21
+ typedef struct fpe_key_st FPE_KEY;
22
+
23
+ /*** FF1 ***/
24
+ FPE_KEY* FPE_ff1_create_key(const char *key, const char *tweak, unsigned int radix);
25
+
26
+ void FPE_ff1_delete_key(FPE_KEY *key);
27
+
28
+ void FPE_ff1_encrypt(char *plaintext, char *ciphertext, FPE_KEY *key);
29
+ //void FPE_ff1_encrypt(unsigned int *plaintext, unsigned int *ciphertext, unsigned int txtlen, FPE_KEY *key);
30
+ //void FPE_ff1_decrypt(unsigned int *ciphertext, unsigned int *plaintext, unsigned int txtlen, FPE_KEY *key);
31
+ void FPE_ff1_decrypt(char *ciphertext, char *plaintext, FPE_KEY *key);
32
+
33
+ /*** FF3 ***/
34
+ FPE_KEY* FPE_ff3_create_key(const char *key, const char *tweak, unsigned int radix);
35
+ FPE_KEY* FPE_ff3_1_create_key(const char *key, const char *tweak, unsigned int radix);
36
+
37
+ void FPE_ff3_delete_key(FPE_KEY *key);
38
+
39
+ void FPE_ff3_encrypt(char *plaintext, char *ciphertext, FPE_KEY *key);
40
+ void FPE_ff3_decrypt(char *ciphertext, char *plaintext, FPE_KEY *key);
41
+ //void FPE_ff3_decrypt(unsigned int *ciphertext, unsigned int *plaintext, unsigned int inlen, FPE_KEY *key);
42
+
43
+ # ifdef __cplusplus
44
+ }
45
+ # endif
46
+
47
+ #endif
@@ -0,0 +1,84 @@
1
+ #include <assert.h>
2
+ #include "fpe_locl.h"
3
+
4
+ // quick power: result = x ^ e
5
+ void pow_uv(BIGNUM *pow_u, BIGNUM *pow_v, unsigned int x, int u, int v, BN_CTX *ctx)
6
+ {
7
+ BN_CTX_start(ctx);
8
+ BIGNUM *base = BN_CTX_get(ctx),
9
+ *e = BN_CTX_get(ctx);
10
+
11
+ BN_set_word(base, x);
12
+ if (u > v) {
13
+ BN_set_word(e, v);
14
+ BN_exp(pow_v, base, e, ctx);
15
+ BN_mul(pow_u, pow_v, base, ctx);
16
+ } else {
17
+ BN_set_word(e, u);
18
+ BN_exp(pow_u, base, e, ctx);
19
+ if (u == v) BN_copy(pow_v, pow_u);
20
+ else BN_mul(pow_v, pow_u, base, ctx);
21
+ }
22
+
23
+ BN_CTX_end(ctx);
24
+ return;
25
+
26
+ /*
27
+ // old veresion, classical quick power
28
+ mpz_t temp;
29
+ mpz_init_set_ui(result, 1);
30
+ mpz_init_set_ui(temp, x);
31
+ while (e) {
32
+ if (e & 1) mpz_mul(result, result, temp);
33
+ mpz_mul(temp, temp, temp);
34
+ e >>= 1;
35
+ }
36
+ mpz_clear(temp);
37
+ return;
38
+ */
39
+ }
40
+
41
+ void hex2chars(const char hex[], unsigned char result[])
42
+ {
43
+ int len = strlen(hex);
44
+ char temp[3];
45
+ temp[2] = 0x00;
46
+
47
+ int j = 0;
48
+ for (int i = 0; i < len; i += 2) {
49
+ temp[0] = hex[i];
50
+ temp[1] = hex[i + 1];
51
+ result[j] = (char)strtol(temp, NULL, 16);
52
+ ++j;
53
+ }
54
+ }
55
+
56
+ void map_chars(char str[], unsigned int result[])
57
+ {
58
+ int len = strlen(str);
59
+
60
+ for (int i = 0; i < len; ++i) {
61
+ if (str[i] >= 'a')
62
+ result[i] = str[i] - 'a' + 10;
63
+ else
64
+ result[i] = str[i] - '0';
65
+ }
66
+ }
67
+
68
+ void inverse_map_chars(unsigned int result[], char str[], int len)
69
+ {
70
+ for (int i = 0; i < len; ++i) {
71
+ if (result[i] < 10)
72
+ str[i] = (result[i] + '0');
73
+ else
74
+ str[i] = result[i] - 10 + 'a';
75
+ }
76
+ str[len] = '\0';
77
+ }
78
+
79
+ void display_as_hex(char* name, unsigned char *val, unsigned int vlen)
80
+ {
81
+ printf("%s:",name);
82
+ for (int i = 0; i < vlen; ++i) printf(" %02x", val[i]);
83
+ puts("");
84
+ }
@@ -0,0 +1,22 @@
1
+ #ifndef HEADER_FPE_LOCL_H
2
+ # define HEADER_FPE_LOCL_H
3
+
4
+ #include <string.h>
5
+ #include <openssl/bn.h>
6
+
7
+ // ceil and floor for x / (2 ^ bit)
8
+ # define ceil2(x, bit) ( ((x) >> (bit)) + ( ((x) & ((1 << (bit)) - 1)) > 0 ) )
9
+ # define floor2(x, bit) ( (x) >> (bit) )
10
+
11
+ void pow_uv(BIGNUM *pow_u, BIGNUM *pow_v, unsigned int x, int u, int v, BN_CTX *ctx);
12
+
13
+ void map_chars(char str[], unsigned int result[]);
14
+ void inverse_map_chars(unsigned int result[], char str[], int len);
15
+ void hex2chars(const char hex[], unsigned char result[]);
16
+
17
+ void display_as_hex(char *name, unsigned char *k, unsigned int klen);
18
+ //int log2(int x);
19
+
20
+ #endif
21
+
22
+