2 #include "DIPE_Internal.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>
20 size_t dipe_h_length(element_t elem
, size_t dimension
) {
21 return 16 /*cid*/ + dimension
* element_length_in_bytes(elem
);
24 void dipe_generate_h(const 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]);
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
);
39 element_to_bytes(coded
, encapkey
);
41 hmac_sha256_set_key(&ctx
, SHA256_DIGEST_SIZE
, salt
);
43 (nettle_hash_update_func
*)hmac_sha256_update
,
44 (nettle_hash_digest_func
*)hmac_sha256_digest
,
50 /* Data format is iv | enc(4 byte len | ptxt | 0 padding) | tag
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
;
55 uint32_t coded_ptxtlen
;
57 ctxt_len
-= 16; /* Tag */
58 if (ctxt_len
< ptxt_len
+ 4) return 0;
61 gcm_aes128_set_key(&ctx
, key
);
62 gcm_aes128_set_iv(&ctx
, 12, iv
);
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
);
71 while (ctxt_len
>= 16) {
72 gcm_aes128_encrypt(&ctx
, 16, ctxt
, block
);
78 memcpy(block
, ptxt
, min((size_t)16, ptxt_len
));
80 ptxt_len
-= min((size_t)16, ptxt_len
);
85 gcm_aes128_encrypt(&ctx
, ctxt_len
, ctxt
, block
);
89 gcm_aes128_digest(&ctx
, 16, ctxt
);
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
;
97 gcm_aes128_set_key(&ctx
, key
);
98 gcm_aes128_set_iv(&ctx
, 12, iv
);
99 len
-= 16; /* GCM tag */
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
);
111 gcm_aes128_decrypt(&ctx
, len
, ptxt
, ctxt
);
114 gcm_aes128_digest(&ctx
, 16, block
);
116 /* error case is with return code 0, see manual
117 * https://www.lysator.liu.se/~nisse/nettle/nettle.html#Miscellaneous-functions
119 if (memeql_sec(ctxt
, block
, 16) == 0)
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
129 void dipe_init(FILE* configfp
, dipe_param_t
* param
) {
131 (*param
) = (dipe_param_t
)malloc(sizeof(dipe_param
));
132 fread(buffer
, 1, 2<<16, configfp
);
134 pairing_init_set_buf((*param
)->pairing
, buffer
, 2<<16);
136 element_init_G1((*param
)->g1
, (*param
)->pairing
);
137 element_init_G2((*param
)->g2
, (*param
)->pairing
);
138 element_init_GT((*param
)->gt
, (*param
)->pairing
);
140 element_random((*param
)->g1
);
141 element_random((*param
)->g2
);
142 pairing_apply((*param
)->gt
, (*param
)->g1
, (*param
)->g2
, (*param
)->pairing
);
145 pairing_t
* dipe_get_pairing(dipe_param_t param
) {
146 return &(param
->pairing
);
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
));
153 (*sk
)->dimension
= (*pk
)->dimension
= dimension
;
154 element_init_Zr((*pk
)->aid
, param
->pairing
);
155 element_init_Zr((*sk
)->aid
, param
->pairing
);
156 element_random((*pk
)->aid
);
157 element_set((*sk
)->aid
, (*pk
)->aid
);
159 element_init_Zr((*sk
)->a
, param
->pairing
);
160 element_init_GT((*pk
)->a
, param
->pairing
);
161 element_random((*sk
)->a
);
162 element_pow_zn((*pk
)->a
, param
->gt
, (*sk
)->a
);
164 (*sk
)->k
= (element_t
*)calloc(dimension
, sizeof(element_t
));
165 (*pk
)->k
= (element_t
*)calloc(dimension
, sizeof(element_t
));
166 for (size_t i
= 0; i
< dimension
; ++i
) {
167 element_init_Zr((*sk
)->k
[i
], param
->pairing
);
168 element_init_G1((*pk
)->k
[i
], param
->pairing
);
169 element_random((*sk
)->k
[i
]);
170 element_pow_zn((*pk
)->k
[i
], param
->g1
, (*sk
)->k
[i
]);
174 void dipe_keygen(dipe_param_t param
, dipe_master_secretkey_t msk
, const char* cid
, element_t
* y
, dipe_secretkey_t
* sk
) {
175 *sk
= (dipe_secretkey_t
)malloc(sizeof(dipe_secretkey
));
176 (*sk
)->dimension
= msk
->dimension
;
177 element_init_G2((*sk
)->d
, param
->pairing
);
178 element_init_Zr((*sk
)->aid
, param
->pairing
);
179 element_set((*sk
)->aid
, msk
->aid
);
181 size_t hash_input_length
= dipe_h_length(y
[0], msk
->dimension
);
182 unsigned char hash_input
[hash_input_length
];
184 element_init_G2(h
, param
->pairing
);
186 dipe_generate_h(cid
, y
, msk
->dimension
, hash_input
);
187 element_from_hash(h
, hash_input
, hash_input_length
);
192 element_init_Zr(innerp
, param
->pairing
);
193 element_init_Zr(tmp
, param
->pairing
);
194 element_set0(innerp
);
196 element_from_hash(h
, hash_input
, hash_input_length
);
198 for (size_t i
= 0; i
< msk
->dimension
; ++i
) {
199 element_mul(tmp
, y
[i
], msk
->k
[i
]);
200 element_add(innerp
, innerp
, tmp
);
204 element_init_G2(a2
, param
->pairing
);
205 element_pow_zn(h
, h
, innerp
);
206 element_pow_zn(a2
, param
->g2
, msk
->a
);
207 element_mul((*sk
)->d
, a2
, h
);
210 element_clear(innerp
);
215 void dipe_encap(dipe_param_t param
, size_t mpkcount
, dipe_master_publickey_t
* mpk
, size_t threshold
, element_t
* x
, element_t ptxt
, dipe_ctxt_t
* ctxt
) {
216 *ctxt
= (dipe_ctxt_t
)malloc(sizeof(dipe_ctxt
));
217 (*ctxt
)->dimension
= mpk
[0]->dimension
;
218 (*ctxt
)->sharecount
= mpkcount
- threshold
/* TODO */;
220 element_t r
[(*ctxt
)->sharecount
];
222 element_t faid
[(*ctxt
)->sharecount
];
223 element_t aid
[mpkcount
];
226 element_init_Zr(s
, param
->pairing
);
228 element_init_Zr(r0
, param
->pairing
);
231 element_init_G1((*ctxt
)->s
, param
->pairing
);
232 element_pow_zn((*ctxt
)->s
, param
->g1
, s
);
234 (*ctxt
)->cx
= (element_t
*)calloc((*ctxt
)->dimension
, sizeof(element_t
));
235 (*ctxt
)->shares
= (struct dipe_ctxt_share
*)calloc((*ctxt
)->sharecount
, sizeof(struct dipe_ctxt_share
));
236 for (size_t i
= 0; i
< (*ctxt
)->sharecount
; ++i
) {
237 element_init_Zr((*ctxt
)->shares
[i
].aid
, param
->pairing
);
238 element_init_Zr(faid
[i
], param
->pairing
);
239 element_random((*ctxt
)->shares
[i
].aid
);
240 element_set(faid
[i
], (*ctxt
)->shares
[i
].aid
);
242 element_init_Zr(r
[i
], param
->pairing
);
243 element_random(r
[i
]);
246 element_t
* ashares
[mpkcount
];
247 for (size_t i
= 0; i
< mpkcount
; ++i
) {
248 ashares
[i
] = &(mpk
[i
]->a
);
249 element_init_Zr(aid
[i
], param
->pairing
);
250 element_set(aid
[i
], mpk
[i
]->aid
);
252 element_t
* adummyshares
[(*ctxt
)->sharecount
];
253 for (size_t i
= 0; i
< (*ctxt
)->sharecount
; ++i
) {
254 adummyshares
[i
] = &((*ctxt
)->shares
[i
].c
);
256 dipe_ss_share(param
, mpkcount
, aid
, (*ctxt
)->sharecount
, faid
, 1, ashares
, &((*ctxt
)->c
), adummyshares
);
258 for (size_t i
= 0; i
< (*ctxt
)->sharecount
; ++i
) {
259 element_pow_zn((*ctxt
)->shares
[i
].c
, (*ctxt
)->shares
[i
].c
, s
);
261 element_pow_zn((*ctxt
)->c
, (*ctxt
)->c
, s
);
262 element_mul((*ctxt
)->c
, (*ctxt
)->c
, ptxt
);
265 element_t
* kshares
[mpkcount
];
266 for (size_t i
= 0; i
< mpkcount
; ++i
) {
267 kshares
[i
] = mpk
[i
]->k
;
269 element_t
* kdummyshares
[(*ctxt
)->sharecount
];
270 for (size_t i
= 0; i
< (*ctxt
)->sharecount
; ++i
) {
271 kdummyshares
[i
] = (*ctxt
)->shares
[i
].cx
= (element_t
*)calloc((*ctxt
)->dimension
, sizeof(element_t
));
275 for (size_t i
= 0; i
< (*ctxt
)->sharecount
; ++i
) {
276 element_init_G1((*ctxt
)->cx
[i
], param
->pairing
);
278 element_init_G1(tmp
, param
->pairing
);
279 dipe_ss_share(param
, mpkcount
, aid
, (*ctxt
)->sharecount
, faid
, (*ctxt
)->dimension
, kshares
, (*ctxt
)->cx
, kdummyshares
);
281 for (size_t i
= 0; i
< (*ctxt
)->sharecount
; ++i
) {
282 for (size_t j
= 0; j
< (*ctxt
)->dimension
; ++j
) {
283 element_pow_zn((*ctxt
)->shares
[i
].cx
[j
], (*ctxt
)->shares
[i
].cx
[j
], s
);
284 element_pow_zn(tmp
, param
->g1
, x
[j
]);
285 element_pow_zn(tmp
, tmp
, r
[i
]);
286 element_mul((*ctxt
)->shares
[i
].cx
[j
], (*ctxt
)->shares
[i
].cx
[j
], tmp
);
289 for (size_t j
= 0; j
< (*ctxt
)->dimension
; ++j
) {
290 element_pow_zn((*ctxt
)->cx
[j
], (*ctxt
)->cx
[j
], s
);
291 element_pow_zn(tmp
, param
->g1
, x
[j
]);
292 element_pow_zn(tmp
, tmp
, r0
);
293 element_mul((*ctxt
)->cx
[j
], (*ctxt
)->cx
[j
], tmp
);
297 for (size_t i
= 0; i
< (*ctxt
)->sharecount
; ++i
) {
299 element_clear(faid
[i
]);
301 for (size_t i
= 0; i
< mpkcount
; ++i
) {
302 element_clear(aid
[i
]);
310 void dipe_decap(dipe_param_t param
, size_t skcount
, dipe_secretkey_t
* sk
, const char* cid
, element_t
* y
, dipe_ctxt_t ctxt
, element_t ptxt
) {
311 size_t hash_input_length
= dipe_h_length(y
[0], sk
[0]->dimension
);
312 unsigned char hash_input
[hash_input_length
];
314 element_init_G2(h
, param
->pairing
);
316 dipe_generate_h(cid
, y
, sk
[0]->dimension
, hash_input
);
317 element_from_hash(h
, hash_input
, hash_input_length
);
322 element_init_GT(tmp
, param
->pairing
);
323 element_init_GT(innerp
, param
->pairing
);
324 element_init_G2(hy
, param
->pairing
);
326 element_t aid
[skcount
+ ctxt
->sharecount
];
327 element_t
* beta
[skcount
+ ctxt
->sharecount
];
328 for (size_t i
= 0; i
< skcount
; ++i
) {
329 beta
[i
] = (element_t
*)calloc(1, sizeof(element_t
));
330 element_init_GT(*(beta
[i
]), param
->pairing
);
331 element_init_Zr(aid
[i
], param
->pairing
);
332 element_set(aid
[i
], sk
[i
]->aid
);
333 pairing_apply(*(beta
[i
]), ctxt
->s
, sk
[i
]->d
, param
->pairing
);
335 for (size_t i
= 0; i
< ctxt
->sharecount
; ++i
) {
336 beta
[skcount
+i
] = (element_t
*)calloc(1, sizeof(element_t
));
337 element_init_GT(*(beta
[skcount
+i
]), param
->pairing
);
338 element_init_Zr(aid
[skcount
+i
], param
->pairing
);
339 element_set(aid
[skcount
+i
], ctxt
->shares
[i
].aid
);
341 element_set1(innerp
);
342 for (size_t j
= 0; j
< sk
[0]->dimension
; ++j
) {
343 element_pow_zn(hy
, h
, y
[j
]);
344 element_printf("%B %B\n", ctxt
->shares
[i
].cx
[j
], hy
);
345 pairing_apply(tmp
, ctxt
->shares
[i
].cx
[j
], hy
, param
->pairing
);
346 element_mul(innerp
, innerp
, tmp
);
348 element_mul(*(beta
[skcount
+i
]), ctxt
->shares
[i
].c
, innerp
);
351 element_t recover
[1];
352 dipe_ss_recover(param
, skcount
+ ctxt
->sharecount
, aid
, 1, beta
, recover
);
353 element_set(ptxt
, recover
[0]);
354 element_clear(recover
[0]);
356 element_set1(innerp
);
357 for (size_t i
= 0; i
< sk
[0]->dimension
; ++i
) {
358 element_pow_zn(hy
, h
, y
[i
]);
359 pairing_apply(tmp
, ctxt
->cx
[i
], hy
, param
->pairing
);
360 element_mul(innerp
, innerp
, tmp
);
363 element_invert(ptxt
, ptxt
);
364 element_mul(ptxt
, ptxt
, ctxt
->c
);
365 element_mul(ptxt
, ptxt
, innerp
); /* innerp */
367 for (size_t i
= 0; i
< skcount
+ ctxt
->sharecount
; ++i
) {
368 element_clear(aid
[i
]);
369 element_clear(*(beta
[i
]));
375 element_clear(innerp
);
379 void dipe_encrypt(dipe_param_t param
, size_t mpkcount
, dipe_master_publickey_t
* mpk
, size_t threshold
, element_t
* x
, size_t ptxt_len
, char* ptxt
, size_t ctxt_len
, char* ctxt
) {
385 element_init_GT(key
, param
->pairing
);
387 dipe_generate_aeskey(key
, aes
);
388 dipe_encap(param
, mpkcount
, mpk
, threshold
, x
, key
, &cap
);
389 cap_len
= dipe_serialize_ctxt(param
, cap
, (uint8_t*)ctxt
);
390 ctxt
+= cap_len
; ctxt_len
-= cap_len
;
392 dipe_aes_encrypt(aes
, aes
+16, ptxt_len
, (uint8_t*)ptxt
, ctxt_len
, (uint8_t*)ctxt
);
398 size_t dipe_decrypt(dipe_param_t param
, size_t skcount
, dipe_secretkey_t
* sk
, const char* cid
, element_t
* y
, size_t ctxt_len
, char* ctxt
, char* ptxt
) {
404 element_init_GT(key
, param
->pairing
);
405 cap_len
= dipe_deserialize_ctxt(param
, sk
[0]->dimension
, 0, &cap
, (uint8_t*)ctxt
);
408 dipe_decap(param
, skcount
, sk
, cid
, y
, cap
, key
);
409 dipe_generate_aeskey(key
, aes
);
414 return dipe_aes_decrypt(aes
, aes
+16, ctxt_len
, (uint8_t*)ctxt
, (uint8_t*)ptxt
);
417 /* Note: we're generating random-looking bytes here. Therefore we
418 * can't encode the dimension of the predicate vector (supposed to be
419 * set as system parameter) or information about the secret sharing
420 * (needs to be retrieved by some sort of trial decryption).
422 size_t dipe_serialize_ctxt(__attribute__((unused
)) dipe_param_t param
, dipe_ctxt_t ctxt
, uint8_t* buffer
) {
423 size_t bytes_written
= 0;
424 element_to_bytes_compressed(buffer
, ctxt
->s
);
425 buffer
+= element_length_in_bytes_compressed(ctxt
->s
);
426 bytes_written
+= element_length_in_bytes_compressed(ctxt
->s
);
428 for (size_t i
= 0; i
< ctxt
->dimension
; ++i
) {
429 element_to_bytes_compressed(buffer
, ctxt
->cx
[i
]);
430 buffer
+= element_length_in_bytes_compressed(ctxt
->cx
[i
]);
431 bytes_written
+= element_length_in_bytes_compressed(ctxt
->cx
[i
]);
434 element_to_bytes(buffer
, ctxt
->c
);
435 buffer
+= element_length_in_bytes(ctxt
->c
);
436 bytes_written
+= element_length_in_bytes(ctxt
->c
);
438 for (size_t j
= 0; j
< ctxt
->sharecount
; ++j
) {
439 element_to_bytes(buffer
, ctxt
->shares
[j
].aid
);
440 buffer
+= element_length_in_bytes(ctxt
->shares
[j
].aid
);
441 bytes_written
+= element_length_in_bytes(ctxt
->shares
[j
].aid
);
443 for (size_t i
= 0; i
< ctxt
->dimension
; ++i
) {
444 element_to_bytes_compressed(buffer
, ctxt
->shares
[j
].cx
[i
]);
445 buffer
+= element_length_in_bytes_compressed(ctxt
->shares
[j
].cx
[i
]);
446 bytes_written
+= element_length_in_bytes_compressed(ctxt
->shares
[j
].cx
[i
]);
449 element_to_bytes(buffer
, ctxt
->shares
[j
].c
);
450 buffer
+= element_length_in_bytes(ctxt
->shares
[j
].c
);
451 bytes_written
+= element_length_in_bytes(ctxt
->shares
[j
].c
);
454 return bytes_written
;
457 size_t dipe_deserialize_ctxt(dipe_param_t param
, size_t dimension
, size_t shares
, dipe_ctxt_t
* ctxt
, uint8_t* buffer
) {
458 size_t bytes_read
= 0;
459 *ctxt
= (dipe_ctxt_t
)malloc(sizeof(dipe_ctxt
));
460 (*ctxt
)->dimension
= dimension
;
461 (*ctxt
)->sharecount
= shares
;
463 element_init_G1((*ctxt
)->s
, param
->pairing
);
464 element_from_bytes_compressed((*ctxt
)->s
, buffer
);
465 buffer
+= element_length_in_bytes_compressed((*ctxt
)->s
);
466 bytes_read
+= element_length_in_bytes_compressed((*ctxt
)->s
);
468 (*ctxt
)->cx
= (element_t
*)calloc(dimension
, sizeof(element_t
));
469 for (size_t i
= 0; i
< dimension
; ++i
) {
470 element_init_G1((*ctxt
)->cx
[i
], param
->pairing
);
471 element_from_bytes_compressed((*ctxt
)->cx
[i
], buffer
);
472 buffer
+= element_length_in_bytes_compressed((*ctxt
)->cx
[i
]);
473 bytes_read
+= element_length_in_bytes_compressed((*ctxt
)->cx
[i
]);
476 element_init_GT((*ctxt
)->c
, param
->pairing
);
477 element_from_bytes((*ctxt
)->c
, buffer
);
478 buffer
+= element_length_in_bytes((*ctxt
)->c
);
479 bytes_read
+= element_length_in_bytes((*ctxt
)->c
);
482 (*ctxt
)->shares
= (struct dipe_ctxt_share
*)calloc(shares
, sizeof(struct dipe_ctxt_share
));
483 for (size_t j
= 0; j
< shares
; ++j
) {
484 element_init_Zr((*ctxt
)->shares
[j
].aid
, param
->pairing
);
485 element_from_bytes((*ctxt
)->shares
[j
].aid
, buffer
);
486 buffer
+= element_length_in_bytes((*ctxt
)->shares
[j
].aid
);
487 bytes_read
+= element_length_in_bytes((*ctxt
)->shares
[j
].aid
);
494 size_t dipe_ciphertext_overhead(dipe_param_t param
, size_t dimension
, size_t shares
) {
495 size_t overhead
= 16 + 4 /* IV + Tag + Size */;
499 element_init_G1(t
, param
->pairing
);
500 overhead
+= element_length_in_bytes_compressed(t
);
503 overhead
+= (1+shares
) * dimension
* element_length_in_bytes_compressed(t
);
507 element_init_GT(t
, param
->pairing
);
508 overhead
+= (1+shares
) * element_length_in_bytes(t
);
514 void dipe_free_param(dipe_param_t param
) {
515 element_clear(param
->g1
);
516 element_clear(param
->g2
);
517 element_clear(param
->gt
);
518 pairing_clear(param
->pairing
);
522 void dipe_free_master_secretkey(dipe_master_secretkey_t sk
) {
523 for (size_t i
= 0; i
< sk
->dimension
; ++i
) {
524 element_clear(sk
->k
[i
]);
526 element_clear(sk
->a
);
528 element_clear(sk
->aid
);
532 void dipe_free_master_publickey(dipe_master_publickey_t pk
) {
533 for (size_t i
= 0; i
< pk
->dimension
; ++i
) {
534 element_clear(pk
->k
[i
]);
536 element_clear(pk
->a
);
538 element_clear(pk
->aid
);
542 void dipe_free_secretkey(dipe_secretkey_t sk
) {
543 element_clear(sk
->d
);
544 element_clear(sk
->aid
);
548 void dipe_free_ctxt(dipe_ctxt_t ctxt
) {
549 for (size_t j
= 0; j
< ctxt
->dimension
; ++j
) {
550 element_clear(ctxt
->cx
[j
]);
552 element_clear(ctxt
->c
);
555 for (size_t i
= 0; i
< ctxt
->sharecount
; ++i
) {
556 for (size_t j
= 0; j
< ctxt
->dimension
; ++j
) {
557 element_clear(ctxt
->shares
[i
].cx
[j
]);
559 element_clear(ctxt
->shares
[i
].c
);
560 free(ctxt
->shares
[i
].cx
);
564 element_clear(ctxt
->s
);