gnunet-service-core_kx.c (96708B)
1 /* 2 This file is part of GNUnet. 3 Copyright (C) 2009-2013, 2016, 2024-2026 GNUnet e.V. 4 5 GNUnet is free software: you can redistribute it and/or modify it 6 under the terms of the GNU Affero General Public License as published 7 by the Free Software Foundation, either version 3 of the License, 8 or (at your option) any later version. 9 10 GNUnet is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Affero General Public License for more details. 14 15 You should have received a copy of the GNU Affero General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 SPDX-License-Identifier: AGPL3.0-or-later 19 */ 20 21 /** 22 * TODO: 23 * - We need to implement a rekey (+ACK) that periodically rekeys. 24 * - We may want to reintroduce a heartbeat that needs to be ACKed. Maybe use / merge 25 * with KeyUpdate message. It already contains an update_requested field. 26 * Maybe rename to Heartbeat and add key_updated field to indicate a field update. 27 * That message then always MUST be Acked, if update_requested, then a Heartbeat is 28 * expected in response (w/o update_requested of course). 29 */ 30 31 /** 32 * @file core/gnunet-service-core_kx.c 33 * @brief code for managing the key exchange (SET_KEY, PING, PONG) with other 34 * peers 35 * @author Christian Grothoff, ch3 36 */ 37 #include "gnunet_common.h" 38 #include "gnunet_util_lib.h" 39 #include "platform.h" 40 #include "gnunet-service-core_kx.h" 41 #include "gnunet_transport_core_service.h" 42 #include "gnunet-service-core_sessions.h" 43 #include "gnunet-service-core.h" 44 #include "gnunet_constants.h" 45 #include "gnunet_protocols.h" 46 #include "gnunet_pils_service.h" 47 48 /** 49 * Enable expensive (and possibly problematic for privacy!) logging of KX. 50 */ 51 #define DEBUG_KX 0 52 53 /** 54 * Number of times we try to resend a handshake flight. 55 */ 56 #define RESEND_MAX_TRIES 4 57 58 /** 59 * libsodium has very long symbol names 60 */ 61 #define AEAD_KEY_BYTES crypto_aead_xchacha20poly1305_ietf_KEYBYTES 62 63 /** 64 * libsodium has very long symbol names 65 */ 66 #define AEAD_NONCE_BYTES crypto_aead_xchacha20poly1305_ietf_NPUBBYTES 67 68 /** 69 * libsodium has very long symbol names 70 */ 71 #define AEAD_TAG_BYTES crypto_aead_xchacha20poly1305_ietf_ABYTES 72 73 #define RESEND_TIMEOUT \ 74 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) 75 76 /** 77 * What is the minimum frequency for a heartbeat message? 78 */ 79 #define MIN_HEARTBEAT_FREQUENCY \ 80 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) 81 82 /** 83 * What is the minimum frequency for a HEARTBEAT message? 84 */ 85 #define MIN_HEARTBEAT_FREQUENCY \ 86 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) 87 88 /** 89 * How often do we send a heartbeat? 90 */ 91 #define HEARTBEAT_FREQUENCY \ 92 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12) 93 94 /** 95 * Maximum number of epochs we keep on hand. 96 * This implicitly defines the maximum age of 97 * messages we accept from other peers, depending 98 * on their rekey interval. 99 */ 100 #define MAX_EPOCHS 10 101 102 /** 103 * How often do we rekey/switch to a new epoch? 104 */ 105 #define EPOCH_EXPIRATION \ 106 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12) 107 108 /** 109 * What time difference do we tolerate? 110 */ 111 #define REKEY_TOLERANCE \ 112 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) 113 114 /** 115 * String for expanding early transport secret 116 * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html) 117 */ 118 #define EARLY_DATA_STR "early data" 119 120 /** 121 * String for expanding RHTS 122 * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html) 123 */ 124 #define R_HS_TRAFFIC_STR "r hs traffic" 125 126 /** 127 * String for expanding IHTS 128 * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html) 129 */ 130 #define I_HS_TRAFFIC_STR "i hs traffic" 131 132 /** 133 * String for expanding RATS 134 * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html) 135 */ 136 #define R_AP_TRAFFIC_STR "r ap traffic" 137 138 /** 139 * String for expanding IATS 140 * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html) 141 */ 142 #define I_AP_TRAFFIC_STR "i ap traffic" 143 144 /** 145 * String for expanding derived keys (Handshake and Early) 146 * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html) 147 */ 148 #define DERIVED_STR "derived" 149 150 /** 151 * String for expanding fk_R used for ResponderFinished field 152 * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html) 153 */ 154 #define R_FINISHED_STR "r finished" 155 156 /** 157 * String for expanding fk_I used for InitiatorFinished field 158 * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html) 159 */ 160 #define I_FINISHED_STR "i finished" 161 162 /** 163 * Labeled expand label for CAKE 164 */ 165 #define CAKE_LABEL "cake10" 166 167 /** 168 * String for expanding derived keys (Handshake and Early) 169 * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html) 170 */ 171 #define KEY_STR "key" 172 173 /** 174 * String for expanding derived keys (Handshake and Early) 175 * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html) 176 */ 177 #define TRAFFIC_UPD_STR "traffic upd" 178 179 /** 180 * String for expanding derived keys (Handshake and Early) 181 * (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake.html) 182 */ 183 #define IV_STR "iv" 184 185 186 /** 187 * Indicates whether a peer is in the initiating or receiving role. 188 */ 189 enum GSC_KX_Role 190 { 191 /* Peer is supposed to initiate the key exchange */ 192 ROLE_INITIATOR = 0, 193 194 /* Peer is supposed to wait for the key exchange */ 195 ROLE_RESPONDER = 1, 196 }; 197 198 199 /** 200 * Information about the status of a key exchange with another peer. 201 */ 202 struct GSC_KeyExchangeInfo 203 { 204 /** 205 * DLL. 206 */ 207 struct GSC_KeyExchangeInfo *next; 208 209 /** 210 * DLL. 211 */ 212 struct GSC_KeyExchangeInfo *prev; 213 214 /** 215 * Identity of the peer. 216 */ 217 struct GNUNET_PeerIdentity peer; 218 219 /** 220 * Message queue for sending messages to @a peer. 221 */ 222 struct GNUNET_MQ_Handle *mq; 223 224 /** 225 * Env for resending messages 226 */ 227 struct GNUNET_MQ_Envelope *resend_env; 228 229 /** 230 * Our message stream tokenizer (for encrypted payload). 231 */ 232 struct GNUNET_MessageStreamTokenizer *mst; 233 234 // TODO check ordering - might make it less confusing 235 // TODO consistent naming: ss_e, shared_secret_e or ephemeral_shared_secret? 236 // TODO consider making all the structs here pointers 237 // - they can be checked to be NULL 238 // - valgrind can detect memory issues better (I guess?) 239 240 /** 241 * Own role in the key exchange. Are we supposed to initiate or receive the 242 * handshake? 243 */ 244 enum GSC_KX_Role role; 245 246 // TODO 247 struct GNUNET_ShortHashCode ss_R; 248 struct GNUNET_ShortHashCode ss_e; 249 struct GNUNET_ShortHashCode ss_I; 250 251 /** 252 * Initiator secret key 253 */ 254 struct GNUNET_CRYPTO_HpkePrivateKey sk_e; 255 256 /** 257 * Initiator ephemeral key 258 */ 259 struct GNUNET_CRYPTO_HpkePublicKey pk_e; 260 261 /** 262 * The transcript hash context. 263 * It is fed data from the handshake to be implicitly validated and used to 264 * derive key material. 265 */ 266 struct GNUNET_HashContext *transcript_hash_ctx; 267 268 /** 269 * ES - Early Secret Key 270 * TODO uniform naming: _key? 271 */ 272 struct GNUNET_ShortHashCode early_secret_key; 273 274 /** 275 * ETS - Early traffic secret 276 * TODO 277 */ 278 struct GNUNET_ShortHashCode early_traffic_secret; /* Decrypts InitiatorHello */ 279 280 /** 281 * HS - Handshake secret 282 * TODO 283 */ 284 struct GNUNET_ShortHashCode handshake_secret; 285 286 /** 287 * RHTS - Responder handshake secret 288 * TODO 289 */ 290 struct GNUNET_ShortHashCode rhts; 291 292 /** 293 * IHTS - Initiator handshake secret 294 * TODO 295 */ 296 struct GNUNET_ShortHashCode ihts; 297 298 /** 299 * Master secret key 300 * TODO 301 */ 302 struct GNUNET_ShortHashCode master_secret; 303 304 /** 305 * *ATS - our current application traffic secret by epoch 306 */ 307 struct GNUNET_ShortHashCode current_ats; 308 309 /** 310 * *ATS - other peers application traffic secret by epoch 311 */ 312 struct GNUNET_ShortHashCode their_ats[MAX_EPOCHS]; 313 314 /** 315 * Our currently used epoch for sending. 316 */ 317 uint64_t current_epoch; 318 319 /** 320 * Expiration time of our current epoch 321 */ 322 struct GNUNET_TIME_Absolute current_epoch_expiration; 323 324 /** 325 * Highest seen (or used) epoch of 326 * responder resp initiator.. 327 */ 328 uint64_t their_max_epoch; 329 330 /** 331 * Our current sequence number 332 */ 333 uint64_t current_sqn; 334 335 /** 336 * When should the session time out (if there are no Acks to HEARTBEATs)? 337 */ 338 struct GNUNET_TIME_Absolute timeout; 339 340 /** 341 * Last time we notified monitors 342 */ 343 struct GNUNET_TIME_Absolute last_notify_timeout; 344 345 /** 346 * Task for resending messages during handshake. 347 */ 348 struct GNUNET_SCHEDULER_Task *resend_task; 349 350 /** 351 * Resend tries left 352 */ 353 unsigned int resend_tries_left; 354 355 /** 356 * ID of task used for sending keep-alive pings. 357 * TODO still needed? 358 */ 359 struct GNUNET_SCHEDULER_Task *heartbeat_task; 360 361 /** 362 * #GNUNET_YES if this peer currently has excess bandwidth. 363 * TODO still needed? 364 */ 365 int has_excess_bandwidth; 366 367 /** 368 * What is our connection state? 369 */ 370 enum GNUNET_CORE_KxState status; 371 372 /** 373 * Peer class of the other peer 374 * TODO still needed? 375 */ 376 enum GNUNET_CORE_PeerClass class; 377 378 }; 379 380 /** 381 * DLL 382 */ 383 struct PilsRequest 384 { 385 /** 386 * DLL 387 */ 388 struct PilsRequest *prev; 389 390 /** 391 * DLL 392 */ 393 struct PilsRequest *next; 394 395 /** 396 * The pils operation 397 */ 398 struct GNUNET_PILS_Operation *op; 399 }; 400 401 /** 402 * PILS Operation DLL 403 */ 404 static struct PilsRequest *pils_requests_head; 405 406 /** 407 * PILS Operation DLL 408 */ 409 static struct PilsRequest *pils_requests_tail; 410 411 412 /** 413 * Transport service. 414 */ 415 static struct GNUNET_TRANSPORT_CoreHandle *transport; 416 417 /** 418 * DLL head. 419 */ 420 static struct GSC_KeyExchangeInfo *kx_head; 421 422 /** 423 * DLL tail. 424 */ 425 static struct GSC_KeyExchangeInfo *kx_tail; 426 427 /** 428 * Task scheduled for periodic re-generation (and thus rekeying) of our 429 * ephemeral key. 430 */ 431 static struct GNUNET_SCHEDULER_Task *rekey_task; 432 433 /** 434 * Notification context for broadcasting to monitors. 435 */ 436 static struct GNUNET_NotificationContext *nc; 437 438 /** 439 * Our services info string TODO 440 */ 441 static char *my_services_info = ""; 442 443 static void 444 buffer_clear (void *buf, size_t len) 445 { 446 #if HAVE_MEMSET_S 447 memset_s (buf, len, 0, len); 448 #elif HAVE_EXPLICIT_BZERO 449 explicit_bzero (buf, len); 450 #else 451 volatile unsigned char *p = buf; 452 while (len--) 453 *p++ = 0; 454 #endif 455 } 456 457 458 static void 459 cleanup_handshake_secrets (struct GSC_KeyExchangeInfo *kx) 460 { 461 buffer_clear (&kx->ihts, 462 sizeof kx->ihts); 463 buffer_clear (&kx->rhts, 464 sizeof kx->rhts); 465 buffer_clear (&kx->sk_e, 466 sizeof kx->sk_e); 467 buffer_clear (&kx->ss_I, 468 sizeof kx->ss_I); 469 buffer_clear (&kx->ss_R, 470 sizeof kx->ss_R); 471 buffer_clear (&kx->ss_e, 472 sizeof kx->ss_e); 473 buffer_clear (&kx->master_secret, 474 sizeof kx->master_secret); 475 buffer_clear (&kx->early_secret_key, 476 sizeof kx->early_secret_key); 477 buffer_clear (&kx->early_traffic_secret, 478 sizeof kx->early_traffic_secret); 479 buffer_clear (&kx->handshake_secret, 480 sizeof kx->handshake_secret); 481 } 482 483 484 static void 485 snapshot_transcript (const struct GNUNET_HashContext *ts_hash, 486 struct GNUNET_HashCode *snapshot) 487 { 488 struct GNUNET_HashContext *tmp; 489 490 tmp = GNUNET_CRYPTO_hash_context_copy (ts_hash); 491 GNUNET_CRYPTO_hash_context_finish (tmp, snapshot); 492 } 493 494 495 /** 496 * Inform all monitors about the KX state of the given peer. 497 * 498 * @param kx key exchange state to inform about 499 */ 500 static void 501 monitor_notify_all (struct GSC_KeyExchangeInfo *kx) 502 { 503 struct MonitorNotifyMessage msg; 504 505 msg.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY); 506 msg.header.size = htons (sizeof(msg)); 507 msg.state = htonl ((uint32_t) kx->status); 508 msg.peer = kx->peer; 509 msg.timeout = GNUNET_TIME_absolute_hton (kx->timeout); 510 GNUNET_notification_context_broadcast (nc, &msg.header, GNUNET_NO); 511 kx->last_notify_timeout = kx->timeout; 512 } 513 514 515 static void 516 restart_kx (struct GSC_KeyExchangeInfo *kx); 517 518 /** 519 * Task triggered when a neighbour entry is about to time out 520 * (and we should prevent this by sending an Ack in response 521 * to a heartbeat). 522 * 523 * @param cls the `struct GSC_KeyExchangeInfo` 524 */ 525 static void 526 send_heartbeat (void *cls) 527 { 528 struct GSC_KeyExchangeInfo *kx = cls; 529 struct GNUNET_TIME_Relative retry; 530 struct GNUNET_TIME_Relative left; 531 struct Heartbeat hb; 532 533 kx->heartbeat_task = NULL; 534 left = GNUNET_TIME_absolute_get_remaining (kx->timeout); 535 if (0 == left.rel_value_us) 536 { 537 GNUNET_STATISTICS_update (GSC_stats, 538 gettext_noop ("# sessions terminated by timeout"), 539 1, 540 GNUNET_NO); 541 GSC_SESSIONS_end (&kx->peer); 542 kx->status = GNUNET_CORE_KX_STATE_DOWN; 543 monitor_notify_all (kx); 544 restart_kx (kx); 545 return; 546 } 547 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 548 "Sending HEARTBEAT to `%s'\n", 549 GNUNET_i2s (&kx->peer)); 550 GNUNET_STATISTICS_update (GSC_stats, 551 gettext_noop ("# heartbeat messages sent"), 552 1, 553 GNUNET_NO); 554 hb.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_HEARTBEAT); 555 hb.header.size = htons (sizeof hb); 556 // FIXME when do we request update? 557 hb.flags = 0; 558 GSC_KX_encrypt_and_transmit (kx, &hb, sizeof hb); 559 retry = GNUNET_TIME_relative_max (GNUNET_TIME_relative_divide (left, 2), 560 MIN_HEARTBEAT_FREQUENCY); 561 kx->heartbeat_task = 562 GNUNET_SCHEDULER_add_delayed (retry, &send_heartbeat, kx); 563 } 564 565 566 /** 567 * We've seen a valid message from the other peer. 568 * Update the time when the session would time out 569 * and delay sending our keep alive message further. 570 * 571 * @param kx key exchange where we saw activity 572 */ 573 static void 574 update_timeout (struct GSC_KeyExchangeInfo *kx) 575 { 576 struct GNUNET_TIME_Relative delta; 577 578 kx->timeout = 579 GNUNET_TIME_relative_to_absolute (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT); 580 delta = 581 GNUNET_TIME_absolute_get_difference (kx->last_notify_timeout, kx->timeout); 582 if (delta.rel_value_us > 5LL * 1000LL * 1000LL) 583 { 584 /* we only notify monitors about timeout changes if those 585 are bigger than the threshold (5s) */ 586 monitor_notify_all (kx); 587 } 588 if (NULL != kx->heartbeat_task) 589 GNUNET_SCHEDULER_cancel (kx->heartbeat_task); 590 kx->heartbeat_task = GNUNET_SCHEDULER_add_delayed ( 591 GNUNET_TIME_relative_divide (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT, 2), 592 &send_heartbeat, 593 kx); 594 } 595 596 597 /** 598 * Send initiator hello 599 * 600 * @param kx key exchange context 601 */ 602 static void 603 send_initiator_hello (struct GSC_KeyExchangeInfo *kx); 604 605 606 /** 607 * Deliver P2P message to interested clients. Invokes send twice, 608 * once for clients that want the full message, and once for clients 609 * that only want the header 610 * 611 * @param cls the `struct GSC_KeyExchangeInfo` 612 * @param m the message 613 * @return #GNUNET_OK on success, 614 * #GNUNET_NO to stop further processing (no error) 615 * #GNUNET_SYSERR to stop further processing with error 616 */ 617 static int 618 deliver_message (void *cls, const struct GNUNET_MessageHeader *m) 619 { 620 struct GSC_KeyExchangeInfo *kx = cls; 621 622 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 623 "Decrypted message of type %d from %s\n", 624 ntohs (m->type), 625 GNUNET_i2s (&kx->peer)); 626 GSC_CLIENTS_deliver_message (&kx->peer, 627 m, 628 ntohs (m->size), 629 GNUNET_CORE_OPTION_SEND_FULL_INBOUND); 630 GSC_CLIENTS_deliver_message (&kx->peer, 631 m, 632 sizeof(struct GNUNET_MessageHeader), 633 GNUNET_CORE_OPTION_SEND_HDR_INBOUND); 634 return GNUNET_OK; 635 } 636 637 638 static void 639 restart_kx (struct GSC_KeyExchangeInfo *kx) 640 { 641 const struct GNUNET_HashCode *my_identity_hash; 642 struct GNUNET_HashCode h1; 643 644 // TODO what happens if we're in the middle of a peer id change? 645 // TODO there's a small chance this gets already called when we don't have a 646 // peer id yet. Add a kx, insert into the list, mark it as to be completed 647 // and let the callback to pils finish the rest once we got the peer id 648 649 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 650 "Initiating key exchange with peer %s\n", 651 GNUNET_i2s (&kx->peer)); 652 GNUNET_STATISTICS_update (GSC_stats, 653 gettext_noop ("# key exchanges initiated"), 654 1, 655 GNUNET_NO); 656 657 monitor_notify_all (kx); 658 my_identity_hash = GNUNET_PILS_get_identity_hash (GSC_pils); 659 GNUNET_assert (NULL != my_identity_hash); 660 GNUNET_CRYPTO_hash (&kx->peer, sizeof(struct GNUNET_PeerIdentity), &h1); 661 if (NULL != kx->transcript_hash_ctx) 662 GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx); 663 kx->transcript_hash_ctx = NULL; 664 if (0 < GNUNET_CRYPTO_hash_cmp (&h1, my_identity_hash)) 665 { 666 /* peer with "lower" identity starts KX, otherwise we typically end up 667 with both peers starting the exchange and transmit the 'set key' 668 message twice */ 669 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 670 "I am the initiator, sending hello\n"); 671 kx->role = ROLE_INITIATOR; 672 send_initiator_hello (kx); 673 } 674 else 675 { 676 /* peer with "higher" identity starts a delayed KX, if the "lower" peer 677 * does not start a KX since it sees no reasons to do so */ 678 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 679 "I am the responder, yielding and await initiator hello\n"); 680 kx->status = GNUNET_CORE_KX_STATE_AWAIT_INITIATION; 681 kx->role = ROLE_RESPONDER; 682 monitor_notify_all (kx); 683 } 684 } 685 686 687 /** 688 * Function called by transport to notify us that 689 * a peer connected to us (on the network level). 690 * Starts the key exchange with the given peer. 691 * 692 * @param cls closure (NULL) 693 * @param mq message queue towards peer 694 * @param peer_id (optional, may be NULL) the peer id of the connecting peer 695 * @return key exchange information context 696 */ 697 static void * 698 handle_transport_notify_connect (void *cls, 699 const struct GNUNET_PeerIdentity *peer_id, 700 struct GNUNET_MQ_Handle *mq) 701 { 702 const struct GNUNET_PeerIdentity *my_identity; 703 struct GSC_KeyExchangeInfo *kx; 704 (void) cls; 705 my_identity = GNUNET_PILS_get_identity (GSC_pils); 706 GNUNET_assert (NULL != my_identity); 707 if (0 == memcmp (peer_id, my_identity, sizeof *peer_id)) 708 { 709 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 710 "Ignoring connection to self\n"); 711 return NULL; 712 } 713 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 714 "Incoming connection of peer with %s\n", 715 GNUNET_i2s (peer_id)); 716 717 /* Set up kx struct */ 718 kx = GNUNET_new (struct GSC_KeyExchangeInfo); 719 kx->mst = GNUNET_MST_create (&deliver_message, kx); 720 kx->mq = mq; 721 GNUNET_memcpy (&kx->peer, peer_id, sizeof (struct GNUNET_PeerIdentity)); 722 GNUNET_CONTAINER_DLL_insert (kx_head, kx_tail, kx); 723 724 restart_kx (kx); 725 return kx; 726 } 727 728 729 /** 730 * TODO 731 * propose a new scheme: don't choose an initiator and responder based on 732 * hashing the peer ids, but: 733 * let each peer be their own initiator (and responder) when opening a channel 734 * towards another peer. It should be fine to have two channels in 'both 735 * directions' (one as responder, one as initiator) under the hood. This can be 736 * opaque to the upper layers. 737 * FIXME: (MSC) This is probably a bad idea in terms of security of the AKE! 738 */ 739 740 /** 741 * Schedule for 742 * - forwarding the transcript hash context and 743 * - deriving/generating keys/finished fields 744 * 745 * Forwarding: Deriving Messages 746 * -> pk_e 747 * -> c_R 748 * -> r_I 749 * -> H(pk_R) 750 * -> ETS 751 * -> {pk_I, svcinfo_I}ETS 752 * ---------------------------------------------------- send InitiatorHello 753 * -> c_e 754 * -> r_R 755 * -> *HTS 756 * -> {svcinfo_R, c_I}RHTS 757 * -> finished_R 758 * -> {finished_R}RHTS 759 * -> finished_I 760 * -> RATS_0 761 * -> [{payload}RATS] 762 * ---------------------------------------------------- send ResponderHello 763 * -> {finished_I}IHTS 764 * -> IATS_0 765 * ---------------------------------------------------- send InitiatorDone 766 */ 767 768 // TODO find a way to assert that a key is not yet existing before generating 769 // TODO find a way to assert that a key is not already existing before using 770 /* 771 * Derive early secret and transport secret. 772 * @param kx the key exchange info 773 */ 774 static void 775 derive_es_ets (const struct GNUNET_HashCode *transcript, 776 const struct GNUNET_ShortHashCode *ss_R, 777 struct GNUNET_ShortHashCode *es, 778 struct GNUNET_ShortHashCode *ets) 779 { 780 uint64_t ret; 781 782 ret = GNUNET_CRYPTO_hkdf_extract (es, // prk 783 0, // salt 784 0, // salt_len 785 ss_R, // ikm - initial key material 786 sizeof (*ss_R)); 787 if (GNUNET_OK != ret) 788 { 789 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong extracting ES\n") 790 ; 791 GNUNET_assert (0); 792 } 793 ret = GNUNET_CRYPTO_hkdf_expand ( 794 ets, 795 sizeof (*ets), 796 es, 797 GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL), 798 GNUNET_CRYPTO_kdf_arg_string (EARLY_DATA_STR), 799 GNUNET_CRYPTO_kdf_arg_auto (transcript)); 800 if (GNUNET_OK != ret) 801 { 802 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong expanding ETS\n") 803 ; 804 GNUNET_assert (0); 805 } 806 } 807 808 809 /* 810 * Derive early secret and transport secret. 811 * @param kx the key exchange info 812 */ 813 static void 814 derive_sn (const struct GNUNET_ShortHashCode *secret, 815 unsigned char*sn, 816 size_t sn_len) 817 { 818 GNUNET_assert (GNUNET_OK == 819 GNUNET_CRYPTO_hkdf_expand ( 820 sn, 821 sn_len, 822 secret, 823 GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL), 824 GNUNET_CRYPTO_kdf_arg_string ("sn"))); 825 } 826 827 828 /** 829 * Derive the handshake secret 830 * @param kx key exchange info 831 */ 832 static void 833 derive_hs (const struct GNUNET_ShortHashCode *es, 834 const struct GNUNET_ShortHashCode *ss_e, 835 struct GNUNET_ShortHashCode *handshake_secret) 836 { 837 uint64_t ret; 838 struct GNUNET_ShortHashCode derived_early_secret; 839 840 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deriving HS\n"); 841 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ES: %s\n", GNUNET_B2S (es) 842 ); 843 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ss_e: %s\n", GNUNET_B2S (ss_e)); 844 ret = GNUNET_CRYPTO_hkdf_expand ( 845 &derived_early_secret, 846 sizeof (derived_early_secret), 847 es, 848 GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL), 849 GNUNET_CRYPTO_kdf_arg_string (DERIVED_STR)); 850 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "dES: %s\n", GNUNET_B2S (& 851 derived_early_secret)); 852 if (GNUNET_OK != ret) 853 { 854 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong expanding dES\n") 855 ; 856 GNUNET_assert (0); 857 } 858 // Handshake secret 859 // TODO check: are dES the salt and ss_e the ikm or other way round? 860 ret = GNUNET_CRYPTO_hkdf_extract (handshake_secret, // prk 861 &derived_early_secret, // salt - dES 862 sizeof (derived_early_secret), // salt_len 863 ss_e, // ikm - initial key material 864 sizeof (*ss_e)); 865 if (GNUNET_OK != ret) 866 { 867 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong extracting HS\n") 868 ; 869 GNUNET_assert (0); 870 } 871 } 872 873 874 /** 875 * Derive the initiator handshake secret 876 * @param kx key exchange info 877 */ 878 static void 879 derive_ihts (const struct GNUNET_HashCode *transcript, 880 const struct GNUNET_ShortHashCode *hs, 881 struct GNUNET_ShortHashCode *ihts) 882 { 883 GNUNET_assert (GNUNET_OK == 884 GNUNET_CRYPTO_hkdf_expand ( 885 ihts, // result 886 sizeof (*ihts), // result len 887 hs, // prk? 888 GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL), 889 GNUNET_CRYPTO_kdf_arg_string (I_HS_TRAFFIC_STR), 890 GNUNET_CRYPTO_kdf_arg_auto (transcript))); 891 } 892 893 894 /** 895 * Derive the responder handshake secret 896 * @param kx key exchange info 897 */ 898 static void 899 derive_rhts (const struct GNUNET_HashCode *transcript, 900 const struct GNUNET_ShortHashCode *hs, 901 struct GNUNET_ShortHashCode *rhts) 902 { 903 GNUNET_assert (GNUNET_OK == 904 GNUNET_CRYPTO_hkdf_expand ( 905 rhts, 906 sizeof (*rhts), 907 hs, // prk? TODO 908 GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL), 909 GNUNET_CRYPTO_kdf_arg_string (R_HS_TRAFFIC_STR), 910 GNUNET_CRYPTO_kdf_arg_auto (transcript))); 911 } 912 913 914 /** 915 * Derive the master secret 916 * @param kx key exchange info 917 */ 918 static void 919 derive_ms (const struct GNUNET_ShortHashCode *hs, 920 const struct GNUNET_ShortHashCode *ss_I, 921 struct GNUNET_ShortHashCode *ms) 922 { 923 uint64_t ret; 924 struct GNUNET_ShortHashCode derived_handshake_secret; 925 926 ret = GNUNET_CRYPTO_hkdf_expand ( 927 &derived_handshake_secret, 928 sizeof (derived_handshake_secret), 929 hs, 930 GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL), 931 GNUNET_CRYPTO_kdf_arg_string (DERIVED_STR)); 932 if (GNUNET_OK != ret) 933 { 934 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong expanding dHS\n") 935 ; 936 GNUNET_assert (0); 937 } 938 // TODO check: are dHS the salt and ss_I the ikm or other way round? 939 ret = GNUNET_CRYPTO_hkdf_extract (ms, // prk 940 &derived_handshake_secret, // salt - dHS 941 sizeof (derived_handshake_secret), // salt_len 942 ss_I, // ikm - initial key material 943 sizeof (*ss_I)); 944 if (GNUNET_OK != ret) 945 { 946 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong extracting MS\n") 947 ; 948 GNUNET_assert (0); 949 } 950 } 951 952 953 /** 954 * Generate per record nonce as per 955 * https://www.rfc-editor.org/rfc/rfc8446#section-5.3 956 * using per key nonce and sequence number 957 */ 958 static void 959 generate_per_record_nonce ( 960 uint64_t seq, 961 const uint8_t write_iv[AEAD_NONCE_BYTES], 962 uint8_t per_record_write_iv[AEAD_NONCE_BYTES]) 963 { 964 uint64_t seq_nbo; 965 uint64_t *write_iv_ptr; 966 unsigned int byte_offset; 967 968 seq_nbo = GNUNET_htonll (seq); 969 memcpy (per_record_write_iv, 970 write_iv, 971 AEAD_NONCE_BYTES); 972 byte_offset = 973 AEAD_NONCE_BYTES - sizeof (uint64_t); 974 write_iv_ptr = (uint64_t*) (write_iv + byte_offset); 975 *write_iv_ptr ^= seq_nbo; 976 } 977 978 979 /** 980 * key = HKDF-Expand [I,R][A,H]TS, "key", 32) 981 * nonce = HKDF-Expand ([I,R][A,H]TS, "iv", 24) 982 */ 983 static void 984 derive_per_message_secrets ( 985 const struct GNUNET_ShortHashCode *ts, 986 uint64_t seq, 987 unsigned char key[AEAD_KEY_BYTES], 988 unsigned char nonce[AEAD_NONCE_BYTES]) 989 { 990 unsigned char nonce_tmp[AEAD_NONCE_BYTES]; 991 /* derive actual key */ 992 GNUNET_assert (GNUNET_OK == 993 GNUNET_CRYPTO_hkdf_expand ( 994 key, 995 AEAD_KEY_BYTES, 996 ts, 997 GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL), 998 GNUNET_CRYPTO_kdf_arg_string (KEY_STR))); 999 1000 /* derive nonce */ 1001 GNUNET_assert (GNUNET_OK == 1002 GNUNET_CRYPTO_hkdf_expand ( 1003 nonce_tmp, 1004 AEAD_NONCE_BYTES, 1005 ts, 1006 GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL), 1007 GNUNET_CRYPTO_kdf_arg_string (IV_STR))); 1008 generate_per_record_nonce (seq, 1009 nonce_tmp, 1010 nonce); 1011 } 1012 1013 1014 /** 1015 * Derive the next application secret 1016 * @param kx key exchange info 1017 */ 1018 static void 1019 derive_next_ats (const struct GNUNET_ShortHashCode *old_ats, 1020 struct GNUNET_ShortHashCode *new_ats) 1021 { 1022 int8_t ret; 1023 1024 // FIXME: Not sure of PRK and output may overlap here! 1025 ret = GNUNET_CRYPTO_hkdf_expand ( 1026 new_ats, 1027 sizeof (*new_ats), 1028 old_ats, 1029 GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL), 1030 GNUNET_CRYPTO_kdf_arg_string (TRAFFIC_UPD_STR)); 1031 if (GNUNET_OK != ret) 1032 { 1033 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1034 "Something went wrong deriving next *ATS key\n"); 1035 GNUNET_assert (0); 1036 } 1037 } 1038 1039 1040 /** 1041 * Derive the initiator application secret 1042 * @param kx key exchange info 1043 */ 1044 static void 1045 derive_initial_ats (const struct GNUNET_HashCode *transcript, 1046 const struct GNUNET_ShortHashCode *ms, 1047 enum GSC_KX_Role role, 1048 struct GNUNET_ShortHashCode *initial_ats) 1049 { 1050 const char *traffic_str; 1051 1052 if (ROLE_INITIATOR == role) 1053 traffic_str = I_AP_TRAFFIC_STR; 1054 else 1055 traffic_str = R_AP_TRAFFIC_STR; 1056 GNUNET_assert (GNUNET_OK == 1057 GNUNET_CRYPTO_hkdf_expand ( 1058 initial_ats, // result 1059 sizeof (*initial_ats), // result len 1060 ms, 1061 GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL), 1062 GNUNET_CRYPTO_kdf_arg_string (traffic_str), 1063 GNUNET_CRYPTO_kdf_arg_auto (transcript))); 1064 } 1065 1066 1067 /** 1068 * Generate the responder finished field 1069 * @param kx key exchange info 1070 * @param result location to which the responder finished field will be written 1071 * to 1072 */ 1073 static void 1074 generate_responder_finished (const struct GNUNET_HashCode *transcript, 1075 const struct GNUNET_ShortHashCode *ms, 1076 struct GNUNET_HashCode *result) 1077 { 1078 enum GNUNET_GenericReturnValue ret; 1079 struct GNUNET_CRYPTO_AuthKey fk_R; // We might want to save this in kx? 1080 1081 ret = GNUNET_CRYPTO_hkdf_expand ( 1082 &fk_R, // result 1083 sizeof (fk_R), 1084 ms, 1085 GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL), 1086 GNUNET_CRYPTO_kdf_arg_string (R_FINISHED_STR)); 1087 if (GNUNET_OK != ret) 1088 { 1089 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1090 "Something went wrong expanding fk_R\n"); 1091 GNUNET_assert (0); 1092 } 1093 1094 GNUNET_CRYPTO_hmac (&fk_R, 1095 transcript, 1096 sizeof (*transcript), 1097 result); 1098 } 1099 1100 1101 /** 1102 * Generate the initiator finished field 1103 * @param kx key exchange info 1104 * @param result location to which the initiator finished field will be written 1105 * to 1106 */ 1107 static void 1108 generate_initiator_finished (const struct GNUNET_HashCode *transcript, 1109 const struct GNUNET_ShortHashCode *ms, 1110 struct GNUNET_HashCode *result) 1111 { 1112 enum GNUNET_GenericReturnValue ret; 1113 struct GNUNET_CRYPTO_AuthKey fk_I; // We might want to save this in kx? 1114 1115 ret = GNUNET_CRYPTO_hkdf_expand ( 1116 &fk_I, // result 1117 sizeof (fk_I), 1118 ms, 1119 GNUNET_CRYPTO_kdf_arg_string (CAKE_LABEL), 1120 GNUNET_CRYPTO_kdf_arg_string (I_FINISHED_STR)); 1121 if (GNUNET_OK != ret) 1122 { 1123 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1124 "Something went wrong expanding fk_I\n"); 1125 GNUNET_assert (0); 1126 } 1127 GNUNET_CRYPTO_hmac (&fk_I, 1128 transcript, 1129 sizeof (*transcript), 1130 result); 1131 } 1132 1133 1134 struct InitiatorHelloCtx 1135 { 1136 struct GSC_KeyExchangeInfo *kx; 1137 struct InitiatorHello *ihm_e; 1138 struct PilsRequest *req; 1139 }; 1140 1141 static void 1142 resend_responder_hello (void *cls) 1143 { 1144 struct GSC_KeyExchangeInfo *kx = cls; 1145 1146 kx->resend_task = NULL; 1147 if (0 == kx->resend_tries_left) 1148 { 1149 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1150 "Restarting KX\n"); 1151 restart_kx (kx); 1152 return; 1153 } 1154 kx->resend_tries_left--; 1155 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1156 "Resending responder hello. Retries left: %u\n", 1157 kx->resend_tries_left); 1158 GNUNET_MQ_send_copy (kx->mq, kx->resend_env); 1159 kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT, 1160 &resend_responder_hello, 1161 kx); 1162 } 1163 1164 1165 void 1166 send_responder_hello (struct GSC_KeyExchangeInfo *kx) 1167 { 1168 enum GNUNET_GenericReturnValue ret; 1169 struct GNUNET_CRYPTO_HpkeEncapsulation c_I; 1170 struct ResponderHello *rhm_e; /* responder hello message - encrypted pointer */ 1171 struct GNUNET_MQ_Envelope *env; 1172 struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_kem_challenge; 1173 struct GNUNET_ShortHashCode rhts; 1174 struct GNUNET_ShortHashCode ihts; 1175 struct GNUNET_ShortHashCode hs; 1176 struct GNUNET_ShortHashCode ms; 1177 struct GNUNET_ShortHashCode ss_e; 1178 struct GNUNET_ShortHashCode ss_I; 1179 struct GNUNET_HashContext *hc; 1180 unsigned char enc_key[AEAD_KEY_BYTES]; 1181 unsigned char enc_nonce[AEAD_NONCE_BYTES]; 1182 1183 // 4. encaps -> shared_secret_e, c_e (kemChallenge) 1184 // TODO potentially write this directly into rhm? 1185 ret = GNUNET_CRYPTO_hpke_kem_encaps (&kx->pk_e, // public ephemeral key of initiator 1186 &ephemeral_kem_challenge, // encapsulated key 1187 &ss_e); // key - ss_e 1188 if (GNUNET_OK != ret) 1189 { 1190 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1191 "Something went wrong encapsulating ss_e\n"); 1192 return; 1193 } 1194 hc = GNUNET_CRYPTO_hash_context_copy (kx->transcript_hash_ctx); 1195 // 6. encaps -> shared_secret_I, c_I 1196 ret = GNUNET_CRYPTO_eddsa_kem_encaps (&kx->peer.public_key, // public key of I 1197 &c_I, // encapsulated key 1198 &ss_I); // where to write the key material 1199 if (GNUNET_OK != ret) 1200 { 1201 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1202 "Something went wrong encapsulating ss_I\n"); 1203 GNUNET_CRYPTO_hash_context_abort (hc); 1204 return; 1205 } 1206 // 7. generate RHTS (responder_handshare_secret_key) and RATS (responder_application_traffic_secret_key) (section 5) 1207 { 1208 struct GNUNET_HashCode transcript; 1209 snapshot_transcript (hc, &transcript); 1210 #if DEBUG_KX 1211 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1212 "Transcript snapshot for derivation of HS, MS: `%s'\n", 1213 GNUNET_h2s (&transcript)); 1214 #endif 1215 derive_hs (&kx->early_secret_key, 1216 &ss_e, 1217 &hs); 1218 derive_ms (&hs, &ss_I, &ms); 1219 } 1220 1221 // send ResponderHello 1222 // TODO fill fields / services_info! 1223 // 1. r_R <- random 1224 struct ResponderHelloPayload *rhp; 1225 size_t rhp_len = sizeof (*rhp) + strlen (my_services_info); 1226 unsigned char rhp_buf[rhp_len]; 1227 size_t ct_len; 1228 1229 rhp = (struct ResponderHelloPayload*) rhp_buf; 1230 ct_len = rhp_len // ResponderHelloPayload, fist PT msg 1231 + sizeof (struct GNUNET_HashCode) // Finished hash, second PT msg 1232 + AEAD_TAG_BYTES * 2; // Two tags; 1233 env = GNUNET_MQ_msg_extra (rhm_e, 1234 ct_len, 1235 GNUNET_MESSAGE_TYPE_CORE_RESPONDER_HELLO); 1236 1237 rhm_e->r_R = 1238 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, 1239 UINT64_MAX); 1240 1241 // c_e 1242 GNUNET_memcpy (&rhm_e->c_e, 1243 &ephemeral_kem_challenge, 1244 sizeof (ephemeral_kem_challenge)); 1245 GNUNET_CRYPTO_hash_context_read (hc, 1246 rhm_e, 1247 sizeof (struct ResponderHello)); 1248 // 2. Encrypt ServicesInfo and c_I with RHTS 1249 // derive RHTS 1250 { 1251 struct GNUNET_HashCode transcript; 1252 snapshot_transcript (hc, 1253 &transcript); 1254 #if DEBUG_KX 1255 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1256 "Transcript snapshot for derivation of *HTS: `%s'\n", 1257 GNUNET_h2s (&transcript)); 1258 #endif 1259 derive_rhts (&transcript, 1260 &hs, 1261 &rhts); 1262 derive_ihts (&transcript, 1263 &hs, 1264 &ihts); 1265 derive_per_message_secrets (&rhts, 1266 0, 1267 enc_key, 1268 enc_nonce); 1269 } 1270 // c_I 1271 GNUNET_memcpy (&rhp->c_I, &c_I, sizeof (c_I)); 1272 // Services info empty for now. 1273 GNUNET_memcpy (&rhp[1], 1274 my_services_info, 1275 strlen (my_services_info)); 1276 1277 { 1278 unsigned long long out_ct_len; 1279 struct GNUNET_HashCode finished; 1280 struct GNUNET_HashCode transcript; 1281 unsigned char *finished_buf; 1282 GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt ( 1283 (unsigned char*) &rhm_e[1], /* c - ciphertext */ 1284 &out_ct_len, /* clen_p */ 1285 rhp_buf, /* rhm_p - plaintext message */ 1286 rhp_len, // mlen 1287 NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted 1288 // fields? 1289 NULL, // nsec - unused 1290 enc_nonce, // npub - nonce // FIXME nonce can be reused 1291 enc_key)); // k - key RHTS 1292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1293 "Encrypted and wrote %llu bytes\n", 1294 out_ct_len); 1295 // 3. Create ResponderFinished (Section 6) 1296 // Derive fk_I <- HKDF-Expand (MS, "r finished", NULL) 1297 /* Forward the transcript */ 1298 /* {svcinfo, c_I}RHTS */ 1299 GNUNET_CRYPTO_hash_context_read ( 1300 hc, 1301 &rhm_e[1], 1302 out_ct_len); 1303 1304 finished_buf = ((unsigned char*) &rhm_e[1]) + out_ct_len; 1305 snapshot_transcript (hc, 1306 &transcript); 1307 #if DEBUG_KX 1308 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1309 "Transcript snapshot for derivation of Rfinished: `%s'\n", 1310 GNUNET_h2s (&transcript)); 1311 #endif 1312 generate_responder_finished (&transcript, 1313 &ms, 1314 &finished); 1315 // 4. Encrypt ResponderFinished 1316 derive_per_message_secrets (&rhts, 1317 1, 1318 enc_key, 1319 enc_nonce); 1320 GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt ( 1321 finished_buf, /* c - ciphertext */ 1322 &out_ct_len, /* clen_p */ 1323 (unsigned char*) &finished, /* rhm_p - plaintext message */ 1324 sizeof (finished), // mlen 1325 NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted 1326 // fields? 1327 NULL, // nsec - unused 1328 enc_nonce, // npub 1329 enc_key)); // k - key RHTS 1330 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1331 "Encrypted and wrote %llu bytes\n", 1332 out_ct_len); 1333 /* Forward the transcript 1334 * after responder finished, 1335 * before deriving *ATS and generating finished_I 1336 * (finished_I will be generated when receiving the InitiatorFinished message 1337 * in order to check it) */ 1338 GNUNET_CRYPTO_hash_context_read ( 1339 hc, 1340 finished_buf, 1341 out_ct_len); 1342 // 5. optionally send application data - encrypted with RATS 1343 // We do not really have any application data, instead, we send the ACK 1344 snapshot_transcript (hc, 1345 &transcript); 1346 #if DEBUG_KX 1347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1348 "Transcript snapshot for derivation of *ATS: `%s'\n", 1349 GNUNET_h2s (&transcript)); 1350 #endif 1351 derive_initial_ats (&transcript, 1352 &ms, 1353 ROLE_RESPONDER, 1354 &kx->current_ats); 1355 } 1356 /* Lock into struct */ 1357 GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx); 1358 kx->transcript_hash_ctx = hc; 1359 kx->master_secret = ms; 1360 kx->handshake_secret = hs; 1361 kx->ss_e = ss_e; 1362 kx->ihts = ihts; 1363 kx->rhts = rhts; 1364 kx->ss_I = ss_I; 1365 kx->current_epoch = 0; 1366 kx->current_sqn = 0; 1367 derive_per_message_secrets (&kx->current_ats, 1368 kx->current_sqn, 1369 enc_key, 1370 enc_nonce); 1371 1372 GNUNET_MQ_send_copy (kx->mq, env); 1373 kx->resend_env = env; 1374 kx->resend_tries_left = RESEND_MAX_TRIES; 1375 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent ResponderHello: %d %d\n", kx->role, 1376 kx->status); 1377 1378 kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT, 1379 &resend_responder_hello, 1380 kx); 1381 kx->status = GNUNET_CORE_KX_STATE_RESPONDER_HELLO_SENT; 1382 monitor_notify_all (kx); 1383 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer); 1384 } 1385 1386 1387 static void 1388 handle_initiator_hello_cont (void *cls, const struct GNUNET_ShortHashCode *ss_R) 1389 { 1390 const struct GNUNET_HashCode *my_identity_hash; 1391 struct InitiatorHelloCtx *ihm_ctx = cls; 1392 struct GSC_KeyExchangeInfo *kx = ihm_ctx->kx; 1393 uint32_t ihm_len = ntohs (ihm_ctx->ihm_e->header.size); 1394 unsigned char enc_key[AEAD_KEY_BYTES]; 1395 unsigned char enc_nonce[AEAD_NONCE_BYTES]; 1396 struct GNUNET_HashCode h1; 1397 struct GNUNET_HashCode transcript; 1398 struct GNUNET_ShortHashCode es; 1399 struct GNUNET_ShortHashCode ets; 1400 enum GNUNET_GenericReturnValue ret; 1401 1402 ihm_ctx->req->op = NULL; 1403 GNUNET_CONTAINER_DLL_remove (pils_requests_head, 1404 pils_requests_tail, 1405 ihm_ctx->req); 1406 GNUNET_free (ihm_ctx->req); 1407 1408 1409 GNUNET_memcpy (&kx->pk_e.ecdhe_key, 1410 &ihm_ctx->ihm_e->pk_e, 1411 sizeof (ihm_ctx->ihm_e->pk_e)); 1412 // 5. generate ETS (early_traffic_secret_key, decrypt pk_i 1413 // expand ETS <- expand ES <- extract ss_R 1414 // use ETS to decrypt 1415 1416 /* Forward the transcript hash context over the unencrypted fields to get it 1417 * to the same status that the initiator had when it needed to derive es and 1418 * ets for the encryption */ 1419 GNUNET_CRYPTO_hash_context_read ( 1420 kx->transcript_hash_ctx, 1421 ihm_ctx->ihm_e, 1422 sizeof (struct InitiatorHello)); 1423 snapshot_transcript (kx->transcript_hash_ctx, 1424 &transcript); 1425 #if DEBUG_KX 1426 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1427 "Transcript snapshot for derivation of ES, ETS: `%s'\n", 1428 GNUNET_h2s (&transcript)); 1429 #endif 1430 derive_es_ets (&transcript, ss_R, &es, &ets); 1431 derive_per_message_secrets (&ets, 1432 0, 1433 enc_key, 1434 enc_nonce); 1435 { 1436 struct InitiatorHelloPayload *ihmp; 1437 size_t ct_len = ihm_len - sizeof (struct InitiatorHello); 1438 unsigned char ihmp_buf[ct_len - AEAD_TAG_BYTES]; 1439 ihmp = (struct InitiatorHelloPayload*) ihmp_buf; 1440 ret = crypto_aead_xchacha20poly1305_ietf_decrypt ( 1441 ihmp_buf, // unsigned char *m 1442 NULL, // mlen_p message length 1443 NULL, // unsigned char *nsec - unused: NULL 1444 (unsigned char*) &ihm_ctx->ihm_e[1], // const unsigned char *c - ciphertext 1445 ct_len, // unsigned long long clen - length of ciphertext 1446 // mac, // const unsigned char *mac - authentication tag 1447 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right? 1448 0, // unsigned long long adlen 1449 enc_nonce, // const unsigned char *npub - nonce 1450 enc_key // const unsigned char *k - key 1451 ); 1452 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pid_sender: %s\n", 1453 GNUNET_i2s (&ihmp->pk_I)); 1454 if (0 != ret) 1455 { 1456 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1457 "Something went wrong decrypting: %d\n", ret); 1458 GNUNET_break_op (0); 1459 GNUNET_free (ihm_ctx->ihm_e); 1460 GNUNET_free (ihm_ctx); 1461 restart_kx (kx); 1462 return; 1463 } 1464 /* now forward it considering the encrypted messages that the initiator was 1465 * able to send after deriving the es and ets */ 1466 GNUNET_CRYPTO_hash_context_read (kx->transcript_hash_ctx, 1467 &ihm_ctx->ihm_e[1], 1468 ct_len); 1469 GNUNET_memcpy (&kx->peer, 1470 &ihmp->pk_I, 1471 sizeof (struct GNUNET_PeerIdentity)); 1472 } 1473 1474 my_identity_hash = GNUNET_PILS_get_identity_hash (GSC_pils); 1475 GNUNET_assert (NULL != my_identity_hash); 1476 1477 // We could follow with the rest of the Key Schedule (dES, HS, ...) for now 1478 /* Check that we are actually in the receiving role */ 1479 GNUNET_CRYPTO_hash (&kx->peer, sizeof(struct GNUNET_PeerIdentity), &h1); 1480 if (0 < GNUNET_CRYPTO_hash_cmp (&h1, my_identity_hash)) 1481 { 1482 /* peer with "lower" identity starts KX, otherwise we typically end up 1483 with both peers starting the exchange and transmit the 'set key' 1484 message twice */ 1485 /* Something went wrong - we have the lower value and should have sent the 1486 * InitiatorHello, but instead received it. TODO handle this case 1487 * We might end up in this case if the initiator didn't initiate the 1488 * handshake long enough and the 'responder' initiates the handshake */ 1489 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1490 "Something went wrong - we have the lower value and should have sent the InitiatorHello, but instead received it.\n"); 1491 GNUNET_free (ihm_ctx->ihm_e); 1492 GNUNET_free (ihm_ctx); 1493 GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx); 1494 kx->transcript_hash_ctx = NULL; 1495 return; 1496 } 1497 1498 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer ID of other peer: %s\n", GNUNET_i2s 1499 (&kx->peer)); 1500 /* We update the monitoring peers here because now we know 1501 * that we can decrypt the message AND know the PID 1502 */ 1503 monitor_notify_all (kx); 1504 kx->ss_R = *ss_R; 1505 kx->early_secret_key = es; 1506 kx->early_traffic_secret = ets; 1507 send_responder_hello (kx); 1508 } 1509 1510 1511 static int 1512 check_initiator_hello (void *cls, const struct InitiatorHello *m) 1513 { 1514 uint16_t size = ntohs (m->header.size); 1515 1516 if (size < sizeof (*m) 1517 + sizeof (struct InitiatorHelloPayload) 1518 + AEAD_TAG_BYTES) 1519 { 1520 return GNUNET_SYSERR; 1521 } 1522 return GNUNET_OK; 1523 } 1524 1525 1526 /** 1527 * Handle the InitiatorHello message 1528 * - derives necessary keys from the plaintext parts 1529 * - decrypts the encrypted part 1530 * - replies with ResponderHello message 1531 * @param cls the key exchange info 1532 * @param ihm_e InitiatorHello message 1533 */ 1534 static void 1535 handle_initiator_hello (void *cls, const struct InitiatorHello *ihm_e) 1536 { 1537 const struct GNUNET_HashCode *my_identity_hash; 1538 struct GSC_KeyExchangeInfo *kx = cls; 1539 struct InitiatorHelloCtx *initiator_hello_cls; 1540 size_t ihm_len; 1541 1542 if (ROLE_INITIATOR == kx->role) 1543 { 1544 GNUNET_break_op (0); 1545 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1546 "I am an initiator! Tearing down...\n"); 1547 return; 1548 } 1549 if (kx->status == GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED) 1550 { 1551 GNUNET_break_op (0); 1552 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1553 "Already received InitiatorHello: %d %d\n", kx->role, kx->status 1554 ); 1555 return; 1556 } 1557 else if ((kx->status > GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED) && 1558 (NULL != kx->transcript_hash_ctx)) 1559 { 1560 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1561 "Already received InitiatorHello and sent ResponderHello: %d %d\n", 1562 kx->role, kx->status); 1563 return; 1564 } 1565 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received InitiatorHello: %d %d\n", kx-> 1566 role, kx->status); 1567 GNUNET_assert (NULL == kx->transcript_hash_ctx); 1568 kx->transcript_hash_ctx = GNUNET_CRYPTO_hash_context_start (); 1569 GNUNET_assert (NULL != kx->transcript_hash_ctx); 1570 1571 GNUNET_STATISTICS_update (GSC_stats, 1572 gettext_noop ("# key exchanges initiated"), 1573 1, 1574 GNUNET_NO); 1575 1576 kx->status = GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED; 1577 1578 my_identity_hash = GNUNET_PILS_get_identity_hash (GSC_pils); 1579 GNUNET_assert (NULL != my_identity_hash); 1580 1581 // 1. verify type _INITIATOR_HELLO 1582 // - This is implicytly done by arriving within this handler 1583 // - or is this about verifying the 'additional data' part of aead? 1584 // should it check the encryption + mac? (is this implicitly done 1585 // while decrypting?) 1586 // 2. verify H(pk_R) matches pk_R 1587 if (0 != memcmp (&ihm_e->h_pk_R, 1588 my_identity_hash, 1589 sizeof (struct GNUNET_HashCode))) 1590 { 1591 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1592 "This message is not meant for us (H(PID) mismatch)\n"); 1593 GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx); 1594 kx->transcript_hash_ctx = NULL; 1595 return; 1596 } 1597 // FIXME this sometimes triggers in the tests - why? 1598 // 3. decaps -> shared_secret_R, c_R (kemChallenge) 1599 ihm_len = ntohs (ihm_e->header.size); 1600 initiator_hello_cls = GNUNET_new (struct InitiatorHelloCtx); 1601 initiator_hello_cls->kx = kx; 1602 initiator_hello_cls->ihm_e = GNUNET_malloc (ihm_len); 1603 GNUNET_memcpy (initiator_hello_cls->ihm_e, ihm_e, ihm_len); 1604 initiator_hello_cls->req = GNUNET_new (struct PilsRequest); 1605 GNUNET_CONTAINER_DLL_insert (pils_requests_head, 1606 pils_requests_tail, 1607 initiator_hello_cls->req); 1608 initiator_hello_cls->req->op = 1609 GNUNET_PILS_kem_decaps (GSC_pils, 1610 &ihm_e->c_R, 1611 // encapsulated key 1612 &handle_initiator_hello_cont, 1613 // continuation 1614 initiator_hello_cls); 1615 } 1616 1617 1618 struct ResponderHelloCls 1619 { 1620 /* Current KX session */ 1621 struct GSC_KeyExchangeInfo *kx; 1622 1623 /* responder hello message - encrypted */ 1624 struct ResponderHello rhm_e; 1625 1626 /* responder hello message - plain/decrypted */ 1627 struct ResponderHelloPayload *rhp; 1628 1629 /* Decrypted finish hash */ 1630 struct GNUNET_HashCode decrypted_finish; 1631 1632 /* Encrypted finished CT (for transcript later) */ 1633 char finished_enc[sizeof (struct GNUNET_HashCode) 1634 + AEAD_TAG_BYTES]; 1635 1636 /* Temporary transcript context */ 1637 struct GNUNET_HashContext *hc; 1638 1639 /* Temporary handshake secret */ 1640 struct GNUNET_ShortHashCode hs; 1641 1642 /* Temporary handshake secret */ 1643 struct GNUNET_ShortHashCode ss_e; 1644 1645 /* Temporary handshake secret */ 1646 struct GNUNET_ShortHashCode ihts; 1647 1648 /* Temporary handshake secret */ 1649 struct GNUNET_ShortHashCode rhts; 1650 1651 /* Pending PILS request */ 1652 struct PilsRequest *req; 1653 }; 1654 1655 static void 1656 resend_initiator_done (void *cls) 1657 { 1658 struct GSC_KeyExchangeInfo *kx = cls; 1659 1660 kx->resend_task = NULL; 1661 if (0 == kx->resend_tries_left) 1662 { 1663 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1664 "Restarting KX\n"); 1665 restart_kx (kx); 1666 return; 1667 } 1668 kx->resend_tries_left--; 1669 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1670 "Resending initiator done. Retries left: %u\n", 1671 kx->resend_tries_left); 1672 GNUNET_MQ_send_copy (kx->mq, kx->resend_env); 1673 kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT, 1674 &resend_initiator_done, 1675 kx); 1676 } 1677 1678 1679 static void 1680 handle_responder_hello_cont (void *cls, const struct GNUNET_ShortHashCode *ss_I) 1681 { 1682 struct ResponderHelloCls *rh_ctx = cls; 1683 struct GSC_KeyExchangeInfo *kx = rh_ctx->kx; 1684 struct InitiatorDone *idm_e; /* encrypted */ 1685 struct InitiatorDone idm_local; 1686 struct InitiatorDone *idm_p; /* plaintext */ 1687 struct GNUNET_MQ_Envelope *env; 1688 unsigned char enc_key[AEAD_KEY_BYTES]; 1689 unsigned char enc_nonce[AEAD_NONCE_BYTES]; 1690 struct ConfirmationAck ack_i; 1691 struct GNUNET_HashCode transcript; 1692 struct GNUNET_ShortHashCode ms; 1693 1694 rh_ctx->req->op = NULL; 1695 GNUNET_CONTAINER_DLL_remove (pils_requests_head, 1696 pils_requests_tail, 1697 rh_ctx->req); 1698 GNUNET_free (rh_ctx->req); 1699 // XXX valgrind reports uninitialized memory 1700 // the following is a way to check whether this memory was meant 1701 // memset (&rhm_local, 0, sizeof (rhm_local)); - adapt to cls if still needed 1702 memset (&idm_local, 0, sizeof (idm_local)); 1703 1704 kx->ss_I = *ss_I; 1705 1706 /* derive *ATS */ 1707 derive_ms (&rh_ctx->hs, ss_I, &ms);; 1708 // 5. Create ResponderFinished as per Section 6 and check against decrypted payload. 1709 struct GNUNET_HashCode responder_finished; 1710 // Transcript updates, snapshot again 1711 snapshot_transcript (rh_ctx->hc, 1712 &transcript); 1713 #if DEBUG_KX 1714 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1715 "Transcript snapshot for derivation of Rfinished: `%s'\n", 1716 GNUNET_h2s (&transcript)); 1717 #endif 1718 generate_responder_finished (&transcript, 1719 &ms, 1720 &responder_finished); 1721 if (0 != memcmp (&rh_ctx->decrypted_finish, 1722 &responder_finished, 1723 sizeof (struct GNUNET_HashCode))) 1724 { 1725 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1726 "Could not verify \"responder finished\"\n"); 1727 GNUNET_free (rh_ctx->rhp); 1728 GNUNET_CRYPTO_hash_context_abort (rh_ctx->hc); 1729 GNUNET_free (rh_ctx); 1730 GNUNET_assert (0); 1731 return; 1732 } 1733 1734 1735 /* Forward the transcript 1736 * after generating finished_R, 1737 * before deriving *ATS */ 1738 GNUNET_CRYPTO_hash_context_read ( 1739 rh_ctx->hc, 1740 rh_ctx->finished_enc, 1741 sizeof (rh_ctx->finished_enc)); 1742 1743 // At this point we cannot fail anymore and may lock into kx 1744 GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx); 1745 kx->transcript_hash_ctx = rh_ctx->hc; 1746 kx->ss_I = *ss_I; 1747 kx->handshake_secret = rh_ctx->hs; 1748 kx->ss_e = rh_ctx->ss_e; 1749 kx->ihts = rh_ctx->ihts; 1750 kx->rhts = rh_ctx->rhts; 1751 kx->master_secret = ms; 1752 GNUNET_free (rh_ctx->rhp); 1753 GNUNET_free (rh_ctx); 1754 rh_ctx = NULL; 1755 1756 snapshot_transcript (kx->transcript_hash_ctx, 1757 &transcript); 1758 #if DEBUG_KX 1759 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1760 "Transcript snapshot for derivation of *ATS: `%s'\n", 1761 GNUNET_h2s (&transcript)); 1762 #endif 1763 derive_initial_ats (&transcript, 1764 &kx->master_secret, 1765 ROLE_RESPONDER, 1766 &kx->their_ats[0]); 1767 for (int i = 0; i < MAX_EPOCHS - 1; i++) 1768 { 1769 derive_next_ats (&kx->their_ats[i], 1770 &kx->their_ats[i + 1]); 1771 } 1772 kx->their_max_epoch = MAX_EPOCHS - 1; 1773 1774 derive_per_message_secrets (&kx->ihts, 1775 0, 1776 enc_key, 1777 enc_nonce); 1778 /* Create InitiatorDone message */ 1779 idm_p = &idm_local; /* plaintext */ 1780 env = GNUNET_MQ_msg_extra (idm_e, 1781 sizeof (ack_i) 1782 + AEAD_TAG_BYTES, 1783 GNUNET_MESSAGE_TYPE_CORE_INITIATOR_DONE); 1784 // 6. Create IteratorFinished as per Section 6. 1785 generate_initiator_finished (&transcript, 1786 &kx->master_secret, 1787 &idm_p->finished); 1788 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1789 "InteratorFinished: `%s'\n", 1790 GNUNET_h2s (&idm_p->finished)); 1791 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1792 "Transcript `%s'\n", 1793 GNUNET_h2s (&transcript)); 1794 // 7. Send InteratorFinished message encrypted with the key derived from IHTS to R 1795 1796 GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt ( 1797 (unsigned char*) &idm_e->finished, /* c - ciphertext */ 1798 NULL, /* clen_p */ 1799 (unsigned char*) &idm_p->finished, /* idm_p - plaintext message */ 1800 sizeof (idm_p->finished), // mlen 1801 NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted 1802 // fields? 1803 NULL, // nsec - unused 1804 enc_nonce, // npub - nonce 1805 enc_key)); // k - key IHTS 1806 /* Forward the transcript hash context 1807 * after generating finished_I and RATS_0 1808 * before deriving IATS_0 */ 1809 GNUNET_CRYPTO_hash_context_read (kx->transcript_hash_ctx, 1810 &idm_e->finished, 1811 sizeof (idm_e->finished) 1812 + AEAD_TAG_BYTES); 1813 snapshot_transcript (kx->transcript_hash_ctx, 1814 &transcript); 1815 #if DEBUG_KX 1816 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1817 "Transcript snapshot for derivation of *ATS: `%s'\n", 1818 GNUNET_h2s (&transcript)); 1819 #endif 1820 derive_initial_ats (&transcript, 1821 &kx->master_secret, 1822 ROLE_INITIATOR, 1823 &kx->current_ats); 1824 kx->current_epoch = 0; 1825 kx->current_sqn++; 1826 // 8. optionally encrypt payload TODO 1827 derive_per_message_secrets (&kx->current_ats, 1828 kx->current_sqn, 1829 enc_key, 1830 enc_nonce); 1831 kx->current_sqn++; 1832 ack_i.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ACK); 1833 ack_i.header.size = htons (sizeof ack_i); 1834 GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt ( 1835 (unsigned char*) &idm_e[1], /* c - ciphertext */ 1836 NULL, /* clen_p */ 1837 (unsigned char*) &ack_i, /* rhm_p - plaintext message */ 1838 sizeof ack_i, // mlen 1839 NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted 1840 // fields? 1841 NULL, // nsec - unused 1842 enc_nonce, // npub - nonce // FIXME nonce can be reused 1843 enc_key)); // k - key RHTS 1844 1845 GNUNET_MQ_send_copy (kx->mq, env); 1846 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent InitiatorDone: %d %d\n", kx->role, 1847 kx->status); 1848 1849 1850 kx->resend_env = env; 1851 kx->resend_tries_left = RESEND_MAX_TRIES; 1852 kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT, 1853 &resend_initiator_done, 1854 kx); 1855 kx->status = GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT; 1856 monitor_notify_all (kx); 1857 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer); 1858 } 1859 1860 1861 static int 1862 check_responder_hello (void *cls, const struct ResponderHello *m) 1863 { 1864 uint16_t size = ntohs (m->header.size); 1865 1866 if (size < sizeof (*m) 1867 + sizeof (struct ResponderHelloPayload) 1868 + sizeof (struct GNUNET_HashCode) 1869 + AEAD_TAG_BYTES * 2) 1870 { 1871 return GNUNET_SYSERR; 1872 } 1873 return GNUNET_OK; 1874 } 1875 1876 1877 /** 1878 * Handle Responder Hello message 1879 * @param cls key exchange info 1880 * @param rhm_e ResponderHello message 1881 */ 1882 static void 1883 handle_responder_hello (void *cls, const struct ResponderHello *rhm_e) 1884 { 1885 struct GSC_KeyExchangeInfo *kx = cls; 1886 struct PilsRequest *req; 1887 struct ResponderHelloCls *rh_ctx; 1888 struct GNUNET_HashCode transcript; 1889 struct GNUNET_HashContext *hc; 1890 unsigned char enc_key[AEAD_KEY_BYTES]; 1891 unsigned char enc_nonce[AEAD_NONCE_BYTES]; 1892 enum GNUNET_GenericReturnValue ret; 1893 1894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ResponderHello: %d %d\n", kx-> 1895 role, kx->status); 1896 1897 hc = GNUNET_CRYPTO_hash_context_copy (kx->transcript_hash_ctx); 1898 if (NULL != kx->resend_task) 1899 { 1900 GNUNET_SCHEDULER_cancel (kx->resend_task); 1901 kx->resend_task = NULL; 1902 } 1903 if (NULL != kx->resend_env) 1904 { 1905 GNUNET_free (kx->resend_env); 1906 kx->resend_env = NULL; 1907 } 1908 1909 /* Forward the transcript hash context */ 1910 if (ROLE_RESPONDER == kx->role) 1911 { 1912 GNUNET_break_op (0); 1913 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1914 "I am the responder! Ignoring.\n"); 1915 GNUNET_CRYPTO_hash_context_abort (hc); 1916 return; 1917 } 1918 GNUNET_CRYPTO_hash_context_read (hc, 1919 rhm_e, 1920 sizeof (struct ResponderHello)); 1921 // 1. Verify that the message type is CORE_RESPONDER_HELLO 1922 // - implicitly done by handling this message? 1923 // - or is this about verifying the 'additional data' part of aead? 1924 // should it check the encryption + mac? (is this implicitly done 1925 // while decrypting?) 1926 // 2. sse <- Decaps(ske,ce) 1927 rh_ctx = GNUNET_new (struct ResponderHelloCls); 1928 ret = GNUNET_CRYPTO_hpke_kem_decaps (&kx->sk_e, // secret/private ephemeral key of initiator (us) 1929 &rhm_e->c_e, // encapsulated key 1930 &rh_ctx->ss_e); // key - ss_e 1931 if (GNUNET_OK != ret) 1932 { 1933 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1934 "Something went wrong decapsulating ss_e\n"); 1935 GNUNET_CRYPTO_hash_context_abort (hc); 1936 return; 1937 } 1938 // 3. Generate IHTS and RHTS from Section 5 and decrypt ServicesInfo, cI and ResponderFinished. 1939 snapshot_transcript (hc, &transcript); 1940 #if DEBUG_KX 1941 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1942 "Transcript snapshot for derivation of HS, *HTS: `%s'\n", 1943 GNUNET_h2s (&transcript)); 1944 #endif 1945 derive_hs (&kx->early_secret_key, 1946 &rh_ctx->ss_e, 1947 &rh_ctx->hs); 1948 derive_rhts (&transcript, 1949 &rh_ctx->hs, 1950 &rh_ctx->rhts); 1951 derive_ihts (&transcript, 1952 &rh_ctx->hs, 1953 &rh_ctx->ihts); 1954 derive_per_message_secrets (&rh_ctx->rhts, 1955 0, 1956 enc_key, 1957 enc_nonce); 1958 rh_ctx->kx = kx; 1959 GNUNET_memcpy (&rh_ctx->rhm_e, rhm_e, sizeof (*rhm_e)); 1960 { 1961 unsigned long long int c_len; 1962 unsigned char *finished_buf; 1963 // use RHTS to decrypt 1964 c_len = ntohs (rhm_e->header.size) - sizeof (*rhm_e) 1965 - sizeof (struct GNUNET_HashCode) 1966 - AEAD_TAG_BYTES; // finished ct 1967 rh_ctx->rhp = GNUNET_malloc (c_len 1968 - 1969 AEAD_TAG_BYTES); 1970 rh_ctx->hc = hc; 1971 finished_buf = ((unsigned char*) &rhm_e[1]) + c_len; 1972 /* Forward the transcript_hash_ctx 1973 * after rhts has been generated, 1974 * before generating finished_R*/ 1975 GNUNET_CRYPTO_hash_context_read ( 1976 hc, 1977 &rhm_e[1], 1978 c_len); 1979 1980 ret = crypto_aead_xchacha20poly1305_ietf_decrypt ( 1981 (unsigned char*) rh_ctx->rhp, // unsigned char *m 1982 NULL, // mlen_p message length 1983 NULL, // unsigned char *nsec - unused: NULL 1984 (unsigned char*) &rhm_e[1], // const unsigned char *c - ciphertext 1985 c_len, // unsigned long long clen - length of ciphertext 1986 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right? 1987 0, // unsigned long long adlen 1988 enc_nonce, // const unsigned char *npub - nonce 1989 enc_key // const unsigned char *k - key 1990 ); 1991 if (0 != ret) 1992 { 1993 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1994 "Something went wrong decrypting: %d\n", ret); 1995 GNUNET_free (rh_ctx->rhp); 1996 GNUNET_free (rh_ctx); 1997 GNUNET_CRYPTO_hash_context_abort (hc); 1998 return; 1999 } 2000 // FIXME nonce reuse (see encryption) 2001 derive_per_message_secrets (&rh_ctx->rhts, 2002 1, 2003 enc_key, 2004 enc_nonce); 2005 c_len = sizeof (struct GNUNET_HashCode) 2006 + AEAD_TAG_BYTES; 2007 ret = crypto_aead_xchacha20poly1305_ietf_decrypt ( 2008 (unsigned char*) &rh_ctx->decrypted_finish, // unsigned char *m 2009 NULL, // mlen_p message length 2010 NULL, // unsigned char *nsec - unused: NULL 2011 finished_buf, // const unsigned char *c - ciphertext 2012 c_len, // unsigned long long clen - length of ciphertext 2013 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right? 2014 0, // unsigned long long adlen 2015 enc_nonce, // const unsigned char *npub - nonce 2016 enc_key // const unsigned char *k - key 2017 ); 2018 if (0 != ret) 2019 { 2020 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2021 "Something went wrong decrypting finished field: %d\n", ret); 2022 GNUNET_free (rh_ctx->rhp); 2023 GNUNET_free (rh_ctx); 2024 GNUNET_CRYPTO_hash_context_abort (hc); 2025 return; 2026 } 2027 GNUNET_memcpy (rh_ctx->finished_enc, 2028 finished_buf, 2029 c_len); 2030 } 2031 // 4. ssI <- Decaps(skI,cI). 2032 req = GNUNET_new (struct PilsRequest); 2033 rh_ctx->req = req; 2034 GNUNET_CONTAINER_DLL_insert (pils_requests_head, 2035 pils_requests_tail, 2036 req); 2037 req->op = GNUNET_PILS_kem_decaps (GSC_pils, 2038 &rh_ctx->rhp->c_I, // encapsulated key 2039 &handle_responder_hello_cont, // continuation 2040 rh_ctx); 2041 } 2042 2043 2044 static int 2045 check_initiator_done (void *cls, const struct InitiatorDone *m) 2046 { 2047 uint16_t size = ntohs (m->header.size); 2048 2049 if (size < sizeof (*m) + sizeof (struct ConfirmationAck)) 2050 { 2051 return GNUNET_SYSERR; 2052 } 2053 return GNUNET_OK; 2054 } 2055 2056 2057 /** 2058 * Handle InitiatorDone message 2059 * @param cls key exchange info 2060 * @param idm_e InitiatorDone message 2061 */ 2062 static void 2063 handle_initiator_done (void *cls, const struct InitiatorDone *idm_e) 2064 { 2065 struct GSC_KeyExchangeInfo *kx = cls; 2066 struct InitiatorDone idm_local; 2067 struct InitiatorDone *idm_p = &idm_local; /* plaintext */ 2068 struct GNUNET_HashCode initiator_finished; 2069 struct GNUNET_HashCode transcript; 2070 struct GNUNET_ShortHashCode their_ats; 2071 struct GNUNET_HashContext *hc; 2072 unsigned char enc_key[AEAD_KEY_BYTES]; 2073 unsigned char enc_nonce[AEAD_NONCE_BYTES]; 2074 struct ConfirmationAck ack_i; 2075 struct ConfirmationAck ack_r; 2076 int8_t ret; 2077 2078 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received InitiatorDone: %d %d\n", kx-> 2079 role, kx->status); 2080 if (NULL != kx->resend_task) 2081 { 2082 GNUNET_SCHEDULER_cancel (kx->resend_task); 2083 kx->resend_task = NULL; 2084 } 2085 if (NULL != kx->resend_env) 2086 { 2087 GNUNET_free (kx->resend_env); 2088 kx->resend_env = NULL; 2089 } 2090 if (ROLE_INITIATOR == kx->role) 2091 { 2092 GNUNET_break_op (0); 2093 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2094 "I am the initiator! Tearing down...\n"); 2095 return; 2096 } 2097 derive_per_message_secrets (&kx->ihts, 2098 0, 2099 enc_key, 2100 enc_nonce); 2101 ret = crypto_aead_xchacha20poly1305_ietf_decrypt ( 2102 (unsigned char*) &idm_p->finished, // unsigned char *m 2103 NULL, // mlen_p message length 2104 NULL, // unsigned char *nsec - unused: NULL 2105 (unsigned char*) &idm_e->finished, // const unsigned char *c - ciphertext 2106 sizeof (idm_p->finished) // unsigned long long clen - length of ciphertext 2107 + AEAD_TAG_BYTES, 2108 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right? 2109 0, // unsigned long long adlen 2110 enc_nonce, // const unsigned char *npub - nonce 2111 enc_key // const unsigned char *k - key 2112 ); 2113 if (0 != ret) 2114 { 2115 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2116 "Something went wrong decrypting: %d\n", ret); 2117 return; 2118 } 2119 2120 // - verify finished_I 2121 /* Generate finished_I 2122 * after Forwarding until {finished_R}RHTS 2123 * (did so while we prepared responder hello) 2124 * before forwarding to [{payload}RATS and] {finished_I}IHTS */ 2125 // (look at the end of handle_initiator_hello()) 2126 snapshot_transcript (kx->transcript_hash_ctx, &transcript); 2127 generate_initiator_finished (&transcript, 2128 &kx->master_secret, 2129 &initiator_finished); 2130 if (0 != memcmp (&idm_p->finished, 2131 &initiator_finished, 2132 sizeof (struct GNUNET_HashCode))) 2133 { 2134 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2135 "Could not verify \"initiator finished\" hash.\n"); 2136 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2137 "Want: `%s'\n", 2138 GNUNET_h2s (&initiator_finished)); 2139 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2140 "Have: `%s'\n", 2141 GNUNET_h2s (&idm_p->finished)); 2142 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2143 "Transcript `%s'\n", 2144 GNUNET_h2s (&transcript)); 2145 return; 2146 } 2147 2148 /* Forward the transcript hash_context_read */ 2149 hc = GNUNET_CRYPTO_hash_context_copy (kx->transcript_hash_ctx); 2150 GNUNET_CRYPTO_hash_context_read (hc, 2151 &idm_e->finished, 2152 sizeof (idm_e->finished) 2153 + AEAD_TAG_BYTES); 2154 snapshot_transcript (hc, &transcript); 2155 derive_initial_ats (&transcript, 2156 &kx->master_secret, 2157 ROLE_INITIATOR, 2158 &their_ats); 2159 derive_per_message_secrets (&their_ats, // FIXME other HS epoch? 2160 0, 2161 enc_key, 2162 enc_nonce); 2163 ret = crypto_aead_xchacha20poly1305_ietf_decrypt ( 2164 (unsigned char*) &ack_i, // unsigned char *m 2165 NULL, // mlen_p message length 2166 NULL, // unsigned char *nsec - unused: NULL 2167 (unsigned char*) &idm_e[1], // const unsigned char *c - ciphertext 2168 sizeof (ack_i) + AEAD_TAG_BYTES, // unsigned long long clen - length of ciphertext 2169 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right? 2170 0, // unsigned long long adlen 2171 enc_nonce, // const unsigned char *npub - nonce 2172 enc_key // const unsigned char *k - key 2173 ); 2174 if (0 != ret) 2175 { 2176 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2177 "Something went wrong decrypting the Ack: %d\n", ret); 2178 GNUNET_CRYPTO_hash_context_abort (hc); 2179 return; 2180 } 2181 if ((sizeof ack_i != ntohs (ack_i.header.size)) || 2182 (GNUNET_MESSAGE_TYPE_CORE_ACK != ntohs (ack_i.header.type))) 2183 { 2184 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2185 "Ack invalid!\n"); 2186 GNUNET_CRYPTO_hash_context_abort (hc); 2187 return; 2188 } 2189 GNUNET_memcpy (&kx->their_ats[0], 2190 &their_ats, 2191 sizeof their_ats); 2192 /** 2193 * FIXME we do not really have to calculate all this now 2194 */ 2195 for (int i = 0; i < MAX_EPOCHS - 1; i++) 2196 { 2197 derive_next_ats (&kx->their_ats[i], 2198 &kx->their_ats[i + 1]); 2199 } 2200 GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx); 2201 kx->transcript_hash_ctx = hc; 2202 kx->status = GNUNET_CORE_KX_STATE_RESPONDER_CONNECTED; 2203 kx->current_epoch_expiration = 2204 GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION); 2205 cleanup_handshake_secrets (kx); 2206 monitor_notify_all (kx); 2207 kx->current_sqn = 1; 2208 GSC_SESSIONS_create (&kx->peer, kx, kx->class); 2209 GNUNET_assert (NULL == kx->heartbeat_task); 2210 update_timeout (kx); 2211 ack_r.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ACK); 2212 ack_r.header.size = htons (sizeof ack_r); 2213 GSC_KX_encrypt_and_transmit (kx, 2214 &ack_r, 2215 sizeof ack_r); 2216 2217 GNUNET_TRANSPORT_core_receive_continue (transport, 2218 &kx->peer); 2219 } 2220 2221 2222 /** 2223 * Check an incoming encrypted message before handling it 2224 * @param cls key exchange info 2225 * @param m the encrypted message 2226 */ 2227 static int 2228 check_encrypted_message (void *cls, const struct EncryptedMessage *m) 2229 { 2230 uint16_t size = ntohs (m->header.size) - sizeof(*m); 2231 2232 // TODO check (see check_encrypted ()) 2233 // - check epoch 2234 // - check sequence number 2235 if (size < sizeof(struct GNUNET_MessageHeader)) 2236 { 2237 GNUNET_break_op (0); 2238 return GNUNET_SYSERR; 2239 } 2240 return GNUNET_OK; 2241 } 2242 2243 2244 /** 2245 * Handle a key update 2246 * @param cls key exchange info 2247 * @param m KeyUpdate message 2248 */ 2249 static void 2250 handle_heartbeat (struct GSC_KeyExchangeInfo *kx, 2251 const struct Heartbeat *m) 2252 { 2253 struct GNUNET_ShortHashCode new_ats; 2254 struct ConfirmationAck ack; 2255 2256 if (m->flags & GSC_HEARTBEAT_KEY_UPDATE_REQUESTED) 2257 { 2258 if (kx->current_epoch == UINT64_MAX) 2259 { 2260 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2261 "Max epoch reached (you probably will never see this)\n"); 2262 } 2263 else 2264 { 2265 kx->current_epoch++; 2266 kx->current_epoch_expiration = 2267 GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION); 2268 kx->current_sqn = 0; 2269 derive_next_ats (&kx->current_ats, 2270 &new_ats); 2271 memcpy (&kx->current_ats, 2272 &new_ats, 2273 sizeof new_ats); 2274 } 2275 } 2276 update_timeout (kx); 2277 ack.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ACK); 2278 ack.header.size = htons (sizeof ack); 2279 GSC_KX_encrypt_and_transmit (kx, 2280 &ack, 2281 sizeof ack); 2282 if (NULL != kx->heartbeat_task) 2283 { 2284 GNUNET_SCHEDULER_cancel (kx->heartbeat_task); 2285 kx->heartbeat_task = GNUNET_SCHEDULER_add_delayed (MIN_HEARTBEAT_FREQUENCY, 2286 &send_heartbeat, 2287 kx); 2288 } 2289 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer); 2290 } 2291 2292 2293 static enum GNUNET_GenericReturnValue 2294 check_if_ack_or_heartbeat (struct GSC_KeyExchangeInfo *kx, 2295 const char *buf, 2296 size_t buf_len) 2297 { 2298 struct GNUNET_MessageHeader *msg; 2299 struct ConfirmationAck *ack; 2300 struct Heartbeat *hb; 2301 2302 if (sizeof *msg > buf_len) 2303 return GNUNET_NO; 2304 msg = (struct GNUNET_MessageHeader*) buf; 2305 if (GNUNET_MESSAGE_TYPE_CORE_ACK == ntohs (msg->type)) 2306 { 2307 ack = (struct ConfirmationAck *) buf; 2308 if (sizeof *ack != ntohs (ack->header.size)) 2309 return GNUNET_NO; 2310 } 2311 else if (GNUNET_MESSAGE_TYPE_CORE_HEARTBEAT == ntohs (msg->type)) 2312 { 2313 hb = (struct Heartbeat*) buf; 2314 if (sizeof *hb != ntohs (hb->header.size)) 2315 return GNUNET_NO; 2316 handle_heartbeat (kx, hb); 2317 } 2318 else 2319 { 2320 return GNUNET_NO; 2321 } 2322 2323 /** 2324 * Waiting for ACK or heartbeat 2325 */ 2326 if (kx->status == GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT) 2327 { 2328 GSC_SESSIONS_create (&kx->peer, kx, kx->class); 2329 kx->status = GNUNET_CORE_KX_STATE_INITIATOR_CONNECTED; 2330 kx->current_epoch_expiration = 2331 GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION); 2332 cleanup_handshake_secrets (kx); 2333 if (NULL != kx->resend_task) 2334 GNUNET_SCHEDULER_cancel (kx->resend_task); 2335 kx->resend_task = NULL; 2336 if (NULL != kx->resend_env) 2337 GNUNET_free (kx->resend_env); 2338 kx->resend_env = NULL; 2339 monitor_notify_all (kx); 2340 } 2341 update_timeout (kx); 2342 2343 return GNUNET_YES; 2344 } 2345 2346 2347 /** 2348 * handle an encrypted message 2349 * @param cls key exchange info 2350 * @param m encrypted message 2351 */ 2352 static void 2353 handle_encrypted_message (void *cls, const struct EncryptedMessage *m) 2354 { 2355 struct GSC_KeyExchangeInfo *kx = cls; 2356 uint16_t size = ntohs (m->header.size); 2357 char buf[size - sizeof (*m)] GNUNET_ALIGN; 2358 unsigned char seq_enc_k[crypto_stream_chacha20_ietf_KEYBYTES]; 2359 const unsigned char *seq_enc_nonce; 2360 unsigned char enc_key[AEAD_KEY_BYTES]; 2361 unsigned char enc_nonce[AEAD_NONCE_BYTES]; 2362 struct GNUNET_ShortHashCode new_ats[MAX_EPOCHS]; 2363 uint32_t seq_enc_ctr; 2364 uint64_t epoch; 2365 uint64_t m_seq; 2366 uint64_t m_seq_nbo; 2367 uint64_t c_len; 2368 int8_t ret; 2369 2370 // TODO look at handle_encrypted 2371 // - statistics 2372 2373 if ((kx->status != GNUNET_CORE_KX_STATE_RESPONDER_CONNECTED) && 2374 (kx->status != GNUNET_CORE_KX_STATE_INITIATOR_CONNECTED) && 2375 (kx->status != GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT)) 2376 { 2377 GSC_SESSIONS_end (&kx->peer); 2378 kx->status = GNUNET_CORE_KX_STATE_DOWN; 2379 monitor_notify_all (kx); 2380 restart_kx (kx); 2381 return; 2382 } 2383 update_timeout (kx); 2384 epoch = GNUNET_ntohll (m->epoch); 2385 /** 2386 * Derive temporarily as we want to discard on 2387 * decryption failure(s) 2388 */ 2389 memcpy (new_ats, 2390 kx->their_ats, 2391 MAX_EPOCHS * sizeof (struct GNUNET_ShortHashCode)); 2392 // FIXME here we could introduce logic that sends heartbeats 2393 // with key update request if we have not seen a new 2394 // epoch after a while (e.g. EPOCH_EXPIRATION) 2395 if (kx->their_max_epoch < epoch) 2396 { 2397 /** 2398 * Prevent DoS 2399 * FIXME maybe requires its own limit. 2400 */ 2401 if ((epoch - kx->their_max_epoch) > 2 * MAX_EPOCHS) 2402 { 2403 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2404 "Epoch %" PRIu64 " is too new, will not decrypt...\n", 2405 epoch); 2406 GSC_SESSIONS_end (&kx->peer); 2407 kx->status = GNUNET_CORE_KX_STATE_DOWN; 2408 monitor_notify_all (kx); 2409 restart_kx (kx); 2410 return; 2411 } 2412 for (int i = kx->their_max_epoch; i < epoch; i++) 2413 { 2414 derive_next_ats (&new_ats[i % MAX_EPOCHS], 2415 &new_ats[(i + 1) % MAX_EPOCHS]); 2416 } 2417 } 2418 else if ((kx->their_max_epoch - epoch) > MAX_EPOCHS) 2419 { 2420 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2421 "Epoch %" PRIu64 " is too old, cannot decrypt...\n", 2422 epoch); 2423 return; 2424 } 2425 derive_sn ( 2426 &new_ats[epoch % MAX_EPOCHS], 2427 seq_enc_k, 2428 sizeof seq_enc_k); 2429 /* compute the sequence number */ 2430 seq_enc_ctr = *((uint32_t*) m->tag); 2431 seq_enc_nonce = &m->tag[sizeof (uint32_t)]; 2432 #if DEBUG_KX 2433 GNUNET_print_bytes (&new_ats[epoch % MAX_EPOCHS], 2434 sizeof (struct GNUNET_ShortHashCode), 2435 8, 2436 GNUNET_NO); 2437 GNUNET_print_bytes (seq_enc_k, 2438 sizeof seq_enc_k, 2439 8, 2440 GNUNET_NO); 2441 GNUNET_print_bytes ((char*) &seq_enc_ctr, 2442 sizeof seq_enc_ctr, 2443 8, 2444 GNUNET_NO); 2445 #endif 2446 crypto_stream_chacha20_ietf_xor_ic ( 2447 (unsigned char*) &m_seq_nbo, 2448 (unsigned char*) &m->sequence_number, 2449 sizeof (uint64_t), 2450 seq_enc_nonce, 2451 ntohl (seq_enc_ctr), 2452 seq_enc_k); 2453 m_seq = GNUNET_ntohll (m_seq_nbo); 2454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2455 "Received encrypted message in epoch %" PRIu64 2456 " with E(SQN=%" PRIu64 ")=%" PRIu64 2457 "\n", 2458 epoch, 2459 m_seq, 2460 m->sequence_number); 2461 /* We are the initiator and as we are going to receive, 2462 * we are using the responder key material */ 2463 derive_per_message_secrets (&new_ats[epoch], 2464 m_seq, 2465 enc_key, 2466 enc_nonce); 2467 // TODO checking sequence numbers - handle the case of out-of-sync messages! 2468 // for now only decrypt the payload 2469 // TODO encrypt other fields, too! 2470 // TODO 2471 // c_len = size - offsetof (); 2472 c_len = size - sizeof (struct EncryptedMessage); 2473 ret = crypto_aead_xchacha20poly1305_ietf_decrypt_detached ( 2474 (unsigned char*) buf, // m - plain message 2475 NULL, // nsec - unused 2476 (unsigned char*) &m[1], // c - ciphertext 2477 c_len, // clen 2478 (const unsigned char*) &m->tag, // mac 2479 NULL, // ad - additional data TODO 2480 0, // adlen 2481 enc_nonce, // npub 2482 enc_key // k 2483 ); 2484 if (0 != ret) 2485 { 2486 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2487 "Something went wrong decrypting message\n"); 2488 GNUNET_break_op (0); // FIXME handle gracefully 2489 return; 2490 } 2491 kx->their_max_epoch = epoch; 2492 memcpy (&kx->their_ats, 2493 new_ats, 2494 MAX_EPOCHS * sizeof (struct GNUNET_ShortHashCode)); 2495 2496 if (GNUNET_NO == check_if_ack_or_heartbeat (kx, 2497 buf, 2498 sizeof buf)) 2499 { 2500 if (kx->status == GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT) 2501 { 2502 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2503 "Dropping message as we are still waiting for handshake ACK\n"); 2504 GNUNET_break_op (0); 2505 return; 2506 } 2507 if (GNUNET_OK != 2508 GNUNET_MST_from_buffer (kx->mst, 2509 buf, 2510 sizeof buf, 2511 GNUNET_YES, 2512 GNUNET_NO)) 2513 GNUNET_break_op (0); 2514 } 2515 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer); 2516 } 2517 2518 2519 /** 2520 * Function called by transport telling us that a peer 2521 * disconnected. 2522 * Stop key exchange with the given peer. Clean up key material. 2523 * 2524 * @param cls closure 2525 * @param peer the peer that disconnected 2526 * @param handler_cls the `struct GSC_KeyExchangeInfo` of the peer 2527 */ 2528 static void 2529 handle_transport_notify_disconnect (void *cls, 2530 const struct GNUNET_PeerIdentity *peer, 2531 void *handler_cls) 2532 { 2533 struct GSC_KeyExchangeInfo *kx = handler_cls; 2534 (void) cls; 2535 2536 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2537 "Peer `%s' disconnected from us.\n", 2538 GNUNET_i2s (&kx->peer)); 2539 GSC_SESSIONS_end (&kx->peer); 2540 GNUNET_STATISTICS_update (GSC_stats, 2541 gettext_noop ("# key exchanges stopped"), 2542 1, 2543 GNUNET_NO); 2544 if (NULL != kx->resend_task) 2545 { 2546 GNUNET_SCHEDULER_cancel (kx->resend_task); 2547 kx->resend_task = NULL; 2548 } 2549 if (NULL != kx->resend_env) 2550 { 2551 GNUNET_free (kx->resend_env); 2552 kx->resend_env = NULL; 2553 } 2554 if (NULL != kx->heartbeat_task) 2555 { 2556 GNUNET_SCHEDULER_cancel (kx->heartbeat_task); 2557 kx->heartbeat_task = NULL; 2558 } 2559 kx->status = GNUNET_CORE_KX_PEER_DISCONNECT; 2560 monitor_notify_all (kx); 2561 if (kx->transcript_hash_ctx) 2562 { 2563 GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx); 2564 kx->transcript_hash_ctx = NULL; 2565 } 2566 GNUNET_CONTAINER_DLL_remove (kx_head, kx_tail, kx); 2567 GNUNET_MST_destroy (kx->mst); 2568 GNUNET_free (kx); 2569 } 2570 2571 2572 static void 2573 resend_initiator_hello (void *cls) 2574 { 2575 struct GSC_KeyExchangeInfo *kx = cls; 2576 2577 kx->resend_task = NULL; 2578 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2579 "Resending InitiatorHello.\n"); 2580 GNUNET_MQ_send_copy (kx->mq, kx->resend_env); 2581 // FIXME (Exponential) backoff? 2582 kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT, 2583 &resend_initiator_hello, 2584 kx); 2585 } 2586 2587 2588 /** 2589 * Send initiator hello 2590 * 2591 * @param kx key exchange context 2592 */ 2593 static void 2594 send_initiator_hello (struct GSC_KeyExchangeInfo *kx) 2595 { 2596 const struct GNUNET_PeerIdentity *my_identity; 2597 struct GNUNET_MQ_Envelope *env; 2598 struct GNUNET_ShortHashCode es; 2599 struct GNUNET_ShortHashCode ets; 2600 struct GNUNET_ShortHashCode ss_R; 2601 struct InitiatorHelloPayload *ihmp; /* initiator hello message - buffer on stack */ 2602 struct InitiatorHello *ihm_e; /* initiator hello message - encrypted */ 2603 long long unsigned int c_len; 2604 unsigned char enc_key[AEAD_KEY_BYTES]; 2605 unsigned char enc_nonce[AEAD_NONCE_BYTES]; 2606 enum GNUNET_GenericReturnValue ret; 2607 size_t pt_len; 2608 2609 my_identity = GNUNET_PILS_get_identity (GSC_pils); 2610 GNUNET_assert (NULL != my_identity); 2611 2612 pt_len = sizeof (*ihmp) + strlen (my_services_info); 2613 c_len = pt_len + AEAD_TAG_BYTES; 2614 env = GNUNET_MQ_msg_extra (ihm_e, 2615 c_len, 2616 GNUNET_MESSAGE_TYPE_CORE_INITIATOR_HELLO); 2617 ihmp = (struct InitiatorHelloPayload*) &ihm_e[1]; 2618 ihmp->peer_class = htons (GNUNET_CORE_CLASS_UNKNOWN); // TODO set this to a meaningful 2619 GNUNET_memcpy (&ihmp->pk_I, 2620 my_identity, 2621 sizeof (struct GNUNET_PeerIdentity)); 2622 GNUNET_CRYPTO_hash (&kx->peer, /* what to hash */ // TODO do we do this twice? 2623 sizeof (struct GNUNET_PeerIdentity), 2624 &ihm_e->h_pk_R); /* result */ 2625 // TODO init hashcontext/transcript_hash 2626 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send InitiatorHello: %d %d\n", kx->role, 2627 kx->status); 2628 GNUNET_assert (NULL == kx->transcript_hash_ctx); 2629 kx->transcript_hash_ctx = GNUNET_CRYPTO_hash_context_start (); 2630 GNUNET_assert (NULL != kx->transcript_hash_ctx); 2631 // TODO fill services_info 2632 2633 // 1. Encaps 2634 ret = GNUNET_CRYPTO_eddsa_kem_encaps (&kx->peer.public_key, // public ephemeral key of initiator 2635 &ihm_e->c_R, // encapsulated key 2636 &ss_R); // key - ss_R 2637 if (GNUNET_OK != ret) 2638 { 2639 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2640 "Something went wrong encapsulating ss_R\n"); 2641 // TODO handle 2642 } 2643 // 2. generate rR (uint64_t) - is this the nonce? Naming seems not quite 2644 // consistent 2645 ihm_e->r_I = 2646 GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, 2647 UINT64_MAX); 2648 // 3. generate sk_e/pk_e - ephemeral key 2649 GNUNET_CRYPTO_ecdhe_key_create (&kx->sk_e.ecdhe_key); 2650 GNUNET_CRYPTO_ecdhe_key_get_public ( 2651 &kx->sk_e.ecdhe_key, 2652 &kx->pk_e.ecdhe_key); 2653 GNUNET_memcpy (&ihm_e->pk_e, 2654 &kx->pk_e.ecdhe_key, 2655 sizeof (kx->pk_e.ecdhe_key)); 2656 // 4. generate ETS to encrypt 2657 // generate ETS (early_traffic_secret_key, decrypt pk_i 2658 // expand ETS <- expand ES <- extract ss_R 2659 // use ETS to decrypt 2660 GNUNET_CRYPTO_hash_context_read (kx->transcript_hash_ctx, 2661 ihm_e, 2662 sizeof (struct InitiatorHello)); 2663 { 2664 struct GNUNET_HashCode transcript; 2665 snapshot_transcript (kx->transcript_hash_ctx, 2666 &transcript); 2667 derive_es_ets (&transcript, 2668 &ss_R, 2669 &es, 2670 &ets); 2671 derive_per_message_secrets (&ets, 2672 0, 2673 enc_key, 2674 enc_nonce); 2675 } 2676 // 5. encrypt 2677 2678 ret = crypto_aead_xchacha20poly1305_ietf_encrypt ( 2679 (unsigned char*) &ihm_e[1], /* c - ciphertext */ 2680 // mac, 2681 // NULL, // maclen_p 2682 &c_len, /* clen_p */ 2683 (unsigned char*) ihmp, /* m - plaintext message */ 2684 pt_len, // mlen 2685 NULL, 0, // ad, adlen // FIXME maybe over the unencrypted header? 2686 // fields? 2687 NULL, // nsec - unused 2688 enc_nonce, // npub - nonce 2689 enc_key); // k - key 2690 if (0 != ret) 2691 { 2692 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong encrypting\n"); 2693 GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx); 2694 kx->transcript_hash_ctx = NULL; 2695 GNUNET_MQ_discard (env); 2696 return; 2697 } 2698 /* Forward the transcript */ 2699 GNUNET_CRYPTO_hash_context_read ( 2700 kx->transcript_hash_ctx, 2701 &ihm_e[1], 2702 c_len); 2703 2704 kx->status = GNUNET_CORE_KX_STATE_INITIATOR_HELLO_SENT; 2705 kx->early_secret_key = es; 2706 kx->early_traffic_secret = ets; 2707 kx->ss_R = ss_R; 2708 monitor_notify_all (kx); 2709 GNUNET_MQ_send_copy (kx->mq, env); 2710 kx->resend_env = env; 2711 kx->resend_tries_left = RESEND_MAX_TRIES; 2712 kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT, 2713 &resend_initiator_hello, 2714 kx); 2715 } 2716 2717 2718 static void 2719 check_rekey (struct GSC_KeyExchangeInfo *kx) 2720 { 2721 struct GNUNET_ShortHashCode new_ats; 2722 2723 if ((UINT64_MAX == kx->current_sqn) || 2724 (GNUNET_TIME_absolute_is_past (kx->current_epoch_expiration))) 2725 { 2726 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2727 "Epoch expiration %" PRIu64 " SQN %" PRIu64 2728 ", incrementing epoch...\n", 2729 kx->current_epoch_expiration.abs_value_us, 2730 kx->current_sqn); 2731 // Can this trigger? Maybe if we receive a lot of 2732 // heartbeats? 2733 GNUNET_assert (UINT64_MAX > kx->current_epoch); 2734 kx->current_epoch++; 2735 kx->current_epoch_expiration = 2736 GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION); 2737 kx->current_sqn = 0; 2738 derive_next_ats (&kx->current_ats, 2739 &new_ats); 2740 memcpy (&kx->current_ats, 2741 &new_ats, 2742 sizeof new_ats); 2743 } 2744 } 2745 2746 2747 /** 2748 * Encrypt and transmit payload 2749 * @param kx key exchange info 2750 * @param payload the payload 2751 * @param payload_size size of the payload 2752 */ 2753 void 2754 GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx, 2755 const void *payload, 2756 size_t payload_size) 2757 { 2758 struct GNUNET_MQ_Envelope *env; 2759 struct EncryptedMessage *encrypted_msg; 2760 unsigned char enc_key[AEAD_KEY_BYTES]; 2761 unsigned char enc_nonce[AEAD_NONCE_BYTES]; 2762 unsigned char seq_enc_k[crypto_stream_chacha20_ietf_KEYBYTES]; 2763 uint64_t sqn; 2764 uint64_t epoch; 2765 int8_t ret; 2766 2767 encrypted_msg = NULL; 2768 2769 check_rekey (kx); 2770 sqn = kx->current_sqn; 2771 epoch = kx->current_epoch; 2772 /* We are the sender and as we are going to send, 2773 * we are using the initiator key material */ 2774 derive_per_message_secrets (&kx->current_ats, 2775 sqn, 2776 enc_key, 2777 enc_nonce); 2778 kx->current_sqn++; 2779 derive_sn (&kx->current_ats, 2780 seq_enc_k, 2781 sizeof seq_enc_k); 2782 env = GNUNET_MQ_msg_extra (encrypted_msg, 2783 payload_size, 2784 GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE_CAKE); 2785 // only encrypt the payload for now 2786 // TODO encrypt other fields as well 2787 ret = crypto_aead_xchacha20poly1305_ietf_encrypt_detached ( 2788 (unsigned char*) &encrypted_msg[1], // c - resulting ciphertext 2789 (unsigned char*) &encrypted_msg->tag, // mac - resulting mac/tag 2790 NULL, // maclen 2791 (unsigned char*) payload, // m - plain message 2792 payload_size, // mlen 2793 NULL, // ad - additional data TODO also cover the unencrypted part (epoch) 2794 0, // adlen 2795 NULL, // nsec - unused 2796 enc_nonce, // npub nonce 2797 enc_key // k - key 2798 ); 2799 if (0 != ret) 2800 { 2801 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2802 "Something went wrong encrypting message\n"); 2803 GNUNET_assert (0); 2804 } 2805 { 2806 /* compute the sequence number */ 2807 unsigned char *seq_enc_nonce; 2808 uint64_t seq_nbo; 2809 uint32_t seq_enc_ctr; 2810 2811 seq_nbo = GNUNET_htonll (sqn); 2812 seq_enc_ctr = *((uint32_t*) encrypted_msg->tag); 2813 seq_enc_nonce = &encrypted_msg->tag[sizeof (uint32_t)]; 2814 crypto_stream_chacha20_ietf_xor_ic ( 2815 (unsigned char*) &encrypted_msg->sequence_number, 2816 (unsigned char*) &seq_nbo, 2817 sizeof seq_nbo, 2818 seq_enc_nonce, 2819 ntohl (seq_enc_ctr), 2820 seq_enc_k); 2821 #if DEBUG_KX 2822 GNUNET_print_bytes (seq_enc_k, 2823 sizeof seq_enc_k, 2824 8, 2825 GNUNET_NO); 2826 GNUNET_print_bytes ((char*) &seq_enc_ctr, 2827 sizeof seq_enc_ctr, 2828 8, 2829 GNUNET_NO); 2830 #endif 2831 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2832 "Sending encrypted message with E(SQN=%" PRIu64 ")=%" PRIu64 2833 "\n", 2834 sqn, 2835 encrypted_msg->sequence_number); 2836 } 2837 encrypted_msg->epoch = GNUNET_htonll (epoch); 2838 2839 // TODO actually copy payload 2840 GNUNET_MQ_send (kx->mq, env); 2841 } 2842 2843 2844 void 2845 GSC_KX_start (void) 2846 { 2847 const struct GNUNET_PeerIdentity *my_identity; 2848 struct GNUNET_MQ_MessageHandler handlers[] = { 2849 GNUNET_MQ_hd_var_size (initiator_hello, 2850 GNUNET_MESSAGE_TYPE_CORE_INITIATOR_HELLO, 2851 struct InitiatorHello, 2852 NULL), 2853 GNUNET_MQ_hd_var_size (initiator_done, 2854 GNUNET_MESSAGE_TYPE_CORE_INITIATOR_DONE, 2855 struct InitiatorDone, 2856 NULL), 2857 GNUNET_MQ_hd_var_size (responder_hello, 2858 GNUNET_MESSAGE_TYPE_CORE_RESPONDER_HELLO, 2859 struct ResponderHello, 2860 NULL), 2861 GNUNET_MQ_hd_var_size (encrypted_message, // TODO rename? 2862 GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE_CAKE, // TODO rename! 2863 struct EncryptedMessage, 2864 NULL), 2865 GNUNET_MQ_handler_end () 2866 }; 2867 2868 my_identity = GNUNET_PILS_get_identity (GSC_pils); 2869 GNUNET_assert (NULL != my_identity); 2870 2871 nc = GNUNET_notification_context_create (1); 2872 transport = 2873 GNUNET_TRANSPORT_core_connect (GSC_cfg, 2874 my_identity, 2875 handlers, 2876 NULL, // cls - this connection-independant 2877 // cls seems not to be needed. 2878 // the connection-specific cls 2879 // will be set as a return value 2880 // of 2881 // handle_transport_notify_connect 2882 &handle_transport_notify_connect, 2883 &handle_transport_notify_disconnect); 2884 if (NULL == transport) 2885 { 2886 GSC_KX_done (); 2887 return; 2888 } 2889 2890 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2891 "Connected to TRANSPORT\n"); 2892 2893 GSC_complete_initialization_cb (); 2894 } 2895 2896 2897 void 2898 pid_change_cb (void *cls, 2899 const struct GNUNET_HELLO_Parser *parser, 2900 const struct GNUNET_HashCode *hash) 2901 { 2902 if (NULL != transport) 2903 return; 2904 2905 GSC_KX_start (); 2906 } 2907 2908 2909 /** 2910 * Initialize KX subsystem. 2911 * 2912 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure 2913 */ 2914 int 2915 GSC_KX_init (void) 2916 { 2917 GSC_pils = GNUNET_PILS_connect (GSC_cfg, 2918 &pid_change_cb, 2919 NULL); 2920 if (NULL == GSC_pils) 2921 { 2922 GSC_KX_done (); 2923 return GNUNET_SYSERR; 2924 } 2925 2926 return GNUNET_OK; 2927 } 2928 2929 2930 /** 2931 * Shutdown KX subsystem. 2932 */ 2933 void 2934 GSC_KX_done () 2935 { 2936 struct PilsRequest *pr; 2937 while (NULL != (pr = pils_requests_head)) 2938 { 2939 GNUNET_CONTAINER_DLL_remove (pils_requests_head, 2940 pils_requests_tail, 2941 pr); 2942 if (NULL != pr->op) 2943 GNUNET_PILS_cancel (pr->op); 2944 GNUNET_free (pr); 2945 } 2946 if (NULL != GSC_pils) 2947 { 2948 GNUNET_PILS_disconnect (GSC_pils); 2949 GSC_pils = NULL; 2950 } 2951 if (NULL != transport) 2952 { 2953 GNUNET_TRANSPORT_core_disconnect (transport); 2954 transport = NULL; 2955 } 2956 if (NULL != rekey_task) 2957 { 2958 GNUNET_SCHEDULER_cancel (rekey_task); 2959 rekey_task = NULL; 2960 } 2961 if (NULL != nc) 2962 { 2963 GNUNET_notification_context_destroy (nc); 2964 nc = NULL; 2965 } 2966 } 2967 2968 2969 /** 2970 * Check how many messages are queued for the given neighbour. 2971 * 2972 * @param kxinfo data about neighbour to check 2973 * @return number of items in the message queue 2974 */ 2975 unsigned int 2976 GSC_NEIGHBOURS_get_queue_length (const struct GSC_KeyExchangeInfo *kxinfo) 2977 { 2978 return GNUNET_MQ_get_length (kxinfo->mq); 2979 } 2980 2981 2982 int 2983 GSC_NEIGHBOURS_check_excess_bandwidth (const struct GSC_KeyExchangeInfo *kxinfo) 2984 { 2985 return kxinfo->has_excess_bandwidth; 2986 } 2987 2988 2989 /** 2990 * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request. For this 2991 * request type, the client does not have to have transmitted an INIT 2992 * request. All current peers are returned, regardless of which 2993 * message types they accept. 2994 * 2995 * @param mq message queue to add for monitoring 2996 */ 2997 void 2998 GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq) 2999 { 3000 struct GNUNET_MQ_Envelope *env; 3001 struct MonitorNotifyMessage *done_msg; 3002 struct GSC_KeyExchangeInfo *kx; 3003 3004 GNUNET_notification_context_add (nc, mq); 3005 for (kx = kx_head; NULL != kx; kx = kx->next) 3006 { 3007 struct GNUNET_MQ_Envelope *env_notify; 3008 struct MonitorNotifyMessage *msg; 3009 3010 env_notify = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY); 3011 msg->state = htonl ((uint32_t) kx->status); 3012 msg->peer = kx->peer; 3013 msg->timeout = GNUNET_TIME_absolute_hton (kx->timeout); 3014 GNUNET_MQ_send (mq, env_notify); 3015 } 3016 env = GNUNET_MQ_msg (done_msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY); 3017 done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED); 3018 done_msg->timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS); 3019 GNUNET_MQ_send (mq, env); 3020 } 3021 3022 3023 /* end of gnunet-service-core_kx.c */