GNUnet debian-0.24.3-29-g453fda2cf
 
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 1
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, // result
804 sizeof (*ets), // result len
805 es,
806 CAKE_LABEL, strlen (CAKE_LABEL),
808 transcript,
809 sizeof (*transcript),
810 NULL, 0);
811 if (GNUNET_OK != ret)
812 {
813 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong expanding ETS\n")
814 ;
815 GNUNET_assert (0);
816 }
817}
818
819
820/*
821 * Derive early secret and transport secret.
822 * @param kx the key exchange info
823 */
824static void
825derive_sn (const struct GNUNET_ShortHashCode *secret,
826 unsigned char*sn,
827 size_t sn_len)
828{
830 GNUNET_CRYPTO_hkdf_expand (sn, // result
831 sn_len,
832 secret,
833 CAKE_LABEL, strlen (CAKE_LABEL),
834 "sn", strlen ("sn"),
835 NULL));
836}
837
838
843static void
845 const struct GNUNET_ShortHashCode *ss_e,
847{
848 uint64_t ret;
849 struct GNUNET_ShortHashCode derived_early_secret;
850
851 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Deriving HS\n");
853 );
854 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ss_e: %s\n", GNUNET_B2S (ss_e));
855 ret = GNUNET_CRYPTO_hkdf_expand (&derived_early_secret, // result
856 sizeof (derived_early_secret),
857 es,
858 CAKE_LABEL, strlen (CAKE_LABEL),
859 DERIVED_STR, strlen (DERIVED_STR),
860 NULL);
862 derived_early_secret));
863 if (GNUNET_OK != ret)
864 {
865 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong expanding dES\n")
866 ;
867 GNUNET_assert (0);
868 }
869 // Handshake secret
870 // TODO check: are dES the salt and ss_e the ikm or other way round?
871 ret = GNUNET_CRYPTO_hkdf_extract (handshake_secret, // prk
872 &derived_early_secret, // salt - dES
873 sizeof (derived_early_secret), // salt_len
874 ss_e, // ikm - initial key material
875 sizeof (*ss_e));
876 if (GNUNET_OK != ret)
877 {
878 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong extracting HS\n")
879 ;
880 GNUNET_assert (0);
881 }
882}
883
884
889static void
890derive_ihts (const struct GNUNET_HashCode *transcript,
891 const struct GNUNET_ShortHashCode *hs,
892 struct GNUNET_ShortHashCode *ihts)
893{
895 GNUNET_CRYPTO_hkdf_expand (ihts, // result
896 sizeof (*ihts), // result len
897 hs, // prk?
898 CAKE_LABEL, strlen (CAKE_LABEL),
900 strlen (I_HS_TRAFFIC_STR),
901 transcript,
902 sizeof (*transcript),
903 NULL));
904}
905
906
911static void
912derive_rhts (const struct GNUNET_HashCode *transcript,
913 const struct GNUNET_ShortHashCode *hs,
914 struct GNUNET_ShortHashCode *rhts)
915{
917 GNUNET_CRYPTO_hkdf_expand (rhts, // result
918 sizeof (*rhts), // result len
919 hs, // prk? TODO
920 CAKE_LABEL, strlen (CAKE_LABEL),
922 strlen (R_HS_TRAFFIC_STR),
923 transcript,
924 sizeof (*transcript),
925 NULL));
926}
927
928
933static void
935 const struct GNUNET_ShortHashCode *ss_I,
936 struct GNUNET_ShortHashCode *ms)
937{
938 uint64_t ret;
939 struct GNUNET_ShortHashCode derived_handshake_secret;
940
941 ret = GNUNET_CRYPTO_hkdf_expand (&derived_handshake_secret, // result
942 sizeof (derived_handshake_secret), // result len
943 hs, // prk? TODO
944 CAKE_LABEL, strlen (CAKE_LABEL),
945 DERIVED_STR, strlen (DERIVED_STR),
946 NULL);
947 if (GNUNET_OK != ret)
948 {
949 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong expanding dHS\n")
950 ;
951 GNUNET_assert (0);
952 }
953 // TODO check: are dHS the salt and ss_I the ikm or other way round?
954 ret = GNUNET_CRYPTO_hkdf_extract (ms, // prk
955 &derived_handshake_secret, // salt - dHS
956 sizeof (derived_handshake_secret), // salt_len
957 ss_I, // ikm - initial key material
958 sizeof (*ss_I));
959 if (GNUNET_OK != ret)
960 {
961 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong extracting MS\n")
962 ;
963 GNUNET_assert (0);
964 }
965}
966
967
973static void
975 uint64_t seq,
976 const uint8_t write_iv[AEAD_NONCE_BYTES],
977 uint8_t per_record_write_iv[AEAD_NONCE_BYTES])
978{
979 uint64_t seq_nbo;
980 uint64_t *write_iv_ptr;
981 unsigned int byte_offset;
982
983 seq_nbo = GNUNET_htonll (seq);
984 memcpy (per_record_write_iv,
985 write_iv,
987 byte_offset =
988 AEAD_NONCE_BYTES - sizeof (uint64_t);
989 write_iv_ptr = (uint64_t*) (write_iv + byte_offset);
990 *write_iv_ptr ^= seq_nbo;
991}
992
993
998static void
1000 const struct GNUNET_ShortHashCode *ts,
1001 uint64_t seq,
1002 unsigned char key[AEAD_KEY_BYTES],
1003 unsigned char nonce[AEAD_NONCE_BYTES])
1004{
1005 unsigned char nonce_tmp[AEAD_NONCE_BYTES];
1006 /* derive actual key */
1010 ts,
1011 CAKE_LABEL, strlen (CAKE_LABEL),
1012 KEY_STR,
1013 strlen (KEY_STR),
1014 NULL));
1015
1016 /* derive nonce */
1018 GNUNET_CRYPTO_hkdf_expand (nonce_tmp,
1020 ts,
1021 CAKE_LABEL, strlen (CAKE_LABEL),
1022 IV_STR,
1023 strlen (IV_STR),
1024 NULL));
1026 nonce_tmp,
1027 nonce);
1028}
1029
1030
1035static void
1037 struct GNUNET_ShortHashCode *new_ats)
1038{
1039 int8_t ret;
1040
1041 // FIXME: Not sure of PRK and output may overlap here!
1042 ret = GNUNET_CRYPTO_hkdf_expand (new_ats, // result
1043 sizeof (*new_ats), // result len
1044 old_ats,
1045 CAKE_LABEL, strlen (CAKE_LABEL),
1047 NULL);
1048 if (GNUNET_OK != ret)
1049 {
1051 "Something went wrong deriving next *ATS key\n");
1052 GNUNET_assert (0);
1053 }
1054}
1055
1056
1061static void
1062derive_initial_ats (const struct GNUNET_HashCode *transcript,
1063 const struct GNUNET_ShortHashCode *ms,
1064 enum GSC_KX_Role role,
1065 struct GNUNET_ShortHashCode *initial_ats)
1066{
1067 const char *traffic_str;
1068
1069 if (ROLE_INITIATOR == role)
1070 traffic_str = I_AP_TRAFFIC_STR;
1071 else
1072 traffic_str = R_AP_TRAFFIC_STR;
1074 GNUNET_CRYPTO_hkdf_expand (initial_ats, // result
1075 sizeof (*initial_ats), // result len
1076 ms,
1077 CAKE_LABEL, strlen (CAKE_LABEL),
1078 traffic_str,
1079 strlen (traffic_str),
1080 transcript,
1081 sizeof (*transcript),
1082 NULL));
1083}
1084
1085
1092static void
1094 const struct GNUNET_ShortHashCode *ms,
1095 struct GNUNET_HashCode *result)
1096{
1098 struct GNUNET_CRYPTO_AuthKey fk_R; // We might want to save this in kx?
1099
1100 ret = GNUNET_CRYPTO_hkdf_expand (&fk_R, // result
1101 sizeof (fk_R),
1102 ms,
1103 CAKE_LABEL, strlen (CAKE_LABEL),
1105 NULL);
1106 if (GNUNET_OK != ret)
1107 {
1109 "Something went wrong expanding fk_R\n");
1110 GNUNET_assert (0);
1111 }
1112
1113 GNUNET_CRYPTO_hmac (&fk_R,
1114 transcript,
1115 sizeof (*transcript),
1116 result);
1117}
1118
1119
1126static void
1128 const struct GNUNET_ShortHashCode *ms,
1129 struct GNUNET_HashCode *result)
1130{
1132 struct GNUNET_CRYPTO_AuthKey fk_I; // We might want to save this in kx?
1133
1134 ret = GNUNET_CRYPTO_hkdf_expand (&fk_I, // result
1135 sizeof (fk_I),
1136 ms,
1137 CAKE_LABEL, strlen (CAKE_LABEL),
1139 NULL);
1140 if (GNUNET_OK != ret)
1141 {
1143 "Something went wrong expanding fk_I\n");
1144 GNUNET_assert (0);
1145 }
1146 GNUNET_CRYPTO_hmac (&fk_I,
1147 transcript,
1148 sizeof (*transcript),
1149 result);
1150}
1151
1152
1159
1160static void
1162{
1163 struct GSC_KeyExchangeInfo *kx = cls;
1164
1165 kx->resend_task = NULL;
1166 if (0 == kx->resend_tries_left)
1167 {
1169 "Restarting KX\n");
1170 restart_kx (kx);
1171 return;
1172 }
1173 kx->resend_tries_left--;
1175 "Resending responder hello. Retries left: %u\n",
1176 kx->resend_tries_left);
1180 kx);
1181}
1182
1183
1184void
1186{
1189 struct ResponderHello *rhm_e; /* responder hello message - encrypted pointer */
1190 struct GNUNET_MQ_Envelope *env;
1191 struct GNUNET_CRYPTO_HpkeEncapsulation ephemeral_kem_challenge;
1192 struct GNUNET_ShortHashCode rhts;
1193 struct GNUNET_ShortHashCode ihts;
1194 struct GNUNET_ShortHashCode hs;
1195 struct GNUNET_ShortHashCode ms;
1196 struct GNUNET_ShortHashCode ss_e;
1197 struct GNUNET_ShortHashCode ss_I;
1198 struct GNUNET_HashContext *hc;
1199 unsigned char enc_key[AEAD_KEY_BYTES];
1200 unsigned char enc_nonce[AEAD_NONCE_BYTES];
1201
1202 // 4. encaps -> shared_secret_e, c_e (kemChallenge)
1203 // TODO potentially write this directly into rhm?
1204 ret = GNUNET_CRYPTO_hpke_kem_encaps (&kx->pk_e, // public ephemeral key of initiator
1205 &ephemeral_kem_challenge, // encapsulated key
1206 &ss_e); // key - ss_e
1207 if (GNUNET_OK != ret)
1208 {
1210 "Something went wrong encapsulating ss_e\n");
1211 return;
1212 }
1214 // 6. encaps -> shared_secret_I, c_I
1215 ret = GNUNET_CRYPTO_eddsa_kem_encaps (&kx->peer.public_key, // public key of I
1216 &c_I, // encapsulated key
1217 &ss_I); // where to write the key material
1218 if (GNUNET_OK != ret)
1219 {
1221 "Something went wrong encapsulating ss_I\n");
1223 return;
1224 }
1225 // 7. generate RHTS (responder_handshare_secret_key) and RATS (responder_application_traffic_secret_key) (section 5)
1226 {
1227 struct GNUNET_HashCode transcript;
1228 snapshot_transcript (hc, &transcript);
1229#if DEBUG_KX
1231 "Transcript snapshot for derivation of HS, MS: `%s'\n",
1232 GNUNET_h2s (&transcript));
1233#endif
1235 &ss_e,
1236 &hs);
1237 derive_ms (&hs, &ss_I, &ms);
1238 }
1239
1240 // send ResponderHello
1241 // TODO fill fields / services_info!
1242 // 1. r_R <- random
1243 struct ResponderHelloPayload *rhp;
1244 size_t rhp_len = sizeof (*rhp) + strlen (my_services_info);
1245 unsigned char rhp_buf[rhp_len];
1246 size_t ct_len;
1247
1248 rhp = (struct ResponderHelloPayload*) rhp_buf;
1249 ct_len = rhp_len // ResponderHelloPayload, fist PT msg
1250 + sizeof (struct GNUNET_HashCode) // Finished hash, second PT msg
1251 + AEAD_TAG_BYTES * 2; // Two tags;
1252 env = GNUNET_MQ_msg_extra (rhm_e,
1253 ct_len,
1255
1256 rhm_e->r_R =
1258 UINT64_MAX);
1259
1260 // c_e
1261 GNUNET_memcpy (&rhm_e->c_e,
1262 &ephemeral_kem_challenge,
1263 sizeof (ephemeral_kem_challenge));
1265 rhm_e,
1266 sizeof (struct ResponderHello));
1267 // 2. Encrypt ServicesInfo and c_I with RHTS
1268 // derive RHTS
1269 {
1270 struct GNUNET_HashCode transcript;
1272 &transcript);
1273#if DEBUG_KX
1275 "Transcript snapshot for derivation of *HTS: `%s'\n",
1276 GNUNET_h2s (&transcript));
1277#endif
1278 derive_rhts (&transcript,
1279 &hs,
1280 &rhts);
1281 derive_ihts (&transcript,
1282 &hs,
1283 &ihts);
1285 0,
1286 enc_key,
1287 enc_nonce);
1288 }
1289 // c_I
1290 GNUNET_memcpy (&rhp->c_I, &c_I, sizeof (c_I));
1291 // Services info empty for now.
1292 GNUNET_memcpy (&rhp[1],
1294 strlen (my_services_info));
1295
1296 {
1297 unsigned long long out_ct_len;
1299 struct GNUNET_HashCode transcript;
1300 unsigned char *finished_buf;
1301 GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
1302 (unsigned char*) &rhm_e[1], /* c - ciphertext */
1303 &out_ct_len, /* clen_p */
1304 rhp_buf, /* rhm_p - plaintext message */
1305 rhp_len, // mlen
1306 NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
1307 // fields?
1308 NULL, // nsec - unused
1309 enc_nonce, // npub - nonce // FIXME nonce can be reused
1310 enc_key)); // k - key RHTS
1312 "Encrypted and wrote %llu bytes\n",
1313 out_ct_len);
1314 // 3. Create ResponderFinished (Section 6)
1315 // Derive fk_I <- HKDF-Expand (MS, "r finished", NULL)
1316 /* Forward the transcript */
1317 /* {svcinfo, c_I}RHTS */
1319 hc,
1320 &rhm_e[1],
1321 out_ct_len);
1322
1323 finished_buf = ((unsigned char*) &rhm_e[1]) + out_ct_len;
1325 &transcript);
1326#if DEBUG_KX
1328 "Transcript snapshot for derivation of Rfinished: `%s'\n",
1329 GNUNET_h2s (&transcript));
1330#endif
1331 generate_responder_finished (&transcript,
1332 &ms,
1333 &finished);
1334 // 4. Encrypt ResponderFinished
1336 1,
1337 enc_key,
1338 enc_nonce);
1339 GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
1340 finished_buf, /* c - ciphertext */
1341 &out_ct_len, /* clen_p */
1342 (unsigned char*) &finished, /* rhm_p - plaintext message */
1343 sizeof (finished), // mlen
1344 NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
1345 // fields?
1346 NULL, // nsec - unused
1347 enc_nonce, // npub
1348 enc_key)); // k - key RHTS
1350 "Encrypted and wrote %llu bytes\n",
1351 out_ct_len);
1352 /* Forward the transcript
1353 * after responder finished,
1354 * before deriving *ATS and generating finished_I
1355 * (finished_I will be generated when receiving the InitiatorFinished message
1356 * in order to check it) */
1358 hc,
1359 finished_buf,
1360 out_ct_len);
1361 // 5. optionally send application data - encrypted with RATS
1362 // We do not really have any application data, instead, we send the ACK
1364 &transcript);
1365#if DEBUG_KX
1367 "Transcript snapshot for derivation of *ATS: `%s'\n",
1368 GNUNET_h2s (&transcript));
1369#endif
1370 derive_initial_ats (&transcript,
1371 &ms,
1373 &kx->current_ats);
1374 }
1375 /* Lock into struct */
1377 kx->transcript_hash_ctx = hc;
1378 kx->master_secret = ms;
1379 kx->handshake_secret = hs;
1380 kx->ss_e = ss_e;
1381 kx->ihts = ihts;
1382 kx->rhts = rhts;
1383 kx->ss_I = ss_I;
1384 kx->current_epoch = 0;
1385 kx->current_sqn = 0;
1387 kx->current_sqn,
1388 enc_key,
1389 enc_nonce);
1390
1391 GNUNET_MQ_send_copy (kx->mq, env);
1392 kx->resend_env = env;
1394 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent ResponderHello\n");
1395
1398 kx);
1400 monitor_notify_all (kx);
1401 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
1402}
1403
1404
1405static void
1407{
1408 struct InitiatorHelloCtx *ihm_ctx = cls;
1409 struct GSC_KeyExchangeInfo *kx = ihm_ctx->kx;
1410 uint32_t ihm_len = ntohs (ihm_ctx->ihm_e->header.size);
1411 unsigned char enc_key[AEAD_KEY_BYTES];
1412 unsigned char enc_nonce[AEAD_NONCE_BYTES];
1413 struct GNUNET_HashCode h1;
1414 struct GNUNET_HashCode h2;
1415 struct GNUNET_HashCode transcript;
1416 struct GNUNET_ShortHashCode es;
1417 struct GNUNET_ShortHashCode ets;
1419
1420 ihm_ctx->req->op = NULL;
1423 ihm_ctx->req);
1424 GNUNET_free (ihm_ctx->req);
1425
1426
1427 GNUNET_memcpy (&kx->pk_e,
1428 &ihm_ctx->ihm_e->pk_e,
1429 sizeof (ihm_ctx->ihm_e->pk_e));
1430 // 5. generate ETS (early_traffic_secret_key, decrypt pk_i
1431 // expand ETS <- expand ES <- extract ss_R
1432 // use ETS to decrypt
1433
1434 /* Forward the transcript hash context over the unencrypted fields to get it
1435 * to the same status that the initiator had when it needed to derive es and
1436 * ets for the encryption */
1439 ihm_ctx->ihm_e,
1440 sizeof (struct InitiatorHello));
1442 &transcript);
1443#if DEBUG_KX
1445 "Transcript snapshot for derivation of ES, ETS: `%s'\n",
1446 GNUNET_h2s (&transcript));
1447#endif
1448 derive_es_ets (&transcript, ss_R, &es, &ets);
1450 0,
1451 enc_key,
1452 enc_nonce);
1453 {
1454 struct InitiatorHelloPayload *ihmp;
1455 size_t ct_len = ihm_len - sizeof (struct InitiatorHello);
1456 unsigned char ihmp_buf[ct_len - AEAD_TAG_BYTES];
1457 ihmp = (struct InitiatorHelloPayload*) ihmp_buf;
1458 ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
1459 ihmp_buf, // unsigned char *m
1460 NULL, // mlen_p message length
1461 NULL, // unsigned char *nsec - unused: NULL
1462 (unsigned char*) &ihm_ctx->ihm_e[1], // const unsigned char *c - cyphertext
1463 ct_len, // unsigned long long clen - length of cyphertext
1464 // mac, // const unsigned char *mac - authentication tag
1465 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right?
1466 0, // unsigned long long adlen
1467 enc_nonce, // const unsigned char *npub - nonce
1468 enc_key // const unsigned char *k - key
1469 );
1470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "pid_sender: %s\n",
1471 GNUNET_i2s (&ihmp->pk_I));
1472 if (0 != ret)
1473 {
1475 "Something went wrong decrypting: %d\n", ret);
1476 GNUNET_break_op (0);
1477 GNUNET_free (ihm_ctx->ihm_e);
1478 GNUNET_free (ihm_ctx);
1480 kx->transcript_hash_ctx = NULL;
1481 return;
1482 }
1483 /* now forward it considering the encrypted messages that the initiator was
1484 * able to send after deriving the es and ets */
1486 &ihm_ctx->ihm_e[1],
1487 ct_len);
1488 GNUNET_memcpy (&kx->peer,
1489 &ihmp->pk_I,
1490 sizeof (struct GNUNET_PeerIdentity));
1491 }
1492 // We could follow with the rest of the Key Schedule (dES, HS, ...) for now
1493 /* Check that we are actually in the receiving role */
1494 GNUNET_CRYPTO_hash (&kx->peer, sizeof(struct GNUNET_PeerIdentity), &h1);
1496 sizeof(struct GNUNET_PeerIdentity),
1497 &h2);
1498 if (0 < GNUNET_CRYPTO_hash_cmp (&h1, &h2))
1499 {
1500 /* peer with "lower" identity starts KX, otherwise we typically end up
1501 with both peers starting the exchange and transmit the 'set key'
1502 message twice */
1503 /* Something went wrong - we have the lower value and should have sent the
1504 * InitiatorHello, but instead received it. TODO handle this case
1505 * We might end up in this case if the initiator didn't initiate the
1506 * handshake long enough and the 'responder' initiates the handshake */
1508 "Something went wrong - we have the lower value and should have sent the InitiatorHello, but instead received it.\n");
1509 GNUNET_free (ihm_ctx->ihm_e);
1510 GNUNET_free (ihm_ctx);
1512 kx->transcript_hash_ctx = NULL;
1513 return;
1514 }
1515
1516 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer ID of other peer: %s\n", GNUNET_i2s
1517 (&kx->peer));
1518 /* We update the monitoring peers here because now we know
1519 * that we can decrypt the message AND know the PID
1520 */
1521 monitor_notify_all (kx);
1522 kx->ss_R = *ss_R;
1523 kx->early_secret_key = es;
1524 kx->early_traffic_secret = ets;
1526}
1527
1528
1529static int
1530check_initiator_hello (void *cls, const struct InitiatorHello *m)
1531{
1532 uint16_t size = ntohs (m->header.size);
1533
1534 if (size < sizeof (*m)
1535 + sizeof (struct InitiatorHelloPayload)
1537 {
1538 return GNUNET_SYSERR;
1539 }
1540 return GNUNET_OK;
1541}
1542
1543
1552static void
1553handle_initiator_hello (void *cls, const struct InitiatorHello *ihm_e)
1554{
1555 struct GSC_KeyExchangeInfo *kx = cls;
1556 struct GNUNET_HashCode hash_compare;
1557 struct InitiatorHelloCtx *initiator_hello_cls;
1558 size_t ihm_len;
1559
1560 if (ROLE_INITIATOR == kx->role)
1561 {
1562 GNUNET_break_op (0);
1564 "I am an initiator! Tearing down...\n");
1565 return;
1566 }
1568 {
1569 GNUNET_break_op (0);
1571 "Already received InitiatorHello)\n");
1572 return;
1573 }
1574 GNUNET_assert (NULL == kx->transcript_hash_ctx); // FIXME this triggers sometimes - why?
1577
1578 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received InitiatorHello\n");
1580 gettext_noop ("# key exchanges initiated"),
1581 1,
1582 GNUNET_NO);
1583
1585
1586 // 1. verify type _INITIATOR_HELLO
1587 // - This is implicytly done by arriving within this handler
1588 // - or is this about verifying the 'additional data' part of aead?
1589 // should it check the encryption + mac? (is this implicitly done
1590 // while decrypting?)
1591 // 2. verify H(pk_R) matches pk_R
1593 sizeof (struct GNUNET_PeerIdentity),
1594 &hash_compare); /* result */
1595 if (0 != memcmp (&ihm_e->h_pk_R,
1596 &hash_compare,
1597 sizeof (struct GNUNET_HashCode)))
1598 {
1600 "This message is not meant for us (H(PID) mismatch)\n");
1602 kx->transcript_hash_ctx = NULL;
1603 return;
1604 }
1605 // FIXME this sometimes triggers in the tests - why?
1606 // 3. decaps -> shared_secret_R, c_R (kemChallenge)
1607 ihm_len = ntohs (ihm_e->header.size);
1608 initiator_hello_cls = GNUNET_new (struct InitiatorHelloCtx);
1609 initiator_hello_cls->kx = kx;
1610 initiator_hello_cls->ihm_e = GNUNET_malloc (ihm_len);
1611 GNUNET_memcpy (initiator_hello_cls->ihm_e, ihm_e, ihm_len);
1612 initiator_hello_cls->req = GNUNET_new (struct PilsRequest);
1615 initiator_hello_cls->req);
1616 initiator_hello_cls->req->op =
1618 &ihm_e->c_R,
1619 // encapsulated key
1621 // continuation
1622 initiator_hello_cls);
1623}
1624
1625
1627{
1628 /* Current KX session */
1630
1631 /* responder hello message - encrypted */
1633
1634 /* responder hello message - plain/decrypted */
1636
1637 /* Decrypted finish hash */
1639
1640 /* Encrypted finished CT (for transcript later) */
1641 char finished_enc[sizeof (struct GNUNET_HashCode)
1642 + AEAD_TAG_BYTES];
1643
1644 /* Temporary transcript context */
1646
1647 /* Temporary handshake secret */
1649
1650 /* Temporary handshake secret */
1652
1653 /* Temporary handshake secret */
1655
1656 /* Temporary handshake secret */
1658
1659 /* Pending PILS request */
1661};
1662
1663static void
1665{
1666 struct GSC_KeyExchangeInfo *kx = cls;
1667
1668 kx->resend_task = NULL;
1669 if (0 == kx->resend_tries_left)
1670 {
1672 "Restarting KX\n");
1673 restart_kx (kx);
1674 return;
1675 }
1676 kx->resend_tries_left--;
1678 "Resending initiator done. Retries left: %u\n",
1679 kx->resend_tries_left);
1683 kx);
1684}
1685
1686
1687static void
1689{
1690 struct ResponderHelloCls *rh_ctx = cls;
1691 struct GSC_KeyExchangeInfo *kx = rh_ctx->kx;
1692 struct InitiatorDone *idm_e; /* encrypted */
1693 struct InitiatorDone idm_local;
1694 struct InitiatorDone *idm_p; /* plaintext */
1695 struct GNUNET_MQ_Envelope *env;
1696 unsigned char enc_key[AEAD_KEY_BYTES];
1697 unsigned char enc_nonce[AEAD_NONCE_BYTES];
1698 struct ConfirmationAck ack_i;
1699 struct GNUNET_HashCode transcript;
1700 struct GNUNET_ShortHashCode ms;
1701
1702 rh_ctx->req->op = NULL;
1705 rh_ctx->req);
1706 GNUNET_free (rh_ctx->req);
1707 // XXX valgrind reports uninitialized memory
1708 // the following is a way to check whether this memory was meant
1709 // memset (&rhm_local, 0, sizeof (rhm_local)); - adapt to cls if still needed
1710 memset (&idm_local, 0, sizeof (idm_local));
1711
1712 kx->ss_I = *ss_I;
1713
1714 /* derive *ATS */
1715 derive_ms (&rh_ctx->hs, ss_I, &ms);;
1716 // 5. Create ResponderFinished as per Section 6 and check against decrypted payload.
1717 struct GNUNET_HashCode responder_finished;
1718 // Transcript updates, snapshot again
1719 snapshot_transcript (rh_ctx->hc,
1720 &transcript);
1721#if DEBUG_KX
1723 "Transcript snapshot for derivation of Rfinished: `%s'\n",
1724 GNUNET_h2s (&transcript));
1725#endif
1726 generate_responder_finished (&transcript,
1727 &ms,
1728 &responder_finished);
1729 if (0 != memcmp (&rh_ctx->decrypted_finish,
1730 &responder_finished,
1731 sizeof (struct GNUNET_HashCode)))
1732 {
1734 "Could not verify \"responder finished\"\n");
1735 GNUNET_free (rh_ctx->rhp);
1736 GNUNET_free (rh_ctx->hc);
1737 GNUNET_free (rh_ctx);
1738 GNUNET_assert (0);
1739 }
1740
1741
1742 /* Forward the transcript
1743 * after generating finished_R,
1744 * before deriving *ATS */
1746 rh_ctx->hc,
1747 rh_ctx->finished_enc,
1748 sizeof (rh_ctx->finished_enc));
1749
1750 // At this point we cannot fail anymore and may lock into kx
1752 kx->transcript_hash_ctx = rh_ctx->hc;
1753 kx->ss_I = *ss_I;
1754 kx->handshake_secret = rh_ctx->hs;
1755 kx->ss_e = rh_ctx->ss_e;
1756 kx->ihts = rh_ctx->ihts;
1757 kx->rhts = rh_ctx->rhts;
1758 kx->master_secret = ms;
1759 GNUNET_free (rh_ctx->rhp);
1760 GNUNET_free (rh_ctx);
1761 rh_ctx = NULL;
1762
1764 &transcript);
1765#if DEBUG_KX
1767 "Transcript snapshot for derivation of *ATS: `%s'\n",
1768 GNUNET_h2s (&transcript));
1769#endif
1770 derive_initial_ats (&transcript,
1771 &kx->master_secret,
1773 &kx->their_ats[0]);
1774 for (int i = 0; i < MAX_EPOCHS - 1; i++)
1775 {
1776 derive_next_ats (&kx->their_ats[i],
1777 &kx->their_ats[i + 1]);
1778 }
1779 kx->their_max_epoch = MAX_EPOCHS - 1;
1780
1782 0,
1783 enc_key,
1784 enc_nonce);
1785 /* Create InitiatorDone message */
1786 idm_p = &idm_local; /* plaintext */
1787 env = GNUNET_MQ_msg_extra (idm_e,
1788 sizeof (ack_i)
1791 // 6. Create IteratorFinished as per Section 6.
1792 generate_initiator_finished (&transcript,
1793 &kx->master_secret,
1794 &idm_p->finished);
1796 "Ifinished: `%s'\n",
1797 GNUNET_h2s (&idm_p->finished));
1799 "Transcript `%s'\n",
1800 GNUNET_h2s (&transcript));
1801 // 7. Send InteratorFinished message encrypted with the key derived from IHTS to R
1802
1803 GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
1804 (unsigned char*) &idm_e->finished, /* c - ciphertext */
1805 NULL, /* clen_p */
1806 (unsigned char*) &idm_p->finished, /* idm_p - plaintext message */
1807 sizeof (idm_p->finished), // mlen
1808 NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
1809 // fields?
1810 NULL, // nsec - unused
1811 enc_nonce, // npub - nonce
1812 enc_key)); // k - key IHTS
1813 /* Forward the transcript hash context
1814 * after generating finished_I and RATS_0
1815 * before deriving IATS_0 */
1817 &idm_e->finished,
1818 sizeof (idm_e->finished)
1819 + AEAD_TAG_BYTES);
1821 &transcript);
1822#if DEBUG_KX
1824 "Transcript snapshot for derivation of *ATS: `%s'\n",
1825 GNUNET_h2s (&transcript));
1826#endif
1827 derive_initial_ats (&transcript,
1828 &kx->master_secret,
1830 &kx->current_ats);
1831 kx->current_epoch = 0;
1832 kx->current_sqn++;
1833 // 8. optionally encrypt payload TODO
1835 kx->current_sqn,
1836 enc_key,
1837 enc_nonce);
1838 kx->current_sqn++;
1840 ack_i.header.size = htons (sizeof ack_i);
1841 GNUNET_assert (0 == crypto_aead_xchacha20poly1305_ietf_encrypt (
1842 (unsigned char*) &idm_e[1], /* c - ciphertext */
1843 NULL, /* clen_p */
1844 (unsigned char*) &ack_i, /* rhm_p - plaintext message */
1845 sizeof ack_i, // mlen
1846 NULL, 0, // ad, adlen // FIXME should this not be the other, unencrypted
1847 // fields?
1848 NULL, // nsec - unused
1849 enc_nonce, // npub - nonce // FIXME nonce can be reused
1850 enc_key)); // k - key RHTS
1851
1852 GNUNET_MQ_send_copy (kx->mq, env);
1853 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent InitiatorDone\n");
1854
1855
1856 kx->resend_env = env;
1860 kx);
1862 monitor_notify_all (kx);
1863 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
1864}
1865
1866
1867static int
1868check_responder_hello (void *cls, const struct ResponderHello *m)
1869{
1870 uint16_t size = ntohs (m->header.size);
1871
1872 if (size < sizeof (*m)
1873 + sizeof (struct ResponderHelloPayload)
1874 + sizeof (struct GNUNET_HashCode)
1875 + AEAD_TAG_BYTES * 2)
1876 {
1877 return GNUNET_SYSERR;
1878 }
1879 return GNUNET_OK;
1880}
1881
1882
1888static void
1889handle_responder_hello (void *cls, const struct ResponderHello *rhm_e)
1890{
1891 struct GSC_KeyExchangeInfo *kx = cls;
1892 struct PilsRequest *req;
1893 struct ResponderHelloCls *rh_ctx;
1894 struct GNUNET_HashCode transcript;
1895 struct GNUNET_HashContext *hc;
1896 unsigned char enc_key[AEAD_KEY_BYTES];
1897 unsigned char enc_nonce[AEAD_NONCE_BYTES];
1899
1900 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ResponderHello\n");
1901
1903 if (NULL != kx->resend_task)
1904 {
1906 kx->resend_task = NULL;
1907 }
1908 if (NULL != kx->resend_env)
1909 {
1910 GNUNET_free (kx->resend_env);
1911 kx->resend_env = NULL;
1912 }
1913
1914 /* Forward the transcript hash context */
1915 if (ROLE_RESPONDER == kx->role)
1916 {
1917 GNUNET_break_op (0);
1919 "I am the responder! Ignoring.\n");
1920 return;
1921 }
1923 rhm_e,
1924 sizeof (struct ResponderHello));
1925 // 1. Verify that the message type is CORE_RESPONDER_HELLO
1926 // - implicitly done by handling this message?
1927 // - or is this about verifying the 'additional data' part of aead?
1928 // should it check the encryption + mac? (is this implicitly done
1929 // while decrypting?)
1930 // 2. sse <- Decaps(ske,ce)
1931 rh_ctx = GNUNET_new (struct ResponderHelloCls);
1932 ret = GNUNET_CRYPTO_hpke_kem_decaps (&kx->sk_e, // secret/private ephemeral key of initiator (us)
1933 &rhm_e->c_e, // encapsulated key
1934 &rh_ctx->ss_e); // key - ss_e
1935 if (GNUNET_OK != ret)
1936 {
1938 "Something went wrong decapsulating ss_e\n");
1939 GNUNET_free (hc);
1940 return;
1941 }
1942 // 3. Generate IHTS and RHTS from Section 5 and decrypt ServicesInfo, cI and ResponderFinished.
1943 snapshot_transcript (hc, &transcript);
1944#if DEBUG_KX
1946 "Transcript snapshot for derivation of HS, *HTS: `%s'\n",
1947 GNUNET_h2s (&transcript));
1948#endif
1950 &rh_ctx->ss_e,
1951 &rh_ctx->hs);
1952 derive_rhts (&transcript,
1953 &rh_ctx->hs,
1954 &rh_ctx->rhts);
1955 derive_ihts (&transcript,
1956 &rh_ctx->hs,
1957 &rh_ctx->ihts);
1959 0,
1960 enc_key,
1961 enc_nonce);
1962 rh_ctx->kx = kx;
1963 GNUNET_memcpy (&rh_ctx->rhm_e, rhm_e, sizeof (*rhm_e));
1964 {
1965 unsigned long long int c_len;
1966 unsigned char *finished_buf;
1967 // use RHTS to decrypt
1968 c_len = ntohs (rhm_e->header.size) - sizeof (*rhm_e)
1969 - sizeof (struct GNUNET_HashCode)
1970 - AEAD_TAG_BYTES; // finished ct
1971 rh_ctx->rhp = GNUNET_malloc (c_len
1972 -
1974 rh_ctx->hc = hc;
1975 finished_buf = ((unsigned char*) &rhm_e[1]) + c_len;
1976 /* Forward the transcript_hash_ctx
1977 * after rhts has been generated,
1978 * before generating finished_R*/
1980 hc,
1981 &rhm_e[1],
1982 c_len);
1983
1984 ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
1985 (unsigned char*) rh_ctx->rhp, // unsigned char *m
1986 NULL, // mlen_p message length
1987 NULL, // unsigned char *nsec - unused: NULL
1988 (unsigned char*) &rhm_e[1], // const unsigned char *c - cyphertext
1989 c_len, // unsigned long long clen - length of cyphertext
1990 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right?
1991 0, // unsigned long long adlen
1992 enc_nonce, // const unsigned char *npub - nonce
1993 enc_key // const unsigned char *k - key
1994 );
1995 if (0 != ret)
1996 {
1998 "Something went wrong decrypting: %d\n", ret);
1999 GNUNET_free (rh_ctx->rhp);
2000 GNUNET_free (rh_ctx);
2001 GNUNET_free (hc);
2002 return;
2003 }
2004 // FIXME nonce reuse (see encryption)
2006 1,
2007 enc_key,
2008 enc_nonce);
2009 c_len = sizeof (struct GNUNET_HashCode)
2011 ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
2012 (unsigned char*) &rh_ctx->decrypted_finish, // unsigned char *m
2013 NULL, // mlen_p message length
2014 NULL, // unsigned char *nsec - unused: NULL
2015 finished_buf, // const unsigned char *c - cyphertext
2016 c_len, // unsigned long long clen - length of cyphertext
2017 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right?
2018 0, // unsigned long long adlen
2019 enc_nonce, // const unsigned char *npub - nonce
2020 enc_key // const unsigned char *k - key
2021 );
2022 if (0 != ret)
2023 {
2025 "Something went wrong decrypting finished field: %d\n", ret);
2026 GNUNET_free (rh_ctx->rhp);
2027 GNUNET_free (rh_ctx);
2028 GNUNET_free (hc);
2029 return;
2030 }
2031 GNUNET_memcpy (rh_ctx->finished_enc,
2032 finished_buf,
2033 c_len);
2034 }
2035 // 4. ssI <- Decaps(skI,cI).
2036 req = GNUNET_new (struct PilsRequest);
2037 rh_ctx->req = req;
2040 req);
2042 &rh_ctx->rhp->c_I, // encapsulated key
2043 &handle_responder_hello_cont, // continuation
2044 rh_ctx);
2045}
2046
2047
2048static int
2049check_initiator_done (void *cls, const struct InitiatorDone *m)
2050{
2051 uint16_t size = ntohs (m->header.size);
2052
2053 if (size < sizeof (*m) + sizeof (struct ConfirmationAck))
2054 {
2055 return GNUNET_SYSERR;
2056 }
2057 return GNUNET_OK;
2058}
2059
2060
2066static void
2067handle_initiator_done (void *cls, const struct InitiatorDone *idm_e)
2068{
2069 struct GSC_KeyExchangeInfo *kx = cls;
2070 struct InitiatorDone idm_local;
2071 struct InitiatorDone *idm_p = &idm_local; /* plaintext */
2072 struct GNUNET_HashCode initiator_finished;
2073 struct GNUNET_HashCode transcript;
2074 struct GNUNET_ShortHashCode their_ats;
2075 struct GNUNET_HashContext *hc;
2076 unsigned char enc_key[AEAD_KEY_BYTES];
2077 unsigned char enc_nonce[AEAD_NONCE_BYTES];
2078 struct ConfirmationAck ack_i;
2079 struct ConfirmationAck ack_r;
2080 int8_t ret;
2081
2082 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received InitiatorDone\n");
2083 if (NULL != kx->resend_task)
2084 {
2086 kx->resend_task = NULL;
2087 }
2088 if (NULL != kx->resend_env)
2089 {
2090 GNUNET_free (kx->resend_env);
2091 kx->resend_env = NULL;
2092 }
2093 if (ROLE_INITIATOR == kx->role)
2094 {
2095 GNUNET_break_op (0);
2097 "I am the initiator! Tearing down...\n");
2098 return;
2099 }
2101 0,
2102 enc_key,
2103 enc_nonce);
2104 ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
2105 (unsigned char*) &idm_p->finished, // unsigned char *m
2106 NULL, // mlen_p message length
2107 NULL, // unsigned char *nsec - unused: NULL
2108 (unsigned char*) &idm_e->finished, // const unsigned char *c - cyphertext
2109 sizeof (idm_p->finished) // unsigned long long clen - length of cyphertext
2111 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right?
2112 0, // unsigned long long adlen
2113 enc_nonce, // const unsigned char *npub - nonce
2114 enc_key // const unsigned char *k - key
2115 );
2116 if (0 != ret)
2117 {
2119 "Something went wrong decrypting: %d\n", ret);
2120 return;
2121 }
2122
2123 // - verify finished_I
2124 /* Generate finished_I
2125 * after Forwarding until {finished_R}RHTS
2126 * (did so while we prepared responder hello)
2127 * before forwarding to [{payload}RATS and] {finished_I}IHTS */
2128 // (look at the end of handle_initiator_hello())
2129 snapshot_transcript (kx->transcript_hash_ctx, &transcript);
2130 generate_initiator_finished (&transcript,
2131 &kx->master_secret,
2132 &initiator_finished);
2133 if (0 != memcmp (&idm_p->finished,
2134 &initiator_finished,
2135 sizeof (struct GNUNET_HashCode)))
2136 {
2138 "Could not verify \"initiator finished\" hash.\n");
2140 "Want: `%s'\n",
2141 GNUNET_h2s (&initiator_finished));
2143 "Have: `%s'\n",
2144 GNUNET_h2s (&idm_p->finished));
2146 "Transcript `%s'\n",
2147 GNUNET_h2s (&transcript));
2148 return;
2149 }
2150
2151 /* Forward the transcript hash_context_read */
2154 &idm_e->finished,
2155 sizeof (idm_e->finished)
2156 + AEAD_TAG_BYTES);
2157 snapshot_transcript (hc, &transcript);
2158 derive_initial_ats (&transcript,
2159 &kx->master_secret,
2161 &their_ats);
2162 derive_per_message_secrets (&their_ats, // FIXME other HS epoch?
2163 0,
2164 enc_key,
2165 enc_nonce);
2166 ret = crypto_aead_xchacha20poly1305_ietf_decrypt (
2167 (unsigned char*) &ack_i, // unsigned char *m
2168 NULL, // mlen_p message length
2169 NULL, // unsigned char *nsec - unused: NULL
2170 (unsigned char*) &idm_e[1], // const unsigned char *c - cyphertext
2171 sizeof (ack_i) + AEAD_TAG_BYTES, // unsigned long long clen - length of cyphertext
2172 NULL, // const unsigned char *ad - additional data (optional) TODO those should be used, right?
2173 0, // unsigned long long adlen
2174 enc_nonce, // const unsigned char *npub - nonce
2175 enc_key // const unsigned char *k - key
2176 );
2177 if (0 != ret)
2178 {
2180 "Something went wrong decrypting the Ack: %d\n", ret);
2182 return;
2183 }
2184 if ((sizeof ack_i != ntohs (ack_i.header.size)) ||
2185 (GNUNET_MESSAGE_TYPE_CORE_ACK != ntohs (ack_i.header.type)))
2186 {
2188 "Ack invalid!\n");
2190 return;
2191 }
2192 GNUNET_memcpy (&kx->their_ats[0],
2193 &their_ats,
2194 sizeof their_ats);
2198 for (int i = 0; i < MAX_EPOCHS - 1; i++)
2199 {
2200 derive_next_ats (&kx->their_ats[i],
2201 &kx->their_ats[i + 1]);
2202 }
2204 kx->transcript_hash_ctx = hc;
2209 monitor_notify_all (kx);
2210 kx->current_sqn = 1;
2211 GSC_SESSIONS_create (&kx->peer, kx, kx->class);
2212 GNUNET_assert (NULL == kx->heartbeat_task);
2213 update_timeout (kx);
2215 ack_r.header.size = htons (sizeof ack_r);
2217 &ack_r,
2218 sizeof ack_r);
2219
2220 GNUNET_TRANSPORT_core_receive_continue (transport,
2221 &kx->peer);
2222}
2223
2224
2230static int
2232{
2233 uint16_t size = ntohs (m->header.size) - sizeof(*m);
2234
2235 // TODO check (see check_encrypted ())
2236 // - check epoch
2237 // - check sequence number
2238 if (size < sizeof(struct GNUNET_MessageHeader))
2239 {
2240 GNUNET_break_op (0);
2241 return GNUNET_SYSERR;
2242 }
2243 return GNUNET_OK;
2244}
2245
2246
2252static void
2254 const struct Heartbeat *m)
2255{
2256 struct GNUNET_ShortHashCode new_ats;
2257 struct ConfirmationAck ack;
2258
2260 {
2261 if (kx->current_epoch == UINT64_MAX)
2262 {
2264 "Max epoch reached (you probably will never see this)\n");
2265 }
2266 else
2267 {
2268 kx->current_epoch++;
2271 kx->current_sqn = 0;
2273 &new_ats);
2274 memcpy (&kx->current_ats,
2275 &new_ats,
2276 sizeof new_ats);
2277 }
2278 }
2279 update_timeout (kx);
2281 ack.header.size = htons (sizeof ack);
2283 &ack,
2284 sizeof ack);
2285 if (NULL != kx->heartbeat_task)
2286 {
2290 kx);
2291 }
2292 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
2293}
2294
2295
2296static enum GNUNET_GenericReturnValue
2298 const char *buf,
2299 size_t buf_len)
2300{
2301 struct GNUNET_MessageHeader *msg;
2302 struct ConfirmationAck *ack;
2303 struct Heartbeat *hb;
2304
2305 if (sizeof *msg > buf_len)
2306 return GNUNET_NO;
2307 msg = (struct GNUNET_MessageHeader*) buf;
2308 if (GNUNET_MESSAGE_TYPE_CORE_ACK == ntohs (msg->type))
2309 {
2310 ack = (struct ConfirmationAck *) buf;
2311 if (sizeof *ack != ntohs (ack->header.size))
2312 return GNUNET_NO;
2313 }
2314 else if (GNUNET_MESSAGE_TYPE_CORE_HEARTBEAT == ntohs (msg->type))
2315 {
2316 hb = (struct Heartbeat*) buf;
2317 if (sizeof *hb != ntohs (hb->header.size))
2318 return GNUNET_NO;
2319 handle_heartbeat (kx, hb);
2320 }
2321 else
2322 {
2323 return GNUNET_NO;
2324 }
2325
2330 {
2331 GSC_SESSIONS_create (&kx->peer, kx, kx->class);
2336 if (NULL != kx->resend_task)
2338 kx->resend_task = NULL;
2339 if (NULL != kx->resend_env)
2340 GNUNET_free (kx->resend_env);
2341 kx->resend_env = NULL;
2342 monitor_notify_all (kx);
2343 }
2344 update_timeout (kx);
2345
2346 return GNUNET_YES;
2347}
2348
2349
2355static void
2357{
2358 struct GSC_KeyExchangeInfo *kx = cls;
2359 uint16_t size = ntohs (m->header.size);
2360 char buf[size - sizeof (*m)] GNUNET_ALIGN;
2361 unsigned char seq_enc_k[crypto_stream_chacha20_ietf_KEYBYTES];
2362 const unsigned char *seq_enc_nonce;
2363 unsigned char enc_key[AEAD_KEY_BYTES];
2364 unsigned char enc_nonce[AEAD_NONCE_BYTES];
2365 struct GNUNET_ShortHashCode new_ats[MAX_EPOCHS];
2366 uint32_t seq_enc_ctr;
2367 uint64_t epoch;
2368 uint64_t m_seq;
2369 uint64_t m_seq_nbo;
2370 uint64_t c_len;
2371 int8_t ret;
2372
2373 // TODO look at handle_encrypted
2374 // - statistics
2375
2379 {
2380 GSC_SESSIONS_end (&kx->peer);
2382 monitor_notify_all (kx);
2383 restart_kx (kx);
2384 return;
2385 }
2386 update_timeout (kx);
2387 epoch = GNUNET_ntohll (m->epoch);
2392 memcpy (new_ats,
2393 kx->their_ats,
2394 MAX_EPOCHS * sizeof (struct GNUNET_ShortHashCode));
2395 // FIXME here we could introduce logic that sends hearbeats
2396 // with key update request if we have not seen a new
2397 // epoch after a while (e.g. EPOCH_EXPIRATION)
2398 if (kx->their_max_epoch < epoch)
2399 {
2404 if ((epoch - kx->their_max_epoch) > 2 * MAX_EPOCHS)
2405 {
2407 "Epoch %" PRIu64 " is too new, will not decrypt...\n",
2408 epoch);
2409 GSC_SESSIONS_end (&kx->peer);
2411 monitor_notify_all (kx);
2412 restart_kx (kx);
2413 return;
2414 }
2415 for (int i = kx->their_max_epoch; i < epoch; i++)
2416 {
2417 derive_next_ats (&new_ats[i % MAX_EPOCHS],
2418 &new_ats[(i + 1) % MAX_EPOCHS]);
2419 }
2420 }
2421 else if ((kx->their_max_epoch - epoch) > MAX_EPOCHS)
2422 {
2424 "Epoch %" PRIu64 " is too old, cannot decrypt...\n",
2425 epoch);
2426 return;
2427 }
2428 derive_sn (
2429 &new_ats[epoch % MAX_EPOCHS],
2430 seq_enc_k,
2431 sizeof seq_enc_k);
2432 /* compute the sequence number */
2433 seq_enc_ctr = *((uint32_t*) m->tag);
2434 seq_enc_nonce = &m->tag[sizeof (uint32_t)];
2435#if DEBUG_KX
2436 GNUNET_print_bytes (&new_ats[epoch % MAX_EPOCHS],
2437 sizeof (struct GNUNET_ShortHashCode),
2438 8,
2439 GNUNET_NO);
2440 GNUNET_print_bytes (seq_enc_k,
2441 sizeof seq_enc_k,
2442 8,
2443 GNUNET_NO);
2444 GNUNET_print_bytes ((char*) &seq_enc_ctr,
2445 16,
2446 8,
2447 GNUNET_NO);
2448#endif
2449 crypto_stream_chacha20_ietf_xor_ic (
2450 (unsigned char*) &m_seq_nbo,
2451 (unsigned char*) &m->sequence_number,
2452 sizeof (uint64_t),
2453 seq_enc_nonce,
2454 ntohl (seq_enc_ctr),
2455 seq_enc_k);
2456 m_seq = GNUNET_ntohll (m_seq_nbo);
2458 "Received encrypted message in epoch %" PRIu64
2459 " with E(SQN=%" PRIu64 ")=%" PRIu64
2460 "\n",
2461 epoch,
2462 m_seq,
2463 m->sequence_number);
2464 /* We are the initiator and as we are going to receive,
2465 * we are using the responder key material */
2466 derive_per_message_secrets (&new_ats[epoch],
2467 m_seq,
2468 enc_key,
2469 enc_nonce);
2470 // TODO checking sequence numbers - handle the case of out-of-sync messages!
2471 // for now only decrypt the payload
2472 // TODO encrypt other fields, too!
2473 // TODO
2474 // c_len = size - offsetof ();
2475 c_len = size - sizeof (struct EncryptedMessage);
2476 ret = crypto_aead_xchacha20poly1305_ietf_decrypt_detached (
2477 (unsigned char*) buf, // m - plain message
2478 NULL, // nsec - unused
2479 (unsigned char*) &m[1], // c - ciphertext
2480 c_len, // clen
2481 (const unsigned char*) &m->tag, // mac
2482 NULL, // ad - additional data TODO
2483 0, // adlen
2484 enc_nonce, // npub
2485 enc_key // k
2486 );
2487 if (0 != ret)
2488 {
2490 "Something went wrong decrypting message\n");
2491 GNUNET_break_op (0); // FIXME handle gracefully
2492 return;
2493 }
2494 kx->their_max_epoch = epoch;
2495 memcpy (&kx->their_ats,
2496 new_ats,
2497 MAX_EPOCHS * sizeof (struct GNUNET_ShortHashCode));
2498
2500 buf,
2501 sizeof buf))
2502 {
2504 {
2506 "Dropping message as we are still waiting for handshake ACK\n");
2507 GNUNET_break_op (0);
2508 return;
2509 }
2510 if (GNUNET_OK !=
2512 buf,
2513 sizeof buf,
2514 GNUNET_YES,
2515 GNUNET_NO))
2516 GNUNET_break_op (0);
2517 }
2518 GNUNET_TRANSPORT_core_receive_continue (transport, &kx->peer);
2519}
2520
2521
2531static void
2533 const struct GNUNET_PeerIdentity *peer,
2534 void *handler_cls)
2535{
2536 struct GSC_KeyExchangeInfo *kx = handler_cls;
2537 (void) cls;
2538
2540 "Peer `%s' disconnected from us.\n",
2541 GNUNET_i2s (&kx->peer));
2542 GSC_SESSIONS_end (&kx->peer);
2544 gettext_noop ("# key exchanges stopped"),
2545 1,
2546 GNUNET_NO);
2547 if (NULL != kx->resend_task)
2548 {
2550 kx->resend_task = NULL;
2551 }
2552 if (NULL != kx->resend_env)
2553 {
2554 GNUNET_free (kx->resend_env);
2555 kx->resend_env = NULL;
2556 }
2557 if (NULL != kx->heartbeat_task)
2558 {
2560 kx->heartbeat_task = NULL;
2561 }
2563 monitor_notify_all (kx);
2565 GNUNET_MST_destroy (kx->mst);
2566 GNUNET_free (kx);
2567}
2568
2569
2570static void
2572{
2573 struct GSC_KeyExchangeInfo *kx = cls;
2574
2575 kx->resend_task = NULL;
2577 "Resending initiator hello.\n");
2579 // FIXME (Exponential) backoff?
2582 kx);
2583}
2584
2585
2591static void
2593{
2594 struct GNUNET_MQ_Envelope *env;
2595 struct GNUNET_ShortHashCode es;
2596 struct GNUNET_ShortHashCode ets;
2597 struct GNUNET_ShortHashCode ss_R;
2598 struct InitiatorHelloPayload *ihmp; /* initiator hello message - buffer on stack */
2599 struct InitiatorHello *ihm_e; /* initiator hello message - encrypted */
2600 long long unsigned int c_len;
2601 unsigned char enc_key[AEAD_KEY_BYTES];
2602 unsigned char enc_nonce[AEAD_NONCE_BYTES];
2604 size_t pt_len;
2605
2606 pt_len = sizeof (*ihmp) + strlen (my_services_info);
2607 c_len = pt_len + AEAD_TAG_BYTES;
2608 env = GNUNET_MQ_msg_extra (ihm_e,
2609 c_len,
2611 ihmp = (struct InitiatorHelloPayload*) &ihm_e[1];
2612 ihmp->peer_class = htons (GNUNET_CORE_CLASS_UNKNOWN); // TODO set this to a meaningful
2613 GNUNET_memcpy (&ihmp->pk_I,
2615 sizeof (GSC_my_identity));
2616 GNUNET_CRYPTO_hash (&kx->peer, /* what to hash */ // TODO do we do this twice?
2617 sizeof (struct GNUNET_PeerIdentity),
2618 &ihm_e->h_pk_R); /* result */
2619 // TODO init hashcontext/transcript_hash
2620 GNUNET_assert (NULL == kx->transcript_hash_ctx);
2622 GNUNET_assert (NULL != kx->transcript_hash_ctx);
2623 // TODO fill services_info
2624
2625 // 1. Encaps
2626 ret = GNUNET_CRYPTO_eddsa_kem_encaps (&kx->peer.public_key, // public ephemeral key of initiator
2627 &ihm_e->c_R, // encapsulated key
2628 &ss_R); // key - ss_R
2629 if (GNUNET_OK != ret)
2630 {
2632 "Something went wrong encapsulating ss_R\n");
2633 // TODO handle
2634 }
2635 // 2. generate rR (uint64_t) - is this the nonce? Naming seems not quite
2636 // consistent
2637 ihm_e->r_I =
2639 UINT64_MAX);
2640 // 3. generate sk_e/pk_e - ephemeral key
2643 &kx->sk_e,
2644 &kx->pk_e);
2645 GNUNET_memcpy (&ihm_e->pk_e, &kx->pk_e, sizeof (kx->pk_e));
2646 // 4. generate ETS to encrypt
2647 // generate ETS (early_traffic_secret_key, decrypt pk_i
2648 // expand ETS <- expand ES <- extract ss_R
2649 // use ETS to decrypt
2651 ihm_e,
2652 sizeof (struct InitiatorHello));
2653 {
2654 struct GNUNET_HashCode transcript;
2656 &transcript);
2657 derive_es_ets (&transcript,
2658 &ss_R,
2659 &es,
2660 &ets);
2662 0,
2663 enc_key,
2664 enc_nonce);
2665 }
2666 // 5. encrypt
2667
2668 ret = crypto_aead_xchacha20poly1305_ietf_encrypt (
2669 (unsigned char*) &ihm_e[1], /* c - ciphertext */
2670 // mac,
2671 // NULL, // maclen_p
2672 &c_len, /* clen_p */
2673 (unsigned char*) ihmp, /* m - plaintext message */
2674 pt_len, // mlen
2675 NULL, 0, // ad, adlen // FIXME maybe over the unencrypted header?
2676 // fields?
2677 NULL, // nsec - unused
2678 enc_nonce, // npub - nonce
2679 enc_key); // k - key
2680 if (0 != ret)
2681 {
2682 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Something went wrong encrypting\n");
2684 kx->transcript_hash_ctx = NULL;
2685 return;
2686 }
2687 /* Forward the transcript */
2690 &ihm_e[1],
2691 c_len);
2692
2694 kx->early_secret_key = es;
2695 kx->early_traffic_secret = ets;
2696 kx->ss_R = ss_R;
2697 monitor_notify_all (kx);
2698 GNUNET_MQ_send_copy (kx->mq, env);
2699 kx->resend_env = env;
2703 kx);
2704}
2705
2706static void
2708{
2709 struct GNUNET_ShortHashCode new_ats;
2710
2711 if ((UINT64_MAX == kx->current_sqn) ||
2713 {
2715 "Epoch expiration %" PRIu64 " SQN %" PRIu64
2716 ", incrementing epoch...\n",
2718 kx->current_sqn);
2719 // Can this trigger? Maybe if we receive a lot of
2720 // heatbeats?
2721 GNUNET_assert (UINT64_MAX > kx->current_epoch);
2722 kx->current_epoch++;
2725 kx->current_sqn = 0;
2727 &new_ats);
2728 memcpy (&kx->current_ats,
2729 &new_ats,
2730 sizeof new_ats);
2731 }
2732}
2733
2740void
2742 const void *payload,
2743 size_t payload_size)
2744{
2745 struct GNUNET_MQ_Envelope *env;
2746 struct EncryptedMessage *encrypted_msg;
2747 unsigned char enc_key[AEAD_KEY_BYTES];
2748 unsigned char enc_nonce[AEAD_NONCE_BYTES];
2749 unsigned char seq_enc_k[crypto_stream_chacha20_ietf_KEYBYTES];
2750 uint64_t sqn;
2751 uint64_t epoch;
2752 int8_t ret;
2753
2754 encrypted_msg = NULL;
2755
2756 check_rekey (kx);
2757 sqn = kx->current_sqn;
2758 epoch = kx->current_epoch;
2759 /* We are the sender and as we are going to send,
2760 * we are using the initiator key material */
2762 sqn,
2763 enc_key,
2764 enc_nonce);
2765 kx->current_sqn++;
2766 derive_sn (&kx->current_ats,
2767 seq_enc_k,
2768 sizeof seq_enc_k);
2769 env = GNUNET_MQ_msg_extra (encrypted_msg,
2770 payload_size,
2772 // only encrypt the payload for now
2773 // TODO encrypt other fields as well
2774 ret = crypto_aead_xchacha20poly1305_ietf_encrypt_detached (
2775 (unsigned char*) &encrypted_msg[1], // c - resulting ciphertext
2776 (unsigned char*) &encrypted_msg->tag, // mac - resulting mac/tag
2777 NULL, // maclen
2778 (unsigned char*) payload, // m - plain message
2779 payload_size, // mlen
2780 NULL, // ad - additional data TODO also cover the unencrypted part (epoch)
2781 0, // adlen
2782 NULL, // nsec - unused
2783 enc_nonce, // npub nonce
2784 enc_key // k - key
2785 );
2786 if (0 != ret)
2787 {
2789 "Something went wrong encrypting message\n");
2790 GNUNET_assert (0);
2791 }
2792 {
2793 /* compute the sequence number */
2794 unsigned char *seq_enc_nonce;
2795 uint64_t seq_nbo;
2796 uint32_t seq_enc_ctr;
2797
2798 seq_nbo = GNUNET_htonll (sqn);
2799 seq_enc_ctr = *((uint32_t*) encrypted_msg->tag);
2800 seq_enc_nonce = &encrypted_msg->tag[sizeof (uint32_t)];
2801 crypto_stream_chacha20_ietf_xor_ic (
2802 (unsigned char*) &encrypted_msg->sequence_number,
2803 (unsigned char*) &seq_nbo,
2804 sizeof seq_nbo,
2805 seq_enc_nonce,
2806 ntohl (seq_enc_ctr),
2807 seq_enc_k);
2808#if DEBUG_KX
2809 GNUNET_print_bytes (seq_enc_k,
2810 sizeof seq_enc_k,
2811 8,
2812 GNUNET_NO);
2813 GNUNET_print_bytes ((char*) &seq_enc_ctr,
2814 16,
2815 8,
2816 GNUNET_NO);
2817#endif
2819 "Sending encrypted message with E(SQN=%" PRIu64 ")=%" PRIu64
2820 "\n",
2821 sqn,
2822 encrypted_msg->sequence_number);
2823 }
2824 encrypted_msg->epoch = GNUNET_htonll (epoch);
2825
2826 // TODO actually copy payload
2827 GNUNET_MQ_send (kx->mq, env);
2828}
2829
2830
2837static void
2839 const struct GNUNET_HELLO_Parser *parser,
2840 const struct GNUNET_HashCode *hash)
2841{
2842 (void) cls;
2844 // TODO check that hash matches last fed hash
2846 "This peer has now a new peer id: %s\n",
2848 // TODO if changing from old peer_id to new peer_id: tear down old
2849 // connections, try restart connections over kept addresses?
2850 /* Continue initialisation of core */
2851 if (GNUNET_YES == init_phase)
2852 {
2855 }
2856}
2857
2858
2864int
2866{
2868 GNUNET_MQ_hd_var_size (initiator_hello,
2870 struct InitiatorHello,
2871 NULL),
2872 GNUNET_MQ_hd_var_size (initiator_done,
2874 struct InitiatorDone,
2875 NULL),
2876 GNUNET_MQ_hd_var_size (responder_hello,
2878 struct ResponderHello,
2879 NULL),
2880 GNUNET_MQ_hd_var_size (encrypted_message, // TODO rename?
2882 struct EncryptedMessage,
2883 NULL),
2885 };
2886
2890 NULL); // TODO potentially wait
2891 // until we have a peer_id?
2892 // pay attention to whether
2893 // we have one anyways
2894 if (NULL == pils)
2895 {
2896 GSC_KX_done ();
2897 return GNUNET_SYSERR;
2898 }
2899
2901 transport =
2904 handlers,
2905 NULL, // cls - this connection-independant
2906 // cls seems not to be needed.
2907 // the connection-specific cls
2908 // will be set as a return value
2909 // of
2910 // handle_transport_notify_connect
2913 if (NULL == transport)
2914 {
2915 GSC_KX_done ();
2916 return GNUNET_SYSERR;
2917 }
2919 "Connected to TRANSPORT\n");
2920 return GNUNET_OK;
2921}
2922
2923
2927void
2929{
2930 struct PilsRequest *pr;
2931 while (NULL != (pr = pils_requests_head))
2932 {
2935 pr);
2936 if (NULL != pr->op)
2937 GNUNET_PILS_cancel (pr->op);
2938 GNUNET_free (pr);
2939 }
2940 if (NULL != pils)
2941 {
2943 pils = NULL;
2944 }
2945 if (NULL != transport)
2946 {
2948 transport = NULL;
2949 }
2950 if (NULL != rekey_task)
2951 {
2953 rekey_task = NULL;
2954 }
2955 if (NULL != nc)
2956 {
2958 nc = NULL;
2959 }
2960}
2961
2962
2969unsigned int
2971{
2972 return GNUNET_MQ_get_length (kxinfo->mq);
2973}
2974
2975
2976int
2978{
2979 return kxinfo->has_excess_bandwidth;
2980}
2981
2982
2991void
2993{
2994 struct GNUNET_MQ_Envelope *env;
2995 struct MonitorNotifyMessage *done_msg;
2996 struct GSC_KeyExchangeInfo *kx;
2997
2999 for (kx = kx_head; NULL != kx; kx = kx->next)
3000 {
3001 struct GNUNET_MQ_Envelope *env_notify;
3002 struct MonitorNotifyMessage *msg;
3003
3005 msg->state = htonl ((uint32_t) kx->status);
3006 msg->peer = kx->peer;
3007 msg->timeout = GNUNET_TIME_absolute_hton (kx->timeout);
3008 GNUNET_MQ_send (mq, env_notify);
3009 }
3011 done_msg->state = htonl ((uint32_t) GNUNET_CORE_KX_ITERATION_FINISHED);
3014}
3015
3016
3017/* 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_encaps(const struct GNUNET_CRYPTO_EcdhePublicKey *pkR, struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Encapsulate key material for a X25519 public key.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hpke_kem_decaps(const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, const struct GNUNET_CRYPTO_HpkeEncapsulation *c, struct GNUNET_ShortHashCode *prk)
Decapsulate a key for a private X25519 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)
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.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_hkdf_expand(void *result, size_t out_len, const struct GNUNET_ShortHashCode *prk,...)
HKDF-Expand using SHA256.
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.
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_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.
#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:980
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:1277
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:552
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:640
bool GNUNET_TIME_absolute_is_past(struct GNUNET_TIME_Absolute abs)
Test if abs is truly in the past (excluding now).
Definition time.c:671
#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
Private ECC key encoded for transmission.
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and encr...
HPKE DHKEM encapsulation (X25519) See RFC 9180.
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:136
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.
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_CRYPTO_EcdhePrivateKey sk_e
Initiator secret key.
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_EcdhePublicKey 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.