gnunet-service-core_kx.c (96590B)
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 "platform.h" 38 #include "gnunet_common.h" 39 #include "gnunet_util_lib.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 (UINT64_MAX); 1239 1240 // c_e 1241 GNUNET_memcpy (&rhm_e->c_e, 1242 &ephemeral_kem_challenge, 1243 sizeof (ephemeral_kem_challenge)); 1244 GNUNET_CRYPTO_hash_context_read (hc, 1245 rhm_e, 1246 sizeof (struct ResponderHello)); 1247 // 2. Encrypt ServicesInfo and c_I with RHTS 1248 // derive RHTS 1249 { 1250 struct GNUNET_HashCode transcript; 1251 snapshot_transcript (hc, 1252 &transcript); 1253 #if DEBUG_KX 1254 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1255 "Transcript snapshot for derivation of *HTS: `%s'\n", 1256 GNUNET_h2s (&transcript)); 1257 #endif 1258 derive_rhts (&transcript, 1259 &hs, 1260 &rhts); 1261 derive_ihts (&transcript, 1262 &hs, 1263 &ihts); 1264 derive_per_message_secrets (&rhts, 1265 0, 1266 enc_key, 1267 enc_nonce); 1268 } 1269 // c_I 1270 GNUNET_memcpy (&rhp->c_I, &c_I, sizeof (c_I)); 1271 // Services info empty for now. 1272 GNUNET_memcpy (&rhp[1], 1273 my_services_info, 1274 strlen (my_services_info)); 1275 1276 { 1277 unsigned long long out_ct_len; 1278 struct GNUNET_HashCode finished; 1279 struct GNUNET_HashCode transcript; 1280 unsigned char *finished_buf; 1281 GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt ( 1282 (unsigned char*) &rhm_e[1], /* c - ciphertext */ 1283 &out_ct_len, /* clen_p */ 1284 rhp_buf, /* rhm_p - plaintext message */ 1285 rhp_len, // mlen 1286 NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted 1287 // fields? 1288 NULL, // nsec - unused 1289 enc_nonce, // npub - nonce // FIXME nonce can be reused 1290 enc_key)); // k - key RHTS 1291 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1292 "Encrypted and wrote %llu bytes\n", 1293 out_ct_len); 1294 // 3. Create ResponderFinished (Section 6) 1295 // Derive fk_I <- HKDF-Expand (MS, "r finished", NULL) 1296 /* Forward the transcript */ 1297 /* {svcinfo, c_I}RHTS */ 1298 GNUNET_CRYPTO_hash_context_read ( 1299 hc, 1300 &rhm_e[1], 1301 out_ct_len); 1302 1303 finished_buf = ((unsigned char*) &rhm_e[1]) + out_ct_len; 1304 snapshot_transcript (hc, 1305 &transcript); 1306 #if DEBUG_KX 1307 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1308 "Transcript snapshot for derivation of Rfinished: `%s'\n", 1309 GNUNET_h2s (&transcript)); 1310 #endif 1311 generate_responder_finished (&transcript, 1312 &ms, 1313 &finished); 1314 // 4. Encrypt ResponderFinished 1315 derive_per_message_secrets (&rhts, 1316 1, 1317 enc_key, 1318 enc_nonce); 1319 GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt ( 1320 finished_buf, /* c - ciphertext */ 1321 &out_ct_len, /* clen_p */ 1322 (unsigned char*) &finished, /* rhm_p - plaintext message */ 1323 sizeof (finished), // mlen 1324 NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted 1325 // fields? 1326 NULL, // nsec - unused 1327 enc_nonce, // npub 1328 enc_key)); // k - key RHTS 1329 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1330 "Encrypted and wrote %llu bytes\n", 1331 out_ct_len); 1332 /* Forward the transcript 1333 * after responder finished, 1334 * before deriving *ATS and generating finished_I 1335 * (finished_I will be generated when receiving the InitiatorFinished message 1336 * in order to check it) */ 1337 GNUNET_CRYPTO_hash_context_read ( 1338 hc, 1339 finished_buf, 1340 out_ct_len); 1341 // 5. optionally send application data - encrypted with RATS 1342 // We do not really have any application data, instead, we send the ACK 1343 snapshot_transcript (hc, 1344 &transcript); 1345 #if DEBUG_KX 1346 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1347 "Transcript snapshot for derivation of *ATS: `%s'\n", 1348 GNUNET_h2s (&transcript)); 1349 #endif 1350 derive_initial_ats (&transcript, 1351 &ms, 1352 ROLE_RESPONDER, 1353 &kx->current_ats); 1354 } 1355 /* Lock into struct */ 1356 GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx); 1357 kx->transcript_hash_ctx = hc; 1358 kx->master_secret = ms; 1359 kx->handshake_secret = hs; 1360 kx->ss_e = ss_e; 1361 kx->ihts = ihts; 1362 kx->rhts = rhts; 1363 kx->ss_I = ss_I; 1364 kx->current_epoch = 0; 1365 kx->current_sqn = 0; 1366 derive_per_message_secrets (&kx->current_ats, 1367 kx->current_sqn, 1368 enc_key, 1369 enc_nonce); 1370 1371 GNUNET_MQ_send_copy (kx->mq, env); 1372 kx->resend_env = env; 1373 kx->resend_tries_left = RESEND_MAX_TRIES; 1374 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent ResponderHello: %d %d\n", kx->role, 1375 kx->status); 1376 1377 kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT, 1378 &resend_responder_hello, 1379 kx); 1380 kx->status = GNUNET_CORE_KX_STATE_RESPONDER_HELLO_SENT; 1381 monitor_notify_all (kx); 1382 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer); 1383 } 1384 1385 1386 static void 1387 handle_initiator_hello_cont (void *cls, const struct GNUNET_ShortHashCode *ss_R) 1388 { 1389 const struct GNUNET_HashCode *my_identity_hash; 1390 struct InitiatorHelloCtx *ihm_ctx = cls; 1391 struct GSC_KeyExchangeInfo *kx = ihm_ctx->kx; 1392 uint32_t ihm_len = ntohs (ihm_ctx->ihm_e->header.size); 1393 unsigned char enc_key[AEAD_KEY_BYTES]; 1394 unsigned char enc_nonce[AEAD_NONCE_BYTES]; 1395 struct GNUNET_HashCode h1; 1396 struct GNUNET_HashCode transcript; 1397 struct GNUNET_ShortHashCode es; 1398 struct GNUNET_ShortHashCode ets; 1399 enum GNUNET_GenericReturnValue ret; 1400 1401 ihm_ctx->req->op = NULL; 1402 GNUNET_CONTAINER_DLL_remove (pils_requests_head, 1403 pils_requests_tail, 1404 ihm_ctx->req); 1405 GNUNET_free (ihm_ctx->req); 1406 1407 1408 GNUNET_memcpy (&kx->pk_e.ecdhe_key, 1409 &ihm_ctx->ihm_e->pk_e, 1410 sizeof (ihm_ctx->ihm_e->pk_e)); 1411 // 5. generate ETS (early_traffic_secret_key, decrypt pk_i 1412 // expand ETS <- expand ES <- extract ss_R 1413 // use ETS to decrypt 1414 1415 /* Forward the transcript hash context over the unencrypted fields to get it 1416 * to the same status that the initiator had when it needed to derive es and 1417 * ets for the encryption */ 1418 GNUNET_CRYPTO_hash_context_read ( 1419 kx->transcript_hash_ctx, 1420 ihm_ctx->ihm_e, 1421 sizeof (struct InitiatorHello)); 1422 snapshot_transcript (kx->transcript_hash_ctx, 1423 &transcript); 1424 #if DEBUG_KX 1425 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1426 "Transcript snapshot for derivation of ES, ETS: `%s'\n", 1427 GNUNET_h2s (&transcript)); 1428 #endif 1429 derive_es_ets (&transcript, ss_R, &es, &ets); 1430 derive_per_message_secrets (&ets, 1431 0, 1432 enc_key, 1433 enc_nonce); 1434 { 1435 struct InitiatorHelloPayload *ihmp; 1436 size_t ct_len = ihm_len - sizeof (struct InitiatorHello); 1437 unsigned char ihmp_buf[ct_len - AEAD_TAG_BYTES]; 1438 ihmp = (struct InitiatorHelloPayload*) ihmp_buf; 1439 ret = crypto_aead_xchacha20poly1305_ietf_decrypt ( 1440 ihmp_buf, // unsigned char *m 1441 NULL, // mlen_p message length 1442 NULL, // unsigned char *nsec - unused: NULL 1443 (unsigned char*) &ihm_ctx->ihm_e[1], // const unsigned char *c - ciphertext 1444 ct_len, // unsigned long long clen - length of ciphertext 1445 // mac, // const unsigned char *mac - authentication tag 1446 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right? 1447 0, // unsigned long long adlen 1448 enc_nonce, // const unsigned char *npub - nonce 1449 enc_key // const unsigned char *k - key 1450 ); 1451 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pid_sender: %s\n", 1452 GNUNET_i2s (&ihmp->pk_I)); 1453 if (0 != ret) 1454 { 1455 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1456 "Something went wrong decrypting: %d\n", ret); 1457 GNUNET_break_op (0); 1458 GNUNET_free (ihm_ctx->ihm_e); 1459 GNUNET_free (ihm_ctx); 1460 restart_kx (kx); 1461 return; 1462 } 1463 /* now forward it considering the encrypted messages that the initiator was 1464 * able to send after deriving the es and ets */ 1465 GNUNET_CRYPTO_hash_context_read (kx->transcript_hash_ctx, 1466 &ihm_ctx->ihm_e[1], 1467 ct_len); 1468 GNUNET_memcpy (&kx->peer, 1469 &ihmp->pk_I, 1470 sizeof (struct GNUNET_PeerIdentity)); 1471 } 1472 1473 my_identity_hash = GNUNET_PILS_get_identity_hash (GSC_pils); 1474 GNUNET_assert (NULL != my_identity_hash); 1475 1476 // We could follow with the rest of the Key Schedule (dES, HS, ...) for now 1477 /* Check that we are actually in the receiving role */ 1478 GNUNET_CRYPTO_hash (&kx->peer, sizeof(struct GNUNET_PeerIdentity), &h1); 1479 if (0 < GNUNET_CRYPTO_hash_cmp (&h1, my_identity_hash)) 1480 { 1481 /* peer with "lower" identity starts KX, otherwise we typically end up 1482 with both peers starting the exchange and transmit the 'set key' 1483 message twice */ 1484 /* Something went wrong - we have the lower value and should have sent the 1485 * InitiatorHello, but instead received it. TODO handle this case 1486 * We might end up in this case if the initiator didn't initiate the 1487 * handshake long enough and the 'responder' initiates the handshake */ 1488 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1489 "Something went wrong - we have the lower value and should have sent the InitiatorHello, but instead received it.\n"); 1490 GNUNET_free (ihm_ctx->ihm_e); 1491 GNUNET_free (ihm_ctx); 1492 GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx); 1493 kx->transcript_hash_ctx = NULL; 1494 return; 1495 } 1496 1497 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer ID of other peer: %s\n", GNUNET_i2s 1498 (&kx->peer)); 1499 /* We update the monitoring peers here because now we know 1500 * that we can decrypt the message AND know the PID 1501 */ 1502 monitor_notify_all (kx); 1503 kx->ss_R = *ss_R; 1504 kx->early_secret_key = es; 1505 kx->early_traffic_secret = ets; 1506 send_responder_hello (kx); 1507 } 1508 1509 1510 static int 1511 check_initiator_hello (void *cls, const struct InitiatorHello *m) 1512 { 1513 uint16_t size = ntohs (m->header.size); 1514 1515 if (size < sizeof (*m) 1516 + sizeof (struct InitiatorHelloPayload) 1517 + AEAD_TAG_BYTES) 1518 { 1519 return GNUNET_SYSERR; 1520 } 1521 return GNUNET_OK; 1522 } 1523 1524 1525 /** 1526 * Handle the InitiatorHello message 1527 * - derives necessary keys from the plaintext parts 1528 * - decrypts the encrypted part 1529 * - replies with ResponderHello message 1530 * @param cls the key exchange info 1531 * @param ihm_e InitiatorHello message 1532 */ 1533 static void 1534 handle_initiator_hello (void *cls, const struct InitiatorHello *ihm_e) 1535 { 1536 const struct GNUNET_HashCode *my_identity_hash; 1537 struct GSC_KeyExchangeInfo *kx = cls; 1538 struct InitiatorHelloCtx *initiator_hello_cls; 1539 size_t ihm_len; 1540 1541 if (ROLE_INITIATOR == kx->role) 1542 { 1543 GNUNET_break_op (0); 1544 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1545 "I am an initiator! Tearing down...\n"); 1546 return; 1547 } 1548 if (kx->status == GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED) 1549 { 1550 GNUNET_break_op (0); 1551 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1552 "Already received InitiatorHello: %d %d\n", kx->role, kx->status 1553 ); 1554 return; 1555 } 1556 else if ((kx->status > GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED) && 1557 (NULL != kx->transcript_hash_ctx)) 1558 { 1559 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1560 "Already received InitiatorHello and sent ResponderHello: %d %d\n", 1561 kx->role, kx->status); 1562 return; 1563 } 1564 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received InitiatorHello: %d %d\n", kx-> 1565 role, kx->status); 1566 GNUNET_assert (NULL == kx->transcript_hash_ctx); 1567 kx->transcript_hash_ctx = GNUNET_CRYPTO_hash_context_start (); 1568 GNUNET_assert (NULL != kx->transcript_hash_ctx); 1569 1570 GNUNET_STATISTICS_update (GSC_stats, 1571 gettext_noop ("# key exchanges initiated"), 1572 1, 1573 GNUNET_NO); 1574 1575 kx->status = GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED; 1576 1577 my_identity_hash = GNUNET_PILS_get_identity_hash (GSC_pils); 1578 GNUNET_assert (NULL != my_identity_hash); 1579 1580 // 1. verify type _INITIATOR_HELLO 1581 // - This is implicytly done by arriving within this handler 1582 // - or is this about verifying the 'additional data' part of aead? 1583 // should it check the encryption + mac? (is this implicitly done 1584 // while decrypting?) 1585 // 2. verify H(pk_R) matches pk_R 1586 if (0 != memcmp (&ihm_e->h_pk_R, 1587 my_identity_hash, 1588 sizeof (struct GNUNET_HashCode))) 1589 { 1590 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1591 "This message is not meant for us (H(PID) mismatch)\n"); 1592 GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx); 1593 kx->transcript_hash_ctx = NULL; 1594 return; 1595 } 1596 // FIXME this sometimes triggers in the tests - why? 1597 // 3. decaps -> shared_secret_R, c_R (kemChallenge) 1598 ihm_len = ntohs (ihm_e->header.size); 1599 initiator_hello_cls = GNUNET_new (struct InitiatorHelloCtx); 1600 initiator_hello_cls->kx = kx; 1601 initiator_hello_cls->ihm_e = GNUNET_malloc (ihm_len); 1602 GNUNET_memcpy (initiator_hello_cls->ihm_e, ihm_e, ihm_len); 1603 initiator_hello_cls->req = GNUNET_new (struct PilsRequest); 1604 GNUNET_CONTAINER_DLL_insert (pils_requests_head, 1605 pils_requests_tail, 1606 initiator_hello_cls->req); 1607 initiator_hello_cls->req->op = 1608 GNUNET_PILS_kem_decaps (GSC_pils, 1609 &ihm_e->c_R, 1610 // encapsulated key 1611 &handle_initiator_hello_cont, 1612 // continuation 1613 initiator_hello_cls); 1614 } 1615 1616 1617 struct ResponderHelloCls 1618 { 1619 /* Current KX session */ 1620 struct GSC_KeyExchangeInfo *kx; 1621 1622 /* responder hello message - encrypted */ 1623 struct ResponderHello rhm_e; 1624 1625 /* responder hello message - plain/decrypted */ 1626 struct ResponderHelloPayload *rhp; 1627 1628 /* Decrypted finish hash */ 1629 struct GNUNET_HashCode decrypted_finish; 1630 1631 /* Encrypted finished CT (for transcript later) */ 1632 char finished_enc[sizeof (struct GNUNET_HashCode) 1633 + AEAD_TAG_BYTES]; 1634 1635 /* Temporary transcript context */ 1636 struct GNUNET_HashContext *hc; 1637 1638 /* Temporary handshake secret */ 1639 struct GNUNET_ShortHashCode hs; 1640 1641 /* Temporary handshake secret */ 1642 struct GNUNET_ShortHashCode ss_e; 1643 1644 /* Temporary handshake secret */ 1645 struct GNUNET_ShortHashCode ihts; 1646 1647 /* Temporary handshake secret */ 1648 struct GNUNET_ShortHashCode rhts; 1649 1650 /* Pending PILS request */ 1651 struct PilsRequest *req; 1652 }; 1653 1654 static void 1655 resend_initiator_done (void *cls) 1656 { 1657 struct GSC_KeyExchangeInfo *kx = cls; 1658 1659 kx->resend_task = NULL; 1660 if (0 == kx->resend_tries_left) 1661 { 1662 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1663 "Restarting KX\n"); 1664 restart_kx (kx); 1665 return; 1666 } 1667 kx->resend_tries_left--; 1668 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1669 "Resending initiator done. Retries left: %u\n", 1670 kx->resend_tries_left); 1671 GNUNET_MQ_send_copy (kx->mq, kx->resend_env); 1672 kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT, 1673 &resend_initiator_done, 1674 kx); 1675 } 1676 1677 1678 static void 1679 handle_responder_hello_cont (void *cls, const struct GNUNET_ShortHashCode *ss_I) 1680 { 1681 struct ResponderHelloCls *rh_ctx = cls; 1682 struct GSC_KeyExchangeInfo *kx = rh_ctx->kx; 1683 struct InitiatorDone *idm_e; /* encrypted */ 1684 struct InitiatorDone idm_local; 1685 struct InitiatorDone *idm_p; /* plaintext */ 1686 struct GNUNET_MQ_Envelope *env; 1687 unsigned char enc_key[AEAD_KEY_BYTES]; 1688 unsigned char enc_nonce[AEAD_NONCE_BYTES]; 1689 struct ConfirmationAck ack_i; 1690 struct GNUNET_HashCode transcript; 1691 struct GNUNET_ShortHashCode ms; 1692 1693 rh_ctx->req->op = NULL; 1694 GNUNET_CONTAINER_DLL_remove (pils_requests_head, 1695 pils_requests_tail, 1696 rh_ctx->req); 1697 GNUNET_free (rh_ctx->req); 1698 // XXX valgrind reports uninitialized memory 1699 // the following is a way to check whether this memory was meant 1700 // memset (&rhm_local, 0, sizeof (rhm_local)); - adapt to cls if still needed 1701 memset (&idm_local, 0, sizeof (idm_local)); 1702 1703 kx->ss_I = *ss_I; 1704 1705 /* derive *ATS */ 1706 derive_ms (&rh_ctx->hs, ss_I, &ms);; 1707 // 5. Create ResponderFinished as per Section 6 and check against decrypted payload. 1708 struct GNUNET_HashCode responder_finished; 1709 // Transcript updates, snapshot again 1710 snapshot_transcript (rh_ctx->hc, 1711 &transcript); 1712 #if DEBUG_KX 1713 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1714 "Transcript snapshot for derivation of Rfinished: `%s'\n", 1715 GNUNET_h2s (&transcript)); 1716 #endif 1717 generate_responder_finished (&transcript, 1718 &ms, 1719 &responder_finished); 1720 if (0 != memcmp (&rh_ctx->decrypted_finish, 1721 &responder_finished, 1722 sizeof (struct GNUNET_HashCode))) 1723 { 1724 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1725 "Could not verify \"responder finished\"\n"); 1726 GNUNET_free (rh_ctx->rhp); 1727 GNUNET_CRYPTO_hash_context_abort (rh_ctx->hc); 1728 GNUNET_free (rh_ctx); 1729 GNUNET_assert (0); 1730 return; 1731 } 1732 1733 1734 /* Forward the transcript 1735 * after generating finished_R, 1736 * before deriving *ATS */ 1737 GNUNET_CRYPTO_hash_context_read ( 1738 rh_ctx->hc, 1739 rh_ctx->finished_enc, 1740 sizeof (rh_ctx->finished_enc)); 1741 1742 // At this point we cannot fail anymore and may lock into kx 1743 GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx); 1744 kx->transcript_hash_ctx = rh_ctx->hc; 1745 kx->ss_I = *ss_I; 1746 kx->handshake_secret = rh_ctx->hs; 1747 kx->ss_e = rh_ctx->ss_e; 1748 kx->ihts = rh_ctx->ihts; 1749 kx->rhts = rh_ctx->rhts; 1750 kx->master_secret = ms; 1751 GNUNET_free (rh_ctx->rhp); 1752 GNUNET_free (rh_ctx); 1753 rh_ctx = NULL; 1754 1755 snapshot_transcript (kx->transcript_hash_ctx, 1756 &transcript); 1757 #if DEBUG_KX 1758 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1759 "Transcript snapshot for derivation of *ATS: `%s'\n", 1760 GNUNET_h2s (&transcript)); 1761 #endif 1762 derive_initial_ats (&transcript, 1763 &kx->master_secret, 1764 ROLE_RESPONDER, 1765 &kx->their_ats[0]); 1766 for (int i = 0; i < MAX_EPOCHS - 1; i++) 1767 { 1768 derive_next_ats (&kx->their_ats[i], 1769 &kx->their_ats[i + 1]); 1770 } 1771 kx->their_max_epoch = MAX_EPOCHS - 1; 1772 1773 derive_per_message_secrets (&kx->ihts, 1774 0, 1775 enc_key, 1776 enc_nonce); 1777 /* Create InitiatorDone message */ 1778 idm_p = &idm_local; /* plaintext */ 1779 env = GNUNET_MQ_msg_extra (idm_e, 1780 sizeof (ack_i) 1781 + AEAD_TAG_BYTES, 1782 GNUNET_MESSAGE_TYPE_CORE_INITIATOR_DONE); 1783 // 6. Create IteratorFinished as per Section 6. 1784 generate_initiator_finished (&transcript, 1785 &kx->master_secret, 1786 &idm_p->finished); 1787 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1788 "InteratorFinished: `%s'\n", 1789 GNUNET_h2s (&idm_p->finished)); 1790 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1791 "Transcript `%s'\n", 1792 GNUNET_h2s (&transcript)); 1793 // 7. Send InteratorFinished message encrypted with the key derived from IHTS to R 1794 1795 GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt ( 1796 (unsigned char*) &idm_e->finished, /* c - ciphertext */ 1797 NULL, /* clen_p */ 1798 (unsigned char*) &idm_p->finished, /* idm_p - plaintext message */ 1799 sizeof (idm_p->finished), // mlen 1800 NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted 1801 // fields? 1802 NULL, // nsec - unused 1803 enc_nonce, // npub - nonce 1804 enc_key)); // k - key IHTS 1805 /* Forward the transcript hash context 1806 * after generating finished_I and RATS_0 1807 * before deriving IATS_0 */ 1808 GNUNET_CRYPTO_hash_context_read (kx->transcript_hash_ctx, 1809 &idm_e->finished, 1810 sizeof (idm_e->finished) 1811 + AEAD_TAG_BYTES); 1812 snapshot_transcript (kx->transcript_hash_ctx, 1813 &transcript); 1814 #if DEBUG_KX 1815 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1816 "Transcript snapshot for derivation of *ATS: `%s'\n", 1817 GNUNET_h2s (&transcript)); 1818 #endif 1819 derive_initial_ats (&transcript, 1820 &kx->master_secret, 1821 ROLE_INITIATOR, 1822 &kx->current_ats); 1823 kx->current_epoch = 0; 1824 kx->current_sqn++; 1825 // 8. optionally encrypt payload TODO 1826 derive_per_message_secrets (&kx->current_ats, 1827 kx->current_sqn, 1828 enc_key, 1829 enc_nonce); 1830 kx->current_sqn++; 1831 ack_i.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ACK); 1832 ack_i.header.size = htons (sizeof ack_i); 1833 GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt ( 1834 (unsigned char*) &idm_e[1], /* c - ciphertext */ 1835 NULL, /* clen_p */ 1836 (unsigned char*) &ack_i, /* rhm_p - plaintext message */ 1837 sizeof ack_i, // mlen 1838 NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted 1839 // fields? 1840 NULL, // nsec - unused 1841 enc_nonce, // npub - nonce // FIXME nonce can be reused 1842 enc_key)); // k - key RHTS 1843 1844 GNUNET_MQ_send_copy (kx->mq, env); 1845 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent InitiatorDone: %d %d\n", kx->role, 1846 kx->status); 1847 1848 1849 kx->resend_env = env; 1850 kx->resend_tries_left = RESEND_MAX_TRIES; 1851 kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT, 1852 &resend_initiator_done, 1853 kx); 1854 kx->status = GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT; 1855 monitor_notify_all (kx); 1856 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer); 1857 } 1858 1859 1860 static int 1861 check_responder_hello (void *cls, const struct ResponderHello *m) 1862 { 1863 uint16_t size = ntohs (m->header.size); 1864 1865 if (size < sizeof (*m) 1866 + sizeof (struct ResponderHelloPayload) 1867 + sizeof (struct GNUNET_HashCode) 1868 + AEAD_TAG_BYTES * 2) 1869 { 1870 return GNUNET_SYSERR; 1871 } 1872 return GNUNET_OK; 1873 } 1874 1875 1876 /** 1877 * Handle Responder Hello message 1878 * @param cls key exchange info 1879 * @param rhm_e ResponderHello message 1880 */ 1881 static void 1882 handle_responder_hello (void *cls, const struct ResponderHello *rhm_e) 1883 { 1884 struct GSC_KeyExchangeInfo *kx = cls; 1885 struct PilsRequest *req; 1886 struct ResponderHelloCls *rh_ctx; 1887 struct GNUNET_HashCode transcript; 1888 struct GNUNET_HashContext *hc; 1889 unsigned char enc_key[AEAD_KEY_BYTES]; 1890 unsigned char enc_nonce[AEAD_NONCE_BYTES]; 1891 enum GNUNET_GenericReturnValue ret; 1892 1893 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ResponderHello: %d %d\n", kx-> 1894 role, kx->status); 1895 1896 hc = GNUNET_CRYPTO_hash_context_copy (kx->transcript_hash_ctx); 1897 if (NULL != kx->resend_task) 1898 { 1899 GNUNET_SCHEDULER_cancel (kx->resend_task); 1900 kx->resend_task = NULL; 1901 } 1902 if (NULL != kx->resend_env) 1903 { 1904 GNUNET_free (kx->resend_env); 1905 kx->resend_env = NULL; 1906 } 1907 1908 /* Forward the transcript hash context */ 1909 if (ROLE_RESPONDER == kx->role) 1910 { 1911 GNUNET_break_op (0); 1912 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 1913 "I am the responder! Ignoring.\n"); 1914 GNUNET_CRYPTO_hash_context_abort (hc); 1915 return; 1916 } 1917 GNUNET_CRYPTO_hash_context_read (hc, 1918 rhm_e, 1919 sizeof (struct ResponderHello)); 1920 // 1. Verify that the message type is CORE_RESPONDER_HELLO 1921 // - implicitly done by handling this message? 1922 // - or is this about verifying the 'additional data' part of aead? 1923 // should it check the encryption + mac? (is this implicitly done 1924 // while decrypting?) 1925 // 2. sse <- Decaps(ske,ce) 1926 rh_ctx = GNUNET_new (struct ResponderHelloCls); 1927 ret = GNUNET_CRYPTO_hpke_kem_decaps (&kx->sk_e, // secret/private ephemeral key of initiator (us) 1928 &rhm_e->c_e, // encapsulated key 1929 &rh_ctx->ss_e); // key - ss_e 1930 if (GNUNET_OK != ret) 1931 { 1932 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1933 "Something went wrong decapsulating ss_e\n"); 1934 GNUNET_CRYPTO_hash_context_abort (hc); 1935 return; 1936 } 1937 // 3. Generate IHTS and RHTS from Section 5 and decrypt ServicesInfo, cI and ResponderFinished. 1938 snapshot_transcript (hc, &transcript); 1939 #if DEBUG_KX 1940 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1941 "Transcript snapshot for derivation of HS, *HTS: `%s'\n", 1942 GNUNET_h2s (&transcript)); 1943 #endif 1944 derive_hs (&kx->early_secret_key, 1945 &rh_ctx->ss_e, 1946 &rh_ctx->hs); 1947 derive_rhts (&transcript, 1948 &rh_ctx->hs, 1949 &rh_ctx->rhts); 1950 derive_ihts (&transcript, 1951 &rh_ctx->hs, 1952 &rh_ctx->ihts); 1953 derive_per_message_secrets (&rh_ctx->rhts, 1954 0, 1955 enc_key, 1956 enc_nonce); 1957 rh_ctx->kx = kx; 1958 GNUNET_memcpy (&rh_ctx->rhm_e, rhm_e, sizeof (*rhm_e)); 1959 { 1960 unsigned long long int c_len; 1961 unsigned char *finished_buf; 1962 // use RHTS to decrypt 1963 c_len = ntohs (rhm_e->header.size) - sizeof (*rhm_e) 1964 - sizeof (struct GNUNET_HashCode) 1965 - AEAD_TAG_BYTES; // finished ct 1966 rh_ctx->rhp = GNUNET_malloc (c_len 1967 - 1968 AEAD_TAG_BYTES); 1969 rh_ctx->hc = hc; 1970 finished_buf = ((unsigned char*) &rhm_e[1]) + c_len; 1971 /* Forward the transcript_hash_ctx 1972 * after rhts has been generated, 1973 * before generating finished_R*/ 1974 GNUNET_CRYPTO_hash_context_read ( 1975 hc, 1976 &rhm_e[1], 1977 c_len); 1978 1979 ret = crypto_aead_xchacha20poly1305_ietf_decrypt ( 1980 (unsigned char*) rh_ctx->rhp, // unsigned char *m 1981 NULL, // mlen_p message length 1982 NULL, // unsigned char *nsec - unused: NULL 1983 (unsigned char*) &rhm_e[1], // const unsigned char *c - ciphertext 1984 c_len, // unsigned long long clen - length of ciphertext 1985 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right? 1986 0, // unsigned long long adlen 1987 enc_nonce, // const unsigned char *npub - nonce 1988 enc_key // const unsigned char *k - key 1989 ); 1990 if (0 != ret) 1991 { 1992 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1993 "Something went wrong decrypting: %d\n", ret); 1994 GNUNET_free (rh_ctx->rhp); 1995 GNUNET_free (rh_ctx); 1996 GNUNET_CRYPTO_hash_context_abort (hc); 1997 return; 1998 } 1999 // FIXME nonce reuse (see encryption) 2000 derive_per_message_secrets (&rh_ctx->rhts, 2001 1, 2002 enc_key, 2003 enc_nonce); 2004 c_len = sizeof (struct GNUNET_HashCode) 2005 + AEAD_TAG_BYTES; 2006 ret = crypto_aead_xchacha20poly1305_ietf_decrypt ( 2007 (unsigned char*) &rh_ctx->decrypted_finish, // unsigned char *m 2008 NULL, // mlen_p message length 2009 NULL, // unsigned char *nsec - unused: NULL 2010 finished_buf, // const unsigned char *c - ciphertext 2011 c_len, // unsigned long long clen - length of ciphertext 2012 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right? 2013 0, // unsigned long long adlen 2014 enc_nonce, // const unsigned char *npub - nonce 2015 enc_key // const unsigned char *k - key 2016 ); 2017 if (0 != ret) 2018 { 2019 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2020 "Something went wrong decrypting finished field: %d\n", ret); 2021 GNUNET_free (rh_ctx->rhp); 2022 GNUNET_free (rh_ctx); 2023 GNUNET_CRYPTO_hash_context_abort (hc); 2024 return; 2025 } 2026 GNUNET_memcpy (rh_ctx->finished_enc, 2027 finished_buf, 2028 c_len); 2029 } 2030 // 4. ssI <- Decaps(skI,cI). 2031 req = GNUNET_new (struct PilsRequest); 2032 rh_ctx->req = req; 2033 GNUNET_CONTAINER_DLL_insert (pils_requests_head, 2034 pils_requests_tail, 2035 req); 2036 req->op = GNUNET_PILS_kem_decaps (GSC_pils, 2037 &rh_ctx->rhp->c_I, // encapsulated key 2038 &handle_responder_hello_cont, // continuation 2039 rh_ctx); 2040 } 2041 2042 2043 static int 2044 check_initiator_done (void *cls, const struct InitiatorDone *m) 2045 { 2046 uint16_t size = ntohs (m->header.size); 2047 2048 if (size < sizeof (*m) + sizeof (struct ConfirmationAck)) 2049 { 2050 return GNUNET_SYSERR; 2051 } 2052 return GNUNET_OK; 2053 } 2054 2055 2056 /** 2057 * Handle InitiatorDone message 2058 * @param cls key exchange info 2059 * @param idm_e InitiatorDone message 2060 */ 2061 static void 2062 handle_initiator_done (void *cls, const struct InitiatorDone *idm_e) 2063 { 2064 struct GSC_KeyExchangeInfo *kx = cls; 2065 struct InitiatorDone idm_local; 2066 struct InitiatorDone *idm_p = &idm_local; /* plaintext */ 2067 struct GNUNET_HashCode initiator_finished; 2068 struct GNUNET_HashCode transcript; 2069 struct GNUNET_ShortHashCode their_ats; 2070 struct GNUNET_HashContext *hc; 2071 unsigned char enc_key[AEAD_KEY_BYTES]; 2072 unsigned char enc_nonce[AEAD_NONCE_BYTES]; 2073 struct ConfirmationAck ack_i; 2074 struct ConfirmationAck ack_r; 2075 int8_t ret; 2076 2077 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received InitiatorDone: %d %d\n", kx-> 2078 role, kx->status); 2079 if (NULL != kx->resend_task) 2080 { 2081 GNUNET_SCHEDULER_cancel (kx->resend_task); 2082 kx->resend_task = NULL; 2083 } 2084 if (NULL != kx->resend_env) 2085 { 2086 GNUNET_free (kx->resend_env); 2087 kx->resend_env = NULL; 2088 } 2089 if (ROLE_INITIATOR == kx->role) 2090 { 2091 GNUNET_break_op (0); 2092 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2093 "I am the initiator! Tearing down...\n"); 2094 return; 2095 } 2096 derive_per_message_secrets (&kx->ihts, 2097 0, 2098 enc_key, 2099 enc_nonce); 2100 ret = crypto_aead_xchacha20poly1305_ietf_decrypt ( 2101 (unsigned char*) &idm_p->finished, // unsigned char *m 2102 NULL, // mlen_p message length 2103 NULL, // unsigned char *nsec - unused: NULL 2104 (unsigned char*) &idm_e->finished, // const unsigned char *c - ciphertext 2105 sizeof (idm_p->finished) // unsigned long long clen - length of ciphertext 2106 + AEAD_TAG_BYTES, 2107 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right? 2108 0, // unsigned long long adlen 2109 enc_nonce, // const unsigned char *npub - nonce 2110 enc_key // const unsigned char *k - key 2111 ); 2112 if (0 != ret) 2113 { 2114 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2115 "Something went wrong decrypting: %d\n", ret); 2116 return; 2117 } 2118 2119 // - verify finished_I 2120 /* Generate finished_I 2121 * after Forwarding until {finished_R}RHTS 2122 * (did so while we prepared responder hello) 2123 * before forwarding to [{payload}RATS and] {finished_I}IHTS */ 2124 // (look at the end of handle_initiator_hello()) 2125 snapshot_transcript (kx->transcript_hash_ctx, &transcript); 2126 generate_initiator_finished (&transcript, 2127 &kx->master_secret, 2128 &initiator_finished); 2129 if (0 != memcmp (&idm_p->finished, 2130 &initiator_finished, 2131 sizeof (struct GNUNET_HashCode))) 2132 { 2133 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2134 "Could not verify \"initiator finished\" hash.\n"); 2135 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2136 "Want: `%s'\n", 2137 GNUNET_h2s (&initiator_finished)); 2138 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2139 "Have: `%s'\n", 2140 GNUNET_h2s (&idm_p->finished)); 2141 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2142 "Transcript `%s'\n", 2143 GNUNET_h2s (&transcript)); 2144 return; 2145 } 2146 2147 /* Forward the transcript hash_context_read */ 2148 hc = GNUNET_CRYPTO_hash_context_copy (kx->transcript_hash_ctx); 2149 GNUNET_CRYPTO_hash_context_read (hc, 2150 &idm_e->finished, 2151 sizeof (idm_e->finished) 2152 + AEAD_TAG_BYTES); 2153 snapshot_transcript (hc, &transcript); 2154 derive_initial_ats (&transcript, 2155 &kx->master_secret, 2156 ROLE_INITIATOR, 2157 &their_ats); 2158 derive_per_message_secrets (&their_ats, // FIXME other HS epoch? 2159 0, 2160 enc_key, 2161 enc_nonce); 2162 ret = crypto_aead_xchacha20poly1305_ietf_decrypt ( 2163 (unsigned char*) &ack_i, // unsigned char *m 2164 NULL, // mlen_p message length 2165 NULL, // unsigned char *nsec - unused: NULL 2166 (unsigned char*) &idm_e[1], // const unsigned char *c - ciphertext 2167 sizeof (ack_i) + AEAD_TAG_BYTES, // unsigned long long clen - length of ciphertext 2168 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right? 2169 0, // unsigned long long adlen 2170 enc_nonce, // const unsigned char *npub - nonce 2171 enc_key // const unsigned char *k - key 2172 ); 2173 if (0 != ret) 2174 { 2175 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2176 "Something went wrong decrypting the Ack: %d\n", ret); 2177 GNUNET_CRYPTO_hash_context_abort (hc); 2178 return; 2179 } 2180 if ((sizeof ack_i != ntohs (ack_i.header.size)) || 2181 (GNUNET_MESSAGE_TYPE_CORE_ACK != ntohs (ack_i.header.type))) 2182 { 2183 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2184 "Ack invalid!\n"); 2185 GNUNET_CRYPTO_hash_context_abort (hc); 2186 return; 2187 } 2188 GNUNET_memcpy (&kx->their_ats[0], 2189 &their_ats, 2190 sizeof their_ats); 2191 /** 2192 * FIXME we do not really have to calculate all this now 2193 */ 2194 for (int i = 0; i < MAX_EPOCHS - 1; i++) 2195 { 2196 derive_next_ats (&kx->their_ats[i], 2197 &kx->their_ats[i + 1]); 2198 } 2199 GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx); 2200 kx->transcript_hash_ctx = hc; 2201 kx->status = GNUNET_CORE_KX_STATE_RESPONDER_CONNECTED; 2202 kx->current_epoch_expiration = 2203 GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION); 2204 cleanup_handshake_secrets (kx); 2205 monitor_notify_all (kx); 2206 kx->current_sqn = 1; 2207 GSC_SESSIONS_create (&kx->peer, kx, kx->class); 2208 GNUNET_assert (NULL == kx->heartbeat_task); 2209 update_timeout (kx); 2210 ack_r.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ACK); 2211 ack_r.header.size = htons (sizeof ack_r); 2212 GSC_KX_encrypt_and_transmit (kx, 2213 &ack_r, 2214 sizeof ack_r); 2215 2216 GNUNET_TRANSPORT_core_receive_continue (transport, 2217 &kx->peer); 2218 } 2219 2220 2221 /** 2222 * Check an incoming encrypted message before handling it 2223 * @param cls key exchange info 2224 * @param m the encrypted message 2225 */ 2226 static int 2227 check_encrypted_message (void *cls, const struct EncryptedMessage *m) 2228 { 2229 uint16_t size = ntohs (m->header.size) - sizeof(*m); 2230 2231 // TODO check (see check_encrypted ()) 2232 // - check epoch 2233 // - check sequence number 2234 if (size < sizeof(struct GNUNET_MessageHeader)) 2235 { 2236 GNUNET_break_op (0); 2237 return GNUNET_SYSERR; 2238 } 2239 return GNUNET_OK; 2240 } 2241 2242 2243 /** 2244 * Handle a key update 2245 * @param cls key exchange info 2246 * @param m KeyUpdate message 2247 */ 2248 static void 2249 handle_heartbeat (struct GSC_KeyExchangeInfo *kx, 2250 const struct Heartbeat *m) 2251 { 2252 struct GNUNET_ShortHashCode new_ats; 2253 struct ConfirmationAck ack; 2254 2255 if (m->flags & GSC_HEARTBEAT_KEY_UPDATE_REQUESTED) 2256 { 2257 if (kx->current_epoch == UINT64_MAX) 2258 { 2259 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2260 "Max epoch reached (you probably will never see this)\n"); 2261 } 2262 else 2263 { 2264 kx->current_epoch++; 2265 kx->current_epoch_expiration = 2266 GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION); 2267 kx->current_sqn = 0; 2268 derive_next_ats (&kx->current_ats, 2269 &new_ats); 2270 memcpy (&kx->current_ats, 2271 &new_ats, 2272 sizeof new_ats); 2273 } 2274 } 2275 update_timeout (kx); 2276 ack.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_ACK); 2277 ack.header.size = htons (sizeof ack); 2278 GSC_KX_encrypt_and_transmit (kx, 2279 &ack, 2280 sizeof ack); 2281 if (NULL != kx->heartbeat_task) 2282 { 2283 GNUNET_SCHEDULER_cancel (kx->heartbeat_task); 2284 kx->heartbeat_task = GNUNET_SCHEDULER_add_delayed (MIN_HEARTBEAT_FREQUENCY, 2285 &send_heartbeat, 2286 kx); 2287 } 2288 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer); 2289 } 2290 2291 2292 static enum GNUNET_GenericReturnValue 2293 check_if_ack_or_heartbeat (struct GSC_KeyExchangeInfo *kx, 2294 const char *buf, 2295 size_t buf_len) 2296 { 2297 struct GNUNET_MessageHeader *msg; 2298 struct ConfirmationAck *ack; 2299 struct Heartbeat *hb; 2300 2301 if (sizeof *msg > buf_len) 2302 return GNUNET_NO; 2303 msg = (struct GNUNET_MessageHeader*) buf; 2304 if (GNUNET_MESSAGE_TYPE_CORE_ACK == ntohs (msg->type)) 2305 { 2306 ack = (struct ConfirmationAck *) buf; 2307 if (sizeof *ack != ntohs (ack->header.size)) 2308 return GNUNET_NO; 2309 } 2310 else if (GNUNET_MESSAGE_TYPE_CORE_HEARTBEAT == ntohs (msg->type)) 2311 { 2312 hb = (struct Heartbeat*) buf; 2313 if (sizeof *hb != ntohs (hb->header.size)) 2314 return GNUNET_NO; 2315 handle_heartbeat (kx, hb); 2316 } 2317 else 2318 { 2319 return GNUNET_NO; 2320 } 2321 2322 /** 2323 * Waiting for ACK or heartbeat 2324 */ 2325 if (kx->status == GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT) 2326 { 2327 GSC_SESSIONS_create (&kx->peer, kx, kx->class); 2328 kx->status = GNUNET_CORE_KX_STATE_INITIATOR_CONNECTED; 2329 kx->current_epoch_expiration = 2330 GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION); 2331 cleanup_handshake_secrets (kx); 2332 if (NULL != kx->resend_task) 2333 GNUNET_SCHEDULER_cancel (kx->resend_task); 2334 kx->resend_task = NULL; 2335 if (NULL != kx->resend_env) 2336 GNUNET_free (kx->resend_env); 2337 kx->resend_env = NULL; 2338 monitor_notify_all (kx); 2339 } 2340 update_timeout (kx); 2341 2342 return GNUNET_YES; 2343 } 2344 2345 2346 /** 2347 * handle an encrypted message 2348 * @param cls key exchange info 2349 * @param m encrypted message 2350 */ 2351 static void 2352 handle_encrypted_message (void *cls, const struct EncryptedMessage *m) 2353 { 2354 struct GSC_KeyExchangeInfo *kx = cls; 2355 uint16_t size = ntohs (m->header.size); 2356 char buf[size - sizeof (*m)] GNUNET_ALIGN; 2357 unsigned char seq_enc_k[crypto_stream_chacha20_ietf_KEYBYTES]; 2358 const unsigned char *seq_enc_nonce; 2359 unsigned char enc_key[AEAD_KEY_BYTES]; 2360 unsigned char enc_nonce[AEAD_NONCE_BYTES]; 2361 struct GNUNET_ShortHashCode new_ats[MAX_EPOCHS]; 2362 uint32_t seq_enc_ctr; 2363 uint64_t epoch; 2364 uint64_t m_seq; 2365 uint64_t m_seq_nbo; 2366 uint64_t c_len; 2367 int8_t ret; 2368 2369 // TODO look at handle_encrypted 2370 // - statistics 2371 2372 if ((kx->status != GNUNET_CORE_KX_STATE_RESPONDER_CONNECTED) && 2373 (kx->status != GNUNET_CORE_KX_STATE_INITIATOR_CONNECTED) && 2374 (kx->status != GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT)) 2375 { 2376 GSC_SESSIONS_end (&kx->peer); 2377 kx->status = GNUNET_CORE_KX_STATE_DOWN; 2378 monitor_notify_all (kx); 2379 restart_kx (kx); 2380 return; 2381 } 2382 update_timeout (kx); 2383 epoch = GNUNET_ntohll (m->epoch); 2384 /** 2385 * Derive temporarily as we want to discard on 2386 * decryption failure(s) 2387 */ 2388 memcpy (new_ats, 2389 kx->their_ats, 2390 MAX_EPOCHS * sizeof (struct GNUNET_ShortHashCode)); 2391 // FIXME here we could introduce logic that sends heartbeats 2392 // with key update request if we have not seen a new 2393 // epoch after a while (e.g. EPOCH_EXPIRATION) 2394 if (kx->their_max_epoch < epoch) 2395 { 2396 /** 2397 * Prevent DoS 2398 * FIXME maybe requires its own limit. 2399 */ 2400 if ((epoch - kx->their_max_epoch) > 2 * MAX_EPOCHS) 2401 { 2402 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2403 "Epoch %" PRIu64 " is too new, will not decrypt...\n", 2404 epoch); 2405 GSC_SESSIONS_end (&kx->peer); 2406 kx->status = GNUNET_CORE_KX_STATE_DOWN; 2407 monitor_notify_all (kx); 2408 restart_kx (kx); 2409 return; 2410 } 2411 for (int i = kx->their_max_epoch; i < epoch; i++) 2412 { 2413 derive_next_ats (&new_ats[i % MAX_EPOCHS], 2414 &new_ats[(i + 1) % MAX_EPOCHS]); 2415 } 2416 } 2417 else if ((kx->their_max_epoch - epoch) > MAX_EPOCHS) 2418 { 2419 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2420 "Epoch %" PRIu64 " is too old, cannot decrypt...\n", 2421 epoch); 2422 return; 2423 } 2424 derive_sn ( 2425 &new_ats[epoch % MAX_EPOCHS], 2426 seq_enc_k, 2427 sizeof seq_enc_k); 2428 /* compute the sequence number */ 2429 seq_enc_ctr = *((uint32_t*) m->tag); 2430 seq_enc_nonce = &m->tag[sizeof (uint32_t)]; 2431 #if DEBUG_KX 2432 GNUNET_print_bytes (&new_ats[epoch % MAX_EPOCHS], 2433 sizeof (struct GNUNET_ShortHashCode), 2434 8, 2435 GNUNET_NO); 2436 GNUNET_print_bytes (seq_enc_k, 2437 sizeof seq_enc_k, 2438 8, 2439 GNUNET_NO); 2440 GNUNET_print_bytes ((char*) &seq_enc_ctr, 2441 sizeof seq_enc_ctr, 2442 8, 2443 GNUNET_NO); 2444 #endif 2445 crypto_stream_chacha20_ietf_xor_ic ( 2446 (unsigned char*) &m_seq_nbo, 2447 (unsigned char*) &m->sequence_number, 2448 sizeof (uint64_t), 2449 seq_enc_nonce, 2450 ntohl (seq_enc_ctr), 2451 seq_enc_k); 2452 m_seq = GNUNET_ntohll (m_seq_nbo); 2453 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2454 "Received encrypted message in epoch %" PRIu64 2455 " with E(SQN=%" PRIu64 ")=%" PRIu64 2456 "\n", 2457 epoch, 2458 m_seq, 2459 m->sequence_number); 2460 /* We are the initiator and as we are going to receive, 2461 * we are using the responder key material */ 2462 derive_per_message_secrets (&new_ats[epoch], 2463 m_seq, 2464 enc_key, 2465 enc_nonce); 2466 // TODO checking sequence numbers - handle the case of out-of-sync messages! 2467 // for now only decrypt the payload 2468 // TODO encrypt other fields, too! 2469 // TODO 2470 // c_len = size - offsetof (); 2471 c_len = size - sizeof (struct EncryptedMessage); 2472 ret = crypto_aead_xchacha20poly1305_ietf_decrypt_detached ( 2473 (unsigned char*) buf, // m - plain message 2474 NULL, // nsec - unused 2475 (unsigned char*) &m[1], // c - ciphertext 2476 c_len, // clen 2477 (const unsigned char*) &m->tag, // mac 2478 NULL, // ad - additional data TODO 2479 0, // adlen 2480 enc_nonce, // npub 2481 enc_key // k 2482 ); 2483 if (0 != ret) 2484 { 2485 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2486 "Something went wrong decrypting message\n"); 2487 GNUNET_break_op (0); // FIXME handle gracefully 2488 return; 2489 } 2490 kx->their_max_epoch = epoch; 2491 memcpy (&kx->their_ats, 2492 new_ats, 2493 MAX_EPOCHS * sizeof (struct GNUNET_ShortHashCode)); 2494 2495 if (GNUNET_NO == check_if_ack_or_heartbeat (kx, 2496 buf, 2497 sizeof buf)) 2498 { 2499 if (kx->status == GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT) 2500 { 2501 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2502 "Dropping message as we are still waiting for handshake ACK\n"); 2503 GNUNET_break_op (0); 2504 return; 2505 } 2506 if (GNUNET_OK != 2507 GNUNET_MST_from_buffer (kx->mst, 2508 buf, 2509 sizeof buf, 2510 GNUNET_YES, 2511 GNUNET_NO)) 2512 GNUNET_break_op (0); 2513 } 2514 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer); 2515 } 2516 2517 2518 /** 2519 * Function called by transport telling us that a peer 2520 * disconnected. 2521 * Stop key exchange with the given peer. Clean up key material. 2522 * 2523 * @param cls closure 2524 * @param peer the peer that disconnected 2525 * @param handler_cls the `struct GSC_KeyExchangeInfo` of the peer 2526 */ 2527 static void 2528 handle_transport_notify_disconnect (void *cls, 2529 const struct GNUNET_PeerIdentity *peer, 2530 void *handler_cls) 2531 { 2532 struct GSC_KeyExchangeInfo *kx = handler_cls; 2533 (void) cls; 2534 2535 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2536 "Peer `%s' disconnected from us.\n", 2537 GNUNET_i2s (&kx->peer)); 2538 GSC_SESSIONS_end (&kx->peer); 2539 GNUNET_STATISTICS_update (GSC_stats, 2540 gettext_noop ("# key exchanges stopped"), 2541 1, 2542 GNUNET_NO); 2543 if (NULL != kx->resend_task) 2544 { 2545 GNUNET_SCHEDULER_cancel (kx->resend_task); 2546 kx->resend_task = NULL; 2547 } 2548 if (NULL != kx->resend_env) 2549 { 2550 GNUNET_free (kx->resend_env); 2551 kx->resend_env = NULL; 2552 } 2553 if (NULL != kx->heartbeat_task) 2554 { 2555 GNUNET_SCHEDULER_cancel (kx->heartbeat_task); 2556 kx->heartbeat_task = NULL; 2557 } 2558 kx->status = GNUNET_CORE_KX_PEER_DISCONNECT; 2559 monitor_notify_all (kx); 2560 if (kx->transcript_hash_ctx) 2561 { 2562 GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx); 2563 kx->transcript_hash_ctx = NULL; 2564 } 2565 GNUNET_CONTAINER_DLL_remove (kx_head, kx_tail, kx); 2566 GNUNET_MST_destroy (kx->mst); 2567 GNUNET_free (kx); 2568 } 2569 2570 2571 static void 2572 resend_initiator_hello (void *cls) 2573 { 2574 struct GSC_KeyExchangeInfo *kx = cls; 2575 2576 kx->resend_task = NULL; 2577 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, 2578 "Resending InitiatorHello.\n"); 2579 GNUNET_MQ_send_copy (kx->mq, kx->resend_env); 2580 // FIXME (Exponential) backoff? 2581 kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT, 2582 &resend_initiator_hello, 2583 kx); 2584 } 2585 2586 2587 /** 2588 * Send initiator hello 2589 * 2590 * @param kx key exchange context 2591 */ 2592 static void 2593 send_initiator_hello (struct GSC_KeyExchangeInfo *kx) 2594 { 2595 const struct GNUNET_PeerIdentity *my_identity; 2596 struct GNUNET_MQ_Envelope *env; 2597 struct GNUNET_ShortHashCode es; 2598 struct GNUNET_ShortHashCode ets; 2599 struct GNUNET_ShortHashCode ss_R; 2600 struct InitiatorHelloPayload *ihmp; /* initiator hello message - buffer on stack */ 2601 struct InitiatorHello *ihm_e; /* initiator hello message - encrypted */ 2602 long long unsigned int c_len; 2603 unsigned char enc_key[AEAD_KEY_BYTES]; 2604 unsigned char enc_nonce[AEAD_NONCE_BYTES]; 2605 enum GNUNET_GenericReturnValue ret; 2606 size_t pt_len; 2607 2608 my_identity = GNUNET_PILS_get_identity (GSC_pils); 2609 GNUNET_assert (NULL != my_identity); 2610 2611 pt_len = sizeof (*ihmp) + strlen (my_services_info); 2612 c_len = pt_len + AEAD_TAG_BYTES; 2613 env = GNUNET_MQ_msg_extra (ihm_e, 2614 c_len, 2615 GNUNET_MESSAGE_TYPE_CORE_INITIATOR_HELLO); 2616 ihmp = (struct InitiatorHelloPayload*) &ihm_e[1]; 2617 ihmp->peer_class = htons (GNUNET_CORE_CLASS_UNKNOWN); // TODO set this to a meaningful 2618 GNUNET_memcpy (&ihmp->pk_I, 2619 my_identity, 2620 sizeof (struct GNUNET_PeerIdentity)); 2621 GNUNET_CRYPTO_hash (&kx->peer, /* what to hash */ // TODO do we do this twice? 2622 sizeof (struct GNUNET_PeerIdentity), 2623 &ihm_e->h_pk_R); /* result */ 2624 // TODO init hashcontext/transcript_hash 2625 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send InitiatorHello: %d %d\n", kx->role, 2626 kx->status); 2627 GNUNET_assert (NULL == kx->transcript_hash_ctx); 2628 kx->transcript_hash_ctx = GNUNET_CRYPTO_hash_context_start (); 2629 GNUNET_assert (NULL != kx->transcript_hash_ctx); 2630 // TODO fill services_info 2631 2632 // 1. Encaps 2633 ret = GNUNET_CRYPTO_eddsa_kem_encaps (&kx->peer.public_key, // public ephemeral key of initiator 2634 &ihm_e->c_R, // encapsulated key 2635 &ss_R); // key - ss_R 2636 if (GNUNET_OK != ret) 2637 { 2638 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2639 "Something went wrong encapsulating ss_R\n"); 2640 // TODO handle 2641 } 2642 // 2. generate rR (uint64_t) - is this the nonce? Naming seems not quite 2643 // consistent 2644 ihm_e->r_I = 2645 GNUNET_CRYPTO_random_u64 (UINT64_MAX); 2646 // 3. generate sk_e/pk_e - ephemeral key 2647 GNUNET_CRYPTO_ecdhe_key_create (&kx->sk_e.ecdhe_key); 2648 GNUNET_CRYPTO_ecdhe_key_get_public ( 2649 &kx->sk_e.ecdhe_key, 2650 &kx->pk_e.ecdhe_key); 2651 GNUNET_memcpy (&ihm_e->pk_e, 2652 &kx->pk_e.ecdhe_key, 2653 sizeof (kx->pk_e.ecdhe_key)); 2654 // 4. generate ETS to encrypt 2655 // generate ETS (early_traffic_secret_key, decrypt pk_i 2656 // expand ETS <- expand ES <- extract ss_R 2657 // use ETS to decrypt 2658 GNUNET_CRYPTO_hash_context_read (kx->transcript_hash_ctx, 2659 ihm_e, 2660 sizeof (struct InitiatorHello)); 2661 { 2662 struct GNUNET_HashCode transcript; 2663 snapshot_transcript (kx->transcript_hash_ctx, 2664 &transcript); 2665 derive_es_ets (&transcript, 2666 &ss_R, 2667 &es, 2668 &ets); 2669 derive_per_message_secrets (&ets, 2670 0, 2671 enc_key, 2672 enc_nonce); 2673 } 2674 // 5. encrypt 2675 2676 ret = crypto_aead_xchacha20poly1305_ietf_encrypt ( 2677 (unsigned char*) &ihm_e[1], /* c - ciphertext */ 2678 // mac, 2679 // NULL, // maclen_p 2680 &c_len, /* clen_p */ 2681 (unsigned char*) ihmp, /* m - plaintext message */ 2682 pt_len, // mlen 2683 NULL, 0, // ad, adlen // FIXME maybe over the unencrypted header? 2684 // fields? 2685 NULL, // nsec - unused 2686 enc_nonce, // npub - nonce 2687 enc_key); // k - key 2688 if (0 != ret) 2689 { 2690 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong encrypting\n"); 2691 GNUNET_CRYPTO_hash_context_abort (kx->transcript_hash_ctx); 2692 kx->transcript_hash_ctx = NULL; 2693 GNUNET_MQ_discard (env); 2694 return; 2695 } 2696 /* Forward the transcript */ 2697 GNUNET_CRYPTO_hash_context_read ( 2698 kx->transcript_hash_ctx, 2699 &ihm_e[1], 2700 c_len); 2701 2702 kx->status = GNUNET_CORE_KX_STATE_INITIATOR_HELLO_SENT; 2703 kx->early_secret_key = es; 2704 kx->early_traffic_secret = ets; 2705 kx->ss_R = ss_R; 2706 monitor_notify_all (kx); 2707 GNUNET_MQ_send_copy (kx->mq, env); 2708 kx->resend_env = env; 2709 kx->resend_tries_left = RESEND_MAX_TRIES; 2710 kx->resend_task = GNUNET_SCHEDULER_add_delayed (RESEND_TIMEOUT, 2711 &resend_initiator_hello, 2712 kx); 2713 } 2714 2715 2716 static void 2717 check_rekey (struct GSC_KeyExchangeInfo *kx) 2718 { 2719 struct GNUNET_ShortHashCode new_ats; 2720 2721 if ((UINT64_MAX == kx->current_sqn) || 2722 (GNUNET_TIME_absolute_is_past (kx->current_epoch_expiration))) 2723 { 2724 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2725 "Epoch expiration %" PRIu64 " SQN %" PRIu64 2726 ", incrementing epoch...\n", 2727 kx->current_epoch_expiration.abs_value_us, 2728 kx->current_sqn); 2729 // Can this trigger? Maybe if we receive a lot of 2730 // heartbeats? 2731 GNUNET_assert (UINT64_MAX > kx->current_epoch); 2732 kx->current_epoch++; 2733 kx->current_epoch_expiration = 2734 GNUNET_TIME_relative_to_absolute (EPOCH_EXPIRATION); 2735 kx->current_sqn = 0; 2736 derive_next_ats (&kx->current_ats, 2737 &new_ats); 2738 memcpy (&kx->current_ats, 2739 &new_ats, 2740 sizeof new_ats); 2741 } 2742 } 2743 2744 2745 /** 2746 * Encrypt and transmit payload 2747 * @param kx key exchange info 2748 * @param payload the payload 2749 * @param payload_size size of the payload 2750 */ 2751 void 2752 GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx, 2753 const void *payload, 2754 size_t payload_size) 2755 { 2756 struct GNUNET_MQ_Envelope *env; 2757 struct EncryptedMessage *encrypted_msg; 2758 unsigned char enc_key[AEAD_KEY_BYTES]; 2759 unsigned char enc_nonce[AEAD_NONCE_BYTES]; 2760 unsigned char seq_enc_k[crypto_stream_chacha20_ietf_KEYBYTES]; 2761 uint64_t sqn; 2762 uint64_t epoch; 2763 int8_t ret; 2764 2765 encrypted_msg = NULL; 2766 2767 check_rekey (kx); 2768 sqn = kx->current_sqn; 2769 epoch = kx->current_epoch; 2770 /* We are the sender and as we are going to send, 2771 * we are using the initiator key material */ 2772 derive_per_message_secrets (&kx->current_ats, 2773 sqn, 2774 enc_key, 2775 enc_nonce); 2776 kx->current_sqn++; 2777 derive_sn (&kx->current_ats, 2778 seq_enc_k, 2779 sizeof seq_enc_k); 2780 env = GNUNET_MQ_msg_extra (encrypted_msg, 2781 payload_size, 2782 GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE_CAKE); 2783 // only encrypt the payload for now 2784 // TODO encrypt other fields as well 2785 ret = crypto_aead_xchacha20poly1305_ietf_encrypt_detached ( 2786 (unsigned char*) &encrypted_msg[1], // c - resulting ciphertext 2787 (unsigned char*) &encrypted_msg->tag, // mac - resulting mac/tag 2788 NULL, // maclen 2789 (unsigned char*) payload, // m - plain message 2790 payload_size, // mlen 2791 NULL, // ad - additional data TODO also cover the unencrypted part (epoch) 2792 0, // adlen 2793 NULL, // nsec - unused 2794 enc_nonce, // npub nonce 2795 enc_key // k - key 2796 ); 2797 if (0 != ret) 2798 { 2799 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 2800 "Something went wrong encrypting message\n"); 2801 GNUNET_assert (0); 2802 } 2803 { 2804 /* compute the sequence number */ 2805 unsigned char *seq_enc_nonce; 2806 uint64_t seq_nbo; 2807 uint32_t seq_enc_ctr; 2808 2809 seq_nbo = GNUNET_htonll (sqn); 2810 seq_enc_ctr = *((uint32_t*) encrypted_msg->tag); 2811 seq_enc_nonce = &encrypted_msg->tag[sizeof (uint32_t)]; 2812 crypto_stream_chacha20_ietf_xor_ic ( 2813 (unsigned char*) &encrypted_msg->sequence_number, 2814 (unsigned char*) &seq_nbo, 2815 sizeof seq_nbo, 2816 seq_enc_nonce, 2817 ntohl (seq_enc_ctr), 2818 seq_enc_k); 2819 #if DEBUG_KX 2820 GNUNET_print_bytes (seq_enc_k, 2821 sizeof seq_enc_k, 2822 8, 2823 GNUNET_NO); 2824 GNUNET_print_bytes ((char*) &seq_enc_ctr, 2825 sizeof seq_enc_ctr, 2826 8, 2827 GNUNET_NO); 2828 #endif 2829 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2830 "Sending encrypted message with E(SQN=%" PRIu64 ")=%" PRIu64 2831 "\n", 2832 sqn, 2833 encrypted_msg->sequence_number); 2834 } 2835 encrypted_msg->epoch = GNUNET_htonll (epoch); 2836 2837 // TODO actually copy payload 2838 GNUNET_MQ_send (kx->mq, env); 2839 } 2840 2841 2842 void 2843 GSC_KX_start (void) 2844 { 2845 const struct GNUNET_PeerIdentity *my_identity; 2846 struct GNUNET_MQ_MessageHandler handlers[] = { 2847 GNUNET_MQ_hd_var_size (initiator_hello, 2848 GNUNET_MESSAGE_TYPE_CORE_INITIATOR_HELLO, 2849 struct InitiatorHello, 2850 NULL), 2851 GNUNET_MQ_hd_var_size (initiator_done, 2852 GNUNET_MESSAGE_TYPE_CORE_INITIATOR_DONE, 2853 struct InitiatorDone, 2854 NULL), 2855 GNUNET_MQ_hd_var_size (responder_hello, 2856 GNUNET_MESSAGE_TYPE_CORE_RESPONDER_HELLO, 2857 struct ResponderHello, 2858 NULL), 2859 GNUNET_MQ_hd_var_size (encrypted_message, // TODO rename? 2860 GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE_CAKE, // TODO rename! 2861 struct EncryptedMessage, 2862 NULL), 2863 GNUNET_MQ_handler_end () 2864 }; 2865 2866 my_identity = GNUNET_PILS_get_identity (GSC_pils); 2867 GNUNET_assert (NULL != my_identity); 2868 2869 nc = GNUNET_notification_context_create (1); 2870 transport = 2871 GNUNET_TRANSPORT_core_connect (GSC_cfg, 2872 my_identity, 2873 handlers, 2874 NULL, // cls - this connection-independant 2875 // cls seems not to be needed. 2876 // the connection-specific cls 2877 // will be set as a return value 2878 // of 2879 // handle_transport_notify_connect 2880 &handle_transport_notify_connect, 2881 &handle_transport_notify_disconnect); 2882 if (NULL == transport) 2883 { 2884 GSC_KX_done (); 2885 return; 2886 } 2887 2888 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2889 "Connected to TRANSPORT\n"); 2890 2891 GSC_complete_initialization_cb (); 2892 } 2893 2894 2895 void 2896 pid_change_cb (void *cls, 2897 const struct GNUNET_HELLO_Parser *parser, 2898 const struct GNUNET_HashCode *hash) 2899 { 2900 if (NULL != transport) 2901 return; 2902 2903 GSC_KX_start (); 2904 } 2905 2906 2907 /** 2908 * Initialize KX subsystem. 2909 * 2910 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure 2911 */ 2912 int 2913 GSC_KX_init (void) 2914 { 2915 GSC_pils = GNUNET_PILS_connect (GSC_cfg, 2916 &pid_change_cb, 2917 NULL); 2918 if (NULL == GSC_pils) 2919 { 2920 GSC_KX_done (); 2921 return GNUNET_SYSERR; 2922 } 2923 2924 return GNUNET_OK; 2925 } 2926 2927 2928 /** 2929 * Shutdown KX subsystem. 2930 */ 2931 void 2932 GSC_KX_done () 2933 { 2934 struct PilsRequest *pr; 2935 while (NULL != (pr = pils_requests_head)) 2936 { 2937 GNUNET_CONTAINER_DLL_remove (pils_requests_head, 2938 pils_requests_tail, 2939 pr); 2940 if (NULL != pr->op) 2941 GNUNET_PILS_cancel (pr->op); 2942 GNUNET_free (pr); 2943 } 2944 if (NULL != GSC_pils) 2945 { 2946 GNUNET_PILS_disconnect (GSC_pils); 2947 GSC_pils = NULL; 2948 } 2949 if (NULL != transport) 2950 { 2951 GNUNET_TRANSPORT_core_disconnect (transport); 2952 transport = NULL; 2953 } 2954 if (NULL != rekey_task) 2955 { 2956 GNUNET_SCHEDULER_cancel (rekey_task); 2957 rekey_task = NULL; 2958 } 2959 if (NULL != nc) 2960 { 2961 GNUNET_notification_context_destroy (nc); 2962 nc = NULL; 2963 } 2964 } 2965 2966 2967 /** 2968 * Check how many messages are queued for the given neighbour. 2969 * 2970 * @param kxinfo data about neighbour to check 2971 * @return number of items in the message queue 2972 */ 2973 unsigned int 2974 GSC_NEIGHBOURS_get_queue_length (const struct GSC_KeyExchangeInfo *kxinfo) 2975 { 2976 return GNUNET_MQ_get_length (kxinfo->mq); 2977 } 2978 2979 2980 int 2981 GSC_NEIGHBOURS_check_excess_bandwidth (const struct GSC_KeyExchangeInfo *kxinfo) 2982 { 2983 return kxinfo->has_excess_bandwidth; 2984 } 2985 2986 2987 /** 2988 * Handle #GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request. For this 2989 * request type, the client does not have to have transmitted an INIT 2990 * request. All current peers are returned, regardless of which 2991 * message types they accept. 2992 * 2993 * @param mq message queue to add for monitoring 2994 */ 2995 void 2996 GSC_KX_handle_client_monitor_peers (struct GNUNET_MQ_Handle *mq) 2997 { 2998 struct GNUNET_MQ_Envelope *env; 2999 struct MonitorNotifyMessage *done_msg; 3000 struct GSC_KeyExchangeInfo *kx; 3001 3002 GNUNET_notification_context_add (nc, mq); 3003 for (kx = kx_head; NULL != kx; kx = kx->next) 3004 { 3005 struct GNUNET_MQ_Envelope *env_notify; 3006 struct MonitorNotifyMessage *msg; 3007 3008 env_notify = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY); 3009 msg->state = htonl ((uint32_t) kx->status); 3010 msg->peer = kx->peer; 3011 msg->timeout = GNUNET_TIME_absolute_hton (kx->timeout); 3012 GNUNET_MQ_send (mq, env_notify); 3013 } 3014 env = GNUNET_MQ_msg (done_msg, GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY); 3015 done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED); 3016 done_msg->timeout = GNUNET_TIME_absolute_hton (GNUNET_TIME_UNIT_FOREVER_ABS); 3017 GNUNET_MQ_send (mq, env); 3018 } 3019 3020 3021 /* end of gnunet-service-core_kx.c */