GNUnet 0.26.2-114-g7c6b613e3
 
Loading...
Searching...
No Matches
gnunet-service-core_kx.c
Go to the documentation of this file.
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
37#include "gnunet_common.h"
38#include "gnunet_util_lib.h"
39#include "platform.h"
43#include "gnunet-service-core.h"
44#include "gnunet_constants.h"
45#include "gnunet_protocols.h"
46#include "gnunet_pils_service.h"
47
51#define DEBUG_KX 0
52
56#define RESEND_MAX_TRIES 4
57
61#define AEAD_KEY_BYTES crypto_aead_xchacha20poly1305_ietf_KEYBYTES
62
66#define AEAD_NONCE_BYTES crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
67
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
79#define MIN_HEARTBEAT_FREQUENCY \
80 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
81
85#define MIN_HEARTBEAT_FREQUENCY \
86 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
87
91#define HEARTBEAT_FREQUENCY \
92 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
93
100#define MAX_EPOCHS 10
101
105#define EPOCH_EXPIRATION \
106 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
107
111#define REKEY_TOLERANCE \
112 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
113
118#define EARLY_DATA_STR "early data"
119
124#define R_HS_TRAFFIC_STR "r hs traffic"
125
130#define I_HS_TRAFFIC_STR "i hs traffic"
131
136#define R_AP_TRAFFIC_STR "r ap traffic"
137
142#define I_AP_TRAFFIC_STR "i ap traffic"
143
148#define DERIVED_STR "derived"
149
154#define R_FINISHED_STR "r finished"
155
160#define I_FINISHED_STR "i finished"
161
165#define CAKE_LABEL "cake10"
166
171#define KEY_STR "key"
172
177#define TRAFFIC_UPD_STR "traffic upd"
178
183#define IV_STR "iv"
184
185
190{
191 /* Peer is supposed to initiate the key exchange */
193
194 /* Peer is supposed to wait for the key exchange */
196};
197
198
203{
208
213
218
223
228
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
245
246 // TODO
250
255
260
267
273
278 struct GNUNET_ShortHashCode early_traffic_secret; /* Decrypts InitiatorHello */
279
285
291
297
303
308
313
318
323
329
333 uint64_t current_sqn;
334
339
344
349
353 unsigned int resend_tries_left;
354
360
366
371
377
378};
379
383struct PilsRequest
384{
388 struct PilsRequest *prev;
389
393 struct PilsRequest *next;
394
399};
400
405
410
411
416
421
426
432
437
441static char *my_services_info = "";
442
443static void
444buffer_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
458static void
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);
474 sizeof kx->master_secret);
476 sizeof kx->early_secret_key);
478 sizeof kx->early_traffic_secret);
480 sizeof kx->handshake_secret);
481}
482
483
484static void
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
500static void
502{
504
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);
512}
513
514
515static void
517
525static void
526send_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;
535 if (0 == left.rel_value_us)
536 {
538 gettext_noop ("# sessions terminated by timeout"),
539 1,
540 GNUNET_NO);
541 GSC_SESSIONS_end (&kx->peer);
544 restart_kx (kx);
545 return;
546 }
548 "Sending HEARTBEAT to `%s'\n",
549 GNUNET_i2s (&kx->peer));
551 gettext_noop ("# heartbeat messages sent"),
552 1,
553 GNUNET_NO);
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);
561 kx->heartbeat_task =
563}
564
565
573static void
575{
577
578 kx->timeout =
580 delta =
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) */
587 }
588 if (NULL != kx->heartbeat_task)
593 kx);
594}
595
596
602static void
604
605
617static int
618deliver_message (void *cls, const struct GNUNET_MessageHeader *m)
619{
620 struct GSC_KeyExchangeInfo *kx = cls;
621
623 "Decrypted message of type %d from %s\n",
624 ntohs (m->type),
625 GNUNET_i2s (&kx->peer));
627 m,
628 ntohs (m->size),
631 m,
632 sizeof(struct GNUNET_MessageHeader),
634 return GNUNET_OK;
635}
636
637
638static void
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
650 "Initiating key exchange with peer %s\n",
651 GNUNET_i2s (&kx->peer));
653 gettext_noop ("# key exchanges initiated"),
654 1,
655 GNUNET_NO);
656
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)
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 */
670 "I am the initiator, sending hello\n");
671 kx->role = ROLE_INITIATOR;
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 */
679 "I am the responder, yielding and await initiator hello\n");
681 kx->role = ROLE_RESPONDER;
683 }
684}
685
686
697static void *
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;
706 GNUNET_assert (NULL != my_identity);
707 if (0 == memcmp (peer_id, my_identity, sizeof *peer_id))
708 {
710 "Ignoring connection to self\n");
711 return NULL;
712 }
714 "Incoming connection of peer with %s\n",
716
717 /* Set up kx struct */
718 kx = GNUNET_new (struct GSC_KeyExchangeInfo);
720 kx->mq = mq;
721 GNUNET_memcpy (&kx->peer, peer_id, sizeof (struct GNUNET_PeerIdentity));
723
724 restart_kx (kx);
725 return kx;
726}
727
728
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 */
774static void
775derive_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 }
794 ets,
795 sizeof (*ets),
796 es,
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 */
813static void
814derive_sn (const struct GNUNET_ShortHashCode *secret,
815 unsigned char*sn,
816 size_t sn_len)
817{
820 sn,
821 sn_len,
822 secret,
825}
826
827
832static void
834 const struct GNUNET_ShortHashCode *ss_e,
836{
837 uint64_t ret;
838 struct GNUNET_ShortHashCode derived_early_secret;
839
840 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deriving HS\n");
842 );
843 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ss_e: %s\n", GNUNET_B2S (ss_e));
845 &derived_early_secret,
846 sizeof (derived_early_secret),
847 es,
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
878static void
879derive_ihts (const struct GNUNET_HashCode *transcript,
880 const struct GNUNET_ShortHashCode *hs,
881 struct GNUNET_ShortHashCode *ihts)
882{
885 ihts, // result
886 sizeof (*ihts), // result len
887 hs, // prk?
890 GNUNET_CRYPTO_kdf_arg_auto (transcript)));
891}
892
893
898static void
899derive_rhts (const struct GNUNET_HashCode *transcript,
900 const struct GNUNET_ShortHashCode *hs,
901 struct GNUNET_ShortHashCode *rhts)
902{
905 rhts,
906 sizeof (*rhts),
907 hs, // prk? TODO
910 GNUNET_CRYPTO_kdf_arg_auto (transcript)));
911}
912
913
918static void
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
927 &derived_handshake_secret,
928 sizeof (derived_handshake_secret),
929 hs,
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
958static void
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,
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
983static void
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 */
994 key,
996 ts,
999
1000 /* derive nonce */
1003 nonce_tmp,
1005 ts,
1009 nonce_tmp,
1010 nonce);
1011}
1012
1013
1018static void
1020 struct GNUNET_ShortHashCode *new_ats)
1021{
1022 int8_t ret;
1023
1024 // FIXME: Not sure of PRK and output may overlap here!
1026 new_ats,
1027 sizeof (*new_ats),
1028 old_ats,
1031 if (GNUNET_OK != ret)
1032 {
1034 "Something went wrong deriving next *ATS key\n");
1035 GNUNET_assert (0);
1036 }
1037}
1038
1039
1044static void
1045derive_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;
1058 initial_ats, // result
1059 sizeof (*initial_ats), // result len
1060 ms,
1062 GNUNET_CRYPTO_kdf_arg_string (traffic_str),
1063 GNUNET_CRYPTO_kdf_arg_auto (transcript)));
1064}
1065
1066
1073static void
1075 const struct GNUNET_ShortHashCode *ms,
1076 struct GNUNET_HashCode *result)
1077{
1079 struct GNUNET_CRYPTO_AuthKey fk_R; // We might want to save this in kx?
1080
1082 &fk_R, // result
1083 sizeof (fk_R),
1084 ms,
1087 if (GNUNET_OK != ret)
1088 {
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
1107static void
1109 const struct GNUNET_ShortHashCode *ms,
1110 struct GNUNET_HashCode *result)
1111{
1113 struct GNUNET_CRYPTO_AuthKey fk_I; // We might want to save this in kx?
1114
1116 &fk_I, // result
1117 sizeof (fk_I),
1118 ms,
1121 if (GNUNET_OK != ret)
1122 {
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
1140
1141static void
1143{
1144 struct GSC_KeyExchangeInfo *kx = cls;
1145
1146 kx->resend_task = NULL;
1147 if (0 == kx->resend_tries_left)
1148 {
1150 "Restarting KX\n");
1151 restart_kx (kx);
1152 return;
1153 }
1154 kx->resend_tries_left--;
1156 "Resending responder hello. Retries left: %u\n",
1157 kx->resend_tries_left);
1161 kx);
1162}
1163
1164
1165void
1167{
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 {
1191 "Something went wrong encapsulating ss_e\n");
1192 return;
1193 }
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 {
1202 "Something went wrong encapsulating ss_I\n");
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
1212 "Transcript snapshot for derivation of HS, MS: `%s'\n",
1213 GNUNET_h2s (&transcript));
1214#endif
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,
1236
1237 rhm_e->r_R =
1239 UINT64_MAX);
1240
1241 // c_e
1242 GNUNET_memcpy (&rhm_e->c_e,
1243 &ephemeral_kem_challenge,
1244 sizeof (ephemeral_kem_challenge));
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;
1253 &transcript);
1254#if DEBUG_KX
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);
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],
1275 strlen (my_services_info));
1276
1277 {
1278 unsigned long long out_ct_len;
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
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 */
1300 hc,
1301 &rhm_e[1],
1302 out_ct_len);
1303
1304 finished_buf = ((unsigned char*) &rhm_e[1]) + out_ct_len;
1306 &transcript);
1307#if DEBUG_KX
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
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
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) */
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
1345 &transcript);
1346#if DEBUG_KX
1348 "Transcript snapshot for derivation of *ATS: `%s'\n",
1349 GNUNET_h2s (&transcript));
1350#endif
1351 derive_initial_ats (&transcript,
1352 &ms,
1354 &kx->current_ats);
1355 }
1356 /* Lock into struct */
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;
1368 kx->current_sqn,
1369 enc_key,
1370 enc_nonce);
1371
1372 GNUNET_MQ_send_copy (kx->mq, env);
1373 kx->resend_env = env;
1375 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent ResponderHello: %d %d\n", kx->role,
1376 kx->status);
1377
1380 kx);
1382 monitor_notify_all (kx);
1383 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
1384}
1385
1386
1387static void
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;
1401
1402 ihm_ctx->req->op = NULL;
1405 ihm_ctx->req);
1406 GNUNET_free (ihm_ctx->req);
1407
1408
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 */
1421 ihm_ctx->ihm_e,
1422 sizeof (struct InitiatorHello));
1424 &transcript);
1425#if DEBUG_KX
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);
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 {
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 */
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 */
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);
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;
1508}
1509
1510
1511static int
1512check_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)
1519 {
1520 return GNUNET_SYSERR;
1521 }
1522 return GNUNET_OK;
1523}
1524
1525
1534static void
1535handle_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);
1546 "I am an initiator! Tearing down...\n");
1547 return;
1548 }
1550 {
1551 GNUNET_break_op (0);
1553 "Already received InitiatorHello: %d %d\n", kx->role, kx->status
1554 );
1555 return;
1556 }
1558 (NULL != kx->transcript_hash_ctx))
1559 {
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);
1570
1572 gettext_noop ("# key exchanges initiated"),
1573 1,
1574 GNUNET_NO);
1575
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 {
1592 "This message is not meant for us (H(PID) mismatch)\n");
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);
1607 initiator_hello_cls->req);
1608 initiator_hello_cls->req->op =
1610 &ihm_e->c_R,
1611 // encapsulated key
1613 // continuation
1614 initiator_hello_cls);
1615}
1616
1617
1619{
1620 /* Current KX session */
1622
1623 /* responder hello message - encrypted */
1625
1626 /* responder hello message - plain/decrypted */
1628
1629 /* Decrypted finish hash */
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 */
1638
1639 /* Temporary handshake secret */
1641
1642 /* Temporary handshake secret */
1644
1645 /* Temporary handshake secret */
1647
1648 /* Temporary handshake secret */
1650
1651 /* Pending PILS request */
1653};
1654
1655static void
1657{
1658 struct GSC_KeyExchangeInfo *kx = cls;
1659
1660 kx->resend_task = NULL;
1661 if (0 == kx->resend_tries_left)
1662 {
1664 "Restarting KX\n");
1665 restart_kx (kx);
1666 return;
1667 }
1668 kx->resend_tries_left--;
1670 "Resending initiator done. Retries left: %u\n",
1671 kx->resend_tries_left);
1675 kx);
1676}
1677
1678
1679static void
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;
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
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 {
1726 "Could not verify \"responder finished\"\n");
1727 GNUNET_free (rh_ctx->rhp);
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 */
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
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
1757 &transcript);
1758#if DEBUG_KX
1760 "Transcript snapshot for derivation of *ATS: `%s'\n",
1761 GNUNET_h2s (&transcript));
1762#endif
1763 derive_initial_ats (&transcript,
1764 &kx->master_secret,
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
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)
1784 // 6. Create IteratorFinished as per Section 6.
1785 generate_initiator_finished (&transcript,
1786 &kx->master_secret,
1787 &idm_p->finished);
1789 "InteratorFinished: `%s'\n",
1790 GNUNET_h2s (&idm_p->finished));
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 */
1810 &idm_e->finished,
1811 sizeof (idm_e->finished)
1812 + AEAD_TAG_BYTES);
1814 &transcript);
1815#if DEBUG_KX
1817 "Transcript snapshot for derivation of *ATS: `%s'\n",
1818 GNUNET_h2s (&transcript));
1819#endif
1820 derive_initial_ats (&transcript,
1821 &kx->master_secret,
1823 &kx->current_ats);
1824 kx->current_epoch = 0;
1825 kx->current_sqn++;
1826 // 8. optionally encrypt payload TODO
1828 kx->current_sqn,
1829 enc_key,
1830 enc_nonce);
1831 kx->current_sqn++;
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;
1854 kx);
1856 monitor_notify_all (kx);
1857 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
1858}
1859
1860
1861static int
1862check_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
1882static void
1883handle_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];
1893
1894 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ResponderHello: %d %d\n", kx->
1895 role, kx->status);
1896
1898 if (NULL != kx->resend_task)
1899 {
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);
1914 "I am the responder! Ignoring.\n");
1916 return;
1917 }
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 {
1934 "Something went wrong decapsulating ss_e\n");
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
1942 "Transcript snapshot for derivation of HS, *HTS: `%s'\n",
1943 GNUNET_h2s (&transcript));
1944#endif
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);
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 -
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*/
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 {
1994 "Something went wrong decrypting: %d\n", ret);
1995 GNUNET_free (rh_ctx->rhp);
1996 GNUNET_free (rh_ctx);
1998 return;
1999 }
2000 // FIXME nonce reuse (see encryption)
2002 1,
2003 enc_key,
2004 enc_nonce);
2005 c_len = sizeof (struct GNUNET_HashCode)
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 {
2021 "Something went wrong decrypting finished field: %d\n", ret);
2022 GNUNET_free (rh_ctx->rhp);
2023 GNUNET_free (rh_ctx);
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;
2036 req);
2038 &rh_ctx->rhp->c_I, // encapsulated key
2039 &handle_responder_hello_cont, // continuation
2040 rh_ctx);
2041}
2042
2043
2044static int
2045check_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
2062static void
2063handle_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 {
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);
2094 "I am the initiator! Tearing down...\n");
2095 return;
2096 }
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
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 {
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 {
2135 "Could not verify \"initiator finished\" hash.\n");
2137 "Want: `%s'\n",
2138 GNUNET_h2s (&initiator_finished));
2140 "Have: `%s'\n",
2141 GNUNET_h2s (&idm_p->finished));
2143 "Transcript `%s'\n",
2144 GNUNET_h2s (&transcript));
2145 return;
2146 }
2147
2148 /* Forward the transcript hash_context_read */
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,
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 {
2177 "Something went wrong decrypting the Ack: %d\n", ret);
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 {
2185 "Ack invalid!\n");
2187 return;
2188 }
2189 GNUNET_memcpy (&kx->their_ats[0],
2190 &their_ats,
2191 sizeof their_ats);
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 }
2201 kx->transcript_hash_ctx = hc;
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);
2212 ack_r.header.size = htons (sizeof ack_r);
2214 &ack_r,
2215 sizeof ack_r);
2216
2217 GNUNET_TRANSPORT_core_receive_continue (transport,
2218 &kx->peer);
2219}
2220
2221
2227static int
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
2249static void
2251 const struct Heartbeat *m)
2252{
2253 struct GNUNET_ShortHashCode new_ats;
2254 struct ConfirmationAck ack;
2255
2257 {
2258 if (kx->current_epoch == UINT64_MAX)
2259 {
2261 "Max epoch reached (you probably will never see this)\n");
2262 }
2263 else
2264 {
2265 kx->current_epoch++;
2268 kx->current_sqn = 0;
2270 &new_ats);
2271 memcpy (&kx->current_ats,
2272 &new_ats,
2273 sizeof new_ats);
2274 }
2275 }
2276 update_timeout (kx);
2278 ack.header.size = htons (sizeof ack);
2280 &ack,
2281 sizeof ack);
2282 if (NULL != kx->heartbeat_task)
2283 {
2287 kx);
2288 }
2289 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
2290}
2291
2292
2293static enum GNUNET_GenericReturnValue
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
2327 {
2328 GSC_SESSIONS_create (&kx->peer, kx, kx->class);
2333 if (NULL != 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
2352static void
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
2376 {
2377 GSC_SESSIONS_end (&kx->peer);
2379 monitor_notify_all (kx);
2380 restart_kx (kx);
2381 return;
2382 }
2383 update_timeout (kx);
2384 epoch = GNUNET_ntohll (m->epoch);
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 {
2401 if ((epoch - kx->their_max_epoch) > 2 * MAX_EPOCHS)
2402 {
2404 "Epoch %" PRIu64 " is too new, will not decrypt...\n",
2405 epoch);
2406 GSC_SESSIONS_end (&kx->peer);
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 {
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);
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 {
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
2497 buf,
2498 sizeof buf))
2499 {
2501 {
2503 "Dropping message as we are still waiting for handshake ACK\n");
2504 GNUNET_break_op (0);
2505 return;
2506 }
2507 if (GNUNET_OK !=
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
2528static void
2530 const struct GNUNET_PeerIdentity *peer,
2531 void *handler_cls)
2532{
2533 struct GSC_KeyExchangeInfo *kx = handler_cls;
2534 (void) cls;
2535
2537 "Peer `%s' disconnected from us.\n",
2538 GNUNET_i2s (&kx->peer));
2539 GSC_SESSIONS_end (&kx->peer);
2541 gettext_noop ("# key exchanges stopped"),
2542 1,
2543 GNUNET_NO);
2544 if (NULL != kx->resend_task)
2545 {
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 {
2557 kx->heartbeat_task = NULL;
2558 }
2560 monitor_notify_all (kx);
2561 if (kx->transcript_hash_ctx)
2562 {
2564 kx->transcript_hash_ctx = NULL;
2565 }
2567 GNUNET_MST_destroy (kx->mst);
2568 GNUNET_free (kx);
2569}
2570
2571
2572static void
2574{
2575 struct GSC_KeyExchangeInfo *kx = cls;
2576
2577 kx->resend_task = NULL;
2579 "Resending InitiatorHello.\n");
2581 // FIXME (Exponential) backoff?
2584 kx);
2585}
2586
2587
2593static void
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];
2607 size_t pt_len;
2608
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,
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,
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);
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 {
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 =
2647 UINT64_MAX);
2648 // 3. generate sk_e/pk_e - ephemeral key
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
2661 ihm_e,
2662 sizeof (struct InitiatorHello));
2663 {
2664 struct GNUNET_HashCode transcript;
2666 &transcript);
2667 derive_es_ets (&transcript,
2668 &ss_R,
2669 &es,
2670 &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");
2694 kx->transcript_hash_ctx = NULL;
2696 return;
2697 }
2698 /* Forward the transcript */
2701 &ihm_e[1],
2702 c_len);
2703
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;
2714 kx);
2715}
2716
2717
2718static void
2720{
2721 struct GNUNET_ShortHashCode new_ats;
2722
2723 if ((UINT64_MAX == kx->current_sqn) ||
2725 {
2727 "Epoch expiration %" PRIu64 " SQN %" PRIu64
2728 ", incrementing epoch...\n",
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++;
2737 kx->current_sqn = 0;
2739 &new_ats);
2740 memcpy (&kx->current_ats,
2741 &new_ats,
2742 sizeof new_ats);
2743 }
2744}
2745
2746
2753void
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 */
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,
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 {
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
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
2844void
2846{
2847 const struct GNUNET_PeerIdentity *my_identity;
2849 GNUNET_MQ_hd_var_size (initiator_hello,
2851 struct InitiatorHello,
2852 NULL),
2853 GNUNET_MQ_hd_var_size (initiator_done,
2855 struct InitiatorDone,
2856 NULL),
2857 GNUNET_MQ_hd_var_size (responder_hello,
2859 struct ResponderHello,
2860 NULL),
2861 GNUNET_MQ_hd_var_size (encrypted_message, // TODO rename?
2863 struct EncryptedMessage,
2864 NULL),
2866 };
2867
2869 GNUNET_assert (NULL != my_identity);
2870
2872 transport =
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
2884 if (NULL == transport)
2885 {
2886 GSC_KX_done ();
2887 return;
2888 }
2889
2891 "Connected to TRANSPORT\n");
2892
2894}
2895
2896
2897void
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
2914int
2916{
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
2933void
2935{
2936 struct PilsRequest *pr;
2937 while (NULL != (pr = pils_requests_head))
2938 {
2941 pr);
2942 if (NULL != pr->op)
2943 GNUNET_PILS_cancel (pr->op);
2944 GNUNET_free (pr);
2945 }
2946 if (NULL != GSC_pils)
2947 {
2949 GSC_pils = NULL;
2950 }
2951 if (NULL != transport)
2952 {
2954 transport = NULL;
2955 }
2956 if (NULL != rekey_task)
2957 {
2959 rekey_task = NULL;
2960 }
2961 if (NULL != nc)
2962 {
2964 nc = NULL;
2965 }
2966}
2967
2968
2975unsigned int
2977{
2978 return GNUNET_MQ_get_length (kxinfo->mq);
2979}
2980
2981
2982int
2984{
2985 return kxinfo->has_excess_bandwidth;
2986}
2987
2988
2997void
2999{
3000 struct GNUNET_MQ_Envelope *env;
3001 struct MonitorNotifyMessage *done_msg;
3002 struct GSC_KeyExchangeInfo *kx;
3003
3005 for (kx = kx_head; NULL != kx; kx = kx->next)
3006 {
3007 struct GNUNET_MQ_Envelope *env_notify;
3008 struct MonitorNotifyMessage *msg;
3009
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 }
3017 done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED);
3020}
3021
3022
3023/* end of gnunet-service-core_kx.c */
struct GNUNET_MQ_MessageHandlers handlers[]
Definition 003.c:1
struct GNUNET_MessageHeader * msg
Definition 005.c:2
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
#define GNUNET_CORE_OPTION_SEND_FULL_INBOUND
Client wants all inbound messages in full.
Definition core.h:53
#define GNUNET_CORE_OPTION_SEND_HDR_INBOUND
Client just wants the 4-byte message headers of all inbound messages.
Definition core.h:59
#define gettext_noop(String)
Definition gettext.h:74
static struct GNUNET_ARM_MonitorHandle * m
Monitor connection with ARM.
Definition gnunet-arm.c:103
static int ret
Final status code.
Definition gnunet-arm.c:93
static char * peer_id
Option –peer.
static bool finished
Set to true once we are finished and should exit after sending our final message to the parent.
struct GNUNET_HashCode key
The key used in the DHT.
static int result
Global testing status.
static struct GNUNET_PeerIdentity my_identity
Identity of this peer.
const struct GNUNET_CONFIGURATION_Handle * GSC_cfg
Our configuration.
void GSC_complete_initialization_cb(void)
This function is called from GSC_KX_init() once it got its peer id from pils.
void GSC_CLIENTS_deliver_message(const struct GNUNET_PeerIdentity *sender, const struct GNUNET_MessageHeader *msg, uint16_t msize, uint32_t options)
Deliver P2P message to interested clients.
struct GNUNET_PILS_Handle * GSC_pils
For peer identity access.
struct GNUNET_STATISTICS_Handle * GSC_stats
For creating statistics.
Globals for gnunet-service-core.
#define RESEND_MAX_TRIES
Number of times we try to resend a handshake flight.
static void * handle_transport_notify_connect(void *cls, const struct GNUNET_PeerIdentity *peer_id, struct GNUNET_MQ_Handle *mq)
Function called by transport to notify us that a peer connected to us (on the network level).
static void cleanup_handshake_secrets(struct GSC_KeyExchangeInfo *kx)
unsigned int GSC_NEIGHBOURS_get_queue_length(const struct GSC_KeyExchangeInfo *kxinfo)
Check how many messages are queued for the given neighbour.
int GSC_NEIGHBOURS_check_excess_bandwidth(const struct GSC_KeyExchangeInfo *kxinfo)
Check if the given neighbour has excess bandwidth available.
static int check_initiator_hello(void *cls, const struct InitiatorHello *m)
static int check_responder_hello(void *cls, const struct ResponderHello *m)
static struct GSC_KeyExchangeInfo * kx_tail
DLL tail.
static int check_initiator_done(void *cls, const struct InitiatorDone *m)
void GSC_KX_handle_client_monitor_peers(struct GNUNET_MQ_Handle *mq)
Handle GNUNET_MESSAGE_TYPE_CORE_MONITOR_PEERS request.
static void generate_per_record_nonce(uint64_t seq, const uint8_t write_iv[crypto_aead_xchacha20poly1305_ietf_NPUBBYTES], uint8_t per_record_write_iv[crypto_aead_xchacha20poly1305_ietf_NPUBBYTES])
Generate per record nonce as per https://www.rfc-editor.org/rfc/rfc8446#section-5....
static void handle_responder_hello(void *cls, const struct ResponderHello *rhm_e)
Handle Responder Hello message.
static void send_heartbeat(void *cls)
Task triggered when a neighbour entry is about to time out (and we should prevent this by sending an ...
#define IV_STR
String for expanding derived keys (Handshake and Early) (See https://lsd.gnunet.org/lsd0012/draft-sch...
#define AEAD_TAG_BYTES
libsodium has very long symbol names
#define I_AP_TRAFFIC_STR
String for expanding IATS (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake....
void GSC_KX_start(void)
#define I_FINISHED_STR
String for expanding fk_I used for InitiatorFinished field (See https://lsd.gnunet....
static char * my_services_info
Our services info string TODO.
static void resend_responder_hello(void *cls)
static void handle_transport_notify_disconnect(void *cls, const struct GNUNET_PeerIdentity *peer, void *handler_cls)
Function called by transport telling us that a peer disconnected.
#define MAX_EPOCHS
Maximum number of epochs we keep on hand.
static void derive_ihts(const struct GNUNET_HashCode *transcript, const struct GNUNET_ShortHashCode *hs, struct GNUNET_ShortHashCode *ihts)
Derive the initiator handshake secret.
#define R_FINISHED_STR
String for expanding fk_R used for ResponderFinished field (See https://lsd.gnunet....
static void derive_initial_ats(const struct GNUNET_HashCode *transcript, const struct GNUNET_ShortHashCode *ms, enum GSC_KX_Role role, struct GNUNET_ShortHashCode *initial_ats)
Derive the initiator application secret.
static struct GNUNET_NotificationContext * nc
Notification context for broadcasting to monitors.
#define AEAD_NONCE_BYTES
libsodium has very long symbol names
void GSC_KX_encrypt_and_transmit(struct GSC_KeyExchangeInfo *kx, const void *payload, size_t payload_size)
Encrypt and transmit payload.
static struct PilsRequest * pils_requests_head
PILS Operation DLL.
static void check_rekey(struct GSC_KeyExchangeInfo *kx)
#define R_AP_TRAFFIC_STR
String for expanding RATS (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake....
static void derive_next_ats(const struct GNUNET_ShortHashCode *old_ats, struct GNUNET_ShortHashCode *new_ats)
Derive the next application secret.
static void buffer_clear(void *buf, size_t len)
static void derive_per_message_secrets(const struct GNUNET_ShortHashCode *ts, uint64_t seq, unsigned char key[crypto_aead_xchacha20poly1305_ietf_KEYBYTES], unsigned char nonce[crypto_aead_xchacha20poly1305_ietf_NPUBBYTES])
key = HKDF-Expand [I,R][A,H]TS, "key", 32) nonce = HKDF-Expand ([I,R][A,H]TS, "iv",...
static void derive_rhts(const struct GNUNET_HashCode *transcript, const struct GNUNET_ShortHashCode *hs, struct GNUNET_ShortHashCode *rhts)
Derive the responder handshake secret.
static void generate_responder_finished(const struct GNUNET_HashCode *transcript, const struct GNUNET_ShortHashCode *ms, struct GNUNET_HashCode *result)
Generate the responder finished field.
static void handle_responder_hello_cont(void *cls, const struct GNUNET_ShortHashCode *ss_I)
static struct GSC_KeyExchangeInfo * kx_head
DLL head.
#define AEAD_KEY_BYTES
libsodium has very long symbol names
GSC_KX_Role
Indicates whether a peer is in the initiating or receiving role.
static void generate_initiator_finished(const struct GNUNET_HashCode *transcript, const struct GNUNET_ShortHashCode *ms, struct GNUNET_HashCode *result)
Generate the initiator finished field.
static struct PilsRequest * pils_requests_tail
PILS Operation DLL.
static void snapshot_transcript(const struct GNUNET_HashContext *ts_hash, struct GNUNET_HashCode *snapshot)
static void derive_sn(const struct GNUNET_ShortHashCode *secret, unsigned char *sn, size_t sn_len)
#define MIN_HEARTBEAT_FREQUENCY
What is the minimum frequency for a heartbeat message?
void GSC_KX_done()
Shutdown KX subsystem.
static void derive_ms(const struct GNUNET_ShortHashCode *hs, const struct GNUNET_ShortHashCode *ss_I, struct GNUNET_ShortHashCode *ms)
Derive the master secret.
#define KEY_STR
String for expanding derived keys (Handshake and Early) (See https://lsd.gnunet.org/lsd0012/draft-sch...
static void update_timeout(struct GSC_KeyExchangeInfo *kx)
We've seen a valid message from the other peer.
static void derive_hs(const struct GNUNET_ShortHashCode *es, const struct GNUNET_ShortHashCode *ss_e, struct GNUNET_ShortHashCode *handshake_secret)
Derive the handshake secret.
static void send_initiator_hello(struct GSC_KeyExchangeInfo *kx)
Send initiator hello.
#define I_HS_TRAFFIC_STR
String for expanding IHTS (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake....
#define EARLY_DATA_STR
String for expanding early transport secret (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake....
static void handle_initiator_hello(void *cls, const struct InitiatorHello *ihm_e)
Handle the InitiatorHello message.
static void handle_encrypted_message(void *cls, const struct EncryptedMessage *m)
handle an encrypted message
static void derive_es_ets(const struct GNUNET_HashCode *transcript, const struct GNUNET_ShortHashCode *ss_R, struct GNUNET_ShortHashCode *es, struct GNUNET_ShortHashCode *ets)
TODO propose a new scheme: don't choose an initiator and responder based on hashing the peer ids,...
static int deliver_message(void *cls, const struct GNUNET_MessageHeader *m)
Deliver P2P message to interested clients.
static enum GNUNET_GenericReturnValue check_if_ack_or_heartbeat(struct GSC_KeyExchangeInfo *kx, const char *buf, size_t buf_len)
#define DERIVED_STR
String for expanding derived keys (Handshake and Early) (See https://lsd.gnunet.org/lsd0012/draft-sch...
static int check_encrypted_message(void *cls, const struct EncryptedMessage *m)
Check an incoming encrypted message before handling it.
static void resend_initiator_hello(void *cls)
#define EPOCH_EXPIRATION
How often do we rekey/switch to a new epoch?
static void resend_initiator_done(void *cls)
static void monitor_notify_all(struct GSC_KeyExchangeInfo *kx)
Inform all monitors about the KX state of the given peer.
static struct GNUNET_SCHEDULER_Task * rekey_task
Task scheduled for periodic re-generation (and thus rekeying) of our ephemeral key.
void pid_change_cb(void *cls, const struct GNUNET_HELLO_Parser *parser, const struct GNUNET_HashCode *hash)
#define CAKE_LABEL
Labeled expand label for CAKE.
int GSC_KX_init(void)
Initialize KX subsystem.
static void restart_kx(struct GSC_KeyExchangeInfo *kx)
static void handle_initiator_hello_cont(void *cls, const struct GNUNET_ShortHashCode *ss_R)
static struct GNUNET_TRANSPORT_CoreHandle * transport
Transport service.
static void handle_heartbeat(struct GSC_KeyExchangeInfo *kx, const struct Heartbeat *m)
Handle a key update.
static void handle_initiator_done(void *cls, const struct InitiatorDone *idm_e)
Handle InitiatorDone message.
#define R_HS_TRAFFIC_STR
String for expanding RHTS (See https://lsd.gnunet.org/lsd0012/draft-schanzen-cake....
void send_responder_hello(struct GSC_KeyExchangeInfo *kx)
#define RESEND_TIMEOUT
#define TRAFFIC_UPD_STR
String for expanding derived keys (Handshake and Early) (See https://lsd.gnunet.org/lsd0012/draft-sch...
code for managing the key exchange (SET_KEY, PING, PONG) with other peers
@ GSC_HEARTBEAT_KEY_UPDATE_REQUESTED
A key update is requested.
void GSC_SESSIONS_end(const struct GNUNET_PeerIdentity *pid)
End the session with the given peer (we are no longer connected).
void GSC_SESSIONS_create(const struct GNUNET_PeerIdentity *peer, struct GSC_KeyExchangeInfo *kx, enum GNUNET_CORE_PeerClass class)
Create a session, a key exchange was just completed.
static unsigned long long payload
How much data are we currently storing in the database?
static struct GNUNET_Process * p
Helper process we started.
Definition gnunet-uri.c:38
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
struct GNUNET_PILS_Handle * GNUNET_PILS_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_PILS_PidChangeCallback pid_change_cb, void *cls)
Connect to the PILS service.
Definition pils_api.c:465
void GNUNET_PILS_disconnect(struct GNUNET_PILS_Handle *handle)
Disconnect from the PILS service.
Definition pils_api.c:488
const struct GNUNET_HashCode * GNUNET_PILS_get_identity_hash(const struct GNUNET_PILS_Handle *handle)
Return the hash of the current peer identity from a given handle.
Definition pils_api.c:736
void GNUNET_PILS_cancel(struct GNUNET_PILS_Operation *op)
Cancel request.
Definition pils_api.c:623
const struct GNUNET_PeerIdentity * GNUNET_PILS_get_identity(const struct GNUNET_PILS_Handle *handle)
Return the current peer identity of a given handle.
Definition pils_api.c:727
struct GNUNET_PILS_Operation * GNUNET_PILS_kem_decaps(struct GNUNET_PILS_Handle *handle, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, GNUNET_PILS_DecapsResultCallback cb, void *cb_cls)
Decaps an encapsulated key with our private key.
Definition pils_api.c:568
Constants for network protocols.
API of the transport service towards the CORE service (TNG version)
struct GNUNET_TRANSPORT_CoreHandle * GNUNET_TRANSPORT_core_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const struct GNUNET_PeerIdentity *self, const struct GNUNET_MQ_MessageHandler *handlers, void *cls, GNUNET_TRANSPORT_NotifyConnect nc, GNUNET_TRANSPORT_NotifyDisconnect nd)
Connect to the transport service.
void GNUNET_TRANSPORT_core_disconnect(struct GNUNET_TRANSPORT_CoreHandle *handle)
Disconnect from the transport service.
#define GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT
After how long do we consider a connection to a peer dead if we don't receive messages from the peer?
GNUNET_CORE_PeerClass
The peer class gives a hint about the capabilities of a peer.
GNUNET_CORE_KxState
TODO how does this harmonize with CAKE_CRYPTO_ENABLED?
@ GNUNET_CORE_CLASS_UNKNOWN
The device's capabilities are currently unknown.
@ GNUNET_CORE_KX_PEER_DISCONNECT
Last state of a KX (when it is being terminated).
@ GNUNET_CORE_KX_STATE_RESPONDER_CONNECTED
Connected as responder.
@ GNUNET_CORE_KX_STATE_DOWN
No handshake yet.
@ GNUNET_CORE_KX_STATE_INITIATOR_DONE_SENT
We sent initiator done.
@ GNUNET_CORE_KX_STATE_INITIATOR_HELLO_RECEIVED
We've received the initiator hello.
@ GNUNET_CORE_KX_STATE_AWAIT_INITIATION
We are awating the initiator hello.
@ GNUNET_CORE_KX_STATE_INITIATOR_CONNECTED
Connected as initiator.
@ GNUNET_CORE_KX_STATE_INITIATOR_HELLO_SENT
We sent the initiator hello.
@ GNUNET_CORE_KX_STATE_RESPONDER_HELLO_SENT
We sent the responder hello.
@ GNUNET_CORE_KX_ITERATION_FINISHED
This is not a state in a peer's state machine, but a special value used with the GNUNET_CORE_MonitorC...
void GNUNET_CRYPTO_ecdhe_key_create(struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
Create a new private key.
Definition crypto_ecc.c:454
uint64_t GNUNET_CRYPTO_random_u64(enum GNUNET_CRYPTO_Quality mode, uint64_t max)
Generate a random unsigned 64-bit value.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hpke_kem_decaps(const struct GNUNET_CRYPTO_HpkePrivateKey *priv, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Decapsulate a key for a private X25519 key.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hpke_kem_encaps(const struct GNUNET_CRYPTO_HpkePublicKey *pkR, struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Encapsulate key material for a X25519 public key.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_eddsa_kem_encaps(const struct GNUNET_CRYPTO_EddsaPublicKey *pub, struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Encapsulate key material for a EdDSA public key.
void GNUNET_CRYPTO_ecdhe_key_get_public(const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, struct GNUNET_CRYPTO_EcdhePublicKey *pub)
Extract the public key for the given private key.
Definition crypto_ecc.c:217
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hkdf_extract(struct GNUNET_ShortHashCode *prk, const void *salt, size_t salt_len, const void *ikm, size_t ikm_len)
HKDF-Extract using SHA256.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition crypto_hash.c:41
void GNUNET_CRYPTO_hmac(const struct GNUNET_CRYPTO_AuthKey *key, const void *plaintext, size_t plaintext_len, struct GNUNET_HashCode *hmac)
Calculate HMAC of a message (RFC 2104)
#define GNUNET_CRYPTO_hkdf_expand(result, out_len, prk,...)
HKDF-Expand using SHA256.
int GNUNET_CRYPTO_hash_cmp(const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2)
Compare function for HashCodes, producing a total ordering of all hashcodes.
uint16_t type
The type of the message (GNUNET_MESSAGE_TYPE_XXXX), in big-endian format.
#define GNUNET_log(kind,...)
#define GNUNET_B2S(obj)
Convert a fixed-sized object to a string using GNUNET_b2s().
void GNUNET_CRYPTO_hash_context_read(struct GNUNET_HashContext *hc, const void *buf, size_t size)
Add data to be hashed.
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_copy(const struct GNUNET_HashContext *hc)
Make a copy of the hash computation.
#define GNUNET_CRYPTO_kdf_arg_string(d)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
void * cls
Closure for mv and cb.
void GNUNET_CRYPTO_hash_context_abort(struct GNUNET_HashContext *hc)
Abort hashing, do not bother calculating final result.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
void GNUNET_CRYPTO_hash_context_finish(struct GNUNET_HashContext *hc, struct GNUNET_HashCode *r_hash)
Finish the hash computation.
#define GNUNET_ALIGN
gcc-ism to force alignment; we use this to align char-arrays that may then be cast to 'struct's.
#define GNUNET_CRYPTO_kdf_arg_auto(d)
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format.
struct GNUNET_HashContext * GNUNET_CRYPTO_hash_context_start(void)
Start incremental hashing operation.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
void GNUNET_print_bytes(const void *buf, size_t buf_len, int fold, int in_be)
Print a byte string in hexadecimal ascii notation.
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_notification_context_destroy(struct GNUNET_NotificationContext *nc)
Destroy the context, force disconnect for all subscribers.
Definition nc.c:138
void GNUNET_MQ_send_copy(struct GNUNET_MQ_Handle *mq, const struct GNUNET_MQ_Envelope *ev)
Send a copy of a message with the given message queue.
Definition mq.c:384
unsigned int GNUNET_MQ_get_length(struct GNUNET_MQ_Handle *mq)
Obtain the current length of the message queue.
Definition mq.c:293
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition mq.c:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition mq.c:285
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
struct GNUNET_NotificationContext * GNUNET_notification_context_create(unsigned int queue_length)
Create a new notification context.
Definition nc.c:122
void GNUNET_notification_context_broadcast(struct GNUNET_NotificationContext *nc, const struct GNUNET_MessageHeader *msg, int can_drop)
Send a message to all subscribers of this context.
Definition nc.c:190
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
void GNUNET_notification_context_add(struct GNUNET_NotificationContext *nc, struct GNUNET_MQ_Handle *mq)
Add a subscriber to the notification context.
Definition nc.c:161
#define GNUNET_MESSAGE_TYPE_CORE_HEARTBEAT
Message updating the keys of the peers.
#define GNUNET_MESSAGE_TYPE_CORE_ACK
Acknowledgement of prior messages.
#define GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE_CAKE
Encrypted message.
#define GNUNET_MESSAGE_TYPE_CORE_MONITOR_NOTIFY
Reply for monitor by CORE service.
#define GNUNET_MESSAGE_TYPE_CORE_INITIATOR_DONE
Third and final message of the handshake, second of the initiator.
#define GNUNET_MESSAGE_TYPE_CORE_RESPONDER_HELLO
Reply to the first message from the initiator - first message sent by the responder.
#define GNUNET_MESSAGE_TYPE_CORE_INITIATOR_HELLO
for more detail on the following messages see https://lsd.gnunet.org/lsd0012/draft-schanzen-cake....
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition scheduler.c:1283
enum GNUNET_GenericReturnValue GNUNET_MST_from_buffer(struct GNUNET_MessageStreamTokenizer *mst, const char *buf, size_t size, int purge, int one_shot)
Add incoming data to the receive buffer and call the callback for all complete messages.
Definition mst.c:101
struct GNUNET_MessageStreamTokenizer * GNUNET_MST_create(GNUNET_MessageTokenizerCallback cb, void *cb_cls)
Create a message stream tokenizer.
Definition mst.c:86
void GNUNET_MST_destroy(struct GNUNET_MessageStreamTokenizer *mst)
Destroys a tokenizer.
Definition mst.c:404
void GNUNET_STATISTICS_update(struct GNUNET_STATISTICS_Handle *handle, const char *name, int64_t delta, int make_persistent)
Set statistic value for the peer.
struct GNUNET_TIME_Relative GNUNET_TIME_relative_max(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the maximum of two relative time values.
Definition time.c:352
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition time.c:406
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition time.c:316
struct GNUNET_TIME_Relative GNUNET_TIME_relative_divide(struct GNUNET_TIME_Relative rel, unsigned long long factor)
Divide relative time by a given factor.
Definition time.c:548
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_difference(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Absolute end)
Compute the time difference between the given start and end times.
Definition time.c:423
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition time.c:636
bool GNUNET_TIME_absolute_is_past(struct GNUNET_TIME_Absolute abs)
Test if abs is truly in the past (excluding now).
Definition time.c:667
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
static unsigned int size
Size of the "table".
Definition peer.c:68
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
static struct GNUNET_TIME_Relative delta
Definition speedup.c:36
struct GNUNET_MessageHeader header
Message type is GNUNET_MESSAGE_TYPE_CORE_ACK.
unsigned char tag[crypto_aead_xchacha20poly1305_ietf_ABYTES]
The Poly1305 tag of the encrypted message (which is starting at sequence_number), used to verify mess...
uint64_t sequence_number
Sequence number, in network byte order.
type for (message) authentication keys
HPKE DHKEM encapsulation (X25519) See RFC 9180.
A public key used for decryption.
struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe_key
An ECDHE/X25519 key.
A public key used for encryption.
struct GNUNET_CRYPTO_EcdhePublicKey ecdhe_key
An ECDHE/X25519 key.
Context for parsing HELLOs.
Definition hello-uri.c:233
A 512-bit hashcode.
Handle to a message queue.
Definition mq.c:87
Message handler for a specific message type.
Header for all communications.
Handle to a message stream tokenizer.
Definition mst.c:45
The notification context is the key datastructure for a convenience API used for transmission of noti...
Definition nc.c:77
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
Entry in list of pending tasks.
Definition scheduler.c:141
A 256-bit hashcode.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
Handle for the transport service (includes all of the state for the transport service).
Information about the status of a key exchange with another peer.
struct GSC_KeyExchangeInfo * prev
DLL.
struct GNUNET_ShortHashCode their_ats[10]
*ATS - other peers application traffic secret by epoch
struct GNUNET_ShortHashCode ss_R
struct GNUNET_ShortHashCode ihts
IHTS - Initiator handshake secret TODO.
struct GNUNET_TIME_Absolute current_epoch_expiration
Expiration time of our current epoch.
struct GNUNET_ShortHashCode early_secret_key
ES - Early Secret Key TODO uniform naming: _key?
struct GNUNET_ShortHashCode master_secret
Master secret key TODO.
uint64_t current_sqn
Our current sequence number.
struct GNUNET_TIME_Absolute last_notify_timeout
Last time we notified monitors.
enum GSC_KX_Role role
Own role in the key exchange.
struct GNUNET_MessageStreamTokenizer * mst
Our message stream tokenizer (for encrypted payload).
struct GSC_KeyExchangeInfo * next
DLL.
struct GNUNET_CRYPTO_HpkePrivateKey sk_e
Initiator secret key.
unsigned int resend_tries_left
Resend tries left.
struct GNUNET_SCHEDULER_Task * resend_task
Task for resending messages during handshake.
struct GNUNET_PeerIdentity peer
Identity of the peer.
struct GNUNET_MQ_Handle * mq
Message queue for sending messages to peer.
struct GNUNET_ShortHashCode early_traffic_secret
ETS - Early traffic secret TODO.
uint64_t their_max_epoch
Highest seen (or used) epoch of responder resp initiator.
struct GNUNET_TIME_Absolute timeout
When should the session time out (if there are no Acks to HEARTBEATs)?
struct GNUNET_MQ_Envelope * resend_env
Env for resending messages.
struct GNUNET_ShortHashCode rhts
RHTS - Responder handshake secret TODO.
struct GNUNET_ShortHashCode ss_I
struct GNUNET_ShortHashCode handshake_secret
HS - Handshake secret TODO.
struct GNUNET_ShortHashCode ss_e
int has_excess_bandwidth
GNUNET_YES if this peer currently has excess bandwidth.
enum GNUNET_CORE_KxState status
What is our connection state?
struct GNUNET_CRYPTO_HpkePublicKey pk_e
Initiator ephemeral key.
struct GNUNET_HashContext * transcript_hash_ctx
The transcript hash context.
uint64_t current_epoch
Our currently used epoch for sending.
enum GNUNET_CORE_PeerClass class
Peer class of the other peer TODO still needed?
struct GNUNET_ShortHashCode current_ats
*ATS - our current application traffic secret by epoch
struct GNUNET_SCHEDULER_Task * heartbeat_task
ID of task used for sending keep-alive pings.
struct GNUNET_MessageHeader header
Message type is #GNUNET_MESSAGE_TYPE_CORE_PONG.
uint32_t flags
Flags.
struct GNUNET_HashCode finished
TODO {Finished} - encrypted.
struct PilsRequest * req
struct InitiatorHello * ihm_e
struct GSC_KeyExchangeInfo * kx
struct GNUNET_PeerIdentity pk_I
Sender Peer ID.
uint16_t peer_class
The peer class of the sending peer TODO part of services info?
uint64_t r_I
Random number to make replay attacks harder.
struct GNUNET_CRYPTO_EcdhePublicKey pk_e
Ephemeral public edx25519 key.
struct GNUNET_CRYPTO_HpkeEncapsulation c_R
Key encapsulation.
struct GNUNET_MessageHeader header
Message type is #GNUNET_MESSAGE_TYPE_CORE_PONG.
struct GNUNET_HashCode h_pk_R
Hash of the responder peer id.
Message sent by the service to monitor clients to notify them about a peer changing status.
Definition core.h:313
uint32_t state
New peer state, an enum GNUNET_CORE_KxState in NBO.
Definition core.h:322
struct GNUNET_TIME_AbsoluteNBO timeout
How long will we stay in this state (if nothing else happens)?
Definition core.h:332
struct GNUNET_PILS_Operation * op
The pils operation.
struct PilsRequest * next
DLL.
struct PilsRequest * prev
DLL.
struct GNUNET_ShortHashCode ss_e
struct GNUNET_ShortHashCode ihts
struct GNUNET_ShortHashCode rhts
struct ResponderHello rhm_e
struct ResponderHelloPayload * rhp
struct GSC_KeyExchangeInfo * kx
char finished_enc[sizeof(struct GNUNET_HashCode)+crypto_aead_xchacha20poly1305_ietf_ABYTES]
struct GNUNET_HashContext * hc
struct GNUNET_HashCode decrypted_finish
struct GNUNET_ShortHashCode hs
struct PilsRequest * req
struct GNUNET_CRYPTO_HpkeEncapsulation c_I
Challenge encapsulation c_I.
struct GNUNET_CRYPTO_HpkeEncapsulation c_e
Ephemeral key encapsulation c_e.
uint64_t r_R
Random number to make replay attacks harder.
struct GNUNET_MessageHeader header
Message type is #GNUNET_MESSAGE_TYPE_CORE_PONG.