aboutsummaryrefslogtreecommitdiff
path: root/src/gnsrecord/gnsrecord_crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gnsrecord/gnsrecord_crypto.c')
-rw-r--r--src/gnsrecord/gnsrecord_crypto.c315
1 files changed, 222 insertions, 93 deletions
diff --git a/src/gnsrecord/gnsrecord_crypto.c b/src/gnsrecord/gnsrecord_crypto.c
index c8919760a..9c551a936 100644
--- a/src/gnsrecord/gnsrecord_crypto.c
+++ b/src/gnsrecord/gnsrecord_crypto.c
@@ -37,6 +37,61 @@
37 37
38#define LOG(kind, ...) GNUNET_log_from (kind, "gnsrecord", __VA_ARGS__) 38#define LOG(kind, ...) GNUNET_log_from (kind, "gnsrecord", __VA_ARGS__)
39 39
40ssize_t
41ecdsa_symmetric_decrypt (
42 const void *block,
43 size_t size,
44 const unsigned char *key,
45 const unsigned char *ctr,
46 void *result)
47{
48 gcry_cipher_hd_t handle;
49 int rc;
50
51 GNUNET_assert (0 == gcry_cipher_open (&handle, GCRY_CIPHER_AES256,
52 GCRY_CIPHER_MODE_CTR, 0));
53 rc = gcry_cipher_setkey (handle,
54 key,
55 GNUNET_CRYPTO_AES_KEY_LENGTH);
56 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
57 rc = gcry_cipher_setctr (handle,
58 ctr,
59 GNUNET_CRYPTO_AES_KEY_LENGTH / 2);
60 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
61 GNUNET_assert (0 == gcry_cipher_decrypt (handle, result, size, block, size));
62 gcry_cipher_close (handle);
63 return size;
64}
65
66
67
68ssize_t
69ecdsa_symmetric_encrypt (
70 const void *block,
71 size_t size,
72 const unsigned char *key,
73 const unsigned char *ctr,
74 void *result)
75{
76 gcry_cipher_hd_t handle;
77 int rc;
78
79 GNUNET_assert (0 == gcry_cipher_open (&handle, GCRY_CIPHER_AES256,
80 GCRY_CIPHER_MODE_CTR, 0));
81 rc = gcry_cipher_setkey (handle,
82 key,
83 GNUNET_CRYPTO_AES_KEY_LENGTH);
84 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
85 rc = gcry_cipher_setctr (handle,
86 ctr,
87 GNUNET_CRYPTO_AES_KEY_LENGTH / 2);
88 GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY));
89 GNUNET_assert (0 == gcry_cipher_encrypt (handle, result, size, block, size));
90 gcry_cipher_close (handle);
91 return size;
92}
93
94
40 95
41/** 96/**
42 * Derive session key and iv from label and public key. 97 * Derive session key and iv from label and public key.
@@ -47,25 +102,31 @@
47 * @param pub public key to use for KDF 102 * @param pub public key to use for KDF
48 */ 103 */
49static void 104static void
50derive_block_aes_key (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, 105derive_block_aes_key (unsigned char *ctr,
51 struct GNUNET_CRYPTO_SymmetricSessionKey *skey, 106 unsigned char *key,
52 const char *label, 107 const char *label,
108 uint64_t exp,
53 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub) 109 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
54{ 110{
55 static const char ctx_key[] = "gns-aes-ctx-key"; 111 static const char ctx_key[] = "gns-aes-ctx-key";
56 static const char ctx_iv[] = "gns-aes-ctx-iv"; 112 static const char ctx_iv[] = "gns-aes-ctx-iv";
57 113
58 GNUNET_CRYPTO_kdf (skey, sizeof(struct GNUNET_CRYPTO_SymmetricSessionKey), 114 GNUNET_CRYPTO_kdf (key, GNUNET_CRYPTO_AES_KEY_LENGTH,
59 ctx_key, strlen (ctx_key), 115 ctx_key, strlen (ctx_key),
60 pub, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey), 116 pub, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
61 label, strlen (label), 117 label, strlen (label),
62 NULL, 0); 118 NULL, 0);
63 GNUNET_CRYPTO_kdf (iv, sizeof(struct 119 memset (ctr, 0, GNUNET_CRYPTO_AES_KEY_LENGTH / 2);
64 GNUNET_CRYPTO_SymmetricInitializationVector), 120 /** 4 byte nonce **/
121 GNUNET_CRYPTO_kdf (ctr, 4,
65 ctx_iv, strlen (ctx_iv), 122 ctx_iv, strlen (ctx_iv),
66 pub, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey), 123 pub, sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
67 label, strlen (label), 124 label, strlen (label),
68 NULL, 0); 125 NULL, 0);
126 /** Expiration time 64 bit. **/
127 memcpy (ctr + 4, &exp, sizeof (exp));
128 /** Set counter part to 1 **/
129 ctr[15] |= 0x01;
69} 130}
70 131
71 132
@@ -81,19 +142,20 @@ derive_block_aes_key (struct GNUNET_CRYPTO_SymmetricInitializationVector *iv,
81 * @return NULL on error (block too large) 142 * @return NULL on error (block too large)
82 */ 143 */
83static struct GNUNET_GNSRECORD_Block * 144static struct GNUNET_GNSRECORD_Block *
84block_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, 145block_create_ecdsa (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
85 const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey, 146 const struct GNUNET_CRYPTO_EcdsaPublicKey *pkey,
86 struct GNUNET_TIME_Absolute expire, 147 struct GNUNET_TIME_Absolute expire,
87 const char *label, 148 const char *label,
88 const struct GNUNET_GNSRECORD_Data *rd, 149 const struct GNUNET_GNSRECORD_Data *rd,
89 unsigned int rd_count) 150 unsigned int rd_count)
90{ 151{
91 ssize_t payload_len = GNUNET_GNSRECORD_records_get_size (rd_count, 152 ssize_t payload_len = GNUNET_GNSRECORD_records_get_size (rd_count,
92 rd); 153 rd);
93 struct GNUNET_GNSRECORD_Block *block; 154 struct GNUNET_GNSRECORD_Block *block;
155 struct GNUNET_GNSRECORD_EcdsaBlock *ecblock;
94 struct GNUNET_CRYPTO_EcdsaPrivateKey *dkey; 156 struct GNUNET_CRYPTO_EcdsaPrivateKey *dkey;
95 struct GNUNET_CRYPTO_SymmetricInitializationVector iv; 157 unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2];
96 struct GNUNET_CRYPTO_SymmetricSessionKey skey; 158 unsigned char skey[GNUNET_CRYPTO_AES_KEY_LENGTH];
97 struct GNUNET_GNSRECORD_Data rdc[GNUNET_NZL (rd_count)]; 159 struct GNUNET_GNSRECORD_Data rdc[GNUNET_NZL (rd_count)];
98 uint32_t rd_count_nbo; 160 uint32_t rd_count_nbo;
99 struct GNUNET_TIME_Absolute now; 161 struct GNUNET_TIME_Absolute now;
@@ -140,35 +202,38 @@ block_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
140 block = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Block) 202 block = GNUNET_malloc (sizeof(struct GNUNET_GNSRECORD_Block)
141 + sizeof(uint32_t) 203 + sizeof(uint32_t)
142 + payload_len); 204 + payload_len);
143 block->purpose.size = htonl (sizeof(uint32_t) 205 ecblock = &block->ecdsa_block;
144 + payload_len 206 block->type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
145 + sizeof(struct 207 ecblock->purpose.size = htonl (sizeof(uint32_t)
146 GNUNET_CRYPTO_EccSignaturePurpose) 208 + payload_len
147 + sizeof(struct GNUNET_TIME_AbsoluteNBO)); 209 + sizeof(struct
148 block->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN); 210 GNUNET_CRYPTO_EccSignaturePurpose)
149 block->expiration_time = GNUNET_TIME_absolute_hton (expire); 211 + sizeof(struct GNUNET_TIME_AbsoluteNBO));
212 ecblock->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
213 ecblock->expiration_time = GNUNET_TIME_absolute_hton (expire);
150 /* encrypt and sign */ 214 /* encrypt and sign */
151 dkey = GNUNET_CRYPTO_ecdsa_private_key_derive (key, 215 dkey = GNUNET_CRYPTO_ecdsa_private_key_derive (key,
152 label, 216 label,
153 "gns"); 217 "gns");
154 GNUNET_CRYPTO_ecdsa_key_get_public (dkey, 218 GNUNET_CRYPTO_ecdsa_key_get_public (dkey,
155 &block->derived_key); 219 &ecblock->derived_key);
156 derive_block_aes_key (&iv, 220 derive_block_aes_key (ctr,
157 &skey, 221 skey,
158 label, 222 label,
223 ecblock->expiration_time.abs_value_us__,
159 pkey); 224 pkey);
160 GNUNET_break (payload_len + sizeof(uint32_t) == 225 GNUNET_break (payload_len + sizeof(uint32_t) ==
161 GNUNET_CRYPTO_symmetric_encrypt (payload, 226 ecdsa_symmetric_encrypt (payload,
162 payload_len 227 payload_len
163 + sizeof(uint32_t), 228 + sizeof(uint32_t),
164 &skey, 229 skey,
165 &iv, 230 ctr,
166 &block[1])); 231 &ecblock[1]));
167 } 232 }
168 if (GNUNET_OK != 233 if (GNUNET_OK !=
169 GNUNET_CRYPTO_ecdsa_sign_ (dkey, 234 GNUNET_CRYPTO_ecdsa_sign_ (dkey,
170 &block->purpose, 235 &ecblock->purpose,
171 &block->signature)) 236 &ecblock->signature))
172 { 237 {
173 GNUNET_break (0); 238 GNUNET_break (0);
174 GNUNET_free (dkey); 239 GNUNET_free (dkey);
@@ -191,7 +256,7 @@ block_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
191 * @return NULL on error (block too large) 256 * @return NULL on error (block too large)
192 */ 257 */
193struct GNUNET_GNSRECORD_Block * 258struct GNUNET_GNSRECORD_Block *
194GNUNET_GNSRECORD_block_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, 259GNUNET_GNSRECORD_block_create (const struct GNUNET_IDENTITY_PrivateKey *key,
195 struct GNUNET_TIME_Absolute expire, 260 struct GNUNET_TIME_Absolute expire,
196 const char *label, 261 const char *label,
197 const struct GNUNET_GNSRECORD_Data *rd, 262 const struct GNUNET_GNSRECORD_Data *rd,
@@ -199,14 +264,21 @@ GNUNET_GNSRECORD_block_create (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
199{ 264{
200 struct GNUNET_CRYPTO_EcdsaPublicKey pkey; 265 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
201 266
202 GNUNET_CRYPTO_ecdsa_key_get_public (key, 267 switch (ntohl (key->type))
203 &pkey); 268 {
204 return block_create (key, 269 case GNUNET_GNSRECORD_TYPE_PKEY:
205 &pkey, 270 GNUNET_CRYPTO_ecdsa_key_get_public (&key->ecdsa_key,
206 expire, 271 &pkey);
207 label, 272 return block_create_ecdsa (&key->ecdsa_key,
208 rd, 273 &pkey,
209 rd_count); 274 expire,
275 label,
276 rd,
277 rd_count);
278 default:
279 GNUNET_assert (0);
280 }
281 return NULL;
210} 282}
211 283
212 284
@@ -240,12 +312,19 @@ struct KeyCacheLine
240 * @return NULL on error (block too large) 312 * @return NULL on error (block too large)
241 */ 313 */
242struct GNUNET_GNSRECORD_Block * 314struct GNUNET_GNSRECORD_Block *
243GNUNET_GNSRECORD_block_create2 (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key, 315GNUNET_GNSRECORD_block_create2 (const struct GNUNET_IDENTITY_PrivateKey *pkey,
244 struct GNUNET_TIME_Absolute expire, 316 struct GNUNET_TIME_Absolute expire,
245 const char *label, 317 const char *label,
246 const struct GNUNET_GNSRECORD_Data *rd, 318 const struct GNUNET_GNSRECORD_Data *rd,
247 unsigned int rd_count) 319 unsigned int rd_count)
248{ 320{
321 const struct GNUNET_CRYPTO_EcdsaPrivateKey *key;
322
323 if (GNUNET_IDENTITY_TYPE_ECDSA != ntohl (pkey->type))
324 {
325 return NULL; // FIXME
326 }
327 key = &pkey->ecdsa_key;
249#define CSIZE 64 328#define CSIZE 64
250 static struct KeyCacheLine cache[CSIZE]; 329 static struct KeyCacheLine cache[CSIZE];
251 struct KeyCacheLine *line; 330 struct KeyCacheLine *line;
@@ -261,12 +340,12 @@ GNUNET_GNSRECORD_block_create2 (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
261 &line->pkey); 340 &line->pkey);
262 } 341 }
263#undef CSIZE 342#undef CSIZE
264 return block_create (key, 343 return block_create_ecdsa (key,
265 &line->pkey, 344 &line->pkey,
266 expire, 345 expire,
267 label, 346 label,
268 rd, 347 rd,
269 rd_count); 348 rd_count);
270} 349}
271 350
272 351
@@ -277,40 +356,40 @@ GNUNET_GNSRECORD_block_create2 (const struct GNUNET_CRYPTO_EcdsaPrivateKey *key,
277 * @param block block to verify 356 * @param block block to verify
278 * @return #GNUNET_OK if the signature is valid 357 * @return #GNUNET_OK if the signature is valid
279 */ 358 */
280int 359enum GNUNET_GenericReturnValue
281GNUNET_GNSRECORD_block_verify (const struct GNUNET_GNSRECORD_Block *block) 360GNUNET_GNSRECORD_block_verify (const struct GNUNET_GNSRECORD_Block *block)
282{ 361{
362 const struct GNUNET_CRYPTO_EcdsaPublicKey *key;
363 const struct GNUNET_GNSRECORD_EcdsaBlock *ecblock;
364
365 if (GNUNET_GNSRECORD_TYPE_PKEY != ntohl (block->type))
366 {
367 GNUNET_break (0);
368 return GNUNET_NO;
369 }
370 ecblock = &block->ecdsa_block;
371 key = &ecblock->derived_key;
372
283 return GNUNET_CRYPTO_ecdsa_verify_ (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN, 373 return GNUNET_CRYPTO_ecdsa_verify_ (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN,
284 &block->purpose, 374 &ecblock->purpose,
285 &block->signature, 375 &ecblock->signature,
286 &block->derived_key); 376 key);
287} 377}
288 378
289 379
290/** 380enum GNUNET_GenericReturnValue
291 * Decrypt block. 381block_decrypt_ecdsa (const struct GNUNET_GNSRECORD_EcdsaBlock *block,
292 * 382 const struct
293 * @param block block to decrypt 383 GNUNET_CRYPTO_EcdsaPublicKey *zone_key,
294 * @param zone_key public key of the zone 384 const char *label,
295 * @param label the name for the records 385 GNUNET_GNSRECORD_RecordCallback proc,
296 * @param proc function to call with the result 386 void *proc_cls)
297 * @param proc_cls closure for proc
298 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was
299 * not well-formed
300 */
301int
302GNUNET_GNSRECORD_block_decrypt (const struct GNUNET_GNSRECORD_Block *block,
303 const struct
304 GNUNET_CRYPTO_EcdsaPublicKey *zone_key,
305 const char *label,
306 GNUNET_GNSRECORD_RecordCallback proc,
307 void *proc_cls)
308{ 387{
309 size_t payload_len = ntohl (block->purpose.size) 388 size_t payload_len = ntohl (block->purpose.size)
310 - sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) 389 - sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
311 - sizeof(struct GNUNET_TIME_AbsoluteNBO); 390 - sizeof(struct GNUNET_TIME_AbsoluteNBO);
312 struct GNUNET_CRYPTO_SymmetricInitializationVector iv; 391 unsigned char ctr[GNUNET_CRYPTO_AES_KEY_LENGTH / 2];
313 struct GNUNET_CRYPTO_SymmetricSessionKey skey; 392 unsigned char key[GNUNET_CRYPTO_AES_KEY_LENGTH];
314 393
315 if (ntohl (block->purpose.size) < 394 if (ntohl (block->purpose.size) <
316 sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose) 395 sizeof(struct GNUNET_CRYPTO_EccSignaturePurpose)
@@ -319,18 +398,19 @@ GNUNET_GNSRECORD_block_decrypt (const struct GNUNET_GNSRECORD_Block *block,
319 GNUNET_break_op (0); 398 GNUNET_break_op (0);
320 return GNUNET_SYSERR; 399 return GNUNET_SYSERR;
321 } 400 }
322 derive_block_aes_key (&iv, 401 derive_block_aes_key (ctr,
323 &skey, 402 key,
324 label, 403 label,
404 block->expiration_time.abs_value_us__,
325 zone_key); 405 zone_key);
326 { 406 {
327 char payload[payload_len]; 407 char payload[payload_len];
328 uint32_t rd_count; 408 uint32_t rd_count;
329 409
330 GNUNET_break (payload_len == 410 GNUNET_break (payload_len ==
331 GNUNET_CRYPTO_symmetric_decrypt (&block[1], payload_len, 411 ecdsa_symmetric_decrypt (&block[1], payload_len,
332 &skey, &iv, 412 key, ctr,
333 payload)); 413 payload));
334 GNUNET_memcpy (&rd_count, 414 GNUNET_memcpy (&rd_count,
335 payload, 415 payload,
336 sizeof(uint32_t)); 416 sizeof(uint32_t));
@@ -426,6 +506,39 @@ GNUNET_GNSRECORD_block_decrypt (const struct GNUNET_GNSRECORD_Block *block,
426 506
427 507
428/** 508/**
509 * Decrypt block.
510 *
511 * @param block block to decrypt
512 * @param zone_key public key of the zone
513 * @param label the name for the records
514 * @param proc function to call with the result
515 * @param proc_cls closure for proc
516 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was
517 * not well-formed
518 */
519enum GNUNET_GenericReturnValue
520GNUNET_GNSRECORD_block_decrypt (const struct GNUNET_GNSRECORD_Block *block,
521 const struct
522 GNUNET_IDENTITY_PublicKey *zone_key,
523 const char *label,
524 GNUNET_GNSRECORD_RecordCallback proc,
525 void *proc_cls)
526{
527 const struct GNUNET_CRYPTO_EcdsaPublicKey *key;
528
529 if (GNUNET_IDENTITY_TYPE_ECDSA != ntohl (zone_key->type))
530 {
531 return GNUNET_NO;
532 }
533 key = &zone_key->ecdsa_key;
534
535 return block_decrypt_ecdsa (&block->ecdsa_block,
536 key, label, proc, proc_cls);
537
538}
539
540
541/**
429 * Calculate the DHT query for a given @a label in a given @a zone. 542 * Calculate the DHT query for a given @a label in a given @a zone.
430 * 543 *
431 * @param zone private key of the zone 544 * @param zone private key of the zone
@@ -434,17 +547,24 @@ GNUNET_GNSRECORD_block_decrypt (const struct GNUNET_GNSRECORD_Block *block,
434 */ 547 */
435void 548void
436GNUNET_GNSRECORD_query_from_private_key (const struct 549GNUNET_GNSRECORD_query_from_private_key (const struct
437 GNUNET_CRYPTO_EcdsaPrivateKey *zone, 550 GNUNET_IDENTITY_PrivateKey *zone,
438 const char *label, 551 const char *label,
439 struct GNUNET_HashCode *query) 552 struct GNUNET_HashCode *query)
440{ 553{
441 struct GNUNET_CRYPTO_EcdsaPublicKey pub; 554 struct GNUNET_IDENTITY_PublicKey pub;
442 555 switch (ntohl (zone->type))
443 GNUNET_CRYPTO_ecdsa_key_get_public (zone, 556 {
444 &pub); 557 case GNUNET_GNSRECORD_TYPE_PKEY:
445 GNUNET_GNSRECORD_query_from_public_key (&pub, 558
446 label, 559 GNUNET_IDENTITY_key_get_public (zone,
447 query); 560 &pub);
561 GNUNET_GNSRECORD_query_from_public_key (&pub,
562 label,
563 query);
564 break;
565 default:
566 GNUNET_assert (0);
567 }
448} 568}
449 569
450 570
@@ -457,18 +577,27 @@ GNUNET_GNSRECORD_query_from_private_key (const struct
457 */ 577 */
458void 578void
459GNUNET_GNSRECORD_query_from_public_key (const struct 579GNUNET_GNSRECORD_query_from_public_key (const struct
460 GNUNET_CRYPTO_EcdsaPublicKey *pub, 580 GNUNET_IDENTITY_PublicKey *pub,
461 const char *label, 581 const char *label,
462 struct GNUNET_HashCode *query) 582 struct GNUNET_HashCode *query)
463{ 583{
464 struct GNUNET_CRYPTO_EcdsaPublicKey pd; 584 struct GNUNET_IDENTITY_PublicKey pd;
465 GNUNET_CRYPTO_ecdsa_public_key_derive (pub, 585
466 label, 586 switch (ntohl (pub->type))
467 "gns", 587 {
468 &pd); 588 case GNUNET_GNSRECORD_TYPE_PKEY:
469 GNUNET_CRYPTO_hash (&pd, 589 pd.type = pub->type;
470 sizeof(pd), 590 GNUNET_CRYPTO_ecdsa_public_key_derive (&pub->ecdsa_key,
471 query); 591 label,
592 "gns",
593 &pd.ecdsa_key);
594 GNUNET_CRYPTO_hash (&pd.ecdsa_key,
595 sizeof (pd.ecdsa_key),
596 query);
597 break;
598 default:
599 GNUNET_assert (0);
600 }
472} 601}
473 602
474 603