diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-02-05 20:49:21 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-02-05 20:49:21 +0000 |
commit | ca35f67faee8371fa763bdf49f04a8d5d4cdc021 (patch) | |
tree | 5535df5e5a2428ed838c6a0e60b2c6c68a7842c5 /src/core | |
parent | dd7cca21c5dbaef4d56f92bab3932f0f73d092d1 (diff) | |
download | gnunet-ca35f67faee8371fa763bdf49f04a8d5d4cdc021.tar.gz gnunet-ca35f67faee8371fa763bdf49f04a8d5d4cdc021.zip |
switching to ECDHE cryptography f, implementation is incomplete and INSECURE, do not use for anything but testing
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/Makefile.am | 2 | ||||
-rw-r--r-- | src/core/gnunet-service-core.c | 12 | ||||
-rw-r--r-- | src/core/gnunet-service-core_kx.c | 963 | ||||
-rw-r--r-- | src/core/gnunet-service-core_kx.h | 8 | ||||
-rw-r--r-- | src/core/gnunet-service-core_neighbours.c | 4 |
5 files changed, 396 insertions, 593 deletions
diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 6d073da1f..a3ef13f5a 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am | |||
@@ -46,8 +46,6 @@ gnunet_service_core_SOURCES = \ | |||
46 | gnunet-service-core_sessions.c gnunet-service-core_sessions.h \ | 46 | gnunet-service-core_sessions.c gnunet-service-core_sessions.h \ |
47 | gnunet-service-core_typemap.c gnunet-service-core_typemap.h | 47 | gnunet-service-core_typemap.c gnunet-service-core_typemap.h |
48 | gnunet_service_core_LDADD = \ | 48 | gnunet_service_core_LDADD = \ |
49 | $(top_builddir)/src/hello/libgnunethello.la \ | ||
50 | $(top_builddir)/src/peerinfo/libgnunetpeerinfo.la \ | ||
51 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | 49 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ |
52 | $(top_builddir)/src/transport/libgnunettransport.la \ | 50 | $(top_builddir)/src/transport/libgnunettransport.la \ |
53 | $(top_builddir)/src/util/libgnunetutil.la \ | 51 | $(top_builddir)/src/util/libgnunetutil.la \ |
diff --git a/src/core/gnunet-service-core.c b/src/core/gnunet-service-core.c index 095e12405..2be833fa0 100644 --- a/src/core/gnunet-service-core.c +++ b/src/core/gnunet-service-core.c | |||
@@ -56,7 +56,7 @@ static struct GNUNET_SERVER_Handle *GSC_server; | |||
56 | /** | 56 | /** |
57 | * Hostkey generation context | 57 | * Hostkey generation context |
58 | */ | 58 | */ |
59 | static struct GNUNET_CRYPTO_RsaKeyGenerationContext *keygen; | 59 | static struct GNUNET_CRYPTO_EccKeyGenerationContext *keygen; |
60 | 60 | ||
61 | 61 | ||
62 | /** | 62 | /** |
@@ -72,7 +72,7 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
72 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service shutting down.\n"); | 72 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core service shutting down.\n"); |
73 | if (NULL != keygen) | 73 | if (NULL != keygen) |
74 | { | 74 | { |
75 | GNUNET_CRYPTO_rsa_key_create_stop (keygen); | 75 | GNUNET_CRYPTO_ecc_key_create_stop (keygen); |
76 | keygen = NULL; | 76 | keygen = NULL; |
77 | } | 77 | } |
78 | GSC_CLIENTS_done (); | 78 | GSC_CLIENTS_done (); |
@@ -99,14 +99,14 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
99 | */ | 99 | */ |
100 | static void | 100 | static void |
101 | key_generation_cb (void *cls, | 101 | key_generation_cb (void *cls, |
102 | struct GNUNET_CRYPTO_RsaPrivateKey *pk, | 102 | struct GNUNET_CRYPTO_EccPrivateKey *pk, |
103 | const char *emsg) | 103 | const char *emsg) |
104 | { | 104 | { |
105 | keygen = NULL; | 105 | keygen = NULL; |
106 | if (NULL == pk) | 106 | if (NULL == pk) |
107 | { | 107 | { |
108 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 108 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
109 | _("Failed to read hostkey: %s\n"), | 109 | _("Failed to read or generate private key: %s\n"), |
110 | emsg); | 110 | emsg); |
111 | GNUNET_SCHEDULER_shutdown (); | 111 | GNUNET_SCHEDULER_shutdown (); |
112 | return; | 112 | return; |
@@ -141,7 +141,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, | |||
141 | GSC_cfg = c; | 141 | GSC_cfg = c; |
142 | GSC_server = server; | 142 | GSC_server = server; |
143 | if (GNUNET_OK != | 143 | if (GNUNET_OK != |
144 | GNUNET_CONFIGURATION_get_value_filename (GSC_cfg, "GNUNETD", "HOSTKEY", | 144 | GNUNET_CONFIGURATION_get_value_filename (GSC_cfg, "PEER", "PRIVATE_KEY", |
145 | &keyfile)) | 145 | &keyfile)) |
146 | { | 146 | { |
147 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 147 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
@@ -155,7 +155,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, | |||
155 | NULL); | 155 | NULL); |
156 | GNUNET_SERVER_suspend (server); | 156 | GNUNET_SERVER_suspend (server); |
157 | GSC_TYPEMAP_init (); | 157 | GSC_TYPEMAP_init (); |
158 | keygen = GNUNET_CRYPTO_rsa_key_create_start (keyfile, &key_generation_cb, NULL); | 158 | keygen = GNUNET_CRYPTO_ecc_key_create_start (keyfile, &key_generation_cb, NULL); |
159 | GNUNET_free (keyfile); | 159 | GNUNET_free (keyfile); |
160 | if (NULL == keygen) | 160 | if (NULL == keygen) |
161 | { | 161 | { |
diff --git a/src/core/gnunet-service-core_kx.c b/src/core/gnunet-service-core_kx.c index b2fc2a971..f7fbfcf68 100644 --- a/src/core/gnunet-service-core_kx.c +++ b/src/core/gnunet-service-core_kx.c | |||
@@ -30,8 +30,6 @@ | |||
30 | #include "gnunet-service-core_neighbours.h" | 30 | #include "gnunet-service-core_neighbours.h" |
31 | #include "gnunet-service-core_sessions.h" | 31 | #include "gnunet-service-core_sessions.h" |
32 | #include "gnunet_statistics_service.h" | 32 | #include "gnunet_statistics_service.h" |
33 | #include "gnunet_peerinfo_service.h" | ||
34 | #include "gnunet_hello_lib.h" | ||
35 | #include "gnunet_constants.h" | 33 | #include "gnunet_constants.h" |
36 | #include "gnunet_signatures.h" | 34 | #include "gnunet_signatures.h" |
37 | #include "gnunet_protocols.h" | 35 | #include "gnunet_protocols.h" |
@@ -39,14 +37,9 @@ | |||
39 | 37 | ||
40 | 38 | ||
41 | /** | 39 | /** |
42 | * Set to GNUNET_YES to perform some slightly expensive internal invariant checks. | ||
43 | */ | ||
44 | #define EXTRA_CHECKS GNUNET_YES | ||
45 | |||
46 | /** | ||
47 | * How long do we wait for SET_KEY confirmation initially? | 40 | * How long do we wait for SET_KEY confirmation initially? |
48 | */ | 41 | */ |
49 | #define INITIAL_SET_KEY_RETRY_FREQUENCY GNUNET_TIME_relative_multiply (MAX_SET_KEY_DELAY, 1) | 42 | #define INITIAL_SET_KEY_RETRY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) |
50 | 43 | ||
51 | /** | 44 | /** |
52 | * What is the minimum frequency for a PING message? | 45 | * What is the minimum frequency for a PING message? |
@@ -56,8 +49,12 @@ | |||
56 | /** | 49 | /** |
57 | * How often do we rekey? | 50 | * How often do we rekey? |
58 | */ | 51 | */ |
59 | #define REKEY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 90) | 52 | #define REKEY_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 12) |
60 | 53 | ||
54 | /** | ||
55 | * What time difference do we tolerate? | ||
56 | */ | ||
57 | #define REKEY_TOLERANCE GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 5) | ||
61 | 58 | ||
62 | /** | 59 | /** |
63 | * What is the maximum age of a message for us to consider processing | 60 | * What is the maximum age of a message for us to consider processing |
@@ -68,13 +65,61 @@ | |||
68 | */ | 65 | */ |
69 | #define MAX_MESSAGE_AGE GNUNET_TIME_UNIT_DAYS | 66 | #define MAX_MESSAGE_AGE GNUNET_TIME_UNIT_DAYS |
70 | 67 | ||
68 | |||
69 | |||
70 | GNUNET_NETWORK_STRUCT_BEGIN | ||
71 | |||
71 | /** | 72 | /** |
72 | * What is the maximum delay for a SET_KEY message? | 73 | * Message transmitted with the signed ephemeral key of a peer. The |
74 | * session key is then derived from the two ephemeral keys (ECDHE). | ||
73 | */ | 75 | */ |
74 | #define MAX_SET_KEY_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10) | 76 | struct EphemeralKeyMessage |
77 | { | ||
78 | |||
79 | /** | ||
80 | * Message type is CORE_EPHEMERAL_KEY. | ||
81 | */ | ||
82 | struct GNUNET_MessageHeader header; | ||
83 | |||
84 | /** | ||
85 | * Status of the sender (should be in "enum PeerStateMachine"), nbo. | ||
86 | */ | ||
87 | int32_t sender_status GNUNET_PACKED; | ||
75 | 88 | ||
89 | /** | ||
90 | * An ECC signature of the 'origin' asserting the validity of | ||
91 | * the given ephemeral key. | ||
92 | */ | ||
93 | struct GNUNET_CRYPTO_EccSignature signature; | ||
94 | |||
95 | /** | ||
96 | * Information about what is being signed. | ||
97 | */ | ||
98 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | ||
99 | |||
100 | /** | ||
101 | * At what time was this key created (beginning of validity). | ||
102 | */ | ||
103 | struct GNUNET_TIME_AbsoluteNBO creation_time; | ||
104 | |||
105 | /** | ||
106 | * When does the given ephemeral key expire (end of validity). | ||
107 | */ | ||
108 | struct GNUNET_TIME_AbsoluteNBO expiration_time; | ||
109 | |||
110 | /** | ||
111 | * Ephemeral public ECC key (always for NIST P-521) encoded in a format suitable | ||
112 | * for network transmission as created using 'gcry_sexp_sprint'. | ||
113 | */ | ||
114 | struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded ephemeral_key; | ||
115 | |||
116 | /** | ||
117 | * Public key of the signing peer (persistent version, not the ephemeral public key). | ||
118 | */ | ||
119 | struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded origin_public_key; | ||
120 | |||
121 | }; | ||
76 | 122 | ||
77 | GNUNET_NETWORK_STRUCT_BEGIN | ||
78 | 123 | ||
79 | /** | 124 | /** |
80 | * We're sending an (encrypted) PING to the other peer to check if he | 125 | * We're sending an (encrypted) PING to the other peer to check if he |
@@ -128,9 +173,9 @@ struct PongMessage | |||
128 | uint32_t challenge GNUNET_PACKED; | 173 | uint32_t challenge GNUNET_PACKED; |
129 | 174 | ||
130 | /** | 175 | /** |
131 | * Reserved, always 'GNUNET_BANDWIDTH_VALUE_MAX'. | 176 | * Reserved, always zero. |
132 | */ | 177 | */ |
133 | struct GNUNET_BANDWIDTH_Value32NBO reserved; | 178 | uint32_t reserved; |
134 | 179 | ||
135 | /** | 180 | /** |
136 | * Intended target of the PING, used primarily to check | 181 | * Intended target of the PING, used primarily to check |
@@ -141,51 +186,6 @@ struct PongMessage | |||
141 | 186 | ||
142 | 187 | ||
143 | /** | 188 | /** |
144 | * Message transmitted to set (or update) a session key. | ||
145 | */ | ||
146 | struct SetKeyMessage | ||
147 | { | ||
148 | |||
149 | /** | ||
150 | * Message type is either CORE_SET_KEY. | ||
151 | */ | ||
152 | struct GNUNET_MessageHeader header; | ||
153 | |||
154 | /** | ||
155 | * Status of the sender (should be in "enum PeerStateMachine"), nbo. | ||
156 | */ | ||
157 | int32_t sender_status GNUNET_PACKED; | ||
158 | |||
159 | /** | ||
160 | * Purpose of the signature, will be | ||
161 | * GNUNET_SIGNATURE_PURPOSE_SET_KEY. | ||
162 | */ | ||
163 | struct GNUNET_CRYPTO_RsaSignaturePurpose purpose; | ||
164 | |||
165 | /** | ||
166 | * At what time was this key created? | ||
167 | */ | ||
168 | struct GNUNET_TIME_AbsoluteNBO creation_time; | ||
169 | |||
170 | /** | ||
171 | * The encrypted session key. | ||
172 | */ | ||
173 | struct GNUNET_CRYPTO_RsaEncryptedData encrypted_key; | ||
174 | |||
175 | /** | ||
176 | * Who is the intended recipient? | ||
177 | */ | ||
178 | struct GNUNET_PeerIdentity target; | ||
179 | |||
180 | /** | ||
181 | * Signature of the stuff above (starting at purpose). | ||
182 | */ | ||
183 | struct GNUNET_CRYPTO_RsaSignature signature; | ||
184 | |||
185 | }; | ||
186 | |||
187 | |||
188 | /** | ||
189 | * Encapsulation for encrypted messages exchanged between | 189 | * Encapsulation for encrypted messages exchanged between |
190 | * peers. Followed by the actual encrypted data. | 190 | * peers. Followed by the actual encrypted data. |
191 | */ | 191 | */ |
@@ -216,9 +216,9 @@ struct EncryptedMessage | |||
216 | uint32_t sequence_number GNUNET_PACKED; | 216 | uint32_t sequence_number GNUNET_PACKED; |
217 | 217 | ||
218 | /** | 218 | /** |
219 | * Reserved, always 'GNUNET_BANDWIDTH_VALUE_MAX'. | 219 | * Reserved, always zero. |
220 | */ | 220 | */ |
221 | struct GNUNET_BANDWIDTH_Value32NBO reserved; | 221 | uint32_t reserved; |
222 | 222 | ||
223 | /** | 223 | /** |
224 | * Timestamp. Used to prevent reply of ancient messages | 224 | * Timestamp. Used to prevent reply of ancient messages |
@@ -263,23 +263,18 @@ enum KxStateMachine | |||
263 | KX_STATE_KEY_RECEIVED, | 263 | KX_STATE_KEY_RECEIVED, |
264 | 264 | ||
265 | /** | 265 | /** |
266 | * The other peer has confirmed our session key with a message | 266 | * The other peer has confirmed our session key + PING with a PONG |
267 | * encrypted with his session key (which we got). Key exchange | 267 | * message encrypted with his session key (which we got). Key |
268 | * is done. | 268 | * exchange is done. |
269 | */ | 269 | */ |
270 | KX_STATE_UP, | 270 | KX_STATE_UP, |
271 | 271 | ||
272 | /** | 272 | /** |
273 | * We're rekeying, so we have received the other peer's session | 273 | * We're rekeying, so we have sent the other peer our new ephemeral |
274 | * key, but he didn't get ours yet. | 274 | * key, but we did not get a matching PONG yet. |
275 | */ | ||
276 | KX_STATE_REKEY, | ||
277 | |||
278 | /** | ||
279 | * We're rekeying but have not yet received confirmation for our new | ||
280 | * key from the other peer. | ||
281 | */ | 275 | */ |
282 | KX_STATE_REKEY_SENT | 276 | KX_STATE_REKEY_SENT |
277 | |||
283 | }; | 278 | }; |
284 | 279 | ||
285 | 280 | ||
@@ -288,62 +283,26 @@ enum KxStateMachine | |||
288 | */ | 283 | */ |
289 | struct GSC_KeyExchangeInfo | 284 | struct GSC_KeyExchangeInfo |
290 | { | 285 | { |
291 | /** | ||
292 | * Identity of the peer. | ||
293 | */ | ||
294 | struct GNUNET_PeerIdentity peer; | ||
295 | 286 | ||
296 | /** | 287 | /** |
297 | * SetKeyMessage to transmit (initialized the first | 288 | * DLL. |
298 | * time our status goes past 'KX_STATE_KEY_SENT'). | ||
299 | */ | 289 | */ |
300 | struct SetKeyMessage skm; | 290 | struct GSC_KeyExchangeInfo *next; |
301 | 291 | ||
302 | /** | 292 | /** |
303 | * PING message we transmit to the other peer. | 293 | * DLL. |
304 | */ | 294 | */ |
305 | struct PingMessage ping; | 295 | struct GSC_KeyExchangeInfo *prev; |
306 | |||
307 | /** | ||
308 | * SetKeyMessage we received and did not process yet. | ||
309 | */ | ||
310 | struct SetKeyMessage *skm_received; | ||
311 | 296 | ||
312 | /** | 297 | /** |
313 | * PING message we received from the other peer and | 298 | * Identity of the peer. |
314 | * did not process yet (or NULL). | ||
315 | */ | ||
316 | struct PingMessage *ping_received; | ||
317 | |||
318 | /** | ||
319 | * PONG message we received from the other peer and | ||
320 | * did not process yet (or NULL). | ||
321 | */ | ||
322 | struct PongMessage *pong_received; | ||
323 | |||
324 | /** | ||
325 | * Encrypted message we received from the other peer and | ||
326 | * did not process yet (or NULL). | ||
327 | */ | ||
328 | struct EncryptedMessage *emsg_received; | ||
329 | |||
330 | /** | ||
331 | * Non-NULL if we are currently looking up HELLOs for this peer. | ||
332 | * for this peer. | ||
333 | */ | ||
334 | struct GNUNET_PEERINFO_IteratorContext *pitr; | ||
335 | |||
336 | /** | ||
337 | * Public key of the neighbour, NULL if we don't have it yet. | ||
338 | */ | 299 | */ |
339 | struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *public_key; | 300 | struct GNUNET_PeerIdentity peer; |
340 | 301 | ||
341 | /** | 302 | /** |
342 | * We received a PONG message before we got the "public_key" | 303 | * PING message we transmit to the other peer. |
343 | * (or the SET_KEY). We keep it here until we have a key | ||
344 | * to decrypt it. NULL if no PONG is pending. | ||
345 | */ | 304 | */ |
346 | struct PongMessage *pending_pong; | 305 | struct PingMessage ping; |
347 | 306 | ||
348 | /** | 307 | /** |
349 | * Key we use to encrypt our messages for the other peer | 308 | * Key we use to encrypt our messages for the other peer |
@@ -358,14 +317,9 @@ struct GSC_KeyExchangeInfo | |||
358 | struct GNUNET_CRYPTO_AesSessionKey decrypt_key; | 317 | struct GNUNET_CRYPTO_AesSessionKey decrypt_key; |
359 | 318 | ||
360 | /** | 319 | /** |
361 | * At what time did we generate our encryption key? | ||
362 | */ | ||
363 | struct GNUNET_TIME_Absolute encrypt_key_created; | ||
364 | |||
365 | /** | ||
366 | * At what time did the other peer generate the decryption key? | 320 | * At what time did the other peer generate the decryption key? |
367 | */ | 321 | */ |
368 | struct GNUNET_TIME_Absolute decrypt_key_created; | 322 | struct GNUNET_TIME_Absolute foreign_key_expires; |
369 | 323 | ||
370 | /** | 324 | /** |
371 | * When should the session time out (if there are no PONGs)? | 325 | * When should the session time out (if there are no PONGs)? |
@@ -418,57 +372,46 @@ struct GSC_KeyExchangeInfo | |||
418 | 372 | ||
419 | 373 | ||
420 | /** | 374 | /** |
421 | * Handle to peerinfo service. | 375 | * Our private key. |
422 | */ | 376 | */ |
423 | static struct GNUNET_PEERINFO_Handle *peerinfo; | 377 | static struct GNUNET_CRYPTO_EccPrivateKey *my_private_key; |
424 | 378 | ||
425 | /** | 379 | /** |
426 | * Our private key. | 380 | * Our ephemeral private key. |
381 | */ | ||
382 | static struct GNUNET_CRYPTO_EccPrivateKey *my_ephemeral_key; | ||
383 | |||
384 | /** | ||
385 | * Current message we send for a key exchange. | ||
427 | */ | 386 | */ |
428 | static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key; | 387 | static struct EphemeralKeyMessage current_ekm; |
429 | 388 | ||
430 | /** | 389 | /** |
431 | * Our public key. | 390 | * Our public key. |
432 | */ | 391 | */ |
433 | static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key; | 392 | static struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded my_public_key; |
434 | 393 | ||
435 | /** | 394 | /** |
436 | * Our message stream tokenizer (for encrypted payload). | 395 | * Our message stream tokenizer (for encrypted payload). |
437 | */ | 396 | */ |
438 | static struct GNUNET_SERVER_MessageStreamTokenizer *mst; | 397 | static struct GNUNET_SERVER_MessageStreamTokenizer *mst; |
439 | 398 | ||
440 | |||
441 | #if EXTRA_CHECKS | ||
442 | /** | 399 | /** |
443 | * Check internal invariants of the given KX record. | 400 | * DLL head. |
444 | * | 401 | */ |
445 | * @param kx record to check | 402 | static struct GSC_KeyExchangeInfo *kx_head; |
446 | * @param file filename for error reporting | ||
447 | * @param line line number for error reporting | ||
448 | */ | ||
449 | static void | ||
450 | check_kx_record (struct GSC_KeyExchangeInfo *kx, | ||
451 | const char *file, | ||
452 | int line) | ||
453 | { | ||
454 | struct GNUNET_HashCode hc; | ||
455 | |||
456 | if (NULL == kx->public_key) | ||
457 | return; | ||
458 | GNUNET_CRYPTO_hash (kx->public_key, sizeof (*kx->public_key), &hc); | ||
459 | GNUNET_assert_at (0 == memcmp (&hc, &kx->peer, sizeof (struct GNUNET_HashCode)), file, line); | ||
460 | } | ||
461 | |||
462 | 403 | ||
463 | /** | 404 | /** |
464 | * Check internal invariants of the given KX record. | 405 | * DLL tail. |
465 | * | ||
466 | * @param kx record to check | ||
467 | */ | 406 | */ |
468 | #define CHECK_KX(kx) check_kx_record(kx, __FILE__, __LINE__) | 407 | static struct GSC_KeyExchangeInfo *kx_tail; |
469 | #else | 408 | |
470 | #define CHECK_KX(kx) | 409 | /** |
471 | #endif | 410 | * Task scheduled for periodic re-generation (and thus rekeying) of our |
411 | * ephemeral key. | ||
412 | */ | ||
413 | static GNUNET_SCHEDULER_TaskIdentifier rekey_task; | ||
414 | |||
472 | 415 | ||
473 | /** | 416 | /** |
474 | * Derive an authentication key from "set key" information | 417 | * Derive an authentication key from "set key" information |
@@ -476,19 +419,15 @@ check_kx_record (struct GSC_KeyExchangeInfo *kx, | |||
476 | * @param akey authentication key to derive | 419 | * @param akey authentication key to derive |
477 | * @param skey session key to use | 420 | * @param skey session key to use |
478 | * @param seed seed to use | 421 | * @param seed seed to use |
479 | * @param creation_time creation time to use | ||
480 | */ | 422 | */ |
481 | static void | 423 | static void |
482 | derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey, | 424 | derive_auth_key (struct GNUNET_CRYPTO_AuthKey *akey, |
483 | const struct GNUNET_CRYPTO_AesSessionKey *skey, uint32_t seed, | 425 | const struct GNUNET_CRYPTO_AesSessionKey *skey, uint32_t seed) |
484 | struct GNUNET_TIME_Absolute creation_time) | ||
485 | { | 426 | { |
486 | static const char ctx[] = "authentication key"; | 427 | static const char ctx[] = "authentication key"; |
487 | struct GNUNET_TIME_AbsoluteNBO ctbe; | ||
488 | 428 | ||
489 | ctbe = GNUNET_TIME_absolute_hton (creation_time); | ||
490 | GNUNET_CRYPTO_hmac_derive_key (akey, skey, &seed, sizeof (seed), &skey->key, | 429 | GNUNET_CRYPTO_hmac_derive_key (akey, skey, &seed, sizeof (seed), &skey->key, |
491 | sizeof (skey->key), &ctbe, sizeof (ctbe), ctx, | 430 | sizeof (skey->key), ctx, |
492 | sizeof (ctx), NULL); | 431 | sizeof (ctx), NULL); |
493 | } | 432 | } |
494 | 433 | ||
@@ -539,6 +478,31 @@ derive_pong_iv (struct GNUNET_CRYPTO_AesInitializationVector *iv, | |||
539 | 478 | ||
540 | 479 | ||
541 | /** | 480 | /** |
481 | * Derive an AES key from key material | ||
482 | * | ||
483 | * @param sender peer identity of the sender | ||
484 | * @param receiver peer identity of the sender | ||
485 | * @param key_material high entropy key material to use | ||
486 | * @param skey set to derived session key | ||
487 | */ | ||
488 | static void | ||
489 | derive_aes_key (const struct GNUNET_PeerIdentity *sender, | ||
490 | const struct GNUNET_PeerIdentity *receiver, | ||
491 | const struct GNUNET_HashCode *key_material, | ||
492 | struct GNUNET_CRYPTO_AesSessionKey *skey) | ||
493 | { | ||
494 | static const char ctx[] = "aes key generation vector"; | ||
495 | |||
496 | GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_AesSessionKey), | ||
497 | ctx, sizeof (ctx), | ||
498 | skey, sizeof (struct GNUNET_CRYPTO_AesSessionKey), | ||
499 | sender, sizeof (struct GNUNET_PeerIdentity), | ||
500 | receiver, sizeof (struct GNUNET_PeerIdentity), | ||
501 | NULL); | ||
502 | } | ||
503 | |||
504 | |||
505 | /** | ||
542 | * Encrypt size bytes from in and write the result to out. Use the | 506 | * Encrypt size bytes from in and write the result to out. Use the |
543 | * key for outbound traffic of the given neighbour. | 507 | * key for outbound traffic of the given neighbour. |
544 | * | 508 | * |
@@ -601,8 +565,7 @@ do_decrypt (struct GSC_KeyExchangeInfo *kx, | |||
601 | return GNUNET_NO; | 565 | return GNUNET_NO; |
602 | } | 566 | } |
603 | if ( (kx->status != KX_STATE_KEY_RECEIVED) && (kx->status != KX_STATE_UP) && | 567 | if ( (kx->status != KX_STATE_KEY_RECEIVED) && (kx->status != KX_STATE_UP) && |
604 | (kx->status != KX_STATE_REKEY_SENT) && | 568 | (kx->status != KX_STATE_REKEY_SENT) ) |
605 | (kx->status != KX_STATE_REKEY) ) | ||
606 | { | 569 | { |
607 | GNUNET_break_op (0); | 570 | GNUNET_break_op (0); |
608 | return GNUNET_SYSERR; | 571 | return GNUNET_SYSERR; |
@@ -651,88 +614,34 @@ set_key_retry_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
651 | struct GSC_KeyExchangeInfo *kx = cls; | 614 | struct GSC_KeyExchangeInfo *kx = cls; |
652 | 615 | ||
653 | kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK; | 616 | kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK; |
654 | kx->set_key_retry_frequency = | 617 | kx->set_key_retry_frequency = GNUNET_TIME_STD_BACKOFF (kx->set_key_retry_frequency); |
655 | GNUNET_TIME_relative_multiply (kx->set_key_retry_frequency, 2); | ||
656 | send_key (kx); | 618 | send_key (kx); |
657 | } | 619 | } |
658 | 620 | ||
659 | 621 | ||
660 | /** | 622 | /** |
661 | * PEERINFO is giving us a HELLO for a peer. Add the public key to | 623 | * Create a fresh PING message for transmission to the other peer. |
662 | * the neighbour's struct and continue with the key exchange. Or, if | ||
663 | * we did not get a HELLO, just do nothing. | ||
664 | * | 624 | * |
665 | * @param cls the 'struct GSC_KeyExchangeInfo' to retry sending the key for | 625 | * @param kx key exchange context to create PING for |
666 | * @param peer the peer for which this is the HELLO | ||
667 | * @param hello HELLO message of that peer | ||
668 | * @param err_msg NULL if successful, otherwise contains error message | ||
669 | */ | 626 | */ |
670 | static void | 627 | static void |
671 | process_hello (void *cls, const struct GNUNET_PeerIdentity *peer, | 628 | setup_fresh_ping (struct GSC_KeyExchangeInfo *kx) |
672 | const struct GNUNET_HELLO_Message *hello, const char *err_msg) | ||
673 | { | 629 | { |
674 | struct GSC_KeyExchangeInfo *kx = cls; | 630 | struct PingMessage pp; |
675 | struct SetKeyMessage *skm; | 631 | struct PingMessage *pm; |
632 | struct GNUNET_CRYPTO_AesInitializationVector iv; | ||
676 | 633 | ||
677 | CHECK_KX (kx); | 634 | pm = &kx->ping; |
678 | if (NULL != err_msg) | 635 | pm->header.size = htons (sizeof (struct PingMessage)); |
679 | { | 636 | pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING); |
680 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 637 | pm->iv_seed = |
681 | _("Error in communication with PEERINFO service\n")); | 638 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX); |
682 | kx->pitr = NULL; | 639 | derive_iv (&iv, &kx->encrypt_key, pm->iv_seed, &kx->peer); |
683 | if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task) | 640 | pp.challenge = kx->ping_challenge; |
684 | GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); | 641 | pp.target = kx->peer; |
685 | kx->retry_set_key_task = | 642 | do_encrypt (kx, &iv, &pp.target, &pm->target, |
686 | GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency, | 643 | sizeof (struct PingMessage) - ((void *) &pm->target - |
687 | &set_key_retry_task, kx); | 644 | (void *) pm)); |
688 | return; | ||
689 | } | ||
690 | if (NULL == peer) | ||
691 | { | ||
692 | kx->pitr = NULL; | ||
693 | if (NULL != kx->public_key) | ||
694 | return; /* done here */ | ||
695 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
696 | "Failed to obtain public key for peer `%4s', delaying processing of SET_KEY\n", | ||
697 | GNUNET_i2s (&kx->peer)); | ||
698 | GNUNET_STATISTICS_update (GSC_stats, | ||
699 | gettext_noop | ||
700 | ("# Delayed connecting due to lack of public key"), | ||
701 | 1, GNUNET_NO); | ||
702 | if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task) | ||
703 | GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); | ||
704 | kx->retry_set_key_task = | ||
705 | GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency, | ||
706 | &set_key_retry_task, kx); | ||
707 | return; | ||
708 | } | ||
709 | GNUNET_break (0 == memcmp (peer, &kx->peer, sizeof (struct GNUNET_PeerIdentity))); | ||
710 | if (NULL != kx->public_key) | ||
711 | { | ||
712 | /* already have public key, why are we here? */ | ||
713 | GNUNET_break (0); | ||
714 | return; | ||
715 | } | ||
716 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->retry_set_key_task); | ||
717 | kx->public_key = | ||
718 | GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded)); | ||
719 | if (GNUNET_OK != GNUNET_HELLO_get_key (hello, kx->public_key)) | ||
720 | { | ||
721 | GNUNET_break (0); | ||
722 | GNUNET_free (kx->public_key); | ||
723 | kx->public_key = NULL; | ||
724 | CHECK_KX (kx); | ||
725 | return; | ||
726 | } | ||
727 | CHECK_KX (kx); | ||
728 | send_key (kx); | ||
729 | if (NULL != kx->skm_received) | ||
730 | { | ||
731 | skm = kx->skm_received; | ||
732 | kx->skm_received = NULL; | ||
733 | GSC_KX_handle_set_key (kx, &skm->header); | ||
734 | GNUNET_free (skm); | ||
735 | } | ||
736 | } | 645 | } |
737 | 646 | ||
738 | 647 | ||
@@ -747,7 +656,8 @@ GSC_KX_start (const struct GNUNET_PeerIdentity *pid) | |||
747 | { | 656 | { |
748 | struct GSC_KeyExchangeInfo *kx; | 657 | struct GSC_KeyExchangeInfo *kx; |
749 | 658 | ||
750 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initiating key exchange with `%s'\n", | 659 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
660 | "Initiating key exchange with `%s'\n", | ||
751 | GNUNET_i2s (pid)); | 661 | GNUNET_i2s (pid)); |
752 | GNUNET_STATISTICS_update (GSC_stats, | 662 | GNUNET_STATISTICS_update (GSC_stats, |
753 | gettext_noop ("# key exchanges initiated"), 1, | 663 | gettext_noop ("# key exchanges initiated"), 1, |
@@ -755,11 +665,11 @@ GSC_KX_start (const struct GNUNET_PeerIdentity *pid) | |||
755 | kx = GNUNET_malloc (sizeof (struct GSC_KeyExchangeInfo)); | 665 | kx = GNUNET_malloc (sizeof (struct GSC_KeyExchangeInfo)); |
756 | kx->peer = *pid; | 666 | kx->peer = *pid; |
757 | kx->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY; | 667 | kx->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY; |
758 | kx->pitr = | 668 | GNUNET_CONTAINER_DLL_insert (kx_head, |
759 | GNUNET_PEERINFO_iterate (peerinfo, pid, | 669 | kx_tail, |
760 | GNUNET_TIME_UNIT_FOREVER_REL /* timeout? */ , | 670 | kx); |
761 | &process_hello, kx); | 671 | kx->status = KX_STATE_KEY_SENT; |
762 | CHECK_KX (kx); | 672 | send_key (kx); |
763 | return kx; | 673 | return kx; |
764 | } | 674 | } |
765 | 675 | ||
@@ -774,11 +684,6 @@ GSC_KX_stop (struct GSC_KeyExchangeInfo *kx) | |||
774 | { | 684 | { |
775 | GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# key exchanges stopped"), | 685 | GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# key exchanges stopped"), |
776 | 1, GNUNET_NO); | 686 | 1, GNUNET_NO); |
777 | if (NULL != kx->pitr) | ||
778 | { | ||
779 | GNUNET_PEERINFO_iterate_cancel (kx->pitr); | ||
780 | kx->pitr = NULL; | ||
781 | } | ||
782 | if (kx->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK) | 687 | if (kx->retry_set_key_task != GNUNET_SCHEDULER_NO_TASK) |
783 | { | 688 | { |
784 | GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); | 689 | GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); |
@@ -789,16 +694,26 @@ GSC_KX_stop (struct GSC_KeyExchangeInfo *kx) | |||
789 | GNUNET_SCHEDULER_cancel (kx->keep_alive_task); | 694 | GNUNET_SCHEDULER_cancel (kx->keep_alive_task); |
790 | kx->keep_alive_task = GNUNET_SCHEDULER_NO_TASK; | 695 | kx->keep_alive_task = GNUNET_SCHEDULER_NO_TASK; |
791 | } | 696 | } |
792 | GNUNET_free_non_null (kx->skm_received); | 697 | GNUNET_CONTAINER_DLL_remove (kx_head, |
793 | GNUNET_free_non_null (kx->ping_received); | 698 | kx_tail, |
794 | GNUNET_free_non_null (kx->pong_received); | 699 | kx); |
795 | GNUNET_free_non_null (kx->emsg_received); | ||
796 | GNUNET_free_non_null (kx->public_key); | ||
797 | GNUNET_free (kx); | 700 | GNUNET_free (kx); |
798 | } | 701 | } |
799 | 702 | ||
800 | 703 | ||
801 | /** | 704 | /** |
705 | * Send our PING to the other peer. | ||
706 | * | ||
707 | * @param kx key exchange context | ||
708 | */ | ||
709 | static void | ||
710 | send_ping (struct GSC_KeyExchangeInfo *kx) | ||
711 | { | ||
712 | GSC_NEIGHBOURS_transmit (&kx->peer, &kx->ping.header, | ||
713 | MIN_PING_FREQUENCY); | ||
714 | } | ||
715 | |||
716 | /** | ||
802 | * We received a SET_KEY message. Validate and update | 717 | * We received a SET_KEY message. Validate and update |
803 | * our key material and status. | 718 | * our key material and status. |
804 | * | 719 | * |
@@ -806,146 +721,142 @@ GSC_KX_stop (struct GSC_KeyExchangeInfo *kx) | |||
806 | * @param msg the set key message we received | 721 | * @param msg the set key message we received |
807 | */ | 722 | */ |
808 | void | 723 | void |
809 | GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *kx, | 724 | GSC_KX_handle_ephemeral_key (struct GSC_KeyExchangeInfo *kx, |
810 | const struct GNUNET_MessageHeader *msg) | 725 | const struct GNUNET_MessageHeader *msg) |
811 | { | 726 | { |
812 | const struct SetKeyMessage *m; | 727 | const struct EphemeralKeyMessage *m; |
813 | struct GNUNET_TIME_Absolute t; | 728 | struct GNUNET_TIME_Absolute start_t; |
814 | struct GNUNET_CRYPTO_AesSessionKey k; | 729 | struct GNUNET_TIME_Absolute end_t; |
815 | struct PingMessage *ping; | 730 | struct GNUNET_TIME_Absolute now; |
816 | struct PongMessage *pong; | 731 | struct GNUNET_PeerIdentity signer_id; |
817 | enum KxStateMachine sender_status; | 732 | enum KxStateMachine sender_status; |
818 | uint16_t size; | 733 | uint16_t size; |
734 | struct GNUNET_HashCode key_material; | ||
819 | 735 | ||
820 | CHECK_KX (kx); | ||
821 | size = ntohs (msg->size); | 736 | size = ntohs (msg->size); |
822 | if (size != sizeof (struct SetKeyMessage)) | 737 | if (sizeof (struct EphemeralKeyMessage) != size) |
823 | { | 738 | { |
824 | GNUNET_break_op (0); | 739 | GNUNET_break_op (0); |
825 | return; | 740 | return; |
826 | } | 741 | } |
827 | m = (const struct SetKeyMessage *) msg; | 742 | m = (const struct EphemeralKeyMessage *) msg; |
828 | GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# session keys received"), | 743 | GNUNET_STATISTICS_update (GSC_stats, gettext_noop ("# ephemeral keys received"), |
829 | 1, GNUNET_NO); | 744 | 1, GNUNET_NO); |
830 | 745 | ||
831 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 746 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
832 | "Core service receives `%s' request from `%4s'.\n", "SET_KEY", | 747 | "Core service receives `%s' request from `%4s'.\n", "EPHEMERAL_KEY", |
833 | GNUNET_i2s (&kx->peer)); | 748 | GNUNET_i2s (&kx->peer)); |
834 | if (NULL == kx->public_key) | 749 | GNUNET_CRYPTO_hash (&m->origin_public_key, |
835 | { | 750 | sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded), |
836 | GNUNET_free_non_null (kx->skm_received); | 751 | &signer_id.hashPubKey); |
837 | kx->skm_received = (struct SetKeyMessage *) GNUNET_copy_message (msg); | ||
838 | return; | ||
839 | } | ||
840 | if (0 != | 752 | if (0 != |
841 | memcmp (&m->target, &GSC_my_identity, | 753 | memcmp (&signer_id, &kx->peer, |
842 | sizeof (struct GNUNET_PeerIdentity))) | 754 | sizeof (struct GNUNET_PeerIdentity))) |
843 | { | 755 | { |
844 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 756 | GNUNET_break_op (0); |
845 | _("`%s' is for `%s', not for me. Ignoring.\n"), "SET_KEY", | ||
846 | GNUNET_i2s (&m->target)); | ||
847 | return; | 757 | return; |
848 | } | 758 | } |
849 | if ((ntohl (m->purpose.size) != | 759 | if ((ntohl (m->purpose.size) != |
850 | sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + | 760 | sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + |
761 | sizeof (struct GNUNET_TIME_AbsoluteNBO) + | ||
851 | sizeof (struct GNUNET_TIME_AbsoluteNBO) + | 762 | sizeof (struct GNUNET_TIME_AbsoluteNBO) + |
852 | sizeof (struct GNUNET_CRYPTO_RsaEncryptedData) + | 763 | sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded) + |
853 | sizeof (struct GNUNET_PeerIdentity)) || | 764 | sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded)) || |
854 | (GNUNET_OK != | 765 | (GNUNET_OK != |
855 | GNUNET_CRYPTO_rsa_verify (GNUNET_SIGNATURE_PURPOSE_SET_KEY, &m->purpose, | 766 | GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY, |
856 | &m->signature, kx->public_key))) | 767 | &m->purpose, |
768 | &m->signature, &m->origin_public_key))) | ||
857 | { | 769 | { |
858 | /* invalid signature */ | 770 | /* invalid signature */ |
859 | CHECK_KX (kx); | ||
860 | GNUNET_break_op (0); | 771 | GNUNET_break_op (0); |
861 | return; | 772 | return; |
862 | } | 773 | } |
863 | t = GNUNET_TIME_absolute_ntoh (m->creation_time); | 774 | start_t = GNUNET_TIME_absolute_ntoh (m->creation_time); |
864 | if (((kx->status == KX_STATE_KEY_RECEIVED) || (kx->status == KX_STATE_UP)) && | 775 | end_t = GNUNET_TIME_absolute_ntoh (m->expiration_time); |
865 | (t.abs_value < kx->decrypt_key_created.abs_value)) | 776 | now = GNUNET_TIME_absolute_get (); |
777 | if ( (end_t.abs_value < GNUNET_TIME_absolute_subtract (now, REKEY_TOLERANCE).abs_value) || | ||
778 | (start_t.abs_value > GNUNET_TIME_absolute_add (now, REKEY_TOLERANCE).abs_value) ) | ||
866 | { | 779 | { |
867 | /* this could rarely happen due to massive re-ordering of | 780 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
868 | * messages on the network level, but is most likely either | 781 | _("Ephemeral key message rejected as its validity range does not match our system time (%llu not in [%llu,%llu]).\n"), |
869 | * a bug or some adversary messing with us. Report. */ | 782 | now.abs_value, |
870 | GNUNET_break_op (0); | 783 | start_t.abs_value, |
784 | end_t.abs_value); | ||
871 | return; | 785 | return; |
872 | } | 786 | } |
873 | if ((GNUNET_CRYPTO_rsa_decrypt | 787 | if (GNUNET_OK != |
874 | (my_private_key, &m->encrypted_key, &k, | 788 | GNUNET_CRYPTO_ecc_ecdh (my_ephemeral_key, |
875 | sizeof (struct GNUNET_CRYPTO_AesSessionKey)) != | 789 | &m->ephemeral_key, |
876 | sizeof (struct GNUNET_CRYPTO_AesSessionKey)) || | 790 | &key_material)) |
877 | (GNUNET_OK != GNUNET_CRYPTO_aes_check_session_key (&k))) | ||
878 | { | 791 | { |
879 | /* failed to decrypt !? */ | 792 | GNUNET_break (0); |
880 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
881 | "Invalid key %x decrypted by %s from message %u (origin: %s)\n", | ||
882 | (unsigned int) GNUNET_CRYPTO_crc32_n (&k, sizeof (struct GNUNET_CRYPTO_AesSessionKey)), | ||
883 | GNUNET_i2s (&GSC_my_identity), | ||
884 | (unsigned int) GNUNET_CRYPTO_crc32_n (&m->encrypted_key, sizeof (struct GNUNET_CRYPTO_RsaEncryptedData)), | ||
885 | GNUNET_h2s (&kx->peer.hashPubKey)); | ||
886 | GNUNET_break_op (0); | ||
887 | return; | 793 | return; |
888 | } | 794 | } |
889 | GNUNET_STATISTICS_update (GSC_stats, | 795 | GNUNET_STATISTICS_update (GSC_stats, |
890 | gettext_noop ("# SET_KEY messages decrypted"), 1, | 796 | gettext_noop ("# EPHEMERAL_KEY messages decrypted"), 1, |
891 | GNUNET_NO); | 797 | GNUNET_NO); |
892 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received SET_KEY from `%s'\n", | 798 | derive_aes_key (&GSC_my_identity, |
893 | GNUNET_i2s (&kx->peer)); | 799 | &kx->peer, |
894 | kx->decrypt_key = k; | 800 | &key_material, |
895 | if (kx->decrypt_key_created.abs_value != t.abs_value) | 801 | &kx->encrypt_key); |
802 | derive_aes_key (&kx->peer, | ||
803 | &GSC_my_identity, | ||
804 | &key_material, | ||
805 | &kx->decrypt_key); | ||
806 | /* fresh key, reset sequence numbers */ | ||
807 | kx->last_sequence_number_received = 0; | ||
808 | kx->last_packets_bitmap = 0; | ||
809 | kx->foreign_key_expires = end_t; | ||
810 | setup_fresh_ping (kx); | ||
811 | |||
812 | /* check if we still need to send the sender our key */ | ||
813 | sender_status = (enum KxStateMachine) ntohl (m->sender_status); | ||
814 | switch (sender_status) | ||
896 | { | 815 | { |
897 | /* fresh key, reset sequence numbers */ | 816 | case KX_STATE_DOWN: |
898 | kx->last_sequence_number_received = 0; | 817 | /* makes no sense, should be at least KX_STATE_KEY_SENT */ |
899 | kx->last_packets_bitmap = 0; | 818 | GNUNET_break_op (0); |
900 | kx->decrypt_key_created = t; | 819 | break; |
820 | case KX_STATE_KEY_SENT: | ||
821 | send_key (kx); | ||
822 | break; | ||
823 | case KX_STATE_KEY_RECEIVED: | ||
824 | case KX_STATE_UP: | ||
825 | case KX_STATE_REKEY_SENT: | ||
826 | /* other peer already got our key */ | ||
827 | break; | ||
828 | default: | ||
829 | GNUNET_break (0); | ||
830 | break; | ||
901 | } | 831 | } |
902 | sender_status = (enum KxStateMachine) ntohl (m->sender_status); | 832 | /* check if we need to confirm everything is fine via PING + PONG */ |
903 | switch (kx->status) | 833 | switch (kx->status) |
904 | { | 834 | { |
905 | case KX_STATE_DOWN: | 835 | case KX_STATE_DOWN: |
906 | kx->status = KX_STATE_KEY_RECEIVED; | 836 | kx->status = KX_STATE_KEY_RECEIVED; |
907 | /* we're not up, so we are already doing 'send_key' */ | 837 | send_ping (kx); |
908 | break; | 838 | break; |
909 | case KX_STATE_KEY_SENT: | 839 | case KX_STATE_KEY_SENT: |
910 | kx->status = KX_STATE_KEY_RECEIVED; | 840 | kx->status = KX_STATE_KEY_RECEIVED; |
911 | /* we're not up, so we are already doing 'send_key' */ | 841 | send_ping (kx); |
912 | break; | 842 | break; |
913 | case KX_STATE_KEY_RECEIVED: | 843 | case KX_STATE_KEY_RECEIVED: |
914 | /* we're not up, so we are already doing 'send_key' */ | 844 | send_ping (kx); |
915 | break; | 845 | break; |
916 | case KX_STATE_UP: | 846 | case KX_STATE_UP: |
917 | if ((sender_status == KX_STATE_DOWN) || | 847 | kx->status = KX_STATE_KEY_RECEIVED; |
918 | (sender_status == KX_STATE_KEY_SENT)) | 848 | /* we got a new key, need to reconfirm! */ |
919 | send_key (kx); /* we are up, but other peer is not! */ | 849 | send_ping (kx); |
920 | break; | ||
921 | case KX_STATE_REKEY: | ||
922 | if ((sender_status == KX_STATE_DOWN) || | ||
923 | (sender_status == KX_STATE_KEY_SENT)) | ||
924 | send_key (kx); /* we are up, but other peer is not! */ | ||
925 | break; | 850 | break; |
926 | case KX_STATE_REKEY_SENT: | 851 | case KX_STATE_REKEY_SENT: |
927 | if ((sender_status == KX_STATE_DOWN) || | 852 | kx->status = KX_STATE_KEY_RECEIVED; |
928 | (sender_status == KX_STATE_KEY_SENT)) | 853 | /* we got a new key, need to reconfirm! */ |
929 | send_key (kx); /* we are up, but other peer is not! */ | 854 | send_ping (kx); |
930 | break; | 855 | break; |
931 | default: | 856 | default: |
932 | GNUNET_break (0); | 857 | GNUNET_break (0); |
933 | break; | 858 | break; |
934 | } | 859 | } |
935 | if (NULL != kx->ping_received) | ||
936 | { | ||
937 | ping = kx->ping_received; | ||
938 | kx->ping_received = NULL; | ||
939 | GSC_KX_handle_ping (kx, &ping->header); | ||
940 | GNUNET_free (ping); | ||
941 | } | ||
942 | if (NULL != kx->pong_received) | ||
943 | { | ||
944 | pong = kx->pong_received; | ||
945 | kx->pong_received = NULL; | ||
946 | GSC_KX_handle_pong (kx, &pong->header); | ||
947 | GNUNET_free (pong); | ||
948 | } | ||
949 | } | 860 | } |
950 | 861 | ||
951 | 862 | ||
@@ -976,12 +887,14 @@ GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *kx, | |||
976 | GNUNET_STATISTICS_update (GSC_stats, | 887 | GNUNET_STATISTICS_update (GSC_stats, |
977 | gettext_noop ("# PING messages received"), 1, | 888 | gettext_noop ("# PING messages received"), 1, |
978 | GNUNET_NO); | 889 | GNUNET_NO); |
979 | if ((kx->status != KX_STATE_KEY_RECEIVED) && (kx->status != KX_STATE_UP) && | 890 | if ( (kx->status != KX_STATE_KEY_RECEIVED) && |
980 | (kx->status != KX_STATE_REKEY_SENT)) | 891 | (kx->status != KX_STATE_UP) && |
892 | (kx->status != KX_STATE_REKEY_SENT)) | ||
981 | { | 893 | { |
982 | /* defer */ | 894 | /* ignore */ |
983 | GNUNET_free_non_null (kx->ping_received); | 895 | GNUNET_STATISTICS_update (GSC_stats, |
984 | kx->ping_received = (struct PingMessage *) GNUNET_copy_message (msg); | 896 | gettext_noop ("# PING messages dropped (out of order)"), 1, |
897 | GNUNET_NO); | ||
985 | return; | 898 | return; |
986 | } | 899 | } |
987 | m = (const struct PingMessage *) msg; | 900 | m = (const struct PingMessage *) msg; |
@@ -1012,10 +925,8 @@ GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *kx, | |||
1012 | GNUNET_break_op (0); | 925 | GNUNET_break_op (0); |
1013 | return; | 926 | return; |
1014 | } | 927 | } |
1015 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received PING from `%s'\n", | ||
1016 | GNUNET_i2s (&kx->peer)); | ||
1017 | /* construct PONG */ | 928 | /* construct PONG */ |
1018 | tx.reserved = GNUNET_BANDWIDTH_VALUE_MAX; | 929 | tx.reserved = 0; |
1019 | tx.challenge = t.challenge; | 930 | tx.challenge = t.challenge; |
1020 | tx.target = t.target; | 931 | tx.target = t.target; |
1021 | tp.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PONG); | 932 | tp.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PONG); |
@@ -1034,76 +945,6 @@ GSC_KX_handle_ping (struct GSC_KeyExchangeInfo *kx, | |||
1034 | 945 | ||
1035 | 946 | ||
1036 | /** | 947 | /** |
1037 | * Create a fresh SET KEY message for transmission to the other peer. | ||
1038 | * Also creates a new key. | ||
1039 | * | ||
1040 | * @param kx key exchange context to create SET KEY message for | ||
1041 | */ | ||
1042 | static void | ||
1043 | setup_fresh_setkey (struct GSC_KeyExchangeInfo *kx) | ||
1044 | { | ||
1045 | struct SetKeyMessage *skm; | ||
1046 | |||
1047 | GNUNET_CRYPTO_aes_create_session_key (&kx->encrypt_key); | ||
1048 | kx->encrypt_key_created = GNUNET_TIME_absolute_get (); | ||
1049 | skm = &kx->skm; | ||
1050 | skm->header.size = htons (sizeof (struct SetKeyMessage)); | ||
1051 | skm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_SET_KEY); | ||
1052 | skm->purpose.size = | ||
1053 | htonl (sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + | ||
1054 | sizeof (struct GNUNET_TIME_AbsoluteNBO) + | ||
1055 | sizeof (struct GNUNET_CRYPTO_RsaEncryptedData) + | ||
1056 | sizeof (struct GNUNET_PeerIdentity)); | ||
1057 | skm->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_KEY); | ||
1058 | skm->creation_time = GNUNET_TIME_absolute_hton (kx->encrypt_key_created); | ||
1059 | skm->target = kx->peer; | ||
1060 | CHECK_KX (kx); | ||
1061 | GNUNET_assert (GNUNET_OK == | ||
1062 | GNUNET_CRYPTO_rsa_encrypt (&kx->encrypt_key, | ||
1063 | sizeof (struct | ||
1064 | GNUNET_CRYPTO_AesSessionKey), | ||
1065 | kx->public_key, | ||
1066 | &skm->encrypted_key)); | ||
1067 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1068 | "Encrypting key %x for %s resulting in message %u (origin: %s)\n", | ||
1069 | (unsigned int) GNUNET_CRYPTO_crc32_n (&kx->encrypt_key, sizeof (struct GNUNET_CRYPTO_AesSessionKey)), | ||
1070 | GNUNET_i2s (&kx->peer), | ||
1071 | (unsigned int) GNUNET_CRYPTO_crc32_n (&skm->encrypted_key, sizeof (struct GNUNET_CRYPTO_RsaEncryptedData)), | ||
1072 | GNUNET_h2s (&GSC_my_identity.hashPubKey)); | ||
1073 | |||
1074 | GNUNET_assert (GNUNET_OK == | ||
1075 | GNUNET_CRYPTO_rsa_sign (my_private_key, &skm->purpose, | ||
1076 | &skm->signature)); | ||
1077 | } | ||
1078 | |||
1079 | |||
1080 | /** | ||
1081 | * Create a fresh PING message for transmission to the other peer. | ||
1082 | * | ||
1083 | * @param kx key exchange context to create PING for | ||
1084 | */ | ||
1085 | static void | ||
1086 | setup_fresh_ping (struct GSC_KeyExchangeInfo *kx) | ||
1087 | { | ||
1088 | struct PingMessage pp; | ||
1089 | struct PingMessage *pm; | ||
1090 | struct GNUNET_CRYPTO_AesInitializationVector iv; | ||
1091 | |||
1092 | pm = &kx->ping; | ||
1093 | pm->header.size = htons (sizeof (struct PingMessage)); | ||
1094 | pm->header.type = htons (GNUNET_MESSAGE_TYPE_CORE_PING); | ||
1095 | pm->iv_seed = | ||
1096 | GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX); | ||
1097 | derive_iv (&iv, &kx->encrypt_key, pm->iv_seed, &kx->peer); | ||
1098 | pp.challenge = kx->ping_challenge; | ||
1099 | pp.target = kx->peer; | ||
1100 | do_encrypt (kx, &iv, &pp.target, &pm->target, | ||
1101 | sizeof (struct PingMessage) - ((void *) &pm->target - | ||
1102 | (void *) pm)); | ||
1103 | } | ||
1104 | |||
1105 | |||
1106 | /** | ||
1107 | * Task triggered when a neighbour entry is about to time out | 948 | * Task triggered when a neighbour entry is about to time out |
1108 | * (and we should prevent this by sending a PING). | 949 | * (and we should prevent this by sending a PING). |
1109 | * | 950 | * |
@@ -1125,7 +966,7 @@ send_keep_alive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
1125 | gettext_noop ("# sessions terminated by timeout"), | 966 | gettext_noop ("# sessions terminated by timeout"), |
1126 | 1, GNUNET_NO); | 967 | 1, GNUNET_NO); |
1127 | GSC_SESSIONS_end (&kx->peer); | 968 | GSC_SESSIONS_end (&kx->peer); |
1128 | kx->status = KX_STATE_DOWN; | 969 | kx->status = KX_STATE_KEY_SENT; |
1129 | send_key (kx); | 970 | send_key (kx); |
1130 | return; | 971 | return; |
1131 | } | 972 | } |
@@ -1168,49 +1009,6 @@ update_timeout (struct GSC_KeyExchangeInfo *kx) | |||
1168 | 1009 | ||
1169 | 1010 | ||
1170 | /** | 1011 | /** |
1171 | * Trigger rekeying event. | ||
1172 | * | ||
1173 | * @param cls the 'struct GSC_KeyExchangeInfo' | ||
1174 | * @param tc schedule context (unused) | ||
1175 | */ | ||
1176 | static void | ||
1177 | trigger_rekey (void *cls, | ||
1178 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1179 | { | ||
1180 | struct GSC_KeyExchangeInfo *kx = cls; | ||
1181 | |||
1182 | GNUNET_break (KX_STATE_UP == kx->status); | ||
1183 | kx->status = KX_STATE_REKEY; | ||
1184 | kx->set_key_retry_frequency = INITIAL_SET_KEY_RETRY_FREQUENCY; | ||
1185 | kx->retry_set_key_task = | ||
1186 | GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency, | ||
1187 | &set_key_retry_task, kx); | ||
1188 | } | ||
1189 | |||
1190 | |||
1191 | /** | ||
1192 | * Schedule rekey operation. | ||
1193 | * | ||
1194 | * @param kx key exchange to schedule rekey for | ||
1195 | */ | ||
1196 | static void | ||
1197 | schedule_rekey (struct GSC_KeyExchangeInfo *kx) | ||
1198 | { | ||
1199 | struct GNUNET_TIME_Relative rdelay; | ||
1200 | |||
1201 | if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task) | ||
1202 | GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); | ||
1203 | rdelay = REKEY_FREQUENCY; | ||
1204 | /* randomize rekey frequency by one minute to avoid synchronization */ | ||
1205 | rdelay.rel_value += GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, | ||
1206 | 60 * 1000); | ||
1207 | kx->retry_set_key_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY, | ||
1208 | &trigger_rekey, | ||
1209 | kx); | ||
1210 | } | ||
1211 | |||
1212 | |||
1213 | /** | ||
1214 | * We received a PONG message. Validate and update our status. | 1012 | * We received a PONG message. Validate and update our status. |
1215 | * | 1013 | * |
1216 | * @param kx key exchange context for the the PONG | 1014 | * @param kx key exchange context for the the PONG |
@@ -1222,7 +1020,6 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, | |||
1222 | { | 1020 | { |
1223 | const struct PongMessage *m; | 1021 | const struct PongMessage *m; |
1224 | struct PongMessage t; | 1022 | struct PongMessage t; |
1225 | struct EncryptedMessage *emsg; | ||
1226 | struct GNUNET_CRYPTO_AesInitializationVector iv; | 1023 | struct GNUNET_CRYPTO_AesInitializationVector iv; |
1227 | uint16_t msize; | 1024 | uint16_t msize; |
1228 | 1025 | ||
@@ -1238,17 +1035,19 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, | |||
1238 | switch (kx->status) | 1035 | switch (kx->status) |
1239 | { | 1036 | { |
1240 | case KX_STATE_DOWN: | 1037 | case KX_STATE_DOWN: |
1038 | GNUNET_STATISTICS_update (GSC_stats, | ||
1039 | gettext_noop ("# PONG messages dropped (connection down)"), 1, | ||
1040 | GNUNET_NO); | ||
1241 | return; | 1041 | return; |
1242 | case KX_STATE_KEY_SENT: | 1042 | case KX_STATE_KEY_SENT: |
1243 | GNUNET_free_non_null (kx->pong_received); | 1043 | GNUNET_STATISTICS_update (GSC_stats, |
1244 | kx->pong_received = (struct PongMessage *) GNUNET_copy_message (msg); | 1044 | gettext_noop ("# PONG messages dropped (out of order)"), 1, |
1045 | GNUNET_NO); | ||
1245 | return; | 1046 | return; |
1246 | case KX_STATE_KEY_RECEIVED: | 1047 | case KX_STATE_KEY_RECEIVED: |
1247 | break; | 1048 | break; |
1248 | case KX_STATE_UP: | 1049 | case KX_STATE_UP: |
1249 | break; | 1050 | break; |
1250 | case KX_STATE_REKEY: | ||
1251 | break; | ||
1252 | case KX_STATE_REKEY_SENT: | 1051 | case KX_STATE_REKEY_SENT: |
1253 | break; | 1052 | break; |
1254 | default: | 1053 | default: |
@@ -1289,13 +1088,19 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, | |||
1289 | } | 1088 | } |
1290 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received PONG from `%s'\n", | 1089 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received PONG from `%s'\n", |
1291 | GNUNET_i2s (&kx->peer)); | 1090 | GNUNET_i2s (&kx->peer)); |
1091 | /* no need to resend key any longer */ | ||
1092 | if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task) | ||
1093 | { | ||
1094 | GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); | ||
1095 | kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK; | ||
1096 | } | ||
1292 | switch (kx->status) | 1097 | switch (kx->status) |
1293 | { | 1098 | { |
1294 | case KX_STATE_DOWN: | 1099 | case KX_STATE_DOWN: |
1295 | GNUNET_break (0); /* should be impossible */ | 1100 | GNUNET_assert (0); /* should be impossible */ |
1296 | return; | 1101 | return; |
1297 | case KX_STATE_KEY_SENT: | 1102 | case KX_STATE_KEY_SENT: |
1298 | GNUNET_break (0); /* should be impossible */ | 1103 | GNUNET_assert (0); /* should be impossible */ |
1299 | return; | 1104 | return; |
1300 | case KX_STATE_KEY_RECEIVED: | 1105 | case KX_STATE_KEY_RECEIVED: |
1301 | GNUNET_STATISTICS_update (GSC_stats, | 1106 | GNUNET_STATISTICS_update (GSC_stats, |
@@ -1304,23 +1109,14 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, | |||
1304 | GNUNET_NO); | 1109 | GNUNET_NO); |
1305 | kx->status = KX_STATE_UP; | 1110 | kx->status = KX_STATE_UP; |
1306 | GSC_SESSIONS_create (&kx->peer, kx); | 1111 | GSC_SESSIONS_create (&kx->peer, kx); |
1307 | CHECK_KX (kx); | ||
1308 | schedule_rekey (kx); | ||
1309 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task); | 1112 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == kx->keep_alive_task); |
1310 | if (NULL != kx->emsg_received) | ||
1311 | { | ||
1312 | emsg = kx->emsg_received; | ||
1313 | kx->emsg_received = NULL; | ||
1314 | GSC_KX_handle_encrypted_message (kx, &emsg->header, NULL, | ||
1315 | 0 /* FIXME: ATSI */ ); | ||
1316 | GNUNET_free (emsg); | ||
1317 | } | ||
1318 | update_timeout (kx); | 1113 | update_timeout (kx); |
1319 | break; | 1114 | break; |
1320 | case KX_STATE_UP: | 1115 | case KX_STATE_UP: |
1321 | update_timeout (kx); | 1116 | GNUNET_STATISTICS_update (GSC_stats, |
1322 | break; | 1117 | gettext_noop |
1323 | case KX_STATE_REKEY: | 1118 | ("# timeouts prevented via PONG"), 1, |
1119 | GNUNET_NO); | ||
1324 | update_timeout (kx); | 1120 | update_timeout (kx); |
1325 | break; | 1121 | break; |
1326 | case KX_STATE_REKEY_SENT: | 1122 | case KX_STATE_REKEY_SENT: |
@@ -1329,7 +1125,6 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, | |||
1329 | ("# rekey operations confirmed via PONG"), 1, | 1125 | ("# rekey operations confirmed via PONG"), 1, |
1330 | GNUNET_NO); | 1126 | GNUNET_NO); |
1331 | kx->status = KX_STATE_UP; | 1127 | kx->status = KX_STATE_UP; |
1332 | schedule_rekey (kx); | ||
1333 | update_timeout (kx); | 1128 | update_timeout (kx); |
1334 | break; | 1129 | break; |
1335 | default: | 1130 | default: |
@@ -1340,86 +1135,25 @@ GSC_KX_handle_pong (struct GSC_KeyExchangeInfo *kx, | |||
1340 | 1135 | ||
1341 | 1136 | ||
1342 | /** | 1137 | /** |
1343 | * Send our key (and encrypted PING) to the other peer. | 1138 | * Send our key to the other peer. |
1344 | * | 1139 | * |
1345 | * @param kx key exchange context | 1140 | * @param kx key exchange context |
1346 | */ | 1141 | */ |
1347 | static void | 1142 | static void |
1348 | send_key (struct GSC_KeyExchangeInfo *kx) | 1143 | send_key (struct GSC_KeyExchangeInfo *kx) |
1349 | { | 1144 | { |
1350 | CHECK_KX (kx); | ||
1351 | if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task) | 1145 | if (GNUNET_SCHEDULER_NO_TASK != kx->retry_set_key_task) |
1352 | { | 1146 | { |
1353 | GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); | 1147 | GNUNET_SCHEDULER_cancel (kx->retry_set_key_task); |
1354 | kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK; | 1148 | kx->retry_set_key_task = GNUNET_SCHEDULER_NO_TASK; |
1355 | } | 1149 | } |
1356 | if (KX_STATE_UP == kx->status) | ||
1357 | return; /* nothing to do */ | ||
1358 | if (NULL == kx->public_key) | ||
1359 | { | ||
1360 | if (NULL != kx->pitr) | ||
1361 | return; | ||
1362 | /* lookup public key, then try again */ | ||
1363 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1364 | "Trying to obtain public key for `%s'\n", | ||
1365 | GNUNET_i2s (&kx->peer)); | ||
1366 | kx->pitr = | ||
1367 | GNUNET_PEERINFO_iterate (peerinfo, &kx->peer, | ||
1368 | GNUNET_TIME_UNIT_FOREVER_REL /* timeout? */ , | ||
1369 | &process_hello, kx); | ||
1370 | return; | ||
1371 | } | ||
1372 | |||
1373 | /* update status */ | ||
1374 | switch (kx->status) | ||
1375 | { | ||
1376 | case KX_STATE_DOWN: | ||
1377 | kx->status = KX_STATE_KEY_SENT; | ||
1378 | /* setup SET KEY message */ | ||
1379 | setup_fresh_setkey (kx); | ||
1380 | setup_fresh_ping (kx); | ||
1381 | GNUNET_STATISTICS_update (GSC_stats, | ||
1382 | gettext_noop | ||
1383 | ("# SET_KEY and PING messages created"), 1, | ||
1384 | GNUNET_NO); | ||
1385 | break; | ||
1386 | case KX_STATE_KEY_SENT: | ||
1387 | break; | ||
1388 | case KX_STATE_KEY_RECEIVED: | ||
1389 | break; | ||
1390 | case KX_STATE_UP: | ||
1391 | GNUNET_break (0); | ||
1392 | return; | ||
1393 | case KX_STATE_REKEY: | ||
1394 | kx->status = KX_STATE_REKEY_SENT; | ||
1395 | /* setup fresh SET KEY message */ | ||
1396 | setup_fresh_setkey (kx); | ||
1397 | setup_fresh_ping (kx); | ||
1398 | GNUNET_STATISTICS_update (GSC_stats, | ||
1399 | gettext_noop | ||
1400 | ("# SET_KEY and PING messages created"), 1, | ||
1401 | GNUNET_NO); | ||
1402 | GNUNET_STATISTICS_update (GSC_stats, | ||
1403 | gettext_noop | ||
1404 | ("# REKEY operations performed"), 1, | ||
1405 | GNUNET_NO); | ||
1406 | break; | ||
1407 | case KX_STATE_REKEY_SENT: | ||
1408 | break; | ||
1409 | default: | ||
1410 | GNUNET_break (0); | ||
1411 | return; | ||
1412 | } | ||
1413 | |||
1414 | /* always update sender status in SET KEY message */ | 1150 | /* always update sender status in SET KEY message */ |
1415 | /* Not sending rekey sent state to be compatible with GNUnet 0.9.2 */ | 1151 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1416 | kx->skm.sender_status = htonl ((int32_t) ((kx->status == KX_STATE_REKEY_SENT) ? | 1152 | "Sending key to `%s' (my status: %d)\n", |
1417 | KX_STATE_KEY_RECEIVED : kx->status)); | 1153 | GNUNET_i2s (&kx->peer), |
1418 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending SET_KEY and PING to `%s'\n", | 1154 | kx->status); |
1419 | GNUNET_i2s (&kx->peer)); | 1155 | current_ekm.sender_status = htonl ((int32_t) (kx->status)); |
1420 | GSC_NEIGHBOURS_transmit (&kx->peer, &kx->skm.header, | 1156 | GSC_NEIGHBOURS_transmit (&kx->peer, ¤t_ekm.header, |
1421 | kx->set_key_retry_frequency); | ||
1422 | GSC_NEIGHBOURS_transmit (&kx->peer, &kx->ping.header, | ||
1423 | kx->set_key_retry_frequency); | 1157 | kx->set_key_retry_frequency); |
1424 | kx->retry_set_key_task = | 1158 | kx->retry_set_key_task = |
1425 | GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency, | 1159 | GNUNET_SCHEDULER_add_delayed (kx->set_key_retry_frequency, |
@@ -1451,7 +1185,7 @@ GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx, | |||
1451 | htonl (GNUNET_CRYPTO_random_u32 | 1185 | htonl (GNUNET_CRYPTO_random_u32 |
1452 | (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX)); | 1186 | (GNUNET_CRYPTO_QUALITY_NONCE, UINT32_MAX)); |
1453 | ph->sequence_number = htonl (++kx->last_sequence_number_sent); | 1187 | ph->sequence_number = htonl (++kx->last_sequence_number_sent); |
1454 | ph->reserved = GNUNET_BANDWIDTH_VALUE_MAX; | 1188 | ph->reserved = 0; |
1455 | ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); | 1189 | ph->timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); |
1456 | memcpy (&ph[1], payload, payload_size); | 1190 | memcpy (&ph[1], payload, payload_size); |
1457 | 1191 | ||
@@ -1466,8 +1200,9 @@ GSC_KX_encrypt_and_transmit (struct GSC_KeyExchangeInfo *kx, | |||
1466 | used - ENCRYPTED_HEADER_SIZE)); | 1200 | used - ENCRYPTED_HEADER_SIZE)); |
1467 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted %u bytes for %s\n", | 1201 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Encrypted %u bytes for %s\n", |
1468 | used - ENCRYPTED_HEADER_SIZE, GNUNET_i2s (&kx->peer)); | 1202 | used - ENCRYPTED_HEADER_SIZE, GNUNET_i2s (&kx->peer)); |
1469 | derive_auth_key (&auth_key, &kx->encrypt_key, ph->iv_seed, | 1203 | derive_auth_key (&auth_key, |
1470 | kx->encrypt_key_created); | 1204 | &kx->encrypt_key, |
1205 | ph->iv_seed); | ||
1471 | GNUNET_CRYPTO_hmac (&auth_key, &em->sequence_number, | 1206 | GNUNET_CRYPTO_hmac (&auth_key, &em->sequence_number, |
1472 | used - ENCRYPTED_HEADER_SIZE, &em->hmac); | 1207 | used - ENCRYPTED_HEADER_SIZE, &em->hmac); |
1473 | GSC_NEIGHBOURS_transmit (&kx->peer, &em->header, | 1208 | GSC_NEIGHBOURS_transmit (&kx->peer, &em->header, |
@@ -1531,31 +1266,35 @@ GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx, | |||
1531 | return; | 1266 | return; |
1532 | } | 1267 | } |
1533 | m = (const struct EncryptedMessage *) msg; | 1268 | m = (const struct EncryptedMessage *) msg; |
1534 | if ((kx->status != KX_STATE_KEY_RECEIVED) && (kx->status != KX_STATE_UP) && | 1269 | if (kx->status != KX_STATE_UP) |
1535 | (kx->status != KX_STATE_REKEY_SENT) ) | ||
1536 | { | 1270 | { |
1537 | GNUNET_STATISTICS_update (GSC_stats, | 1271 | GNUNET_STATISTICS_update (GSC_stats, |
1538 | gettext_noop | 1272 | gettext_noop |
1539 | ("# failed to decrypt message (no session key)"), | 1273 | ("# DATA message dropped (out of order)"), |
1540 | 1, GNUNET_NO); | 1274 | 1, GNUNET_NO); |
1541 | return; | 1275 | return; |
1542 | } | 1276 | } |
1543 | if (KX_STATE_KEY_RECEIVED == kx->status) | 1277 | if (0 == GNUNET_TIME_absolute_get_remaining (kx->foreign_key_expires).rel_value) |
1544 | { | 1278 | { |
1545 | /* defer */ | 1279 | kx->status = KX_STATE_KEY_SENT; |
1546 | GNUNET_free_non_null (kx->emsg_received); | 1280 | GNUNET_STATISTICS_update (GSC_stats, |
1547 | kx->emsg_received = (struct EncryptedMessage *) GNUNET_copy_message (msg); | 1281 | gettext_noop |
1282 | ("# DATA message dropped (session key expired)"), | ||
1283 | 1, GNUNET_NO); | ||
1284 | send_key (kx); | ||
1548 | return; | 1285 | return; |
1549 | } | 1286 | } |
1287 | |||
1550 | /* validate hash */ | 1288 | /* validate hash */ |
1551 | derive_auth_key (&auth_key, &kx->decrypt_key, m->iv_seed, | 1289 | derive_auth_key (&auth_key, &kx->decrypt_key, m->iv_seed); |
1552 | kx->decrypt_key_created); | ||
1553 | GNUNET_CRYPTO_hmac (&auth_key, &m->sequence_number, | 1290 | GNUNET_CRYPTO_hmac (&auth_key, &m->sequence_number, |
1554 | size - ENCRYPTED_HEADER_SIZE, &ph); | 1291 | size - ENCRYPTED_HEADER_SIZE, &ph); |
1555 | if (0 != memcmp (&ph, &m->hmac, sizeof (struct GNUNET_HashCode))) | 1292 | if (0 != memcmp (&ph, &m->hmac, sizeof (struct GNUNET_HashCode))) |
1556 | { | 1293 | { |
1557 | /* checksum failed */ | 1294 | /* checksum failed */ |
1558 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed checksum validation for a message from `%s'\n", GNUNET_i2s (&kx->peer)); | 1295 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1296 | "Failed checksum validation for a message from `%s'\n", | ||
1297 | GNUNET_i2s (&kx->peer)); | ||
1559 | return; | 1298 | return; |
1560 | } | 1299 | } |
1561 | derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity); | 1300 | derive_iv (&iv, &kx->decrypt_key, m->iv_seed, &GSC_my_identity); |
@@ -1572,7 +1311,7 @@ GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx, | |||
1572 | snum = ntohl (pt->sequence_number); | 1311 | snum = ntohl (pt->sequence_number); |
1573 | if (kx->last_sequence_number_received == snum) | 1312 | if (kx->last_sequence_number_received == snum) |
1574 | { | 1313 | { |
1575 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1314 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1576 | "Received duplicate message, ignoring.\n"); | 1315 | "Received duplicate message, ignoring.\n"); |
1577 | /* duplicate, ignore */ | 1316 | /* duplicate, ignore */ |
1578 | GNUNET_STATISTICS_update (GSC_stats, | 1317 | GNUNET_STATISTICS_update (GSC_stats, |
@@ -1583,7 +1322,7 @@ GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx, | |||
1583 | if ((kx->last_sequence_number_received > snum) && | 1322 | if ((kx->last_sequence_number_received > snum) && |
1584 | (kx->last_sequence_number_received - snum > 32)) | 1323 | (kx->last_sequence_number_received - snum > 32)) |
1585 | { | 1324 | { |
1586 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1325 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1587 | "Received ancient out of sequence message, ignoring.\n"); | 1326 | "Received ancient out of sequence message, ignoring.\n"); |
1588 | /* ancient out of sequence, ignore */ | 1327 | /* ancient out of sequence, ignore */ |
1589 | GNUNET_STATISTICS_update (GSC_stats, | 1328 | GNUNET_STATISTICS_update (GSC_stats, |
@@ -1598,7 +1337,7 @@ GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx, | |||
1598 | 1337 | ||
1599 | if ((kx->last_packets_bitmap & rotbit) != 0) | 1338 | if ((kx->last_packets_bitmap & rotbit) != 0) |
1600 | { | 1339 | { |
1601 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1340 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1602 | "Received duplicate message, ignoring.\n"); | 1341 | "Received duplicate message, ignoring.\n"); |
1603 | GNUNET_STATISTICS_update (GSC_stats, | 1342 | GNUNET_STATISTICS_update (GSC_stats, |
1604 | gettext_noop ("# bytes dropped (duplicates)"), | 1343 | gettext_noop ("# bytes dropped (duplicates)"), |
@@ -1624,8 +1363,8 @@ GSC_KX_handle_encrypted_message (struct GSC_KeyExchangeInfo *kx, | |||
1624 | if (GNUNET_TIME_absolute_get_duration (t).rel_value > | 1363 | if (GNUNET_TIME_absolute_get_duration (t).rel_value > |
1625 | MAX_MESSAGE_AGE.rel_value) | 1364 | MAX_MESSAGE_AGE.rel_value) |
1626 | { | 1365 | { |
1627 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | 1366 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1628 | _("Message received far too old (%s). Content ignored.\n"), | 1367 | "Message received far too old (%s). Content ignored.\n", |
1629 | GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (t), GNUNET_YES)); | 1368 | GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (t), GNUNET_YES)); |
1630 | GNUNET_STATISTICS_update (GSC_stats, | 1369 | GNUNET_STATISTICS_update (GSC_stats, |
1631 | gettext_noop | 1370 | gettext_noop |
@@ -1684,28 +1423,89 @@ deliver_message (void *cls, void *client, const struct GNUNET_MessageHeader *m) | |||
1684 | 1423 | ||
1685 | 1424 | ||
1686 | /** | 1425 | /** |
1426 | * Setup the message that links the ephemeral key to our persistent | ||
1427 | * public key and generate the appropriate signature. | ||
1428 | */ | ||
1429 | static void | ||
1430 | sign_ephemeral_key () | ||
1431 | { | ||
1432 | current_ekm.header.size = htons (sizeof (struct EphemeralKeyMessage)); | ||
1433 | current_ekm.header.type = htons (GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY); | ||
1434 | current_ekm.sender_status = 0; /* to be set later */ | ||
1435 | current_ekm.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_SET_ECC_KEY); | ||
1436 | current_ekm.purpose.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + | ||
1437 | sizeof (struct GNUNET_TIME_AbsoluteNBO) + | ||
1438 | sizeof (struct GNUNET_TIME_AbsoluteNBO) + | ||
1439 | sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded) + | ||
1440 | sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded)); | ||
1441 | current_ekm.creation_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ()); | ||
1442 | current_ekm.expiration_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_add (REKEY_FREQUENCY, | ||
1443 | REKEY_TOLERANCE))); | ||
1444 | GNUNET_CRYPTO_ecc_key_get_public (my_ephemeral_key, | ||
1445 | ¤t_ekm.ephemeral_key); | ||
1446 | current_ekm.origin_public_key = my_public_key; | ||
1447 | GNUNET_assert (GNUNET_OK == | ||
1448 | GNUNET_CRYPTO_ecc_sign (my_private_key, | ||
1449 | ¤t_ekm.purpose, | ||
1450 | ¤t_ekm.signature)); | ||
1451 | } | ||
1452 | |||
1453 | |||
1454 | /** | ||
1455 | * Task run to trigger rekeying. | ||
1456 | * | ||
1457 | * @param cls closure, NULL | ||
1458 | * @param tc scheduler context | ||
1459 | */ | ||
1460 | static void | ||
1461 | do_rekey (void *cls, | ||
1462 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1463 | { | ||
1464 | struct GSC_KeyExchangeInfo *pos; | ||
1465 | |||
1466 | rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY, | ||
1467 | &do_rekey, | ||
1468 | NULL); | ||
1469 | if (NULL != my_ephemeral_key) | ||
1470 | GNUNET_CRYPTO_ecc_key_free (my_ephemeral_key); | ||
1471 | my_ephemeral_key = GNUNET_CRYPTO_ecc_key_create (); | ||
1472 | GNUNET_assert (NULL != my_ephemeral_key); | ||
1473 | sign_ephemeral_key (); | ||
1474 | for (pos = kx_head; NULL != pos; pos = pos->next) | ||
1475 | { | ||
1476 | pos->status = KX_STATE_REKEY_SENT; | ||
1477 | send_key (pos); | ||
1478 | } | ||
1479 | } | ||
1480 | |||
1481 | |||
1482 | /** | ||
1687 | * Initialize KX subsystem. | 1483 | * Initialize KX subsystem. |
1688 | * | 1484 | * |
1689 | * @param pk private key to use for the peer | 1485 | * @param pk private key to use for the peer |
1690 | * @return GNUNET_OK on success, GNUNET_SYSERR on failure | 1486 | * @return GNUNET_OK on success, GNUNET_SYSERR on failure |
1691 | */ | 1487 | */ |
1692 | int | 1488 | int |
1693 | GSC_KX_init (struct GNUNET_CRYPTO_RsaPrivateKey *pk) | 1489 | GSC_KX_init (struct GNUNET_CRYPTO_EccPrivateKey *pk) |
1694 | { | 1490 | { |
1491 | GNUNET_assert (NULL != pk); | ||
1695 | my_private_key = pk; | 1492 | my_private_key = pk; |
1696 | GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key); | 1493 | GNUNET_CRYPTO_ecc_key_get_public (my_private_key, &my_public_key); |
1697 | GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), | 1494 | GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key), |
1698 | &GSC_my_identity.hashPubKey); | 1495 | &GSC_my_identity.hashPubKey); |
1699 | peerinfo = GNUNET_PEERINFO_connect (GSC_cfg); | 1496 | my_ephemeral_key = GNUNET_CRYPTO_ecc_key_create (); |
1700 | if (NULL == peerinfo) | 1497 | if (NULL == my_ephemeral_key) |
1701 | { | 1498 | { |
1702 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1499 | GNUNET_break (0); |
1703 | _("Could not access PEERINFO service. Exiting.\n")); | 1500 | GNUNET_CRYPTO_ecc_key_free (my_private_key); |
1704 | GNUNET_CRYPTO_rsa_key_free (my_private_key); | ||
1705 | my_private_key = NULL; | 1501 | my_private_key = NULL; |
1706 | return GNUNET_SYSERR; | 1502 | return GNUNET_SYSERR; |
1707 | } | 1503 | } |
1504 | sign_ephemeral_key (); | ||
1708 | mst = GNUNET_SERVER_mst_create (&deliver_message, NULL); | 1505 | mst = GNUNET_SERVER_mst_create (&deliver_message, NULL); |
1506 | rekey_task = GNUNET_SCHEDULER_add_delayed (REKEY_FREQUENCY, | ||
1507 | &do_rekey, | ||
1508 | NULL); | ||
1709 | return GNUNET_OK; | 1509 | return GNUNET_OK; |
1710 | } | 1510 | } |
1711 | 1511 | ||
@@ -1716,15 +1516,20 @@ GSC_KX_init (struct GNUNET_CRYPTO_RsaPrivateKey *pk) | |||
1716 | void | 1516 | void |
1717 | GSC_KX_done () | 1517 | GSC_KX_done () |
1718 | { | 1518 | { |
1519 | if (GNUNET_SCHEDULER_NO_TASK != rekey_task) | ||
1520 | { | ||
1521 | GNUNET_SCHEDULER_cancel (rekey_task); | ||
1522 | rekey_task = GNUNET_SCHEDULER_NO_TASK; | ||
1523 | } | ||
1719 | if (NULL != my_private_key) | 1524 | if (NULL != my_private_key) |
1720 | { | 1525 | { |
1721 | GNUNET_CRYPTO_rsa_key_free (my_private_key); | 1526 | GNUNET_CRYPTO_ecc_key_free (my_private_key); |
1722 | my_private_key = NULL; | 1527 | my_private_key = NULL; |
1723 | } | 1528 | } |
1724 | if (NULL != peerinfo) | 1529 | if (NULL != my_ephemeral_key) |
1725 | { | 1530 | { |
1726 | GNUNET_PEERINFO_disconnect (peerinfo); | 1531 | GNUNET_CRYPTO_ecc_key_free (my_ephemeral_key); |
1727 | peerinfo = NULL; | 1532 | my_ephemeral_key = NULL; |
1728 | } | 1533 | } |
1729 | if (NULL != mst) | 1534 | if (NULL != mst) |
1730 | { | 1535 | { |
diff --git a/src/core/gnunet-service-core_kx.h b/src/core/gnunet-service-core_kx.h index fcb561e01..6e6d30d8d 100644 --- a/src/core/gnunet-service-core_kx.h +++ b/src/core/gnunet-service-core_kx.h | |||
@@ -37,15 +37,15 @@ struct GSC_KeyExchangeInfo; | |||
37 | 37 | ||
38 | 38 | ||
39 | /** | 39 | /** |
40 | * We received a SET_KEY message. Validate and update | 40 | * We received a EPHEMERAL_KEY message. Validate and update |
41 | * our key material and status. | 41 | * our key material and status. |
42 | * | 42 | * |
43 | * @param kx key exchange status for the corresponding peer | 43 | * @param kx key exchange status for the corresponding peer |
44 | * @param msg the set key message we received | 44 | * @param msg the set key message we received |
45 | */ | 45 | */ |
46 | void | 46 | void |
47 | GSC_KX_handle_set_key (struct GSC_KeyExchangeInfo *kx, | 47 | GSC_KX_handle_ephemeral_key (struct GSC_KeyExchangeInfo *kx, |
48 | const struct GNUNET_MessageHeader *msg); | 48 | const struct GNUNET_MessageHeader *msg); |
49 | 49 | ||
50 | 50 | ||
51 | /** | 51 | /** |
@@ -125,7 +125,7 @@ GSC_KX_stop (struct GSC_KeyExchangeInfo *kx); | |||
125 | * @return GNUNET_OK on success, GNUNET_SYSERR on failure | 125 | * @return GNUNET_OK on success, GNUNET_SYSERR on failure |
126 | */ | 126 | */ |
127 | int | 127 | int |
128 | GSC_KX_init (struct GNUNET_CRYPTO_RsaPrivateKey *pk); | 128 | GSC_KX_init (struct GNUNET_CRYPTO_EccPrivateKey *pk); |
129 | 129 | ||
130 | 130 | ||
131 | /** | 131 | /** |
diff --git a/src/core/gnunet-service-core_neighbours.c b/src/core/gnunet-service-core_neighbours.c index aa77fe47e..7e0086fd6 100644 --- a/src/core/gnunet-service-core_neighbours.c +++ b/src/core/gnunet-service-core_neighbours.c | |||
@@ -400,8 +400,8 @@ handle_transport_receive (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
400 | type = ntohs (message->type); | 400 | type = ntohs (message->type); |
401 | switch (type) | 401 | switch (type) |
402 | { | 402 | { |
403 | case GNUNET_MESSAGE_TYPE_CORE_SET_KEY: | 403 | case GNUNET_MESSAGE_TYPE_CORE_EPHEMERAL_KEY: |
404 | GSC_KX_handle_set_key (n->kxinfo, message); | 404 | GSC_KX_handle_ephemeral_key (n->kxinfo, message); |
405 | break; | 405 | break; |
406 | case GNUNET_MESSAGE_TYPE_CORE_PING: | 406 | case GNUNET_MESSAGE_TYPE_CORE_PING: |
407 | GSC_KX_handle_ping (n->kxinfo, message); | 407 | GSC_KX_handle_ping (n->kxinfo, message); |