GNUnet 0.26.2-20-ga2d76f2e4
 
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-2025 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 "platform.h"
41#include "gnunet-service-core.h"
42#include "gnunet_constants.h"
43#include "gnunet_protocols.h"
44#include "gnunet_pils_service.h"
45
49#define DEBUG_KX 0
50
54#define RESEND_MAX_TRIES 4
55
59#define AEAD_KEY_BYTES crypto_aead_xchacha20poly1305_ietf_KEYBYTES
60
64#define AEAD_NONCE_BYTES crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
65
69#define AEAD_TAG_BYTES crypto_aead_xchacha20poly1305_ietf_ABYTES
70
71#define RESEND_TIMEOUT \
72 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
73
77#define MIN_HEARTBEAT_FREQUENCY \
78 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
79
83#define MIN_HEARTBEAT_FREQUENCY \
84 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
85
89#define HEARTBEAT_FREQUENCY \
90 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
91
98#define MAX_EPOCHS 10
99
103#define EPOCH_EXPIRATION \
104 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12)
105
109#define REKEY_TOLERANCE \
110 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5)
111
116#define EARLY_DATA_STR "early data"
117
122#define R_HS_TRAFFIC_STR "r hs traffic"
123
128#define I_HS_TRAFFIC_STR "i hs traffic"
129
134#define R_AP_TRAFFIC_STR "r ap traffic"
135
140#define I_AP_TRAFFIC_STR "i ap traffic"
141
146#define DERIVED_STR "derived"
147
152#define R_FINISHED_STR "r finished"
153
158#define I_FINISHED_STR "i finished"
159
163#define CAKE_LABEL "cake10"
164
169#define KEY_STR "key"
170
175#define TRAFFIC_UPD_STR "traffic upd"
176
181#define IV_STR "iv"
182
183
188{
189 /* Peer is supposed to initiate the key exchange */
191
192 /* Peer is supposed to wait for the key exchange */
194};
195
196
201{
206
211
216
221
226
231
232 // TODO check ordering - might make it less confusing
233 // TODO consistent naming: ss_e, shared_secret_e or ephemeral_shared_secret?
234 // TODO consider making all the structs here pointers
235 // - they can be checked to be NULL
236 // - valgrind can detect memory issues better (I guess?)
237
243
244 // TODO
248
253
258
265
271
276 struct GNUNET_ShortHashCode early_traffic_secret; /* Decrypts InitiatorHello */
277
283
289
295
301
306
311
316
321
327
331 uint64_t current_sqn;
332
337
342
347
351 unsigned int resend_tries_left;
352
358
364
369
375
376};
377
381struct PilsRequest
382{
386 struct PilsRequest *prev;
387
391 struct PilsRequest *next;
392
397};
398
403
408
409
414
415
420
425
430
436
441
447
451static char *my_services_info = "";
452
453static void
454buffer_clear (void *buf, size_t len)
455{
456#if HAVE_MEMSET_S
457 memset_s (buf, len, 0, len);
458#elif HAVE_EXPLICIT_BZERO
459 explicit_bzero (buf, len);
460#else
461 volatile unsigned char *p = buf;
462 while (len--)
463 *p++ = 0;
464#endif
465}
466
467
468static void
470{
471 buffer_clear (&kx->ihts,
472 sizeof kx->ihts);
473 buffer_clear (&kx->rhts,
474 sizeof kx->rhts);
475 buffer_clear (&kx->sk_e,
476 sizeof kx->sk_e);
477 buffer_clear (&kx->ss_I,
478 sizeof kx->ss_I);
479 buffer_clear (&kx->ss_R,
480 sizeof kx->ss_R);
481 buffer_clear (&kx->ss_e,
482 sizeof kx->ss_e);
484 sizeof kx->master_secret);
486 sizeof kx->early_secret_key);
488 sizeof kx->early_traffic_secret);
490 sizeof kx->handshake_secret);
491}
492
493
494static void
496 struct GNUNET_HashCode *snapshot)
497{
498 struct GNUNET_HashContext *tmp;
499
500 tmp = GNUNET_CRYPTO_hash_context_copy (ts_hash);
501 GNUNET_CRYPTO_hash_context_finish (tmp, snapshot);
502}
503
504
510static void
512{
514
516 msg.header.size = htons (sizeof(msg));
517 msg.state = htonl ((uint32_t) kx->status);
518 msg.peer = kx->peer;
519 msg.timeout = GNUNET_TIME_absolute_hton (kx->timeout);
522}
523
524
525static void
527
535static void
536send_heartbeat (void *cls)
537{
538 struct GSC_KeyExchangeInfo *kx = cls;
539 struct GNUNET_TIME_Relative retry;
540 struct GNUNET_TIME_Relative left;
541 struct Heartbeat hb;
542
543 kx->heartbeat_task = NULL;
545 if (0 == left.rel_value_us)
546 {
548 gettext_noop ("# sessions terminated by timeout"),
549 1,
550 GNUNET_NO);
551 GSC_SESSIONS_end (&kx->peer);
554 restart_kx (kx);
555 return;
556 }
558 "Sending HEARTBEAT to `%s'\n",
559 GNUNET_i2s (&kx->peer));
561 gettext_noop ("# heartbeat messages sent"),
562 1,
563 GNUNET_NO);
565 hb.header.size = htons (sizeof hb);
566 // FIXME when do we request update?
567 hb.flags = 0;
568 GSC_KX_encrypt_and_transmit (kx, &hb, sizeof hb);
571 kx->heartbeat_task =
573}
574
575
583static void
585{
587
588 kx->timeout =
590 delta =
592 if (delta.rel_value_us > 5LL * 1000LL * 1000LL)
593 {
594 /* we only notify monitors about timeout changes if those
595 are bigger than the threshold (5s) */
597 }
598 if (NULL != kx->heartbeat_task)
603 kx);
604}
605
606
612static void
614
615
627static int
628deliver_message (void *cls, const struct GNUNET_MessageHeader *m)
629{
630 struct GSC_KeyExchangeInfo *kx = cls;
631
633 "Decrypted message of type %d from %s\n",
634 ntohs (m->type),
635 GNUNET_i2s (&kx->peer));
637 m,
638 ntohs (m->size),
641 m,
642 sizeof(struct GNUNET_MessageHeader),
644 return GNUNET_OK;
645}
646
647
648static void
650{
651 struct GNUNET_HashCode h1;
652 struct GNUNET_HashCode h2;
653
654 // TODO what happens if we're in the middle of a peer id change?
655 // TODO there's a small chance this gets already called when we don't have a
656 // peer id yet. Add a kx, insert into the list, mark it as to be completed
657 // and let the callback to pils finish the rest once we got the peer id
658
660 "Initiating key exchange with peer %s\n",
661 GNUNET_i2s (&kx->peer));
663 gettext_noop ("# key exchanges initiated"),
664 1,
665 GNUNET_NO);
666
668 GNUNET_CRYPTO_hash (&kx->peer, sizeof(struct GNUNET_PeerIdentity), &h1);
670 sizeof(struct GNUNET_PeerIdentity),
671 &h2);
672 if (NULL != kx->transcript_hash_ctx)
674 kx->transcript_hash_ctx = NULL;
675 if (0 < GNUNET_CRYPTO_hash_cmp (&h1, &h2))
676 {
677 /* peer with "lower" identity starts KX, otherwise we typically end up
678 with both peers starting the exchange and transmit the 'set key'
679 message twice */
681 "I am the initiator, sending hello\n");
682 kx->role = ROLE_INITIATOR;
684 }
685 else
686 {
687 /* peer with "higher" identity starts a delayed KX, if the "lower" peer
688 * does not start a KX since it sees no reasons to do so */
690 "I am the responder, yielding and await initiator hello\n");
692 kx->role = ROLE_RESPONDER;
694 }
695
696}
697
698
709static void *
711 const struct GNUNET_PeerIdentity *peer_id,
712 struct GNUNET_MQ_Handle *mq)
713{
714 struct GSC_KeyExchangeInfo *kx;
715 (void) cls;
716 if (0 == memcmp (peer_id, &GSC_my_identity, sizeof *peer_id))
717 {
719 "Ignoring connection to self\n");
720 return NULL;
721 }
723 "Incoming connection of peer with %s\n",
725
726 /* Set up kx struct */
727 kx = GNUNET_new (struct GSC_KeyExchangeInfo);
729 kx->mq = mq;
730 GNUNET_memcpy (&kx->peer, peer_id, sizeof (struct GNUNET_PeerIdentity));
732
733 restart_kx (kx);
734 return kx;
735}
736
737
777// TODO find a way to assert that a key is not yet existing before generating
778// TODO find a way to assert that a key is not already existing before using
779/*
780 * Derive early secret and transport secret.
781 * @param kx the key exchange info
782 */
783static void
784derive_es_ets (const struct GNUNET_HashCode *transcript,
785 const struct GNUNET_ShortHashCode *ss_R,
786 struct GNUNET_ShortHashCode *es,
787 struct GNUNET_ShortHashCode *ets)
788{
789 uint64_t ret;
790
791 ret = GNUNET_CRYPTO_hkdf_extract (es, // prk
792 0, // salt
793 0, // salt_len
794 ss_R, // ikm - initial key material
795 sizeof (*ss_R));
796 if (GNUNET_OK != ret)
797 {
798 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong extracting ES\n")
799 ;
800 GNUNET_assert (0);
801 }
803 ets,
804 sizeof (*ets),
805 es,
808 GNUNET_CRYPTO_kdf_arg_auto (transcript));
809 if (GNUNET_OK != ret)
810 {
811 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong expanding ETS\n")
812 ;
813 GNUNET_assert (0);
814 }
815}
816
817
818/*
819 * Derive early secret and transport secret.
820 * @param kx the key exchange info
821 */
822static void
823derive_sn (const struct GNUNET_ShortHashCode *secret,
824 unsigned char*sn,
825 size_t sn_len)
826{
829 sn,
830 sn_len,
831 secret,
834}
835
836
841static void
843 const struct GNUNET_ShortHashCode *ss_e,
845{
846 uint64_t ret;
847 struct GNUNET_ShortHashCode derived_early_secret;
848
849 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deriving HS\n");
851 );
852 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ss_e: %s\n", GNUNET_B2S (ss_e));
854 &derived_early_secret,
855 sizeof (derived_early_secret),
856 es,
860 derived_early_secret));
861 if (GNUNET_OK != ret)
862 {
863 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong expanding dES\n")
864 ;
865 GNUNET_assert (0);
866 }
867 // Handshake secret
868 // TODO check: are dES the salt and ss_e the ikm or other way round?
869 ret = GNUNET_CRYPTO_hkdf_extract (handshake_secret, // prk
870 &derived_early_secret, // salt - dES
871 sizeof (derived_early_secret), // salt_len
872 ss_e, // ikm - initial key material
873 sizeof (*ss_e));
874 if (GNUNET_OK != ret)
875 {
876 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong extracting HS\n")
877 ;
878 GNUNET_assert (0);
879 }
880}
881
882
887static void
888derive_ihts (const struct GNUNET_HashCode *transcript,
889 const struct GNUNET_ShortHashCode *hs,
890 struct GNUNET_ShortHashCode *ihts)
891{
894 ihts, // result
895 sizeof (*ihts), // result len
896 hs, // prk?
899 GNUNET_CRYPTO_kdf_arg_auto (transcript)));
900}
901
902
907static void
908derive_rhts (const struct GNUNET_HashCode *transcript,
909 const struct GNUNET_ShortHashCode *hs,
910 struct GNUNET_ShortHashCode *rhts)
911{
914 rhts,
915 sizeof (*rhts),
916 hs, // prk? TODO
919 GNUNET_CRYPTO_kdf_arg_auto (transcript)));
920}
921
922
927static void
929 const struct GNUNET_ShortHashCode *ss_I,
930 struct GNUNET_ShortHashCode *ms)
931{
932 uint64_t ret;
933 struct GNUNET_ShortHashCode derived_handshake_secret;
934
936 &derived_handshake_secret,
937 sizeof (derived_handshake_secret),
938 hs,
941 if (GNUNET_OK != ret)
942 {
943 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong expanding dHS\n")
944 ;
945 GNUNET_assert (0);
946 }
947 // TODO check: are dHS the salt and ss_I the ikm or other way round?
948 ret = GNUNET_CRYPTO_hkdf_extract (ms, // prk
949 &derived_handshake_secret, // salt - dHS
950 sizeof (derived_handshake_secret), // salt_len
951 ss_I, // ikm - initial key material
952 sizeof (*ss_I));
953 if (GNUNET_OK != ret)
954 {
955 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong extracting MS\n")
956 ;
957 GNUNET_assert (0);
958 }
959}
960
961
967static void
969 uint64_t seq,
970 const uint8_t write_iv[AEAD_NONCE_BYTES],
971 uint8_t per_record_write_iv[AEAD_NONCE_BYTES])
972{
973 uint64_t seq_nbo;
974 uint64_t *write_iv_ptr;
975 unsigned int byte_offset;
976
977 seq_nbo = GNUNET_htonll (seq);
978 memcpy (per_record_write_iv,
979 write_iv,
981 byte_offset =
982 AEAD_NONCE_BYTES - sizeof (uint64_t);
983 write_iv_ptr = (uint64_t*) (write_iv + byte_offset);
984 *write_iv_ptr ^= seq_nbo;
985}
986
987
992static void
994 const struct GNUNET_ShortHashCode *ts,
995 uint64_t seq,
996 unsigned char key[AEAD_KEY_BYTES],
997 unsigned char nonce[AEAD_NONCE_BYTES])
998{
999 unsigned char nonce_tmp[AEAD_NONCE_BYTES];
1000 /* derive actual key */
1003 key,
1005 ts,
1008
1009 /* derive nonce */
1012 nonce_tmp,
1014 ts,
1018 nonce_tmp,
1019 nonce);
1020}
1021
1022
1027static void
1029 struct GNUNET_ShortHashCode *new_ats)
1030{
1031 int8_t ret;
1032
1033 // FIXME: Not sure of PRK and output may overlap here!
1035 new_ats,
1036 sizeof (*new_ats),
1037 old_ats,
1040 if (GNUNET_OK != ret)
1041 {
1043 "Something went wrong deriving next *ATS key\n");
1044 GNUNET_assert (0);
1045 }
1046}
1047
1048
1053static void
1054derive_initial_ats (const struct GNUNET_HashCode *transcript,
1055 const struct GNUNET_ShortHashCode *ms,
1056 enum GSC_KX_Role role,
1057 struct GNUNET_ShortHashCode *initial_ats)
1058{
1059 const char *traffic_str;
1060
1061 if (ROLE_INITIATOR == role)
1062 traffic_str = I_AP_TRAFFIC_STR;
1063 else
1064 traffic_str = R_AP_TRAFFIC_STR;
1067 initial_ats, // result
1068 sizeof (*initial_ats), // result len
1069 ms,
1071 GNUNET_CRYPTO_kdf_arg_string (traffic_str),
1072 GNUNET_CRYPTO_kdf_arg_auto (transcript)));
1073}
1074
1075
1082static void
1084 const struct GNUNET_ShortHashCode *ms,
1085 struct GNUNET_HashCode *result)
1086{
1088 struct GNUNET_CRYPTO_AuthKey fk_R; // We might want to save this in kx?
1089
1091 &fk_R, // result
1092 sizeof (fk_R),
1093 ms,
1096 if (GNUNET_OK != ret)
1097 {
1099 "Something went wrong expanding fk_R\n");
1100 GNUNET_assert (0);
1101 }
1102
1103 GNUNET_CRYPTO_hmac (&fk_R,
1104 transcript,
1105 sizeof (*transcript),
1106 result);
1107}
1108
1109
1116static void
1118 const struct GNUNET_ShortHashCode *ms,
1119 struct GNUNET_HashCode *result)
1120{
1122 struct GNUNET_CRYPTO_AuthKey fk_I; // We might want to save this in kx?
1123
1125 &fk_I, // result
1126 sizeof (fk_I),
1127 ms,
1130 if (GNUNET_OK != ret)
1131 {
1133 "Something went wrong expanding fk_I\n");
1134 GNUNET_assert (0);
1135 }
1136 GNUNET_CRYPTO_hmac (&fk_I,
1137 transcript,
1138 sizeof (*transcript),
1139 result);
1140}
1141
1142
1149
1150static void
1152{
1153 struct GSC_KeyExchangeInfo *kx = cls;
1154
1155 kx->resend_task = NULL;
1156 if (0 == kx->resend_tries_left)
1157 {
1159 "Restarting KX\n");
1160 restart_kx (kx);
1161 return;
1162 }
1163 kx->resend_tries_left--;
1165 "Resending responder hello. Retries left: %u\n",
1166 kx->resend_tries_left);
1170 kx);
1171}
1172
1173
1174void
1176{
1179 struct ResponderHello *rhm_e; /* responder hello message - encrypted pointer */
1180 struct GNUNET_MQ_Envelope *env;
1181 struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_kem_challenge;
1182 struct GNUNET_ShortHashCode rhts;
1183 struct GNUNET_ShortHashCode ihts;
1184 struct GNUNET_ShortHashCode hs;
1185 struct GNUNET_ShortHashCode ms;
1186 struct GNUNET_ShortHashCode ss_e;
1187 struct GNUNET_ShortHashCode ss_I;
1188 struct GNUNET_HashContext *hc;
1189 unsigned char enc_key[AEAD_KEY_BYTES];
1190 unsigned char enc_nonce[AEAD_NONCE_BYTES];
1191
1192 // 4. encaps -> shared_secret_e, c_e (kemChallenge)
1193 // TODO potentially write this directly into rhm?
1194 ret = GNUNET_CRYPTO_hpke_kem_encaps (&kx->pk_e, // public ephemeral key of initiator
1195 &ephemeral_kem_challenge, // encapsulated key
1196 &ss_e); // key - ss_e
1197 if (GNUNET_OK != ret)
1198 {
1200 "Something went wrong encapsulating ss_e\n");
1201 return;
1202 }
1204 // 6. encaps -> shared_secret_I, c_I
1205 ret = GNUNET_CRYPTO_eddsa_kem_encaps (&kx->peer.public_key, // public key of I
1206 &c_I, // encapsulated key
1207 &ss_I); // where to write the key material
1208 if (GNUNET_OK != ret)
1209 {
1211 "Something went wrong encapsulating ss_I\n");
1213 return;
1214 }
1215 // 7. generate RHTS (responder_handshare_secret_key) and RATS (responder_application_traffic_secret_key) (section 5)
1216 {
1217 struct GNUNET_HashCode transcript;
1218 snapshot_transcript (hc, &transcript);
1219#if DEBUG_KX
1221 "Transcript snapshot for derivation of HS, MS: `%s'\n",
1222 GNUNET_h2s (&transcript));
1223#endif
1225 &ss_e,
1226 &hs);
1227 derive_ms (&hs, &ss_I, &ms);
1228 }
1229
1230 // send ResponderHello
1231 // TODO fill fields / services_info!
1232 // 1. r_R <- random
1233 struct ResponderHelloPayload *rhp;
1234 size_t rhp_len = sizeof (*rhp) + strlen (my_services_info);
1235 unsigned char rhp_buf[rhp_len];
1236 size_t ct_len;
1237
1238 rhp = (struct ResponderHelloPayload*) rhp_buf;
1239 ct_len = rhp_len // ResponderHelloPayload, fist PT msg
1240 + sizeof (struct GNUNET_HashCode) // Finished hash, second PT msg
1241 + AEAD_TAG_BYTES * 2; // Two tags;
1242 env = GNUNET_MQ_msg_extra (rhm_e,
1243 ct_len,
1245
1246 rhm_e->r_R =
1248 UINT64_MAX);
1249
1250 // c_e
1251 GNUNET_memcpy (&rhm_e->c_e,
1252 &ephemeral_kem_challenge,
1253 sizeof (ephemeral_kem_challenge));
1255 rhm_e,
1256 sizeof (struct ResponderHello));
1257 // 2. Encrypt ServicesInfo and c_I with RHTS
1258 // derive RHTS
1259 {
1260 struct GNUNET_HashCode transcript;
1262 &transcript);
1263#if DEBUG_KX
1265 "Transcript snapshot for derivation of *HTS: `%s'\n",
1266 GNUNET_h2s (&transcript));
1267#endif
1268 derive_rhts (&transcript,
1269 &hs,
1270 &rhts);
1271 derive_ihts (&transcript,
1272 &hs,
1273 &ihts);
1275 0,
1276 enc_key,
1277 enc_nonce);
1278 }
1279 // c_I
1280 GNUNET_memcpy (&rhp->c_I, &c_I, sizeof (c_I));
1281 // Services info empty for now.
1282 GNUNET_memcpy (&rhp[1],
1284 strlen (my_services_info));
1285
1286 {
1287 unsigned long long out_ct_len;
1289 struct GNUNET_HashCode transcript;
1290 unsigned char *finished_buf;
1291 GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
1292 (unsigned char*) &rhm_e[1], /* c - ciphertext */
1293 &out_ct_len, /* clen_p */
1294 rhp_buf, /* rhm_p - plaintext message */
1295 rhp_len, // mlen
1296 NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
1297 // fields?
1298 NULL, // nsec - unused
1299 enc_nonce, // npub - nonce // FIXME nonce can be reused
1300 enc_key)); // k - key RHTS
1302 "Encrypted and wrote %llu bytes\n",
1303 out_ct_len);
1304 // 3. Create ResponderFinished (Section 6)
1305 // Derive fk_I <- HKDF-Expand (MS, "r finished", NULL)
1306 /* Forward the transcript */
1307 /* {svcinfo, c_I}RHTS */
1309 hc,
1310 &rhm_e[1],
1311 out_ct_len);
1312
1313 finished_buf = ((unsigned char*) &rhm_e[1]) + out_ct_len;
1315 &transcript);
1316#if DEBUG_KX
1318 "Transcript snapshot for derivation of Rfinished: `%s'\n",
1319 GNUNET_h2s (&transcript));
1320#endif
1321 generate_responder_finished (&transcript,
1322 &ms,
1323 &finished);
1324 // 4. Encrypt ResponderFinished
1326 1,
1327 enc_key,
1328 enc_nonce);
1329 GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
1330 finished_buf, /* c - ciphertext */
1331 &out_ct_len, /* clen_p */
1332 (unsigned char*) &finished, /* rhm_p - plaintext message */
1333 sizeof (finished), // mlen
1334 NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
1335 // fields?
1336 NULL, // nsec - unused
1337 enc_nonce, // npub
1338 enc_key)); // k - key RHTS
1340 "Encrypted and wrote %llu bytes\n",
1341 out_ct_len);
1342 /* Forward the transcript
1343 * after responder finished,
1344 * before deriving *ATS and generating finished_I
1345 * (finished_I will be generated when receiving the InitiatorFinished message
1346 * in order to check it) */
1348 hc,
1349 finished_buf,
1350 out_ct_len);
1351 // 5. optionally send application data - encrypted with RATS
1352 // We do not really have any application data, instead, we send the ACK
1354 &transcript);
1355#if DEBUG_KX
1357 "Transcript snapshot for derivation of *ATS: `%s'\n",
1358 GNUNET_h2s (&transcript));
1359#endif
1360 derive_initial_ats (&transcript,
1361 &ms,
1363 &kx->current_ats);
1364 }
1365 /* Lock into struct */
1367 kx->transcript_hash_ctx = hc;
1368 kx->master_secret = ms;
1369 kx->handshake_secret = hs;
1370 kx->ss_e = ss_e;
1371 kx->ihts = ihts;
1372 kx->rhts = rhts;
1373 kx->ss_I = ss_I;
1374 kx->current_epoch = 0;
1375 kx->current_sqn = 0;
1377 kx->current_sqn,
1378 enc_key,
1379 enc_nonce);
1380
1381 GNUNET_MQ_send_copy (kx->mq, env);
1382 kx->resend_env = env;
1384 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent ResponderHello\n");
1385
1388 kx);
1390 monitor_notify_all (kx);
1391 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
1392}
1393
1394
1395static void
1397{
1398 struct InitiatorHelloCtx *ihm_ctx = cls;
1399 struct GSC_KeyExchangeInfo *kx = ihm_ctx->kx;
1400 uint32_t ihm_len = ntohs (ihm_ctx->ihm_e->header.size);
1401 unsigned char enc_key[AEAD_KEY_BYTES];
1402 unsigned char enc_nonce[AEAD_NONCE_BYTES];
1403 struct GNUNET_HashCode h1;
1404 struct GNUNET_HashCode h2;
1405 struct GNUNET_HashCode transcript;
1406 struct GNUNET_ShortHashCode es;
1407 struct GNUNET_ShortHashCode ets;
1409
1410 ihm_ctx->req->op = NULL;
1413 ihm_ctx->req);
1414 GNUNET_free (ihm_ctx->req);
1415
1416
1418 &ihm_ctx->ihm_e->pk_e,
1419 sizeof (ihm_ctx->ihm_e->pk_e));
1420 // 5. generate ETS (early_traffic_secret_key, decrypt pk_i
1421 // expand ETS <- expand ES <- extract ss_R
1422 // use ETS to decrypt
1423
1424 /* Forward the transcript hash context over the unencrypted fields to get it
1425 * to the same status that the initiator had when it needed to derive es and
1426 * ets for the encryption */
1429 ihm_ctx->ihm_e,
1430 sizeof (struct InitiatorHello));
1432 &transcript);
1433#if DEBUG_KX
1435 "Transcript snapshot for derivation of ES, ETS: `%s'\n",
1436 GNUNET_h2s (&transcript));
1437#endif
1438 derive_es_ets (&transcript, ss_R, &es, &ets);
1440 0,
1441 enc_key,
1442 enc_nonce);
1443 {
1444 struct InitiatorHelloPayload *ihmp;
1445 size_t ct_len = ihm_len - sizeof (struct InitiatorHello);
1446 unsigned char ihmp_buf[ct_len - AEAD_TAG_BYTES];
1447 ihmp = (struct InitiatorHelloPayload*) ihmp_buf;
1448 ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
1449 ihmp_buf, // unsigned char *m
1450 NULL, // mlen_p message length
1451 NULL, // unsigned char *nsec - unused: NULL
1452 (unsigned char*) &ihm_ctx->ihm_e[1], // const unsigned char *c - ciphertext
1453 ct_len, // unsigned long long clen - length of ciphertext
1454 // mac, // const unsigned char *mac - authentication tag
1455 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right?
1456 0, // unsigned long long adlen
1457 enc_nonce, // const unsigned char *npub - nonce
1458 enc_key // const unsigned char *k - key
1459 );
1460 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pid_sender: %s\n",
1461 GNUNET_i2s (&ihmp->pk_I));
1462 if (0 != ret)
1463 {
1465 "Something went wrong decrypting: %d\n", ret);
1466 GNUNET_break_op (0);
1467 GNUNET_free (ihm_ctx->ihm_e);
1468 GNUNET_free (ihm_ctx);
1470 kx->transcript_hash_ctx = NULL;
1471 return;
1472 }
1473 /* now forward it considering the encrypted messages that the initiator was
1474 * able to send after deriving the es and ets */
1476 &ihm_ctx->ihm_e[1],
1477 ct_len);
1478 GNUNET_memcpy (&kx->peer,
1479 &ihmp->pk_I,
1480 sizeof (struct GNUNET_PeerIdentity));
1481 }
1482 // We could follow with the rest of the Key Schedule (dES, HS, ...) for now
1483 /* Check that we are actually in the receiving role */
1484 GNUNET_CRYPTO_hash (&kx->peer, sizeof(struct GNUNET_PeerIdentity), &h1);
1486 sizeof(struct GNUNET_PeerIdentity),
1487 &h2);
1488 if (0 < GNUNET_CRYPTO_hash_cmp (&h1, &h2))
1489 {
1490 /* peer with "lower" identity starts KX, otherwise we typically end up
1491 with both peers starting the exchange and transmit the 'set key'
1492 message twice */
1493 /* Something went wrong - we have the lower value and should have sent the
1494 * InitiatorHello, but instead received it. TODO handle this case
1495 * We might end up in this case if the initiator didn't initiate the
1496 * handshake long enough and the 'responder' initiates the handshake */
1498 "Something went wrong - we have the lower value and should have sent the InitiatorHello, but instead received it.\n");
1499 GNUNET_free (ihm_ctx->ihm_e);
1500 GNUNET_free (ihm_ctx);
1502 kx->transcript_hash_ctx = NULL;
1503 return;
1504 }
1505
1506 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer ID of other peer: %s\n", GNUNET_i2s
1507 (&kx->peer));
1508 /* We update the monitoring peers here because now we know
1509 * that we can decrypt the message AND know the PID
1510 */
1511 monitor_notify_all (kx);
1512 kx->ss_R = *ss_R;
1513 kx->early_secret_key = es;
1514 kx->early_traffic_secret = ets;
1516}
1517
1518
1519static int
1520check_initiator_hello (void *cls, const struct InitiatorHello *m)
1521{
1522 uint16_t size = ntohs (m->header.size);
1523
1524 if (size < sizeof (*m)
1525 + sizeof (struct InitiatorHelloPayload)
1527 {
1528 return GNUNET_SYSERR;
1529 }
1530 return GNUNET_OK;
1531}
1532
1533
1542static void
1543handle_initiator_hello (void *cls, const struct InitiatorHello *ihm_e)
1544{
1545 struct GSC_KeyExchangeInfo *kx = cls;
1546 struct GNUNET_HashCode hash_compare = { 0 };
1547 struct InitiatorHelloCtx *initiator_hello_cls;
1548 size_t ihm_len;
1549
1550 if (ROLE_INITIATOR == kx->role)
1551 {
1552 GNUNET_break_op (0);
1554 "I am an initiator! Tearing down...\n");
1555 return;
1556 }
1558 {
1559 GNUNET_break_op (0);
1561 "Already received InitiatorHello)\n");
1562 return;
1563 }
1564 GNUNET_assert (NULL == kx->transcript_hash_ctx); // FIXME this triggers sometimes - why?
1567
1568 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received InitiatorHello\n");
1570 gettext_noop ("# key exchanges initiated"),
1571 1,
1572 GNUNET_NO);
1573
1575
1576 // 1. verify type _INITIATOR_HELLO
1577 // - This is implicytly done by arriving within this handler
1578 // - or is this about verifying the 'additional data' part of aead?
1579 // should it check the encryption + mac? (is this implicitly done
1580 // while decrypting?)
1581 // 2. verify H(pk_R) matches pk_R
1583 sizeof (struct GNUNET_PeerIdentity),
1584 &hash_compare); /* result */
1585 if (0 != memcmp (&ihm_e->h_pk_R,
1586 &hash_compare,
1587 sizeof (struct GNUNET_HashCode)))
1588 {
1590 "This message is not meant for us (H(PID) mismatch)\n");
1592 kx->transcript_hash_ctx = NULL;
1593 return;
1594 }
1595 // FIXME this sometimes triggers in the tests - why?
1596 // 3. decaps -> shared_secret_R, c_R (kemChallenge)
1597 ihm_len = ntohs (ihm_e->header.size);
1598 initiator_hello_cls = GNUNET_new (struct InitiatorHelloCtx);
1599 initiator_hello_cls->kx = kx;
1600 initiator_hello_cls->ihm_e = GNUNET_malloc (ihm_len);
1601 GNUNET_memcpy (initiator_hello_cls->ihm_e, ihm_e, ihm_len);
1602 initiator_hello_cls->req = GNUNET_new (struct PilsRequest);
1605 initiator_hello_cls->req);
1606 initiator_hello_cls->req->op =
1608 &ihm_e->c_R,
1609 // encapsulated key
1611 // continuation
1612 initiator_hello_cls);
1613}
1614
1615
1617{
1618 /* Current KX session */
1620
1621 /* responder hello message - encrypted */
1623
1624 /* responder hello message - plain/decrypted */
1626
1627 /* Decrypted finish hash */
1629
1630 /* Encrypted finished CT (for transcript later) */
1631 char finished_enc[sizeof (struct GNUNET_HashCode)
1632 + AEAD_TAG_BYTES];
1633
1634 /* Temporary transcript context */
1636
1637 /* Temporary handshake secret */
1639
1640 /* Temporary handshake secret */
1642
1643 /* Temporary handshake secret */
1645
1646 /* Temporary handshake secret */
1648
1649 /* Pending PILS request */
1651};
1652
1653static void
1655{
1656 struct GSC_KeyExchangeInfo *kx = cls;
1657
1658 kx->resend_task = NULL;
1659 if (0 == kx->resend_tries_left)
1660 {
1662 "Restarting KX\n");
1663 restart_kx (kx);
1664 return;
1665 }
1666 kx->resend_tries_left--;
1668 "Resending initiator done. Retries left: %u\n",
1669 kx->resend_tries_left);
1673 kx);
1674}
1675
1676
1677static void
1679{
1680 struct ResponderHelloCls *rh_ctx = cls;
1681 struct GSC_KeyExchangeInfo *kx = rh_ctx->kx;
1682 struct InitiatorDone *idm_e; /* encrypted */
1683 struct InitiatorDone idm_local;
1684 struct InitiatorDone *idm_p; /* plaintext */
1685 struct GNUNET_MQ_Envelope *env;
1686 unsigned char enc_key[AEAD_KEY_BYTES];
1687 unsigned char enc_nonce[AEAD_NONCE_BYTES];
1688 struct ConfirmationAck ack_i;
1689 struct GNUNET_HashCode transcript;
1690 struct GNUNET_ShortHashCode ms;
1691
1692 rh_ctx->req->op = NULL;
1695 rh_ctx->req);
1696 GNUNET_free (rh_ctx->req);
1697 // XXX valgrind reports uninitialized memory
1698 // the following is a way to check whether this memory was meant
1699 // memset (&rhm_local, 0, sizeof (rhm_local)); - adapt to cls if still needed
1700 memset (&idm_local, 0, sizeof (idm_local));
1701
1702 kx->ss_I = *ss_I;
1703
1704 /* derive *ATS */
1705 derive_ms (&rh_ctx->hs, ss_I, &ms);;
1706 // 5. Create ResponderFinished as per Section 6 and check against decrypted payload.
1707 struct GNUNET_HashCode responder_finished;
1708 // Transcript updates, snapshot again
1709 snapshot_transcript (rh_ctx->hc,
1710 &transcript);
1711#if DEBUG_KX
1713 "Transcript snapshot for derivation of Rfinished: `%s'\n",
1714 GNUNET_h2s (&transcript));
1715#endif
1716 generate_responder_finished (&transcript,
1717 &ms,
1718 &responder_finished);
1719 if (0 != memcmp (&rh_ctx->decrypted_finish,
1720 &responder_finished,
1721 sizeof (struct GNUNET_HashCode)))
1722 {
1724 "Could not verify \"responder finished\"\n");
1725 GNUNET_free (rh_ctx->rhp);
1726 GNUNET_free (rh_ctx->hc);
1727 GNUNET_free (rh_ctx);
1728 GNUNET_assert (0);
1729 }
1730
1731
1732 /* Forward the transcript
1733 * after generating finished_R,
1734 * before deriving *ATS */
1736 rh_ctx->hc,
1737 rh_ctx->finished_enc,
1738 sizeof (rh_ctx->finished_enc));
1739
1740 // At this point we cannot fail anymore and may lock into kx
1742 kx->transcript_hash_ctx = rh_ctx->hc;
1743 kx->ss_I = *ss_I;
1744 kx->handshake_secret = rh_ctx->hs;
1745 kx->ss_e = rh_ctx->ss_e;
1746 kx->ihts = rh_ctx->ihts;
1747 kx->rhts = rh_ctx->rhts;
1748 kx->master_secret = ms;
1749 GNUNET_free (rh_ctx->rhp);
1750 GNUNET_free (rh_ctx);
1751 rh_ctx = NULL;
1752
1754 &transcript);
1755#if DEBUG_KX
1757 "Transcript snapshot for derivation of *ATS: `%s'\n",
1758 GNUNET_h2s (&transcript));
1759#endif
1760 derive_initial_ats (&transcript,
1761 &kx->master_secret,
1763 &kx->their_ats[0]);
1764 for (int i = 0; i < MAX_EPOCHS - 1; i++)
1765 {
1766 derive_next_ats (&kx->their_ats[i],
1767 &kx->their_ats[i + 1]);
1768 }
1769 kx->their_max_epoch = MAX_EPOCHS - 1;
1770
1772 0,
1773 enc_key,
1774 enc_nonce);
1775 /* Create InitiatorDone message */
1776 idm_p = &idm_local; /* plaintext */
1777 env = GNUNET_MQ_msg_extra (idm_e,
1778 sizeof (ack_i)
1781 // 6. Create IteratorFinished as per Section 6.
1782 generate_initiator_finished (&transcript,
1783 &kx->master_secret,
1784 &idm_p->finished);
1786 "Ifinished: `%s'\n",
1787 GNUNET_h2s (&idm_p->finished));
1789 "Transcript `%s'\n",
1790 GNUNET_h2s (&transcript));
1791 // 7. Send InteratorFinished message encrypted with the key derived from IHTS to R
1792
1793 GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
1794 (unsigned char*) &idm_e->finished, /* c - ciphertext */
1795 NULL, /* clen_p */
1796 (unsigned char*) &idm_p->finished, /* idm_p - plaintext message */
1797 sizeof (idm_p->finished), // mlen
1798 NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
1799 // fields?
1800 NULL, // nsec - unused
1801 enc_nonce, // npub - nonce
1802 enc_key)); // k - key IHTS
1803 /* Forward the transcript hash context
1804 * after generating finished_I and RATS_0
1805 * before deriving IATS_0 */
1807 &idm_e->finished,
1808 sizeof (idm_e->finished)
1809 + AEAD_TAG_BYTES);
1811 &transcript);
1812#if DEBUG_KX
1814 "Transcript snapshot for derivation of *ATS: `%s'\n",
1815 GNUNET_h2s (&transcript));
1816#endif
1817 derive_initial_ats (&transcript,
1818 &kx->master_secret,
1820 &kx->current_ats);
1821 kx->current_epoch = 0;
1822 kx->current_sqn++;
1823 // 8. optionally encrypt payload TODO
1825 kx->current_sqn,
1826 enc_key,
1827 enc_nonce);
1828 kx->current_sqn++;
1830 ack_i.header.size = htons (sizeof ack_i);
1831 GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
1832 (unsigned char*) &idm_e[1], /* c - ciphertext */
1833 NULL, /* clen_p */
1834 (unsigned char*) &ack_i, /* rhm_p - plaintext message */
1835 sizeof ack_i, // mlen
1836 NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
1837 // fields?
1838 NULL, // nsec - unused
1839 enc_nonce, // npub - nonce // FIXME nonce can be reused
1840 enc_key)); // k - key RHTS
1841
1842 GNUNET_MQ_send_copy (kx->mq, env);
1843 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent InitiatorDone\n");
1844
1845
1846 kx->resend_env = env;
1850 kx);
1852 monitor_notify_all (kx);
1853 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
1854}
1855
1856
1857static int
1858check_responder_hello (void *cls, const struct ResponderHello *m)
1859{
1860 uint16_t size = ntohs (m->header.size);
1861
1862 if (size < sizeof (*m)
1863 + sizeof (struct ResponderHelloPayload)
1864 + sizeof (struct GNUNET_HashCode)
1865 + AEAD_TAG_BYTES * 2)
1866 {
1867 return GNUNET_SYSERR;
1868 }
1869 return GNUNET_OK;
1870}
1871
1872
1878static void
1879handle_responder_hello (void *cls, const struct ResponderHello *rhm_e)
1880{
1881 struct GSC_KeyExchangeInfo *kx = cls;
1882 struct PilsRequest *req;
1883 struct ResponderHelloCls *rh_ctx;
1884 struct GNUNET_HashCode transcript;
1885 struct GNUNET_HashContext *hc;
1886 unsigned char enc_key[AEAD_KEY_BYTES];
1887 unsigned char enc_nonce[AEAD_NONCE_BYTES];
1889
1890 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ResponderHello\n");
1891
1893 if (NULL != kx->resend_task)
1894 {
1896 kx->resend_task = NULL;
1897 }
1898 if (NULL != kx->resend_env)
1899 {
1900 GNUNET_free (kx->resend_env);
1901 kx->resend_env = NULL;
1902 }
1903
1904 /* Forward the transcript hash context */
1905 if (ROLE_RESPONDER == kx->role)
1906 {
1907 GNUNET_break_op (0);
1909 "I am the responder! Ignoring.\n");
1910 return;
1911 }
1913 rhm_e,
1914 sizeof (struct ResponderHello));
1915 // 1. Verify that the message type is CORE_RESPONDER_HELLO
1916 // - implicitly done by handling this message?
1917 // - or is this about verifying the 'additional data' part of aead?
1918 // should it check the encryption + mac? (is this implicitly done
1919 // while decrypting?)
1920 // 2. sse <- Decaps(ske,ce)
1921 rh_ctx = GNUNET_new (struct ResponderHelloCls);
1922 ret = GNUNET_CRYPTO_hpke_kem_decaps (&kx->sk_e, // secret/private ephemeral key of initiator (us)
1923 &rhm_e->c_e, // encapsulated key
1924 &rh_ctx->ss_e); // key - ss_e
1925 if (GNUNET_OK != ret)
1926 {
1928 "Something went wrong decapsulating ss_e\n");
1929 GNUNET_free (hc);
1930 return;
1931 }
1932 // 3. Generate IHTS and RHTS from Section 5 and decrypt ServicesInfo, cI and ResponderFinished.
1933 snapshot_transcript (hc, &transcript);
1934#if DEBUG_KX
1936 "Transcript snapshot for derivation of HS, *HTS: `%s'\n",
1937 GNUNET_h2s (&transcript));
1938#endif
1940 &rh_ctx->ss_e,
1941 &rh_ctx->hs);
1942 derive_rhts (&transcript,
1943 &rh_ctx->hs,
1944 &rh_ctx->rhts);
1945 derive_ihts (&transcript,
1946 &rh_ctx->hs,
1947 &rh_ctx->ihts);
1949 0,
1950 enc_key,
1951 enc_nonce);
1952 rh_ctx->kx = kx;
1953 GNUNET_memcpy (&rh_ctx->rhm_e, rhm_e, sizeof (*rhm_e));
1954 {
1955 unsigned long long int c_len;
1956 unsigned char *finished_buf;
1957 // use RHTS to decrypt
1958 c_len = ntohs (rhm_e->header.size) - sizeof (*rhm_e)
1959 - sizeof (struct GNUNET_HashCode)
1960 - AEAD_TAG_BYTES; // finished ct
1961 rh_ctx->rhp = GNUNET_malloc (c_len
1962 -
1964 rh_ctx->hc = hc;
1965 finished_buf = ((unsigned char*) &rhm_e[1]) + c_len;
1966 /* Forward the transcript_hash_ctx
1967 * after rhts has been generated,
1968 * before generating finished_R*/
1970 hc,
1971 &rhm_e[1],
1972 c_len);
1973
1974 ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
1975 (unsigned char*) rh_ctx->rhp, // unsigned char *m
1976 NULL, // mlen_p message length
1977 NULL, // unsigned char *nsec - unused: NULL
1978 (unsigned char*) &rhm_e[1], // const unsigned char *c - ciphertext
1979 c_len, // unsigned long long clen - length of ciphertext
1980 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right?
1981 0, // unsigned long long adlen
1982 enc_nonce, // const unsigned char *npub - nonce
1983 enc_key // const unsigned char *k - key
1984 );
1985 if (0 != ret)
1986 {
1988 "Something went wrong decrypting: %d\n", ret);
1989 GNUNET_free (rh_ctx->rhp);
1990 GNUNET_free (rh_ctx);
1991 GNUNET_free (hc);
1992 return;
1993 }
1994 // FIXME nonce reuse (see encryption)
1996 1,
1997 enc_key,
1998 enc_nonce);
1999 c_len = sizeof (struct GNUNET_HashCode)
2001 ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
2002 (unsigned char*) &rh_ctx->decrypted_finish, // unsigned char *m
2003 NULL, // mlen_p message length
2004 NULL, // unsigned char *nsec - unused: NULL
2005 finished_buf, // const unsigned char *c - ciphertext
2006 c_len, // unsigned long long clen - length of ciphertext
2007 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right?
2008 0, // unsigned long long adlen
2009 enc_nonce, // const unsigned char *npub - nonce
2010 enc_key // const unsigned char *k - key
2011 );
2012 if (0 != ret)
2013 {
2015 "Something went wrong decrypting finished field: %d\n", ret);
2016 GNUNET_free (rh_ctx->rhp);
2017 GNUNET_free (rh_ctx);
2018 GNUNET_free (hc);
2019 return;
2020 }
2021 GNUNET_memcpy (rh_ctx->finished_enc,
2022 finished_buf,
2023 c_len);
2024 }
2025 // 4. ssI <- Decaps(skI,cI).
2026 req = GNUNET_new (struct PilsRequest);
2027 rh_ctx->req = req;
2030 req);
2032 &rh_ctx->rhp->c_I, // encapsulated key
2033 &handle_responder_hello_cont, // continuation
2034 rh_ctx);
2035}
2036
2037
2038static int
2039check_initiator_done (void *cls, const struct InitiatorDone *m)
2040{
2041 uint16_t size = ntohs (m->header.size);
2042
2043 if (size < sizeof (*m) + sizeof (struct ConfirmationAck))
2044 {
2045 return GNUNET_SYSERR;
2046 }
2047 return GNUNET_OK;
2048}
2049
2050
2056static void
2057handle_initiator_done (void *cls, const struct InitiatorDone *idm_e)
2058{
2059 struct GSC_KeyExchangeInfo *kx = cls;
2060 struct InitiatorDone idm_local;
2061 struct InitiatorDone *idm_p = &idm_local; /* plaintext */
2062 struct GNUNET_HashCode initiator_finished;
2063 struct GNUNET_HashCode transcript;
2064 struct GNUNET_ShortHashCode their_ats;
2065 struct GNUNET_HashContext *hc;
2066 unsigned char enc_key[AEAD_KEY_BYTES];
2067 unsigned char enc_nonce[AEAD_NONCE_BYTES];
2068 struct ConfirmationAck ack_i;
2069 struct ConfirmationAck ack_r;
2070 int8_t ret;
2071
2072 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received InitiatorDone\n");
2073 if (NULL != kx->resend_task)
2074 {
2076 kx->resend_task = NULL;
2077 }
2078 if (NULL != kx->resend_env)
2079 {
2080 GNUNET_free (kx->resend_env);
2081 kx->resend_env = NULL;
2082 }
2083 if (ROLE_INITIATOR == kx->role)
2084 {
2085 GNUNET_break_op (0);
2087 "I am the initiator! Tearing down...\n");
2088 return;
2089 }
2091 0,
2092 enc_key,
2093 enc_nonce);
2094 ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
2095 (unsigned char*) &idm_p->finished, // unsigned char *m
2096 NULL, // mlen_p message length
2097 NULL, // unsigned char *nsec - unused: NULL
2098 (unsigned char*) &idm_e->finished, // const unsigned char *c - ciphertext
2099 sizeof (idm_p->finished) // unsigned long long clen - length of ciphertext
2101 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right?
2102 0, // unsigned long long adlen
2103 enc_nonce, // const unsigned char *npub - nonce
2104 enc_key // const unsigned char *k - key
2105 );
2106 if (0 != ret)
2107 {
2109 "Something went wrong decrypting: %d\n", ret);
2110 return;
2111 }
2112
2113 // - verify finished_I
2114 /* Generate finished_I
2115 * after Forwarding until {finished_R}RHTS
2116 * (did so while we prepared responder hello)
2117 * before forwarding to [{payload}RATS and] {finished_I}IHTS */
2118 // (look at the end of handle_initiator_hello())
2119 snapshot_transcript (kx->transcript_hash_ctx, &transcript);
2120 generate_initiator_finished (&transcript,
2121 &kx->master_secret,
2122 &initiator_finished);
2123 if (0 != memcmp (&idm_p->finished,
2124 &initiator_finished,
2125 sizeof (struct GNUNET_HashCode)))
2126 {
2128 "Could not verify \"initiator finished\" hash.\n");
2130 "Want: `%s'\n",
2131 GNUNET_h2s (&initiator_finished));
2133 "Have: `%s'\n",
2134 GNUNET_h2s (&idm_p->finished));
2136 "Transcript `%s'\n",
2137 GNUNET_h2s (&transcript));
2138 return;
2139 }
2140
2141 /* Forward the transcript hash_context_read */
2144 &idm_e->finished,
2145 sizeof (idm_e->finished)
2146 + AEAD_TAG_BYTES);
2147 snapshot_transcript (hc, &transcript);
2148 derive_initial_ats (&transcript,
2149 &kx->master_secret,
2151 &their_ats);
2152 derive_per_message_secrets (&their_ats, // FIXME other HS epoch?
2153 0,
2154 enc_key,
2155 enc_nonce);
2156 ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
2157 (unsigned char*) &ack_i, // unsigned char *m
2158 NULL, // mlen_p message length
2159 NULL, // unsigned char *nsec - unused: NULL
2160 (unsigned char*) &idm_e[1], // const unsigned char *c - ciphertext
2161 sizeof (ack_i) + AEAD_TAG_BYTES, // unsigned long long clen - length of ciphertext
2162 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right?
2163 0, // unsigned long long adlen
2164 enc_nonce, // const unsigned char *npub - nonce
2165 enc_key // const unsigned char *k - key
2166 );
2167 if (0 != ret)
2168 {
2170 "Something went wrong decrypting the Ack: %d\n", ret);
2172 return;
2173 }
2174 if ((sizeof ack_i != ntohs (ack_i.header.size)) ||
2175 (GNUNET_MESSAGE_TYPE_CORE_ACK != ntohs (ack_i.header.type)))
2176 {
2178 "Ack invalid!\n");
2180 return;
2181 }
2182 GNUNET_memcpy (&kx->their_ats[0],
2183 &their_ats,
2184 sizeof their_ats);
2188 for (int i = 0; i < MAX_EPOCHS - 1; i++)
2189 {
2190 derive_next_ats (&kx->their_ats[i],
2191 &kx->their_ats[i + 1]);
2192 }
2194 kx->transcript_hash_ctx = hc;
2199 monitor_notify_all (kx);
2200 kx->current_sqn = 1;
2201 GSC_SESSIONS_create (&kx->peer, kx, kx->class);
2202 GNUNET_assert (NULL == kx->heartbeat_task);
2203 update_timeout (kx);
2205 ack_r.header.size = htons (sizeof ack_r);
2207 &ack_r,
2208 sizeof ack_r);
2209
2210 GNUNET_TRANSPORT_core_receive_continue (transport,
2211 &kx->peer);
2212}
2213
2214
2220static int
2222{
2223 uint16_t size = ntohs (m->header.size) - sizeof(*m);
2224
2225 // TODO check (see check_encrypted ())
2226 // - check epoch
2227 // - check sequence number
2228 if (size < sizeof(struct GNUNET_MessageHeader))
2229 {
2230 GNUNET_break_op (0);
2231 return GNUNET_SYSERR;
2232 }
2233 return GNUNET_OK;
2234}
2235
2236
2242static void
2244 const struct Heartbeat *m)
2245{
2246 struct GNUNET_ShortHashCode new_ats;
2247 struct ConfirmationAck ack;
2248
2250 {
2251 if (kx->current_epoch == UINT64_MAX)
2252 {
2254 "Max epoch reached (you probably will never see this)\n");
2255 }
2256 else
2257 {
2258 kx->current_epoch++;
2261 kx->current_sqn = 0;
2263 &new_ats);
2264 memcpy (&kx->current_ats,
2265 &new_ats,
2266 sizeof new_ats);
2267 }
2268 }
2269 update_timeout (kx);
2271 ack.header.size = htons (sizeof ack);
2273 &ack,
2274 sizeof ack);
2275 if (NULL != kx->heartbeat_task)
2276 {
2280 kx);
2281 }
2282 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
2283}
2284
2285
2286static enum GNUNET_GenericReturnValue
2288 const char *buf,
2289 size_t buf_len)
2290{
2291 struct GNUNET_MessageHeader *msg;
2292 struct ConfirmationAck *ack;
2293 struct Heartbeat *hb;
2294
2295 if (sizeof *msg > buf_len)
2296 return GNUNET_NO;
2297 msg = (struct GNUNET_MessageHeader*) buf;
2298 if (GNUNET_MESSAGE_TYPE_CORE_ACK == ntohs (msg->type))
2299 {
2300 ack = (struct ConfirmationAck *) buf;
2301 if (sizeof *ack != ntohs (ack->header.size))
2302 return GNUNET_NO;
2303 }
2304 else if (GNUNET_MESSAGE_TYPE_CORE_HEARTBEAT == ntohs (msg->type))
2305 {
2306 hb = (struct Heartbeat*) buf;
2307 if (sizeof *hb != ntohs (hb->header.size))
2308 return GNUNET_NO;
2309 handle_heartbeat (kx, hb);
2310 }
2311 else
2312 {
2313 return GNUNET_NO;
2314 }
2315
2320 {
2321 GSC_SESSIONS_create (&kx->peer, kx, kx->class);
2326 if (NULL != kx->resend_task)
2328 kx->resend_task = NULL;
2329 if (NULL != kx->resend_env)
2330 GNUNET_free (kx->resend_env);
2331 kx->resend_env = NULL;
2332 monitor_notify_all (kx);
2333 }
2334 update_timeout (kx);
2335
2336 return GNUNET_YES;
2337}
2338
2339
2345static void
2347{
2348 struct GSC_KeyExchangeInfo *kx = cls;
2349 uint16_t size = ntohs (m->header.size);
2350 char buf[size - sizeof (*m)] GNUNET_ALIGN;
2351 unsigned char seq_enc_k[crypto_stream_chacha20_ietf_KEYBYTES];
2352 const unsigned char *seq_enc_nonce;
2353 unsigned char enc_key[AEAD_KEY_BYTES];
2354 unsigned char enc_nonce[AEAD_NONCE_BYTES];
2355 struct GNUNET_ShortHashCode new_ats[MAX_EPOCHS];
2356 uint32_t seq_enc_ctr;
2357 uint64_t epoch;
2358 uint64_t m_seq;
2359 uint64_t m_seq_nbo;
2360 uint64_t c_len;
2361 int8_t ret;
2362
2363 // TODO look at handle_encrypted
2364 // - statistics
2365
2369 {
2370 GSC_SESSIONS_end (&kx->peer);
2372 monitor_notify_all (kx);
2373 restart_kx (kx);
2374 return;
2375 }
2376 update_timeout (kx);
2377 epoch = GNUNET_ntohll (m->epoch);
2382 memcpy (new_ats,
2383 kx->their_ats,
2384 MAX_EPOCHS * sizeof (struct GNUNET_ShortHashCode));
2385 // FIXME here we could introduce logic that sends heartbeats
2386 // with key update request if we have not seen a new
2387 // epoch after a while (e.g. EPOCH_EXPIRATION)
2388 if (kx->their_max_epoch < epoch)
2389 {
2394 if ((epoch - kx->their_max_epoch) > 2 * MAX_EPOCHS)
2395 {
2397 "Epoch %" PRIu64 " is too new, will not decrypt...\n",
2398 epoch);
2399 GSC_SESSIONS_end (&kx->peer);
2401 monitor_notify_all (kx);
2402 restart_kx (kx);
2403 return;
2404 }
2405 for (int i = kx->their_max_epoch; i < epoch; i++)
2406 {
2407 derive_next_ats (&new_ats[i % MAX_EPOCHS],
2408 &new_ats[(i + 1) % MAX_EPOCHS]);
2409 }
2410 }
2411 else if ((kx->their_max_epoch - epoch) > MAX_EPOCHS)
2412 {
2414 "Epoch %" PRIu64 " is too old, cannot decrypt...\n",
2415 epoch);
2416 return;
2417 }
2418 derive_sn (
2419 &new_ats[epoch % MAX_EPOCHS],
2420 seq_enc_k,
2421 sizeof seq_enc_k);
2422 /* compute the sequence number */
2423 seq_enc_ctr = *((uint32_t*) m->tag);
2424 seq_enc_nonce = &m->tag[sizeof (uint32_t)];
2425#if DEBUG_KX
2426 GNUNET_print_bytes (&new_ats[epoch % MAX_EPOCHS],
2427 sizeof (struct GNUNET_ShortHashCode),
2428 8,
2429 GNUNET_NO);
2430 GNUNET_print_bytes (seq_enc_k,
2431 sizeof seq_enc_k,
2432 8,
2433 GNUNET_NO);
2434 GNUNET_print_bytes ((char*) &seq_enc_ctr,
2435 sizeof seq_enc_ctr,
2436 8,
2437 GNUNET_NO);
2438#endif
2439 crypto_stream_chacha20_ietf_xor_ic (
2440 (unsigned char*) &m_seq_nbo,
2441 (unsigned char*) &m->sequence_number,
2442 sizeof (uint64_t),
2443 seq_enc_nonce,
2444 ntohl (seq_enc_ctr),
2445 seq_enc_k);
2446 m_seq = GNUNET_ntohll (m_seq_nbo);
2448 "Received encrypted message in epoch %" PRIu64
2449 " with E(SQN=%" PRIu64 ")=%" PRIu64
2450 "\n",
2451 epoch,
2452 m_seq,
2453 m->sequence_number);
2454 /* We are the initiator and as we are going to receive,
2455 * we are using the responder key material */
2456 derive_per_message_secrets (&new_ats[epoch],
2457 m_seq,
2458 enc_key,
2459 enc_nonce);
2460 // TODO checking sequence numbers - handle the case of out-of-sync messages!
2461 // for now only decrypt the payload
2462 // TODO encrypt other fields, too!
2463 // TODO
2464 // c_len = size - offsetof ();
2465 c_len = size - sizeof (struct EncryptedMessage);
2466 ret = crypto_aead_xchacha20poly1305_ietf_decrypt_detached (
2467 (unsigned char*) buf, // m - plain message
2468 NULL, // nsec - unused
2469 (unsigned char*) &m[1], // c - ciphertext
2470 c_len, // clen
2471 (const unsigned char*) &m->tag, // mac
2472 NULL, // ad - additional data TODO
2473 0, // adlen
2474 enc_nonce, // npub
2475 enc_key // k
2476 );
2477 if (0 != ret)
2478 {
2480 "Something went wrong decrypting message\n");
2481 GNUNET_break_op (0); // FIXME handle gracefully
2482 return;
2483 }
2484 kx->their_max_epoch = epoch;
2485 memcpy (&kx->their_ats,
2486 new_ats,
2487 MAX_EPOCHS * sizeof (struct GNUNET_ShortHashCode));
2488
2490 buf,
2491 sizeof buf))
2492 {
2494 {
2496 "Dropping message as we are still waiting for handshake ACK\n");
2497 GNUNET_break_op (0);
2498 return;
2499 }
2500 if (GNUNET_OK !=
2502 buf,
2503 sizeof buf,
2504 GNUNET_YES,
2505 GNUNET_NO))
2506 GNUNET_break_op (0);
2507 }
2508 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
2509}
2510
2511
2521static void
2523 const struct GNUNET_PeerIdentity *peer,
2524 void *handler_cls)
2525{
2526 struct GSC_KeyExchangeInfo *kx = handler_cls;
2527 (void) cls;
2528
2530 "Peer `%s' disconnected from us.\n",
2531 GNUNET_i2s (&kx->peer));
2532 GSC_SESSIONS_end (&kx->peer);
2534 gettext_noop ("# key exchanges stopped"),
2535 1,
2536 GNUNET_NO);
2537 if (NULL != kx->resend_task)
2538 {
2540 kx->resend_task = NULL;
2541 }
2542 if (NULL != kx->resend_env)
2543 {
2544 GNUNET_free (kx->resend_env);
2545 kx->resend_env = NULL;
2546 }
2547 if (NULL != kx->heartbeat_task)
2548 {
2550 kx->heartbeat_task = NULL;
2551 }
2553 monitor_notify_all (kx);
2555 GNUNET_MST_destroy (kx->mst);
2556 GNUNET_free (kx);
2557}
2558
2559
2560static void
2562{
2563 struct GSC_KeyExchangeInfo *kx = cls;
2564
2565 kx->resend_task = NULL;
2567 "Resending initiator hello.\n");
2569 // FIXME (Exponential) backoff?
2572 kx);
2573}
2574
2575
2581static void
2583{
2584 struct GNUNET_MQ_Envelope *env;
2585 struct GNUNET_ShortHashCode es;
2586 struct GNUNET_ShortHashCode ets;
2587 struct GNUNET_ShortHashCode ss_R;
2588 struct InitiatorHelloPayload *ihmp; /* initiator hello message - buffer on stack */
2589 struct InitiatorHello *ihm_e; /* initiator hello message - encrypted */
2590 long long unsigned int c_len;
2591 unsigned char enc_key[AEAD_KEY_BYTES];
2592 unsigned char enc_nonce[AEAD_NONCE_BYTES];
2594 size_t pt_len;
2595
2596 pt_len = sizeof (*ihmp) + strlen (my_services_info);
2597 c_len = pt_len + AEAD_TAG_BYTES;
2598 env = GNUNET_MQ_msg_extra (ihm_e,
2599 c_len,
2601 ihmp = (struct InitiatorHelloPayload*) &ihm_e[1];
2602 ihmp->peer_class = htons (GNUNET_CORE_CLASS_UNKNOWN); // TODO set this to a meaningful
2603 GNUNET_memcpy (&ihmp->pk_I,
2605 sizeof (GSC_my_identity));
2606 GNUNET_CRYPTO_hash (&kx->peer, /* what to hash */ // TODO do we do this twice?
2607 sizeof (struct GNUNET_PeerIdentity),
2608 &ihm_e->h_pk_R); /* result */
2609 // TODO init hashcontext/transcript_hash
2610 GNUNET_assert (NULL == kx->transcript_hash_ctx);
2612 GNUNET_assert (NULL != kx->transcript_hash_ctx);
2613 // TODO fill services_info
2614
2615 // 1. Encaps
2616 ret = GNUNET_CRYPTO_eddsa_kem_encaps (&kx->peer.public_key, // public ephemeral key of initiator
2617 &ihm_e->c_R, // encapsulated key
2618 &ss_R); // key - ss_R
2619 if (GNUNET_OK != ret)
2620 {
2622 "Something went wrong encapsulating ss_R\n");
2623 // TODO handle
2624 }
2625 // 2. generate rR (uint64_t) - is this the nonce? Naming seems not quite
2626 // consistent
2627 ihm_e->r_I =
2629 UINT64_MAX);
2630 // 3. generate sk_e/pk_e - ephemeral key
2633 &kx->sk_e.ecdhe_key,
2634 &kx->pk_e.ecdhe_key);
2635 GNUNET_memcpy (&ihm_e->pk_e,
2636 &kx->pk_e.ecdhe_key,
2637 sizeof (kx->pk_e.ecdhe_key));
2638 // 4. generate ETS to encrypt
2639 // generate ETS (early_traffic_secret_key, decrypt pk_i
2640 // expand ETS <- expand ES <- extract ss_R
2641 // use ETS to decrypt
2643 ihm_e,
2644 sizeof (struct InitiatorHello));
2645 {
2646 struct GNUNET_HashCode transcript;
2648 &transcript);
2649 derive_es_ets (&transcript,
2650 &ss_R,
2651 &es,
2652 &ets);
2654 0,
2655 enc_key,
2656 enc_nonce);
2657 }
2658 // 5. encrypt
2659
2660 ret = crypto_aead_xchacha20poly1305_ietf_encrypt (
2661 (unsigned char*) &ihm_e[1], /* c - ciphertext */
2662 // mac,
2663 // NULL, // maclen_p
2664 &c_len, /* clen_p */
2665 (unsigned char*) ihmp, /* m - plaintext message */
2666 pt_len, // mlen
2667 NULL, 0, // ad, adlen // FIXME maybe over the unencrypted header?
2668 // fields?
2669 NULL, // nsec - unused
2670 enc_nonce, // npub - nonce
2671 enc_key); // k - key
2672 if (0 != ret)
2673 {
2674 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong encrypting\n");
2676 kx->transcript_hash_ctx = NULL;
2678 return;
2679 }
2680 /* Forward the transcript */
2683 &ihm_e[1],
2684 c_len);
2685
2687 kx->early_secret_key = es;
2688 kx->early_traffic_secret = ets;
2689 kx->ss_R = ss_R;
2690 monitor_notify_all (kx);
2691 GNUNET_MQ_send_copy (kx->mq, env);
2692 kx->resend_env = env;
2696 kx);
2697}
2698
2699
2700static void
2702{
2703 struct GNUNET_ShortHashCode new_ats;
2704
2705 if ((UINT64_MAX == kx->current_sqn) ||
2707 {
2709 "Epoch expiration %" PRIu64 " SQN %" PRIu64
2710 ", incrementing epoch...\n",
2712 kx->current_sqn);
2713 // Can this trigger? Maybe if we receive a lot of
2714 // heartbeats?
2715 GNUNET_assert (UINT64_MAX > kx->current_epoch);
2716 kx->current_epoch++;
2719 kx->current_sqn = 0;
2721 &new_ats);
2722 memcpy (&kx->current_ats,
2723 &new_ats,
2724 sizeof new_ats);
2725 }
2726}
2727
2728
2735void
2737 const void *payload,
2738 size_t payload_size)
2739{
2740 struct GNUNET_MQ_Envelope *env;
2741 struct EncryptedMessage *encrypted_msg;
2742 unsigned char enc_key[AEAD_KEY_BYTES];
2743 unsigned char enc_nonce[AEAD_NONCE_BYTES];
2744 unsigned char seq_enc_k[crypto_stream_chacha20_ietf_KEYBYTES];
2745 uint64_t sqn;
2746 uint64_t epoch;
2747 int8_t ret;
2748
2749 encrypted_msg = NULL;
2750
2751 check_rekey (kx);
2752 sqn = kx->current_sqn;
2753 epoch = kx->current_epoch;
2754 /* We are the sender and as we are going to send,
2755 * we are using the initiator key material */
2757 sqn,
2758 enc_key,
2759 enc_nonce);
2760 kx->current_sqn++;
2761 derive_sn (&kx->current_ats,
2762 seq_enc_k,
2763 sizeof seq_enc_k);
2764 env = GNUNET_MQ_msg_extra (encrypted_msg,
2765 payload_size,
2767 // only encrypt the payload for now
2768 // TODO encrypt other fields as well
2769 ret = crypto_aead_xchacha20poly1305_ietf_encrypt_detached (
2770 (unsigned char*) &encrypted_msg[1], // c - resulting ciphertext
2771 (unsigned char*) &encrypted_msg->tag, // mac - resulting mac/tag
2772 NULL, // maclen
2773 (unsigned char*) payload, // m - plain message
2774 payload_size, // mlen
2775 NULL, // ad - additional data TODO also cover the unencrypted part (epoch)
2776 0, // adlen
2777 NULL, // nsec - unused
2778 enc_nonce, // npub nonce
2779 enc_key // k - key
2780 );
2781 if (0 != ret)
2782 {
2784 "Something went wrong encrypting message\n");
2785 GNUNET_assert (0);
2786 }
2787 {
2788 /* compute the sequence number */
2789 unsigned char *seq_enc_nonce;
2790 uint64_t seq_nbo;
2791 uint32_t seq_enc_ctr;
2792
2793 seq_nbo = GNUNET_htonll (sqn);
2794 seq_enc_ctr = *((uint32_t*) encrypted_msg->tag);
2795 seq_enc_nonce = &encrypted_msg->tag[sizeof (uint32_t)];
2796 crypto_stream_chacha20_ietf_xor_ic (
2797 (unsigned char*) &encrypted_msg->sequence_number,
2798 (unsigned char*) &seq_nbo,
2799 sizeof seq_nbo,
2800 seq_enc_nonce,
2801 ntohl (seq_enc_ctr),
2802 seq_enc_k);
2803#if DEBUG_KX
2804 GNUNET_print_bytes (seq_enc_k,
2805 sizeof seq_enc_k,
2806 8,
2807 GNUNET_NO);
2808 GNUNET_print_bytes ((char*) &seq_enc_ctr,
2809 sizeof seq_enc_ctr,
2810 8,
2811 GNUNET_NO);
2812#endif
2814 "Sending encrypted message with E(SQN=%" PRIu64 ")=%" PRIu64
2815 "\n",
2816 sqn,
2817 encrypted_msg->sequence_number);
2818 }
2819 encrypted_msg->epoch = GNUNET_htonll (epoch);
2820
2821 // TODO actually copy payload
2822 GNUNET_MQ_send (kx->mq, env);
2823}
2824
2825
2832static void
2834 const struct GNUNET_HELLO_Parser *parser,
2835 const struct GNUNET_HashCode *hash)
2836{
2837 (void) cls;
2839 // TODO check that hash matches last fed hash
2841 "This peer has now a new peer id: %s\n",
2843 // TODO if changing from old peer_id to new peer_id: tear down old
2844 // connections, try restart connections over kept addresses?
2845 /* Continue initialisation of core */
2846 if (GNUNET_YES == init_phase)
2847 {
2850 }
2851}
2852
2853
2859int
2861{
2863 GNUNET_MQ_hd_var_size (initiator_hello,
2865 struct InitiatorHello,
2866 NULL),
2867 GNUNET_MQ_hd_var_size (initiator_done,
2869 struct InitiatorDone,
2870 NULL),
2871 GNUNET_MQ_hd_var_size (responder_hello,
2873 struct ResponderHello,
2874 NULL),
2875 GNUNET_MQ_hd_var_size (encrypted_message, // TODO rename?
2877 struct EncryptedMessage,
2878 NULL),
2880 };
2881
2885 NULL); // TODO potentially wait
2886 // until we have a peer_id?
2887 // pay attention to whether
2888 // we have one anyways
2889 if (NULL == pils)
2890 {
2891 GSC_KX_done ();
2892 return GNUNET_SYSERR;
2893 }
2894
2896 transport =
2899 handlers,
2900 NULL, // cls - this connection-independant
2901 // cls seems not to be needed.
2902 // the connection-specific cls
2903 // will be set as a return value
2904 // of
2905 // handle_transport_notify_connect
2908 if (NULL == transport)
2909 {
2910 GSC_KX_done ();
2911 return GNUNET_SYSERR;
2912 }
2914 "Connected to TRANSPORT\n");
2915 return GNUNET_OK;
2916}
2917
2918
2922void
2924{
2925 struct PilsRequest *pr;
2926 while (NULL != (pr = pils_requests_head))
2927 {
2930 pr);
2931 if (NULL != pr->op)
2932 GNUNET_PILS_cancel (pr->op);
2933 GNUNET_free (pr);
2934 }
2935 if (NULL != pils)
2936 {
2938 pils = NULL;
2939 }
2940 if (NULL != transport)
2941 {
2943 transport = NULL;
2944 }
2945 if (NULL != rekey_task)
2946 {
2948 rekey_task = NULL;
2949 }
2950 if (NULL != nc)
2951 {
2953 nc = NULL;
2954 }
2955}
2956
2957
2964unsigned int
2966{
2967 return GNUNET_MQ_get_length (kxinfo->mq);
2968}
2969
2970
2971int
2973{
2974 return kxinfo->has_excess_bandwidth;
2975}
2976
2977
2986void
2988{
2989 struct GNUNET_MQ_Envelope *env;
2990 struct MonitorNotifyMessage *done_msg;
2991 struct GSC_KeyExchangeInfo *kx;
2992
2994 for (kx = kx_head; NULL != kx; kx = kx->next)
2995 {
2996 struct GNUNET_MQ_Envelope *env_notify;
2997 struct MonitorNotifyMessage *msg;
2998
3000 msg->state = htonl ((uint32_t) kx->status);
3001 msg->peer = kx->peer;
3002 msg->timeout = GNUNET_TIME_absolute_hton (kx->timeout);
3003 GNUNET_MQ_send (mq, env_notify);
3004 }
3006 done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED);
3009}
3010
3011
3012/* 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.
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.
struct GNUNET_PeerIdentity GSC_my_identity
Our identity.
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_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.
static void peer_id_change_cb(void *cls, const struct GNUNET_HELLO_Parser *parser, const struct GNUNET_HashCode *hash)
Callback for PILS to be called once the peer id changes.
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....
#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.
static enum GNUNET_GenericReturnValue init_phase
Indicates whether we are still in the initialisation phase (waiting for our peer id).
#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.
#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)
static struct GNUNET_PILS_Handle * pils
Pils service.
#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_OS_Process * p
Helper process we started.
Definition gnunet-uri.c:38
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:367
void GNUNET_PILS_disconnect(struct GNUNET_PILS_Handle *handle)
Disconnect from the PILS service.
Definition pils_api.c:390
void GNUNET_PILS_cancel(struct GNUNET_PILS_Operation *op)
Cancel request.
Definition pils_api.c:495
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:468
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.
const struct GNUNET_PeerIdentity * GNUNET_HELLO_parser_get_id(const struct GNUNET_HELLO_Parser *parser)
Get the PeerIdentity for this builder.
Definition hello-uri.c:353
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 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
@ GNUNET_ERROR_TYPE_INFO
#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:232
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
A handle for the PILS service.
Definition pils_api.c:82
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.