diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-01-17 14:20:59 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-01-17 14:20:59 +0100 |
commit | 23c86a4ca5d1cd879550cd07afed4869475fb765 (patch) | |
tree | a8eace7b55bcbf3545e1590c7868f52b6b6dfeb4 /src | |
parent | 500842f42c4e51c4c5fc3c1cdfc1c1f7166b2d0d (diff) | |
download | gnunet-23c86a4ca5d1cd879550cd07afed4869475fb765.tar.gz gnunet-23c86a4ca5d1cd879550cd07afed4869475fb765.zip |
importing KX logic, integrating encryption logic
Diffstat (limited to 'src')
-rw-r--r-- | src/cadet/gnunet-service-cadet-new.c | 35 | ||||
-rw-r--r-- | src/cadet/gnunet-service-cadet-new.h | 15 | ||||
-rw-r--r-- | src/cadet/gnunet-service-cadet-new_connection.c | 24 | ||||
-rw-r--r-- | src/cadet/gnunet-service-cadet-new_connection.h | 12 | ||||
-rw-r--r-- | src/cadet/gnunet-service-cadet-new_tunnels.c | 689 |
5 files changed, 763 insertions, 12 deletions
diff --git a/src/cadet/gnunet-service-cadet-new.c b/src/cadet/gnunet-service-cadet-new.c index b2f39b3cd..3bb7d9cdf 100644 --- a/src/cadet/gnunet-service-cadet-new.c +++ b/src/cadet/gnunet-service-cadet-new.c | |||
@@ -175,6 +175,16 @@ struct GNUNET_CONTAINER_MultiPeerMap *peers; | |||
175 | */ | 175 | */ |
176 | struct GNUNET_CONTAINER_MultiHashMap *connections; | 176 | struct GNUNET_CONTAINER_MultiHashMap *connections; |
177 | 177 | ||
178 | /** | ||
179 | * How many messages are needed to trigger an AXOLOTL ratchet advance. | ||
180 | */ | ||
181 | unsigned long long ratchet_messages; | ||
182 | |||
183 | /** | ||
184 | * How long until we trigger a ratched advance due to time. | ||
185 | */ | ||
186 | struct GNUNET_TIME_Relative ratchet_time; | ||
187 | |||
178 | 188 | ||
179 | 189 | ||
180 | /** | 190 | /** |
@@ -1221,6 +1231,31 @@ run (void *cls, | |||
1221 | const struct GNUNET_CONFIGURATION_Handle *c, | 1231 | const struct GNUNET_CONFIGURATION_Handle *c, |
1222 | struct GNUNET_SERVICE_Handle *service) | 1232 | struct GNUNET_SERVICE_Handle *service) |
1223 | { | 1233 | { |
1234 | if (GNUNET_OK != | ||
1235 | GNUNET_CONFIGURATION_get_value_number (c, | ||
1236 | "CADET", | ||
1237 | "RATCHET_MESSAGES", | ||
1238 | &ratchet_messages)) | ||
1239 | { | ||
1240 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1241 | "CADET", | ||
1242 | "RATCHET_MESSAGES", | ||
1243 | "needs to be a number"); | ||
1244 | ratchet_messages = 64; | ||
1245 | } | ||
1246 | if (GNUNET_OK != | ||
1247 | GNUNET_CONFIGURATION_get_value_time (c, | ||
1248 | "CADET", | ||
1249 | "RATCHET_TIME", | ||
1250 | &ratchet_time)) | ||
1251 | { | ||
1252 | GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, | ||
1253 | "CADET", | ||
1254 | "RATCHET_TIME", | ||
1255 | "need delay value"); | ||
1256 | ratchet_time = GNUNET_TIME_UNIT_HOURS; | ||
1257 | } | ||
1258 | |||
1224 | my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c); | 1259 | my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (c); |
1225 | if (NULL == my_private_key) | 1260 | if (NULL == my_private_key) |
1226 | { | 1261 | { |
diff --git a/src/cadet/gnunet-service-cadet-new.h b/src/cadet/gnunet-service-cadet-new.h index 416c9d13a..903ceed94 100644 --- a/src/cadet/gnunet-service-cadet-new.h +++ b/src/cadet/gnunet-service-cadet-new.h | |||
@@ -101,6 +101,10 @@ struct CadetPeerPathEntry | |||
101 | 101 | ||
102 | }; | 102 | }; |
103 | 103 | ||
104 | /** | ||
105 | * Entry in list of connections used by tunnel, with metadata. | ||
106 | */ | ||
107 | struct CadetTConnection; | ||
104 | 108 | ||
105 | /** | 109 | /** |
106 | * Active path through the network (used by a tunnel). There may | 110 | * Active path through the network (used by a tunnel). There may |
@@ -156,6 +160,17 @@ extern struct GNUNET_CONTAINER_MultiHashMap *loose_channels; | |||
156 | */ | 160 | */ |
157 | extern struct GNUNET_CONTAINER_MultiPeerMap *peers; | 161 | extern struct GNUNET_CONTAINER_MultiPeerMap *peers; |
158 | 162 | ||
163 | /** | ||
164 | * How many messages are needed to trigger an AXOLOTL ratchet advance. | ||
165 | */ | ||
166 | extern unsigned long long ratchet_messages; | ||
167 | |||
168 | /** | ||
169 | * How long until we trigger a ratched advance due to time. | ||
170 | */ | ||
171 | extern struct GNUNET_TIME_Relative ratchet_time; | ||
172 | |||
173 | |||
159 | 174 | ||
160 | /** | 175 | /** |
161 | * Send a message to a client. | 176 | * Send a message to a client. |
diff --git a/src/cadet/gnunet-service-cadet-new_connection.c b/src/cadet/gnunet-service-cadet-new_connection.c index 1f31331a5..6a9c210b8 100644 --- a/src/cadet/gnunet-service-cadet-new_connection.c +++ b/src/cadet/gnunet-service-cadet-new_connection.c | |||
@@ -21,7 +21,8 @@ | |||
21 | 21 | ||
22 | /** | 22 | /** |
23 | * @file cadet/gnunet-service-cadet-new_connection.c | 23 | * @file cadet/gnunet-service-cadet-new_connection.c |
24 | * @brief | 24 | * @brief management of CORE-level end-to-end connections; establishes |
25 | * end-to-end routes and transmits messages along the route | ||
25 | * @author Bartlomiej Polot | 26 | * @author Bartlomiej Polot |
26 | * @author Christian Grothoff | 27 | * @author Christian Grothoff |
27 | */ | 28 | */ |
@@ -88,6 +89,11 @@ struct CadetConnection | |||
88 | struct CadetPeer *destination; | 89 | struct CadetPeer *destination; |
89 | 90 | ||
90 | /** | 91 | /** |
92 | * Which tunnel is using this connection? | ||
93 | */ | ||
94 | struct CadetTConnection *ct; | ||
95 | |||
96 | /** | ||
91 | * Path we are using to our destination. | 97 | * Path we are using to our destination. |
92 | */ | 98 | */ |
93 | struct CadetPeerPath *path; | 99 | struct CadetPeerPath *path; |
@@ -231,6 +237,19 @@ GCC_get_h (const struct CadetConnection *cc) | |||
231 | 237 | ||
232 | 238 | ||
233 | /** | 239 | /** |
240 | * Return the tunnel associated with this connection. | ||
241 | * | ||
242 | * @param cc connection to query | ||
243 | * @return corresponding entry in the tunnel's connection list | ||
244 | */ | ||
245 | struct CadetTConnection * | ||
246 | GCC_get_ct (struct CadetConnection *cc) | ||
247 | { | ||
248 | return cc->ct; | ||
249 | } | ||
250 | |||
251 | |||
252 | /** | ||
234 | * An ACK was received for this connection, process it. | 253 | * An ACK was received for this connection, process it. |
235 | * | 254 | * |
236 | * @param cc the connection that got the ACK. | 255 | * @param cc the connection that got the ACK. |
@@ -355,6 +374,7 @@ manage_first_hop_mq (void *cls, | |||
355 | * | 374 | * |
356 | * @param destination where to go | 375 | * @param destination where to go |
357 | * @param path which path to take (may not be the full path) | 376 | * @param path which path to take (may not be the full path) |
377 | * @param ct tunnel that uses the connection | ||
358 | * @param ready_cb function to call when ready to transmit | 378 | * @param ready_cb function to call when ready to transmit |
359 | * @param ready_cb_cls closure for @a cb | 379 | * @param ready_cb_cls closure for @a cb |
360 | * @return handle to the connection | 380 | * @return handle to the connection |
@@ -362,6 +382,7 @@ manage_first_hop_mq (void *cls, | |||
362 | struct CadetConnection * | 382 | struct CadetConnection * |
363 | GCC_create (struct CadetPeer *destination, | 383 | GCC_create (struct CadetPeer *destination, |
364 | struct CadetPeerPath *path, | 384 | struct CadetPeerPath *path, |
385 | struct CadetTConnection *ct, | ||
365 | GNUNET_SCHEDULER_TaskCallback ready_cb, | 386 | GNUNET_SCHEDULER_TaskCallback ready_cb, |
366 | void *ready_cb_cls) | 387 | void *ready_cb_cls) |
367 | { | 388 | { |
@@ -373,6 +394,7 @@ GCC_create (struct CadetPeer *destination, | |||
373 | destination); | 394 | destination); |
374 | GNUNET_assert (UINT_MAX > off); | 395 | GNUNET_assert (UINT_MAX > off); |
375 | cc = GNUNET_new (struct CadetConnection); | 396 | cc = GNUNET_new (struct CadetConnection); |
397 | cc->ct = ct; | ||
376 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, | 398 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, |
377 | &cc->cid, | 399 | &cc->cid, |
378 | sizeof (cc->cid)); | 400 | sizeof (cc->cid)); |
diff --git a/src/cadet/gnunet-service-cadet-new_connection.h b/src/cadet/gnunet-service-cadet-new_connection.h index c9738d86e..66d19ae0c 100644 --- a/src/cadet/gnunet-service-cadet-new_connection.h +++ b/src/cadet/gnunet-service-cadet-new_connection.h | |||
@@ -58,6 +58,7 @@ GCC_destroy (struct CadetConnection *cc); | |||
58 | * | 58 | * |
59 | * @param destination where to go | 59 | * @param destination where to go |
60 | * @param path which path to take (may not be the full path) | 60 | * @param path which path to take (may not be the full path) |
61 | * @param ct which tunnel uses this connection | ||
61 | * @param ready_cb function to call when ready to transmit | 62 | * @param ready_cb function to call when ready to transmit |
62 | * @param ready_cb_cls closure for @a cb | 63 | * @param ready_cb_cls closure for @a cb |
63 | * @return handle to the connection | 64 | * @return handle to the connection |
@@ -65,6 +66,7 @@ GCC_destroy (struct CadetConnection *cc); | |||
65 | struct CadetConnection * | 66 | struct CadetConnection * |
66 | GCC_create (struct CadetPeer *destination, | 67 | GCC_create (struct CadetPeer *destination, |
67 | struct CadetPeerPath *path, | 68 | struct CadetPeerPath *path, |
69 | struct CadetTConnection *ct, | ||
68 | GNUNET_SCHEDULER_TaskCallback ready_cb, | 70 | GNUNET_SCHEDULER_TaskCallback ready_cb, |
69 | void *ready_cb_cls); | 71 | void *ready_cb_cls); |
70 | 72 | ||
@@ -87,6 +89,16 @@ GCC_transmit (struct CadetConnection *cc, | |||
87 | 89 | ||
88 | 90 | ||
89 | /** | 91 | /** |
92 | * Return the tunnel associated with this connection. | ||
93 | * | ||
94 | * @param cc connection to query | ||
95 | * @return corresponding entry in the tunnel's connection list | ||
96 | */ | ||
97 | struct CadetTConnection * | ||
98 | GCC_get_ct (struct CadetConnection *cc); | ||
99 | |||
100 | |||
101 | /** | ||
90 | * Obtain the path used by this connection. | 102 | * Obtain the path used by this connection. |
91 | * | 103 | * |
92 | * @param cc connection | 104 | * @param cc connection |
diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.c b/src/cadet/gnunet-service-cadet-new_tunnels.c index 18c469b67..b5a4e0112 100644 --- a/src/cadet/gnunet-service-cadet-new_tunnels.c +++ b/src/cadet/gnunet-service-cadet-new_tunnels.c | |||
@@ -29,6 +29,7 @@ | |||
29 | * - when managing connections, distinguish those that | 29 | * - when managing connections, distinguish those that |
30 | * have (recently) had traffic from those that were | 30 | * have (recently) had traffic from those that were |
31 | * never ready (or not recently) | 31 | * never ready (or not recently) |
32 | * - clean up KX logic! | ||
32 | */ | 33 | */ |
33 | #include "platform.h" | 34 | #include "platform.h" |
34 | #include "gnunet_util_lib.h" | 35 | #include "gnunet_util_lib.h" |
@@ -43,11 +44,33 @@ | |||
43 | #include "gnunet-service-cadet-new_paths.h" | 44 | #include "gnunet-service-cadet-new_paths.h" |
44 | 45 | ||
45 | 46 | ||
47 | #define LOG(level, ...) GNUNET_log_from(level,"cadet-tun",__VA_ARGS__) | ||
48 | |||
49 | |||
46 | /** | 50 | /** |
47 | * How long do we wait until tearing down an idle tunnel? | 51 | * How long do we wait until tearing down an idle tunnel? |
48 | */ | 52 | */ |
49 | #define IDLE_DESTROY_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 90) | 53 | #define IDLE_DESTROY_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 90) |
50 | 54 | ||
55 | /** | ||
56 | * Yuck, replace by 'offsetof' expression? | ||
57 | * FIXME. | ||
58 | */ | ||
59 | #define AX_HEADER_SIZE (sizeof (uint32_t) * 2\ | ||
60 | + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)) | ||
61 | |||
62 | |||
63 | /** | ||
64 | * Maximum number of skipped keys we keep in memory per tunnel. | ||
65 | */ | ||
66 | #define MAX_SKIPPED_KEYS 64 | ||
67 | |||
68 | /** | ||
69 | * Maximum number of keys (and thus ratchet steps) we are willing to | ||
70 | * skip before we decide this is either a bogus packet or a DoS-attempt. | ||
71 | */ | ||
72 | #define MAX_KEY_GAP 256 | ||
73 | |||
51 | 74 | ||
52 | /** | 75 | /** |
53 | * Struct to old keys for skipped messages while advancing the Axolotl ratchet. | 76 | * Struct to old keys for skipped messages while advancing the Axolotl ratchet. |
@@ -271,6 +294,12 @@ struct CadetTunnelQueueEntry | |||
271 | * Envelope of message to send follows. | 294 | * Envelope of message to send follows. |
272 | */ | 295 | */ |
273 | struct GNUNET_MQ_Envelope *env; | 296 | struct GNUNET_MQ_Envelope *env; |
297 | |||
298 | /** | ||
299 | * Where to put the connection identifier into the payload | ||
300 | * of the message in @e env once we have it? | ||
301 | */ | ||
302 | struct GNUNET_CADET_ConnectionTunnelIdentifier *cid; | ||
274 | }; | 303 | }; |
275 | 304 | ||
276 | 305 | ||
@@ -476,6 +505,619 @@ GCT_get_estate (struct CadetTunnel *t) | |||
476 | 505 | ||
477 | 506 | ||
478 | /** | 507 | /** |
508 | * Create a new Axolotl ephemeral (ratchet) key. | ||
509 | * | ||
510 | * @param t Tunnel. | ||
511 | */ | ||
512 | static void | ||
513 | new_ephemeral (struct CadetTunnel *t) | ||
514 | { | ||
515 | GNUNET_free_non_null (t->ax.DHRs); | ||
516 | t->ax.DHRs = GNUNET_CRYPTO_ecdhe_key_create (); | ||
517 | } | ||
518 | |||
519 | |||
520 | /* ************************************** start core crypto ***************************** */ | ||
521 | |||
522 | |||
523 | /** | ||
524 | * Calculate HMAC. | ||
525 | * | ||
526 | * @param plaintext Content to HMAC. | ||
527 | * @param size Size of @c plaintext. | ||
528 | * @param iv Initialization vector for the message. | ||
529 | * @param key Key to use. | ||
530 | * @param hmac[out] Destination to store the HMAC. | ||
531 | */ | ||
532 | static void | ||
533 | t_hmac (const void *plaintext, | ||
534 | size_t size, | ||
535 | uint32_t iv, | ||
536 | const struct GNUNET_CRYPTO_SymmetricSessionKey *key, | ||
537 | struct GNUNET_CADET_Hash *hmac) | ||
538 | { | ||
539 | static const char ctx[] = "cadet authentication key"; | ||
540 | struct GNUNET_CRYPTO_AuthKey auth_key; | ||
541 | struct GNUNET_HashCode hash; | ||
542 | |||
543 | GNUNET_CRYPTO_hmac_derive_key (&auth_key, | ||
544 | key, | ||
545 | &iv, sizeof (iv), | ||
546 | key, sizeof (*key), | ||
547 | ctx, sizeof (ctx), | ||
548 | NULL); | ||
549 | /* Two step: CADET_Hash is only 256 bits, HashCode is 512. */ | ||
550 | GNUNET_CRYPTO_hmac (&auth_key, | ||
551 | plaintext, | ||
552 | size, | ||
553 | &hash); | ||
554 | GNUNET_memcpy (hmac, | ||
555 | &hash, | ||
556 | sizeof (*hmac)); | ||
557 | } | ||
558 | |||
559 | |||
560 | /** | ||
561 | * Perform a HMAC. | ||
562 | * | ||
563 | * @param key Key to use. | ||
564 | * @param hash[out] Resulting HMAC. | ||
565 | * @param source Source key material (data to HMAC). | ||
566 | * @param len Length of @a source. | ||
567 | */ | ||
568 | static void | ||
569 | t_ax_hmac_hash (const struct GNUNET_CRYPTO_SymmetricSessionKey *key, | ||
570 | struct GNUNET_HashCode *hash, | ||
571 | const void *source, | ||
572 | unsigned int len) | ||
573 | { | ||
574 | static const char ctx[] = "axolotl HMAC-HASH"; | ||
575 | struct GNUNET_CRYPTO_AuthKey auth_key; | ||
576 | |||
577 | GNUNET_CRYPTO_hmac_derive_key (&auth_key, | ||
578 | key, | ||
579 | ctx, sizeof (ctx), | ||
580 | NULL); | ||
581 | GNUNET_CRYPTO_hmac (&auth_key, | ||
582 | source, | ||
583 | len, | ||
584 | hash); | ||
585 | } | ||
586 | |||
587 | |||
588 | /** | ||
589 | * Derive a symmetric encryption key from an HMAC-HASH. | ||
590 | * | ||
591 | * @param key Key to use for the HMAC. | ||
592 | * @param[out] out Key to generate. | ||
593 | * @param source Source key material (data to HMAC). | ||
594 | * @param len Length of @a source. | ||
595 | */ | ||
596 | static void | ||
597 | t_hmac_derive_key (const struct GNUNET_CRYPTO_SymmetricSessionKey *key, | ||
598 | struct GNUNET_CRYPTO_SymmetricSessionKey *out, | ||
599 | const void *source, | ||
600 | unsigned int len) | ||
601 | { | ||
602 | static const char ctx[] = "axolotl derive key"; | ||
603 | struct GNUNET_HashCode h; | ||
604 | |||
605 | t_ax_hmac_hash (key, | ||
606 | &h, | ||
607 | source, | ||
608 | len); | ||
609 | GNUNET_CRYPTO_kdf (out, sizeof (*out), | ||
610 | ctx, sizeof (ctx), | ||
611 | &h, sizeof (h), | ||
612 | NULL); | ||
613 | } | ||
614 | |||
615 | |||
616 | /** | ||
617 | * Encrypt data with the axolotl tunnel key. | ||
618 | * | ||
619 | * @param t Tunnel whose key to use. | ||
620 | * @param dst Destination with @a size bytes for the encrypted data. | ||
621 | * @param src Source of the plaintext. Can overlap with @c dst, must contain @a size bytes | ||
622 | * @param size Size of the buffers at @a src and @a dst | ||
623 | */ | ||
624 | static void | ||
625 | t_ax_encrypt (struct CadetTunnel *t, | ||
626 | void *dst, | ||
627 | const void *src, | ||
628 | size_t size) | ||
629 | { | ||
630 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; | ||
631 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
632 | struct CadetTunnelAxolotl *ax; | ||
633 | size_t out_size; | ||
634 | |||
635 | ax = &t->ax; | ||
636 | ax->ratchet_counter++; | ||
637 | if ( (GNUNET_YES == ax->ratchet_allowed) && | ||
638 | ( (ratchet_messages <= ax->ratchet_counter) || | ||
639 | (0 == GNUNET_TIME_absolute_get_remaining (ax->ratchet_expiration).rel_value_us)) ) | ||
640 | { | ||
641 | ax->ratchet_flag = GNUNET_YES; | ||
642 | } | ||
643 | if (GNUNET_YES == ax->ratchet_flag) | ||
644 | { | ||
645 | /* Advance ratchet */ | ||
646 | struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; | ||
647 | struct GNUNET_HashCode dh; | ||
648 | struct GNUNET_HashCode hmac; | ||
649 | static const char ctx[] = "axolotl ratchet"; | ||
650 | |||
651 | new_ephemeral (t); | ||
652 | ax->HKs = ax->NHKs; | ||
653 | |||
654 | /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */ | ||
655 | GNUNET_CRYPTO_ecc_ecdh (ax->DHRs, | ||
656 | &ax->DHRr, | ||
657 | &dh); | ||
658 | t_ax_hmac_hash (&ax->RK, | ||
659 | &hmac, | ||
660 | &dh, | ||
661 | sizeof (dh)); | ||
662 | GNUNET_CRYPTO_kdf (keys, sizeof (keys), | ||
663 | ctx, sizeof (ctx), | ||
664 | &hmac, sizeof (hmac), | ||
665 | NULL); | ||
666 | ax->RK = keys[0]; | ||
667 | ax->NHKs = keys[1]; | ||
668 | ax->CKs = keys[2]; | ||
669 | |||
670 | ax->PNs = ax->Ns; | ||
671 | ax->Ns = 0; | ||
672 | ax->ratchet_flag = GNUNET_NO; | ||
673 | ax->ratchet_allowed = GNUNET_NO; | ||
674 | ax->ratchet_counter = 0; | ||
675 | ax->ratchet_expiration | ||
676 | = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), | ||
677 | ratchet_time); | ||
678 | } | ||
679 | |||
680 | t_hmac_derive_key (&ax->CKs, | ||
681 | &MK, | ||
682 | "0", | ||
683 | 1); | ||
684 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
685 | &MK, | ||
686 | NULL, 0, | ||
687 | NULL); | ||
688 | |||
689 | out_size = GNUNET_CRYPTO_symmetric_encrypt (src, | ||
690 | size, | ||
691 | &MK, | ||
692 | &iv, | ||
693 | dst); | ||
694 | GNUNET_assert (size == out_size); | ||
695 | t_hmac_derive_key (&ax->CKs, | ||
696 | &ax->CKs, | ||
697 | "1", | ||
698 | 1); | ||
699 | } | ||
700 | |||
701 | |||
702 | /** | ||
703 | * Decrypt data with the axolotl tunnel key. | ||
704 | * | ||
705 | * @param t Tunnel whose key to use. | ||
706 | * @param dst Destination for the decrypted data, must contain @a size bytes. | ||
707 | * @param src Source of the ciphertext. Can overlap with @c dst, must contain @a size bytes. | ||
708 | * @param size Size of the @a src and @a dst buffers | ||
709 | */ | ||
710 | static void | ||
711 | t_ax_decrypt (struct CadetTunnel *t, | ||
712 | void *dst, | ||
713 | const void *src, | ||
714 | size_t size) | ||
715 | { | ||
716 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; | ||
717 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
718 | struct CadetTunnelAxolotl *ax; | ||
719 | size_t out_size; | ||
720 | |||
721 | ax = &t->ax; | ||
722 | t_hmac_derive_key (&ax->CKr, | ||
723 | &MK, | ||
724 | "0", | ||
725 | 1); | ||
726 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
727 | &MK, | ||
728 | NULL, 0, | ||
729 | NULL); | ||
730 | GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); | ||
731 | out_size = GNUNET_CRYPTO_symmetric_decrypt (src, | ||
732 | size, | ||
733 | &MK, | ||
734 | &iv, | ||
735 | dst); | ||
736 | GNUNET_assert (out_size == size); | ||
737 | t_hmac_derive_key (&ax->CKr, | ||
738 | &ax->CKr, | ||
739 | "1", | ||
740 | 1); | ||
741 | } | ||
742 | |||
743 | |||
744 | /** | ||
745 | * Encrypt header with the axolotl header key. | ||
746 | * | ||
747 | * @param t Tunnel whose key to use. | ||
748 | * @param msg Message whose header to encrypt. | ||
749 | */ | ||
750 | static void | ||
751 | t_h_encrypt (struct CadetTunnel *t, | ||
752 | struct GNUNET_CADET_Encrypted *msg) | ||
753 | { | ||
754 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
755 | struct CadetTunnelAxolotl *ax; | ||
756 | size_t out_size; | ||
757 | |||
758 | ax = &t->ax; | ||
759 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
760 | &ax->HKs, | ||
761 | NULL, 0, | ||
762 | NULL); | ||
763 | out_size = GNUNET_CRYPTO_symmetric_encrypt (&msg->Ns, | ||
764 | AX_HEADER_SIZE, | ||
765 | &ax->HKs, | ||
766 | &iv, | ||
767 | &msg->Ns); | ||
768 | GNUNET_assert (AX_HEADER_SIZE == out_size); | ||
769 | } | ||
770 | |||
771 | |||
772 | /** | ||
773 | * Decrypt header with the current axolotl header key. | ||
774 | * | ||
775 | * @param t Tunnel whose current ax HK to use. | ||
776 | * @param src Message whose header to decrypt. | ||
777 | * @param dst Where to decrypt header to. | ||
778 | */ | ||
779 | static void | ||
780 | t_h_decrypt (struct CadetTunnel *t, | ||
781 | const struct GNUNET_CADET_Encrypted *src, | ||
782 | struct GNUNET_CADET_Encrypted *dst) | ||
783 | { | ||
784 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
785 | struct CadetTunnelAxolotl *ax; | ||
786 | size_t out_size; | ||
787 | |||
788 | ax = &t->ax; | ||
789 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
790 | &ax->HKr, | ||
791 | NULL, 0, | ||
792 | NULL); | ||
793 | out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns, | ||
794 | AX_HEADER_SIZE, | ||
795 | &ax->HKr, | ||
796 | &iv, | ||
797 | &dst->Ns); | ||
798 | GNUNET_assert (AX_HEADER_SIZE == out_size); | ||
799 | } | ||
800 | |||
801 | |||
802 | /** | ||
803 | * Delete a key from the list of skipped keys. | ||
804 | * | ||
805 | * @param t Tunnel to delete from. | ||
806 | * @param key Key to delete. | ||
807 | */ | ||
808 | static void | ||
809 | delete_skipped_key (struct CadetTunnel *t, | ||
810 | struct CadetTunnelSkippedKey *key) | ||
811 | { | ||
812 | GNUNET_CONTAINER_DLL_remove (t->ax.skipped_head, | ||
813 | t->ax.skipped_tail, | ||
814 | key); | ||
815 | GNUNET_free (key); | ||
816 | t->ax.skipped--; | ||
817 | } | ||
818 | |||
819 | |||
820 | /** | ||
821 | * Decrypt and verify data with the appropriate tunnel key and verify that the | ||
822 | * data has not been altered since it was sent by the remote peer. | ||
823 | * | ||
824 | * @param t Tunnel whose key to use. | ||
825 | * @param dst Destination for the plaintext. | ||
826 | * @param src Source of the message. Can overlap with @c dst. | ||
827 | * @param size Size of the message. | ||
828 | * @return Size of the decrypted data, -1 if an error was encountered. | ||
829 | */ | ||
830 | static ssize_t | ||
831 | try_old_ax_keys (struct CadetTunnel *t, | ||
832 | void *dst, | ||
833 | const struct GNUNET_CADET_Encrypted *src, | ||
834 | size_t size) | ||
835 | { | ||
836 | struct CadetTunnelSkippedKey *key; | ||
837 | struct GNUNET_CADET_Hash *hmac; | ||
838 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
839 | struct GNUNET_CADET_Encrypted plaintext_header; | ||
840 | struct GNUNET_CRYPTO_SymmetricSessionKey *valid_HK; | ||
841 | size_t esize; | ||
842 | size_t res; | ||
843 | size_t len; | ||
844 | unsigned int N; | ||
845 | |||
846 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
847 | "Trying skipped keys\n"); | ||
848 | hmac = &plaintext_header.hmac; | ||
849 | esize = size - sizeof (struct GNUNET_CADET_Encrypted); | ||
850 | |||
851 | /* Find a correct Header Key */ | ||
852 | valid_HK = NULL; | ||
853 | for (key = t->ax.skipped_head; NULL != key; key = key->next) | ||
854 | { | ||
855 | t_hmac (&src->Ns, | ||
856 | AX_HEADER_SIZE + esize, | ||
857 | 0, | ||
858 | &key->HK, | ||
859 | hmac); | ||
860 | if (0 == memcmp (hmac, | ||
861 | &src->hmac, | ||
862 | sizeof (*hmac))) | ||
863 | { | ||
864 | valid_HK = &key->HK; | ||
865 | break; | ||
866 | } | ||
867 | } | ||
868 | if (NULL == key) | ||
869 | return -1; | ||
870 | |||
871 | /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */ | ||
872 | GNUNET_assert (size > sizeof (struct GNUNET_CADET_Encrypted)); | ||
873 | len = size - sizeof (struct GNUNET_CADET_Encrypted); | ||
874 | GNUNET_assert (len >= sizeof (struct GNUNET_MessageHeader)); | ||
875 | |||
876 | /* Decrypt header */ | ||
877 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
878 | &key->HK, | ||
879 | NULL, 0, | ||
880 | NULL); | ||
881 | res = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns, | ||
882 | AX_HEADER_SIZE, | ||
883 | &key->HK, | ||
884 | &iv, | ||
885 | &plaintext_header.Ns); | ||
886 | GNUNET_assert (AX_HEADER_SIZE == res); | ||
887 | |||
888 | /* Find the correct message key */ | ||
889 | N = ntohl (plaintext_header.Ns); | ||
890 | while ( (NULL != key) && | ||
891 | (N != key->Kn) ) | ||
892 | key = key->next; | ||
893 | if ( (NULL == key) || | ||
894 | (0 != memcmp (&key->HK, | ||
895 | valid_HK, | ||
896 | sizeof (*valid_HK))) ) | ||
897 | return -1; | ||
898 | |||
899 | /* Decrypt payload */ | ||
900 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, | ||
901 | &key->MK, | ||
902 | NULL, | ||
903 | 0, | ||
904 | NULL); | ||
905 | res = GNUNET_CRYPTO_symmetric_decrypt (&src[1], | ||
906 | len, | ||
907 | &key->MK, | ||
908 | &iv, | ||
909 | dst); | ||
910 | delete_skipped_key (t, | ||
911 | key); | ||
912 | return res; | ||
913 | } | ||
914 | |||
915 | |||
916 | /** | ||
917 | * Delete a key from the list of skipped keys. | ||
918 | * | ||
919 | * @param t Tunnel to delete from. | ||
920 | * @param HKr Header Key to use. | ||
921 | */ | ||
922 | static void | ||
923 | store_skipped_key (struct CadetTunnel *t, | ||
924 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr) | ||
925 | { | ||
926 | struct CadetTunnelSkippedKey *key; | ||
927 | |||
928 | key = GNUNET_new (struct CadetTunnelSkippedKey); | ||
929 | key->timestamp = GNUNET_TIME_absolute_get (); | ||
930 | key->Kn = t->ax.Nr; | ||
931 | key->HK = t->ax.HKr; | ||
932 | t_hmac_derive_key (&t->ax.CKr, | ||
933 | &key->MK, | ||
934 | "0", | ||
935 | 1); | ||
936 | t_hmac_derive_key (&t->ax.CKr, | ||
937 | &t->ax.CKr, | ||
938 | "1", | ||
939 | 1); | ||
940 | GNUNET_CONTAINER_DLL_insert (t->ax.skipped_head, | ||
941 | t->ax.skipped_tail, | ||
942 | key); | ||
943 | t->ax.skipped++; | ||
944 | t->ax.Nr++; | ||
945 | } | ||
946 | |||
947 | |||
948 | /** | ||
949 | * Stage skipped AX keys and calculate the message key. | ||
950 | * Stores each HK and MK for skipped messages. | ||
951 | * | ||
952 | * @param t Tunnel where to stage the keys. | ||
953 | * @param HKr Header key. | ||
954 | * @param Np Received meesage number. | ||
955 | * @return #GNUNET_OK if keys were stored. | ||
956 | * #GNUNET_SYSERR if an error ocurred (Np not expected). | ||
957 | */ | ||
958 | static int | ||
959 | store_ax_keys (struct CadetTunnel *t, | ||
960 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr, | ||
961 | uint32_t Np) | ||
962 | { | ||
963 | int gap; | ||
964 | |||
965 | gap = Np - t->ax.Nr; | ||
966 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
967 | "Storing skipped keys [%u, %u)\n", | ||
968 | t->ax.Nr, | ||
969 | Np); | ||
970 | if (MAX_KEY_GAP < gap) | ||
971 | { | ||
972 | /* Avoid DoS (forcing peer to do 2^33 chain HMAC operations) */ | ||
973 | /* TODO: start new key exchange on return */ | ||
974 | GNUNET_break_op (0); | ||
975 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
976 | "Got message %u, expected %u+\n", | ||
977 | Np, | ||
978 | t->ax.Nr); | ||
979 | return GNUNET_SYSERR; | ||
980 | } | ||
981 | if (0 > gap) | ||
982 | { | ||
983 | /* Delayed message: don't store keys, flag to try old keys. */ | ||
984 | return GNUNET_SYSERR; | ||
985 | } | ||
986 | |||
987 | while (t->ax.Nr < Np) | ||
988 | store_skipped_key (t, | ||
989 | HKr); | ||
990 | |||
991 | while (t->ax.skipped > MAX_SKIPPED_KEYS) | ||
992 | delete_skipped_key (t, | ||
993 | t->ax.skipped_tail); | ||
994 | return GNUNET_OK; | ||
995 | } | ||
996 | |||
997 | |||
998 | /** | ||
999 | * Decrypt and verify data with the appropriate tunnel key and verify that the | ||
1000 | * data has not been altered since it was sent by the remote peer. | ||
1001 | * | ||
1002 | * @param t Tunnel whose key to use. | ||
1003 | * @param dst Destination for the plaintext. | ||
1004 | * @param src Source of the message. Can overlap with @c dst. | ||
1005 | * @param size Size of the message. | ||
1006 | * @return Size of the decrypted data, -1 if an error was encountered. | ||
1007 | */ | ||
1008 | static ssize_t | ||
1009 | t_ax_decrypt_and_validate (struct CadetTunnel *t, | ||
1010 | void *dst, | ||
1011 | const struct GNUNET_CADET_Encrypted *src, | ||
1012 | size_t size) | ||
1013 | { | ||
1014 | struct CadetTunnelAxolotl *ax; | ||
1015 | struct GNUNET_CADET_Hash msg_hmac; | ||
1016 | struct GNUNET_HashCode hmac; | ||
1017 | struct GNUNET_CADET_Encrypted plaintext_header; | ||
1018 | uint32_t Np; | ||
1019 | uint32_t PNp; | ||
1020 | size_t esize; /* Size of encryped payload */ | ||
1021 | |||
1022 | esize = size - sizeof (struct GNUNET_CADET_Encrypted); | ||
1023 | ax = &t->ax; | ||
1024 | |||
1025 | /* Try current HK */ | ||
1026 | t_hmac (&src->Ns, | ||
1027 | AX_HEADER_SIZE + esize, | ||
1028 | 0, &ax->HKr, | ||
1029 | &msg_hmac); | ||
1030 | if (0 != memcmp (&msg_hmac, | ||
1031 | &src->hmac, | ||
1032 | sizeof (msg_hmac))) | ||
1033 | { | ||
1034 | static const char ctx[] = "axolotl ratchet"; | ||
1035 | struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; /* RKp, NHKp, CKp */ | ||
1036 | struct GNUNET_CRYPTO_SymmetricSessionKey HK; | ||
1037 | struct GNUNET_HashCode dh; | ||
1038 | struct GNUNET_CRYPTO_EcdhePublicKey *DHRp; | ||
1039 | |||
1040 | /* Try Next HK */ | ||
1041 | t_hmac (&src->Ns, | ||
1042 | AX_HEADER_SIZE + esize, | ||
1043 | 0, | ||
1044 | &ax->NHKr, | ||
1045 | &msg_hmac); | ||
1046 | if (0 != memcmp (&msg_hmac, | ||
1047 | &src->hmac, | ||
1048 | sizeof (msg_hmac))) | ||
1049 | { | ||
1050 | /* Try the skipped keys, if that fails, we're out of luck. */ | ||
1051 | return try_old_ax_keys (t, | ||
1052 | dst, | ||
1053 | src, | ||
1054 | size); | ||
1055 | } | ||
1056 | HK = ax->HKr; | ||
1057 | ax->HKr = ax->NHKr; | ||
1058 | t_h_decrypt (t, | ||
1059 | src, | ||
1060 | &plaintext_header); | ||
1061 | Np = ntohl (plaintext_header.Ns); | ||
1062 | PNp = ntohl (plaintext_header.PNs); | ||
1063 | DHRp = &plaintext_header.DHRs; | ||
1064 | store_ax_keys (t, | ||
1065 | &HK, | ||
1066 | PNp); | ||
1067 | |||
1068 | /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */ | ||
1069 | GNUNET_CRYPTO_ecc_ecdh (ax->DHRs, | ||
1070 | DHRp, | ||
1071 | &dh); | ||
1072 | t_ax_hmac_hash (&ax->RK, | ||
1073 | &hmac, | ||
1074 | &dh, sizeof (dh)); | ||
1075 | GNUNET_CRYPTO_kdf (keys, sizeof (keys), | ||
1076 | ctx, sizeof (ctx), | ||
1077 | &hmac, sizeof (hmac), | ||
1078 | NULL); | ||
1079 | |||
1080 | /* Commit "purported" keys */ | ||
1081 | ax->RK = keys[0]; | ||
1082 | ax->NHKr = keys[1]; | ||
1083 | ax->CKr = keys[2]; | ||
1084 | ax->DHRr = *DHRp; | ||
1085 | ax->Nr = 0; | ||
1086 | ax->ratchet_allowed = GNUNET_YES; | ||
1087 | } | ||
1088 | else | ||
1089 | { | ||
1090 | t_h_decrypt (t, | ||
1091 | src, | ||
1092 | &plaintext_header); | ||
1093 | Np = ntohl (plaintext_header.Ns); | ||
1094 | PNp = ntohl (plaintext_header.PNs); | ||
1095 | } | ||
1096 | if ( (Np != ax->Nr) && | ||
1097 | (GNUNET_OK != store_ax_keys (t, | ||
1098 | &ax->HKr, | ||
1099 | Np)) ) | ||
1100 | { | ||
1101 | /* Try the skipped keys, if that fails, we're out of luck. */ | ||
1102 | return try_old_ax_keys (t, | ||
1103 | dst, | ||
1104 | src, | ||
1105 | size); | ||
1106 | } | ||
1107 | |||
1108 | t_ax_decrypt (t, | ||
1109 | dst, | ||
1110 | &src[1], | ||
1111 | esize); | ||
1112 | ax->Nr = Np + 1; | ||
1113 | return esize; | ||
1114 | } | ||
1115 | |||
1116 | |||
1117 | /* ************************************** end core crypto ***************************** */ | ||
1118 | |||
1119 | |||
1120 | /** | ||
479 | * Add a channel to a tunnel. | 1121 | * Add a channel to a tunnel. |
480 | * | 1122 | * |
481 | * @param t Tunnel. | 1123 | * @param t Tunnel. |
@@ -569,6 +1211,8 @@ connection_ready_cb (void *cls) | |||
569 | GNUNET_CONTAINER_DLL_remove (t->tq_head, | 1211 | GNUNET_CONTAINER_DLL_remove (t->tq_head, |
570 | t->tq_tail, | 1212 | t->tq_tail, |
571 | tq); | 1213 | tq); |
1214 | if (NULL != tq->cid) | ||
1215 | *tq->cid = *GCC_get_id (ct->cc); | ||
572 | GCC_transmit (ct->cc, | 1216 | GCC_transmit (ct->cc, |
573 | tq->env); | 1217 | tq->env); |
574 | tq->cont (tq->cont_cls); | 1218 | tq->cont (tq->cont_cls); |
@@ -694,6 +1338,7 @@ consider_path_cb (void *cls, | |||
694 | ct->t = t; | 1338 | ct->t = t; |
695 | ct->cc = GCC_create (t->destination, | 1339 | ct->cc = GCC_create (t->destination, |
696 | path, | 1340 | path, |
1341 | ct, | ||
697 | &connection_ready_cb, | 1342 | &connection_ready_cb, |
698 | t); | 1343 | t); |
699 | /* FIXME: schedule job to kill connection (and path?) if it takes | 1344 | /* FIXME: schedule job to kill connection (and path?) if it takes |
@@ -794,23 +1439,45 @@ GCT_send (struct CadetTunnel *t, | |||
794 | GNUNET_SCHEDULER_TaskCallback cont, | 1439 | GNUNET_SCHEDULER_TaskCallback cont, |
795 | void *cont_cls) | 1440 | void *cont_cls) |
796 | { | 1441 | { |
797 | struct CadetTunnelQueueEntry *q; | 1442 | struct CadetTunnelQueueEntry *tq; |
798 | uint16_t payload_size; | 1443 | uint16_t payload_size; |
1444 | struct GNUNET_MQ_Envelope *env; | ||
1445 | struct GNUNET_CADET_Encrypted *ax_msg; | ||
799 | 1446 | ||
800 | payload_size = ntohs (message->size); | 1447 | /* FIXME: what about KX not yet being ready? (see "is_ready()" check in old code!) */ |
801 | 1448 | ||
802 | q = GNUNET_malloc (sizeof (*q) + | 1449 | payload_size = ntohs (message->size); |
803 | payload_size); | 1450 | env = GNUNET_MQ_msg_extra (ax_msg, |
804 | /* FIXME: encrypt 'message' to end of 'q' */ | 1451 | payload_size, |
805 | q->t = t; | 1452 | GNUNET_MESSAGE_TYPE_CADET_ENCRYPTED); |
806 | q->cont = cont; | 1453 | t_ax_encrypt (t, |
807 | q->cont_cls = cont_cls; | 1454 | &ax_msg[1], |
1455 | message, | ||
1456 | payload_size); | ||
1457 | ax_msg->Ns = htonl (t->ax.Ns++); | ||
1458 | ax_msg->PNs = htonl (t->ax.PNs); | ||
1459 | GNUNET_CRYPTO_ecdhe_key_get_public (t->ax.DHRs, | ||
1460 | &ax_msg->DHRs); | ||
1461 | t_h_encrypt (t, | ||
1462 | ax_msg); | ||
1463 | t_hmac (&ax_msg->Ns, | ||
1464 | AX_HEADER_SIZE + payload_size, | ||
1465 | 0, | ||
1466 | &t->ax.HKs, | ||
1467 | &ax_msg->hmac); | ||
1468 | // ax_msg->pid = htonl (GCC_get_pid (c, fwd)); // FIXME: connection flow-control not (re)implemented yet! | ||
1469 | |||
1470 | tq = GNUNET_malloc (sizeof (*tq)); | ||
1471 | tq->t = t; | ||
1472 | tq->env = env; | ||
1473 | tq->cid = &ax_msg->cid; | ||
1474 | tq->cont = cont; | ||
1475 | tq->cont_cls = cont_cls; | ||
808 | GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, | 1476 | GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, |
809 | t->tq_tail, | 1477 | t->tq_tail, |
810 | q); | 1478 | tq); |
811 | /* FIXME: what about KX being ready? */ | ||
812 | trigger_transmissions (t); | 1479 | trigger_transmissions (t); |
813 | return q; | 1480 | return tq; |
814 | } | 1481 | } |
815 | 1482 | ||
816 | 1483 | ||