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