ruby_clang_fpe 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+