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>
23 struct dipe_master_publickey
{
29 struct dipe_master_secretkey
{
35 struct dipe_secretkey
{
49 size_t dipe_h_length(element_t elem
, size_t dimension
) {
50 return 16 /*cid*/ + dimension
* element_length_in_bytes(elem
);
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]);
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
);
68 element_to_bytes(coded
, encapkey
);
70 hmac_sha256_set_key(&ctx
, SHA256_DIGEST_SIZE
, salt
);
72 (nettle_hash_update_func
*)hmac_sha256_update
,
73 (nettle_hash_digest_func
*)hmac_sha256_digest
,
79 /* Data format is iv | enc(4 byte len | ptxt | 0 padding) | tag
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
;
84 uint32_t coded_ptxtlen
;
86 ctxt_len
-= 16; /* Tag */
87 if (ctxt_len
< ptxt_len
+ 4) return 0;
90 gcm_aes128_set_key(&ctx
, key
);
91 gcm_aes128_set_iv(&ctx
, 12, iv
);
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
);
100 while (ctxt_len
>= 16) {
101 gcm_aes128_encrypt(&ctx
, 16, ctxt
, block
);
102 memset(block
, 0, 16);
107 memcpy(block
, ptxt
, min((size_t)16, ptxt_len
));
109 ptxt_len
-= min((size_t)16, ptxt_len
);
114 gcm_aes128_encrypt(&ctx
, ctxt_len
, ctxt
, block
);
118 gcm_aes128_digest(&ctx
, 16, ctxt
);
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
;
126 gcm_aes128_set_key(&ctx
, key
);
127 gcm_aes128_set_iv(&ctx
, 12, iv
);
128 len
-= 16; /* GCM tag */
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
);
140 gcm_aes128_decrypt(&ctx
, len
, ptxt
, ctxt
);
143 gcm_aes128_digest(&ctx
, 16, block
);
145 /* error case is with return code 0, see manual
146 * https://www.lysator.liu.se/~nisse/nettle/nettle.html#Miscellaneous-functions
148 if (memeql_sec(ctxt
, block
, 16) == 0)
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
158 void dipe_init(FILE* configfp
, dipe_param_t
* param
) {
160 (*param
) = (dipe_param_t
)malloc(sizeof(dipe_param
));
161 fread(buffer
, 1, 2<<16, configfp
);
163 pairing_init_set_buf((*param
)->pairing
, buffer
, 2<<16);
165 element_init_G1((*param
)->g1
, (*param
)->pairing
);
166 element_init_G2((*param
)->g2
, (*param
)->pairing
);
167 element_init_GT((*param
)->gt
, (*param
)->pairing
);
169 element_random((*param
)->g1
);
170 element_random((*param
)->g2
);
171 pairing_apply((*param
)->gt
, (*param
)->g1
, (*param
)->g2
, (*param
)->pairing
);
174 pairing_t
* dipe_get_pairing(dipe_param_t param
) {
175 return &(param
->pairing
);
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
));
182 (*sk
)->dimension
= (*pk
)->dimension
= dimension
;
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
);
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
]);
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
);
204 size_t hash_input_length
= dipe_h_length(y
[0], msk
->dimension
);
205 unsigned char hash_input
[hash_input_length
];
207 element_init_G2(h
, param
->pairing
);
209 dipe_generate_h(cid
, y
, msk
->dimension
, hash_input
);
210 element_from_hash(h
, hash_input
, hash_input_length
);
215 element_init_Zr(innerp
, param
->pairing
);
216 element_init_Zr(tmp
, param
->pairing
);
217 element_set0(innerp
);
219 element_from_hash(h
, hash_input
, hash_input_length
);
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
);
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
);
233 element_clear(innerp
);
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
;
244 element_init_Zr(r
, param
->pairing
);
245 element_init_Zr(s
, param
->pairing
);
250 element_init_G1((*ctxt
)->s
, param
->pairing
);
251 element_pow_zn((*ctxt
)->s
, param
->g1
, s
);
255 element_init_G1(k1
, param
->pairing
);
256 element_init_G1(x1
, param
->pairing
);
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
);
263 element_pow_zn(k1
, mpk
->k
[i
], s
);
265 element_init_G1((*ctxt
)->cx
[i
], param
->pairing
);
266 element_mul((*ctxt
)->cx
[i
], k1
, x1
);
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
);
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
];
287 element_init_G2(h
, param
->pairing
);
289 dipe_generate_h(cid
, y
, sk
->dimension
, hash_input
);
290 element_from_hash(h
, hash_input
, hash_input_length
);
295 element_init_GT(tmp
, param
->pairing
);
296 element_init_GT(innerp
, param
->pairing
);
297 element_init_G2(hy
, param
->pairing
);
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
);
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
);
313 element_clear(innerp
);
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
) {
323 element_init_GT(key
, param
->pairing
);
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
;
330 dipe_aes_encrypt(aes
, aes
+16, ptxt_len
, (uint8_t*)ptxt
, ctxt_len
, (uint8_t*)ctxt
);
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
) {
342 element_init_GT(key
, param
->pairing
);
343 cap_len
= dipe_deserialize_ctxt(param
, sk
->dimension
, &cap
, (uint8_t*)ctxt
);
346 dipe_decap(param
, sk
, cid
, y
, cap
, key
);
347 dipe_generate_aeskey(key
, aes
);
352 return dipe_aes_decrypt(aes
, aes
+16, ctxt_len
, (uint8_t*)ctxt
, (uint8_t*)ptxt
);
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).
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
);
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
]);
372 element_to_bytes(buffer
, ctxt
->c
);
373 buffer
+= element_length_in_bytes(ctxt
->c
);
374 bytes_written
+= element_length_in_bytes(ctxt
->c
);
376 return bytes_written
;
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
;
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
);
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
]);
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
);
405 size_t dipe_ciphertext_overhead(dipe_param_t param
, size_t dimension
) {
406 size_t overhead
= 16 + 4 /* IV + Tag + Size */;
409 element_init_G1(t
, param
->pairing
);
410 overhead
+= element_length_in_bytes_compressed(t
);
411 overhead
+= dimension
* element_length_in_bytes_compressed(t
);
413 element_init_GT(t
, param
->pairing
);
414 overhead
+= element_length_in_bytes(t
);
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
);
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
]);
432 element_clear(sk
->a
);
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
]);
441 element_clear(pk
->a
);
446 void dipe_free_secretkey(dipe_secretkey_t sk
) {
447 element_clear(sk
->d
);
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
]);
455 element_clear(ctxt
->c
);
456 element_clear(ctxt
->s
);