]> git.siccegge.de Git - software/DIPE.git/blob - src/DIPE.cxx
e06f2f3b4b95eeba42176062f70aa74c1b892fa9
[software/DIPE.git] / src / DIPE.cxx
1 #include "DIPE.h"
2
3 #include <string.h>
4 #include <nettle/hkdf.h>
5 #include <nettle/hmac.h>
6 #include <sys/random.h>
7 #include <nettle/gcm.h>
8 #include <nettle/memops.h>
9 #include <arpa/inet.h>
10 #include <algorithm>
11 #include <errno.h>
12
13 using std::min;
14 using std::max;
15
16 struct dipe_param {
17 pairing_t pairing;
18 element_t g1;
19 element_t g2;
20 element_t gt;
21 };
22
23 struct dipe_master_publickey {
24 size_t dimension;
25 element_t a;
26 element_t* k;
27 };
28
29 struct dipe_master_secretkey {
30 size_t dimension;
31 element_t a;
32 element_t* k;
33 };
34
35 struct dipe_secretkey {
36 size_t dimension;
37 element_t d;
38 };
39
40 struct dipe_ctxt {
41 size_t dimension;
42 element_t s;
43 element_t* cx;
44 element_t c;
45 };
46
47
48 namespace {
49 size_t dipe_h_length(element_t elem, size_t dimension) {
50 return 16 /*cid*/ + dimension * element_length_in_bytes(elem);
51 }
52
53 void dipe_generate_h(char* cid, element_t* y, size_t dimension, unsigned char* result) {
54 memcpy(result, cid, 16);
55 unsigned char* next_element = result+16;
56 for (size_t i = 0; i < dimension; ++i) {
57 element_to_bytes(next_element, y[i]);
58 next_element += element_length_in_bytes(y[0]);
59 }
60 }
61
62 void dipe_generate_aeskey(element_t encapkey, uint8_t* aeskey) {
63 struct hmac_sha256_ctx ctx;
64 uint8_t salt[SHA256_DIGEST_SIZE];
65 memset(salt, 0, SHA256_DIGEST_SIZE);
66 size_t elen = element_length_in_bytes(encapkey);
67 uint8_t coded[elen];
68 element_to_bytes(coded, encapkey);
69
70 hmac_sha256_set_key(&ctx, SHA256_DIGEST_SIZE, salt);
71 hkdf_extract(&ctx,
72 (nettle_hash_update_func *)hmac_sha256_update,
73 (nettle_hash_digest_func *)hmac_sha256_digest,
74 SHA256_DIGEST_SIZE,
75 elen, coded,
76 aeskey);
77 }
78
79 /* Data format is iv | enc(4 byte len | ptxt | 0 padding) | tag
80 */
81 int dipe_aes_encrypt(uint8_t* key, uint8_t* iv, size_t ptxt_len, uint8_t* ptxt, size_t ctxt_len, uint8_t* ctxt) {
82 struct gcm_aes128_ctx ctx;
83 uint8_t block[16];
84 uint32_t coded_ptxtlen;
85
86 ctxt_len -= 16; /* Tag */
87 if (ctxt_len < ptxt_len + 4) return 0;
88
89 memset(block, 0, 16);
90 gcm_aes128_set_key(&ctx, key);
91 gcm_aes128_set_iv(&ctx, 12, iv);
92
93 /* First Block */
94 coded_ptxtlen = htonl(ptxt_len);
95 memcpy(block, &coded_ptxtlen, 4);
96 memcpy(block+4, ptxt, min((size_t)12, ptxt_len));
97 ptxt_len -= min((size_t)12, ptxt_len);
98 ptxt += 12;
99
100 while (ctxt_len >= 16) {
101 gcm_aes128_encrypt(&ctx, 16, ctxt, block);
102 memset(block, 0, 16);
103 ctxt_len -= 16;
104 ctxt += 16;
105
106 if (ptxt_len > 0) {
107 memcpy(block, ptxt, min((size_t)16, ptxt_len));
108 ptxt += 16;
109 ptxt_len -= min((size_t)16, ptxt_len);
110 }
111 }
112
113 if (ctxt_len > 0) {
114 gcm_aes128_encrypt(&ctx, ctxt_len, ctxt, block);
115 ctxt += ctxt_len;
116 }
117
118 gcm_aes128_digest(&ctx, 16, ctxt);
119 return 0;
120 }
121
122 int dipe_aes_decrypt(uint8_t* key, uint8_t* iv, size_t len, uint8_t* ctxt, uint8_t* ptxt) {
123 struct gcm_aes128_ctx ctx;
124 uint8_t block[16];
125
126 gcm_aes128_set_key(&ctx, key);
127 gcm_aes128_set_iv(&ctx, 12, iv);
128 len -= 16; /* GCM tag */
129
130
131 gcm_aes128_decrypt(&ctx, min((size_t)16, len), block, ctxt);
132 uint32_t ptxtlen = 0;
133 memcpy(&ptxtlen, block, 4);
134 memcpy(ptxt, block+4, min((size_t)12, len-4));
135 ptxtlen = ntohl(ptxtlen);
136 ctxt += min((size_t)16, len); len -= min((size_t)16, len);
137 ptxt += 12;
138
139 if (len > 0) {
140 gcm_aes128_decrypt(&ctx, len, ptxt, ctxt);
141 ctxt += len;
142 }
143 gcm_aes128_digest(&ctx, 16, block);
144
145 /* error case is with return code 0, see manual
146 * https://www.lysator.liu.se/~nisse/nettle/nettle.html#Miscellaneous-functions
147 */
148 if (memeql_sec(ctxt, block, 16) == 0)
149 return 0;
150 else
151 return ptxtlen;
152 }
153 }
154
155 /* Note: we need a curve where membership checking is hard for all
156 * group elements. See also https://ia.cr/2015/247 and followups
157 */
158 void dipe_init(FILE* configfp, dipe_param_t* param) {
159 char buffer[2<<16];
160 (*param) = (dipe_param_t)malloc(sizeof(dipe_param));
161 fread(buffer, 1, 2<<16, configfp);
162
163 pairing_init_set_buf((*param)->pairing, buffer, 2<<16);
164
165 element_init_G1((*param)->g1, (*param)->pairing);
166 element_init_G2((*param)->g2, (*param)->pairing);
167 element_init_GT((*param)->gt, (*param)->pairing);
168
169 element_random((*param)->g1);
170 element_random((*param)->g2);
171 pairing_apply((*param)->gt, (*param)->g1, (*param)->g2, (*param)->pairing);
172 }
173
174 pairing_t* dipe_get_pairing(dipe_param_t param) {
175 return &(param->pairing);
176 }
177
178 void dipe_master_keygen(dipe_param_t param, size_t dimension, dipe_master_publickey_t* pk, dipe_master_secretkey_t* sk) {
179 *pk = (dipe_master_publickey_t)malloc(sizeof(dipe_master_publickey));
180 *sk = (dipe_master_secretkey_t)malloc(sizeof(dipe_master_secretkey));
181
182 (*sk)->dimension = (*pk)->dimension = dimension;
183
184 element_init_Zr((*sk)->a, param->pairing);
185 element_init_GT((*pk)->a, param->pairing);
186 element_random((*sk)->a);
187 element_pow_zn((*pk)->a, param->gt, (*sk)->a);
188
189 (*sk)->k = (element_t*)calloc(dimension, sizeof(element_t));
190 (*pk)->k = (element_t*)calloc(dimension, sizeof(element_t));
191 for (size_t i = 0; i < dimension; ++i) {
192 element_init_Zr((*sk)->k[i], param->pairing);
193 element_init_G1((*pk)->k[i], param->pairing);
194 element_random((*sk)->k[i]);
195 element_pow_zn((*pk)->k[i], param->g1, (*sk)->k[i]);
196 }
197 }
198
199 void dipe_keygen(dipe_param_t param, dipe_master_secretkey_t msk, char* cid, element_t* y, dipe_secretkey_t* sk) {
200 *sk = (dipe_secretkey_t)malloc(sizeof(dipe_secretkey));
201 (*sk)->dimension = msk->dimension;
202 element_init_G2((*sk)->d, param->pairing);
203
204 size_t hash_input_length = dipe_h_length(y[0], msk->dimension);
205 unsigned char hash_input[hash_input_length];
206 element_t h;
207 element_init_G2(h, param->pairing);
208
209 dipe_generate_h(cid, y, msk->dimension, hash_input);
210 element_from_hash(h, hash_input, hash_input_length);
211
212 element_t innerp;
213 element_t tmp;
214
215 element_init_Zr(innerp, param->pairing);
216 element_init_Zr(tmp, param->pairing);
217 element_set0(innerp);
218
219 element_from_hash(h, hash_input, hash_input_length);
220
221 for (size_t i = 0; i < msk->dimension; ++i) {
222 element_mul(tmp, y[i], msk->k[i]);
223 element_add(innerp, innerp, tmp);
224 }
225
226 element_t a2;
227 element_init_G2(a2, param->pairing);
228 element_pow_zn(h, h, innerp);
229 element_pow_zn(a2, param->g2, msk->a);
230 element_mul((*sk)->d, a2, h);
231
232 element_clear(h);
233 element_clear(innerp);
234 element_clear(tmp);
235 element_clear(a2);
236 }
237
238 void dipe_encap(dipe_param_t param, dipe_master_publickey_t mpk, element_t* x, element_t ptxt, dipe_ctxt_t* ctxt) {
239 *ctxt = (dipe_ctxt_t)malloc(sizeof(dipe_ctxt));
240 (*ctxt)->dimension = mpk->dimension;
241
242 element_t r;
243 element_t s;
244 element_init_Zr(r, param->pairing);
245 element_init_Zr(s, param->pairing);
246
247 element_random(r);
248 element_random(s);
249
250 element_init_G1((*ctxt)->s, param->pairing);
251 element_pow_zn((*ctxt)->s, param->g1, s);
252
253 element_t k1;
254 element_t x1;
255 element_init_G1(k1, param->pairing);
256 element_init_G1(x1, param->pairing);
257
258 (*ctxt)->cx = (element_t*)calloc(mpk->dimension, sizeof(element_t));
259 for (size_t i = 0; i < mpk->dimension; ++i){
260 element_pow_zn(x1, param->g1, x[i]);
261 element_pow_zn(x1, x1, r);
262
263 element_pow_zn(k1, mpk->k[i], s);
264
265 element_init_G1((*ctxt)->cx[i], param->pairing);
266 element_mul((*ctxt)->cx[i], k1, x1);
267 }
268
269 element_t at;
270 element_init_GT(at, param->pairing);
271 element_pow_zn(at, mpk->a, s);
272 element_init_GT((*ctxt)->c, param->pairing);
273 element_mul((*ctxt)->c, at, ptxt);
274
275 element_clear(r);
276 element_clear(s);
277 element_clear(k1);
278 element_clear(x1);
279 element_clear(at);
280 }
281
282
283 void dipe_decap(dipe_param_t param, dipe_secretkey_t sk, char* cid, element_t* y, dipe_ctxt_t ctxt, element_t ptxt) {
284 size_t hash_input_length = dipe_h_length(y[0], sk->dimension);
285 unsigned char hash_input[hash_input_length];
286 element_t h;
287 element_init_G2(h, param->pairing);
288
289 dipe_generate_h(cid, y, sk->dimension, hash_input);
290 element_from_hash(h, hash_input, hash_input_length);
291
292 element_t tmp;
293 element_t innerp;
294 element_t hy;
295 element_init_GT(tmp, param->pairing);
296 element_init_GT(innerp, param->pairing);
297 element_init_G2(hy, param->pairing);
298
299 element_set1(innerp);
300 for (size_t i = 0; i < sk->dimension; ++i) {
301 element_pow_zn(hy, h, y[i]);
302 pairing_apply(tmp, ctxt->cx[i], hy, param->pairing);
303 element_mul(innerp, innerp, tmp);
304 }
305
306 pairing_apply(ptxt, ctxt->s, sk->d, param->pairing);
307 element_invert(ptxt, ptxt);
308 element_mul(ptxt, ptxt, ctxt->c);
309 element_mul(ptxt, ptxt, innerp);
310
311 element_clear(h);
312 element_clear(tmp);
313 element_clear(innerp);
314 element_clear(hy);
315 }
316
317 void dipe_encrypt(dipe_param_t param, dipe_master_publickey_t mpk, element_t* x, size_t ptxt_len, char* ptxt, size_t ctxt_len, char* ctxt) {
318 element_t key;
319 uint8_t aes[32];
320 dipe_ctxt_t cap;
321 size_t cap_len;
322
323 element_init_GT(key, param->pairing);
324 element_random(key);
325 dipe_generate_aeskey(key, aes);
326 dipe_encap(param, mpk, x, key, &cap);
327 cap_len = dipe_serialize_ctxt(param, cap, (uint8_t*)ctxt);
328 ctxt += cap_len; ctxt_len -= cap_len;
329
330 dipe_aes_encrypt(aes, aes+16, ptxt_len, (uint8_t*)ptxt, ctxt_len, (uint8_t*)ctxt);
331
332 dipe_free_ctxt(cap);
333 element_clear(key);
334 }
335
336 size_t dipe_decrypt(dipe_param_t param, dipe_secretkey_t sk, char* cid, element_t* y, size_t ctxt_len, char* ctxt, char* ptxt) {
337 dipe_ctxt_t cap;
338 uint8_t aes[32];
339 element_t key;
340 size_t cap_len;
341
342 element_init_GT(key, param->pairing);
343 cap_len = dipe_deserialize_ctxt(param, sk->dimension, &cap, (uint8_t*)ctxt);
344 ctxt += cap_len;
345 ctxt_len -= cap_len;
346 dipe_decap(param, sk, cid, y, cap, key);
347 dipe_generate_aeskey(key, aes);
348
349 dipe_free_ctxt(cap);
350 element_clear(key);
351
352 return dipe_aes_decrypt(aes, aes+16, ctxt_len, (uint8_t*)ctxt, (uint8_t*)ptxt);
353 }
354
355 /* Note: we're generating random-looking bytes here. Therefore we
356 * can't encode the dimension of the predicate vector (supposed to be
357 * set as system parameter) or information about the secret sharing
358 * (needs to be retrieved by some sort of trial decryption).
359 */
360 size_t dipe_serialize_ctxt(__attribute__((unused)) dipe_param_t param, dipe_ctxt_t ctxt, uint8_t* buffer) {
361 size_t bytes_written = 0;
362 element_to_bytes_compressed(buffer, ctxt->s);
363 buffer += element_length_in_bytes_compressed(ctxt->s);
364 bytes_written += element_length_in_bytes_compressed(ctxt->s);
365
366 for (size_t i = 0; i < ctxt->dimension; ++i) {
367 element_to_bytes_compressed(buffer, ctxt->cx[i]);
368 buffer += element_length_in_bytes_compressed(ctxt->cx[i]);
369 bytes_written += element_length_in_bytes_compressed(ctxt->cx[i]);
370 }
371
372 element_to_bytes(buffer, ctxt->c);
373 buffer += element_length_in_bytes(ctxt->c);
374 bytes_written += element_length_in_bytes(ctxt->c);
375
376 return bytes_written;
377 }
378
379 size_t dipe_deserialize_ctxt(dipe_param_t param, size_t dimension, dipe_ctxt_t* ctxt, uint8_t* buffer) {
380 size_t bytes_read = 0;
381 *ctxt = (dipe_ctxt_t)malloc(sizeof(dipe_ctxt));
382 (*ctxt)->dimension = dimension;
383
384 element_init_G1((*ctxt)->s, param->pairing);
385 element_from_bytes_compressed((*ctxt)->s, buffer);
386 buffer += element_length_in_bytes_compressed((*ctxt)->s);
387 bytes_read += element_length_in_bytes_compressed((*ctxt)->s);
388
389 (*ctxt)->cx = (element_t*)calloc(dimension, sizeof(element_t));
390 for (size_t i = 0; i < dimension; ++i) {
391 element_init_G1((*ctxt)->cx[i], param->pairing);
392 element_from_bytes_compressed((*ctxt)->cx[i], buffer);
393 buffer += element_length_in_bytes_compressed((*ctxt)->cx[i]);
394 bytes_read += element_length_in_bytes_compressed((*ctxt)->cx[i]);
395 }
396
397 element_init_GT((*ctxt)->c, param->pairing);
398 element_from_bytes((*ctxt)->c, buffer);
399 buffer += element_length_in_bytes((*ctxt)->c);
400 bytes_read += element_length_in_bytes((*ctxt)->c);
401
402 return bytes_read;
403 }
404
405 size_t dipe_ciphertext_overhead(dipe_param_t param, size_t dimension) {
406 size_t overhead = 16 + 4 /* IV + Tag + Size */;
407 element_t t;
408
409 element_init_G1(t, param->pairing);
410 overhead += element_length_in_bytes_compressed(t);
411 overhead += dimension * element_length_in_bytes_compressed(t);
412 element_clear(t);
413 element_init_GT(t, param->pairing);
414 overhead += element_length_in_bytes(t);
415 element_clear(t);
416
417 return overhead;
418 }
419
420 void dipe_free_param(dipe_param_t param) {
421 element_clear(param->g1);
422 element_clear(param->g2);
423 element_clear(param->gt);
424 pairing_clear(param->pairing);
425 free(param);
426 }
427
428 void dipe_free_master_secretkey(dipe_master_secretkey_t sk) {
429 for (size_t i = 0; i < sk->dimension; ++i) {
430 element_clear(sk->k[i]);
431 }
432 element_clear(sk->a);
433 free(sk->k);
434 free(sk);
435 }
436
437 void dipe_free_master_publickey(dipe_master_publickey_t pk) {
438 for (size_t i = 0; i < pk->dimension; ++i) {
439 element_clear(pk->k[i]);
440 }
441 element_clear(pk->a);
442 free(pk->k);
443 free(pk);
444 }
445
446 void dipe_free_secretkey(dipe_secretkey_t sk) {
447 element_clear(sk->d);
448 free(sk);
449 }
450
451 void dipe_free_ctxt(dipe_ctxt_t ctxt) {
452 for (size_t i = 0; i < ctxt->dimension; ++i) {
453 element_clear(ctxt->cx[i]);
454 }
455 element_clear(ctxt->c);
456 element_clear(ctxt->s);
457 free(ctxt->cx);
458 free(ctxt);
459 }