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(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
;
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
);
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
]);
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
);
175 size_t hash_input_length
= dipe_h_length(y
[0], msk
->dimension
);
176 unsigned char hash_input
[hash_input_length
];
178 element_init_G2(h
, param
->pairing
);
180 dipe_generate_h(cid
, y
, msk
->dimension
, hash_input
);
181 element_from_hash(h
, hash_input
, hash_input_length
);
186 element_init_Zr(innerp
, param
->pairing
);
187 element_init_Zr(tmp
, param
->pairing
);
188 element_set0(innerp
);
190 element_from_hash(h
, hash_input
, hash_input_length
);
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
);
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
);
204 element_clear(innerp
);
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
;
215 element_init_Zr(r
, param
->pairing
);
216 element_init_Zr(s
, param
->pairing
);
221 element_init_G1((*ctxt
)->s
, param
->pairing
);
222 element_pow_zn((*ctxt
)->s
, param
->g1
, s
);
226 element_init_G1(k1
, param
->pairing
);
227 element_init_G1(x1
, param
->pairing
);
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
);
234 element_pow_zn(k1
, mpk
->k
[i
], s
);
236 element_init_G1((*ctxt
)->cx
[i
], param
->pairing
);
237 element_mul((*ctxt
)->cx
[i
], k1
, x1
);
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
);
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
];
258 element_init_G2(h
, param
->pairing
);
260 dipe_generate_h(cid
, y
, sk
->dimension
, hash_input
);
261 element_from_hash(h
, hash_input
, hash_input_length
);
266 element_init_GT(tmp
, param
->pairing
);
267 element_init_GT(innerp
, param
->pairing
);
268 element_init_G2(hy
, param
->pairing
);
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
);
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
);
284 element_clear(innerp
);
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
) {
294 element_init_GT(key
, param
->pairing
);
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
;
301 dipe_aes_encrypt(aes
, aes
+16, ptxt_len
, (uint8_t*)ptxt
, ctxt_len
, (uint8_t*)ctxt
);
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
) {
313 element_init_GT(key
, param
->pairing
);
314 cap_len
= dipe_deserialize_ctxt(param
, sk
->dimension
, &cap
, (uint8_t*)ctxt
);
317 dipe_decap(param
, sk
, cid
, y
, cap
, key
);
318 dipe_generate_aeskey(key
, aes
);
323 return dipe_aes_decrypt(aes
, aes
+16, ctxt_len
, (uint8_t*)ctxt
, (uint8_t*)ptxt
);
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).
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
);
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
]);
343 element_to_bytes(buffer
, ctxt
->c
);
344 buffer
+= element_length_in_bytes(ctxt
->c
);
345 bytes_written
+= element_length_in_bytes(ctxt
->c
);
347 return bytes_written
;
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
;
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
);
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
]);
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
);
376 size_t dipe_ciphertext_overhead(dipe_param_t param
, size_t dimension
) {
377 size_t overhead
= 16 + 4 /* IV + Tag + Size */;
380 element_init_G1(t
, param
->pairing
);
381 overhead
+= element_length_in_bytes_compressed(t
);
382 overhead
+= dimension
* element_length_in_bytes_compressed(t
);
384 element_init_GT(t
, param
->pairing
);
385 overhead
+= element_length_in_bytes(t
);
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
);
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
]);
403 element_clear(sk
->a
);
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
]);
412 element_clear(pk
->a
);
417 void dipe_free_secretkey(dipe_secretkey_t sk
) {
418 element_clear(sk
->d
);
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
]);
426 element_clear(ctxt
->c
);
427 element_clear(ctxt
->s
);