diff options
Diffstat (limited to 'src/transport/gnunet-service-tng.c')
-rw-r--r-- | src/transport/gnunet-service-tng.c | 378 |
1 files changed, 329 insertions, 49 deletions
diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index 15a634286..e55491990 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c | |||
@@ -56,6 +56,11 @@ | |||
56 | * fully build fragments just before transmission (optimization, should | 56 | * fully build fragments just before transmission (optimization, should |
57 | * reduce CPU and memory use) | 57 | * reduce CPU and memory use) |
58 | * | 58 | * |
59 | * FIXME (without marks in the code!): | ||
60 | * - proper use/initialization of timestamps in messages exchanged | ||
61 | * during DV learning | ||
62 | * - | ||
63 | * | ||
59 | * Optimizations: | 64 | * Optimizations: |
60 | * - use shorthashmap on msg_uuid's when matching reliability/fragment ACKs | 65 | * - use shorthashmap on msg_uuid's when matching reliability/fragment ACKs |
61 | * against our pending message queue (requires additional per neighbour | 66 | * against our pending message queue (requires additional per neighbour |
@@ -260,8 +265,11 @@ struct TransportBackchannelEncapsulationMessage | |||
260 | */ | 265 | */ |
261 | struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key; | 266 | struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_key; |
262 | 267 | ||
263 | // FIXME: probably should add random IV here as well, | 268 | /** |
264 | // especially if we re-use ephemeral keys! | 269 | * We use an IV here as the @e ephemeral_key is re-used for |
270 | * #EPHEMERAL_VALIDITY time to avoid re-signing it all the time. | ||
271 | */ | ||
272 | struct GNUNET_ShortHashCode iv; | ||
265 | 273 | ||
266 | /** | 274 | /** |
267 | * HMAC over the ciphertext of the encrypted, variable-size | 275 | * HMAC over the ciphertext of the encrypted, variable-size |
@@ -287,15 +295,17 @@ struct EphemeralConfirmation | |||
287 | 295 | ||
288 | /** | 296 | /** |
289 | * How long is this signature over the ephemeral key valid? | 297 | * How long is this signature over the ephemeral key valid? |
290 | * Note that the receiver MUST IGNORE the absolute time, and | 298 | * |
291 | * only interpret the value as a mononic time and reject | 299 | * Note that the receiver MUST IGNORE the absolute time, and only interpret |
292 | * "older" values than the last one observed. Even with this, | 300 | * the value as a mononic time and reject "older" values than the last one |
293 | * there is no real guarantee against replay achieved here, | 301 | * observed. This is necessary as we do not want to require synchronized |
294 | * as the latest timestamp is not persisted. This is | 302 | * clocks and may not have a bidirectional communication channel. |
295 | * necessary as we do not want to require synchronized | 303 | * |
296 | * clocks and may not have a bidirectional communication | 304 | * Even with this, there is no real guarantee against replay achieved here, |
297 | * channel. Communicators must protect against replay | 305 | * unless the latest timestamp is persisted. While persistence should be |
298 | * attacks when using backchannel communication! | 306 | * provided via PEERSTORE, we do not consider the mechanism reliable! Thus, |
307 | * communicators must protect against replay attacks when using backchannel | ||
308 | * communication! | ||
299 | */ | 309 | */ |
300 | struct GNUNET_TIME_AbsoluteNBO ephemeral_validity; | 310 | struct GNUNET_TIME_AbsoluteNBO ephemeral_validity; |
301 | 311 | ||
@@ -332,8 +342,18 @@ struct TransportBackchannelRequestPayload | |||
332 | struct GNUNET_CRYPTO_EddsaSignature sender_sig; | 342 | struct GNUNET_CRYPTO_EddsaSignature sender_sig; |
333 | 343 | ||
334 | /** | 344 | /** |
335 | * How long is this signature over the ephemeral key | 345 | * How long is this signature over the ephemeral key valid? |
336 | * valid? | 346 | * |
347 | * Note that the receiver MUST IGNORE the absolute time, and only interpret | ||
348 | * the value as a mononic time and reject "older" values than the last one | ||
349 | * observed. This is necessary as we do not want to require synchronized | ||
350 | * clocks and may not have a bidirectional communication channel. | ||
351 | * | ||
352 | * Even with this, there is no real guarantee against replay achieved here, | ||
353 | * unless the latest timestamp is persisted. While persistence should be | ||
354 | * provided via PEERSTORE, we do not consider the mechanism reliable! Thus, | ||
355 | * communicators must protect against replay attacks when using backchannel | ||
356 | * communication! | ||
337 | */ | 357 | */ |
338 | struct GNUNET_TIME_AbsoluteNBO ephemeral_validity; | 358 | struct GNUNET_TIME_AbsoluteNBO ephemeral_validity; |
339 | 359 | ||
@@ -342,9 +362,10 @@ struct TransportBackchannelRequestPayload | |||
342 | * detect replayed messages. Note that the receiver should remember | 362 | * detect replayed messages. Note that the receiver should remember |
343 | * a list of the recently seen timestamps and only reject messages | 363 | * a list of the recently seen timestamps and only reject messages |
344 | * if the timestamp is in the list, or the list is "full" and the | 364 | * if the timestamp is in the list, or the list is "full" and the |
345 | * timestamp is smaller than the lowest in the list. This list of | 365 | * timestamp is smaller than the lowest in the list. |
346 | * timestamps per peer should be persisted to guard against replays | 366 | * |
347 | * after restarts. | 367 | * Like the @e ephemeral_validity, the list of timestamps per peer should be |
368 | * persisted to guard against replays after restarts. | ||
348 | */ | 369 | */ |
349 | struct GNUNET_TIME_AbsoluteNBO monotonic_time; | 370 | struct GNUNET_TIME_AbsoluteNBO monotonic_time; |
350 | 371 | ||
@@ -505,7 +526,21 @@ struct TransportFragmentAckMessage | |||
505 | 526 | ||
506 | 527 | ||
507 | /** | 528 | /** |
508 | * Content signed by each peer during DV learning. | 529 | * Content signed by the initator during DV learning. |
530 | * | ||
531 | * The signature is required to prevent DDoS attacks. A peer sending out this | ||
532 | * message is potentially generating a lot of traffic that will go back to the | ||
533 | * initator, as peers receiving this message will try to let the initiator | ||
534 | * know that they got the message. | ||
535 | * | ||
536 | * Without this signature, an attacker could abuse this mechanism for traffic | ||
537 | * amplification, sending a lot of traffic to a peer by putting out this type | ||
538 | * of message with the victim's peer identity. | ||
539 | * | ||
540 | * Even with just a signature, traffic amplification would be possible via | ||
541 | * replay attacks. The @e monotonic_time limits such replay attacks, as every | ||
542 | * potential amplificator will check the @e monotonic_time and only respond | ||
543 | * (at most) once per message. | ||
509 | */ | 544 | */ |
510 | struct DvInitPS | 545 | struct DvInitPS |
511 | { | 546 | { |
@@ -515,6 +550,20 @@ struct DvInitPS | |||
515 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | 550 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; |
516 | 551 | ||
517 | /** | 552 | /** |
553 | * Time at the initiator when generating the signature. | ||
554 | * | ||
555 | * Note that the receiver MUST IGNORE the absolute time, and only interpret | ||
556 | * the value as a mononic time and reject "older" values than the last one | ||
557 | * observed. This is necessary as we do not want to require synchronized | ||
558 | * clocks and may not have a bidirectional communication channel. | ||
559 | * | ||
560 | * Even with this, there is no real guarantee against replay achieved here, | ||
561 | * unless the latest timestamp is persisted. Persistence should be | ||
562 | * provided via PEERSTORE if possible. | ||
563 | */ | ||
564 | struct GNUNET_TIME_AbsoluteNBO monotonic_time; | ||
565 | |||
566 | /** | ||
518 | * Challenge value used by the initiator to re-identify the path. | 567 | * Challenge value used by the initiator to re-identify the path. |
519 | */ | 568 | */ |
520 | struct GNUNET_ShortHashCode challenge; | 569 | struct GNUNET_ShortHashCode challenge; |
@@ -524,6 +573,19 @@ struct DvInitPS | |||
524 | 573 | ||
525 | /** | 574 | /** |
526 | * Content signed by each peer during DV learning. | 575 | * Content signed by each peer during DV learning. |
576 | * | ||
577 | * This assues the initiator of the DV learning operation that the hop from @e | ||
578 | * pred via the signing peer to @e succ actually exists. This makes it | ||
579 | * impossible for an adversary to supply the network with bogus routes. | ||
580 | * | ||
581 | * The @e challenge is included to provide replay protection for the | ||
582 | * initiator. This way, the initiator knows that the hop existed after the | ||
583 | * original @e challenge was first transmitted, providing a freshness metric. | ||
584 | * | ||
585 | * Peers other than the initiator that passively learn paths by observing | ||
586 | * these messages do NOT benefit from this. Here, an adversary may indeed | ||
587 | * replay old messages. Thus, passively learned paths should always be | ||
588 | * immediately marked as "potentially stale". | ||
527 | */ | 589 | */ |
528 | struct DvHopPS | 590 | struct DvHopPS |
529 | { | 591 | { |
@@ -841,8 +903,8 @@ struct LearnLaunchEntry | |||
841 | struct GNUNET_ShortHashCode challenge; | 903 | struct GNUNET_ShortHashCode challenge; |
842 | 904 | ||
843 | /** | 905 | /** |
844 | * When did we transmit the DV learn message (used to | 906 | * When did we transmit the DV learn message (used to calculate RTT) and |
845 | * calculate RTT). | 907 | * determine freshness of paths learned via this operation. |
846 | */ | 908 | */ |
847 | struct GNUNET_TIME_Absolute launch_time; | 909 | struct GNUNET_TIME_Absolute launch_time; |
848 | 910 | ||
@@ -850,11 +912,11 @@ struct LearnLaunchEntry | |||
850 | 912 | ||
851 | 913 | ||
852 | /** | 914 | /** |
853 | * Entry in our cache of ephemeral keys we currently use. | 915 | * Entry in our cache of ephemeral keys we currently use. This way, we only |
854 | * This way, we only sign an ephemeral once per @e target, | 916 | * sign an ephemeral once per @e target, and then can re-use it over multiple |
855 | * and then can re-use it over multiple | 917 | * #GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION messages (as |
856 | * #GNUNET_MESSAGE_TYPE_TRANSPORT_BACKCHANNEL_ENCAPSULATION | 918 | * signing is expensive and in some cases we may use backchannel messages a |
857 | * messages (as signing is expensive). | 919 | * lot). |
858 | */ | 920 | */ |
859 | struct EphemeralCacheEntry | 921 | struct EphemeralCacheEntry |
860 | { | 922 | { |
@@ -962,6 +1024,14 @@ struct DistanceVectorHop | |||
962 | struct GNUNET_TIME_Absolute timeout; | 1024 | struct GNUNET_TIME_Absolute timeout; |
963 | 1025 | ||
964 | /** | 1026 | /** |
1027 | * After what time do we know for sure that the path must have existed? | ||
1028 | * Set to ZERO if the path is learned by snooping on DV learn messages | ||
1029 | * initiated by other peers, and to the time at which we generated the | ||
1030 | * challenge for DV learn operations this peer initiated. | ||
1031 | */ | ||
1032 | struct GNUNET_TIME_Absolute freshness; | ||
1033 | |||
1034 | /** | ||
965 | * How many hops in total to the `target` (excluding @e next_hop and `target` itself), | 1035 | * How many hops in total to the `target` (excluding @e next_hop and `target` itself), |
966 | * thus 0 still means a distance of 2 hops (to @e next_hop and then to `target`)? | 1036 | * thus 0 still means a distance of 2 hops (to @e next_hop and then to `target`)? |
967 | */ | 1037 | */ |
@@ -3119,8 +3189,8 @@ lookup_ephemeral (const struct GNUNET_PeerIdentity *pid, | |||
3119 | &ec.purpose, | 3189 | &ec.purpose, |
3120 | &ece->sender_sig)); | 3190 | &ece->sender_sig)); |
3121 | ece->hn = GNUNET_CONTAINER_heap_insert (ephemeral_heap, | 3191 | ece->hn = GNUNET_CONTAINER_heap_insert (ephemeral_heap, |
3122 | ece, | 3192 | ece, |
3123 | ece->ephemeral_validity.abs_value_us); | 3193 | ece->ephemeral_validity.abs_value_us); |
3124 | GNUNET_assert (GNUNET_OK == | 3194 | GNUNET_assert (GNUNET_OK == |
3125 | GNUNET_CONTAINER_multipeermap_put (ephemeral_map, | 3195 | GNUNET_CONTAINER_multipeermap_put (ephemeral_map, |
3126 | &ece->target, | 3196 | &ece->target, |
@@ -3128,8 +3198,8 @@ lookup_ephemeral (const struct GNUNET_PeerIdentity *pid, | |||
3128 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); | 3198 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); |
3129 | if (NULL == ephemeral_task) | 3199 | if (NULL == ephemeral_task) |
3130 | ephemeral_task = GNUNET_SCHEDULER_add_at (ece->ephemeral_validity, | 3200 | ephemeral_task = GNUNET_SCHEDULER_add_at (ece->ephemeral_validity, |
3131 | &expire_ephemerals, | 3201 | &expire_ephemerals, |
3132 | NULL); | 3202 | NULL); |
3133 | } | 3203 | } |
3134 | *private_key = ece->private_key; | 3204 | *private_key = ece->private_key; |
3135 | *ephemeral_key = ece->ephemeral_key; | 3205 | *ephemeral_key = ece->ephemeral_key; |
@@ -3164,6 +3234,169 @@ route_message (const struct GNUNET_PeerIdentity *target, | |||
3164 | 3234 | ||
3165 | 3235 | ||
3166 | /** | 3236 | /** |
3237 | * Structure of the key material used to encrypt backchannel messages. | ||
3238 | */ | ||
3239 | struct BackchannelKeyState | ||
3240 | { | ||
3241 | // FIXME: actual data types in this struct are likely still totally wrong | ||
3242 | /** | ||
3243 | * | ||
3244 | */ | ||
3245 | char hdr_key[128]; | ||
3246 | |||
3247 | /** | ||
3248 | * | ||
3249 | */ | ||
3250 | char body_key[128]; | ||
3251 | |||
3252 | /** | ||
3253 | * | ||
3254 | */ | ||
3255 | char hmac_key[128]; | ||
3256 | }; | ||
3257 | |||
3258 | |||
3259 | static void | ||
3260 | setup_key_state_from_km (const struct GNUNET_HashCode *km, | ||
3261 | const struct GNUNET_HashCode *iv, | ||
3262 | struct BackchannelKeyState *key) | ||
3263 | { | ||
3264 | /* must match #dh_key_derive_eph_pub */ | ||
3265 | GNUNET_assert (GNUNET_YES == | ||
3266 | GNUNET_CRYPTO_kdf (key, | ||
3267 | sizeof (*key), | ||
3268 | "transport-backchannel-key", | ||
3269 | strlen ("transport-backchannel-key"), | ||
3270 | &km, | ||
3271 | sizeof (km), | ||
3272 | iv, | ||
3273 | sizeof (*iv))); | ||
3274 | } | ||
3275 | |||
3276 | |||
3277 | /** | ||
3278 | * Derive backchannel encryption key material from @a priv_ephemeral | ||
3279 | * and @a target and @a iv. | ||
3280 | * | ||
3281 | * @param priv_ephemeral ephemeral private key to use | ||
3282 | * @param target the target peer to encrypt to | ||
3283 | * @param iv unique IV to use | ||
3284 | * @param key[out] set to the key material | ||
3285 | */ | ||
3286 | static void | ||
3287 | dh_key_derive_eph_pid (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ephemeral, | ||
3288 | const struct GNUNET_PeerIdentity *target, | ||
3289 | const struct GNUNET_ShortHashCode *iv, | ||
3290 | struct BackchannelKeyState *key) | ||
3291 | { | ||
3292 | struct GNUNET_HashCode km; | ||
3293 | |||
3294 | GNUNET_assert (GNUNET_YES == | ||
3295 | GNUNET_CRYPTO_ecdsa_ecdh (priv_ephemeral, | ||
3296 | &target->public_key, | ||
3297 | &km)); | ||
3298 | bc_setup_key_state_from_km (&km, | ||
3299 | iv, | ||
3300 | key); | ||
3301 | } | ||
3302 | |||
3303 | |||
3304 | /** | ||
3305 | * Derive backchannel encryption key material from #GST_my_private_key | ||
3306 | * and @a pub_ephemeral and @a iv. | ||
3307 | * | ||
3308 | * @param priv_ephemeral ephemeral private key to use | ||
3309 | * @param target the target peer to encrypt to | ||
3310 | * @param iv unique IV to use | ||
3311 | * @param key[out] set to the key material | ||
3312 | */ | ||
3313 | static void | ||
3314 | dh_key_derive_eph_pub (const struct GNUNET_CRYPTO_EcdhePublicKey *pub_ephemeral, | ||
3315 | const struct GNUNET_ShortHashCode *iv, | ||
3316 | struct BackchannelKeyState *key) | ||
3317 | { | ||
3318 | struct GNUNET_HashCode km; | ||
3319 | |||
3320 | GNUNET_assert (GNUNET_YES == | ||
3321 | GNUNET_CRYPTO_ecdsa_ecdh (GST_my_private_key, | ||
3322 | pub_ephemeral, | ||
3323 | &km)); | ||
3324 | bc_setup_key_state_from_km (&km, | ||
3325 | iv, | ||
3326 | key); | ||
3327 | } | ||
3328 | |||
3329 | |||
3330 | /** | ||
3331 | * Do HMAC calculation for backchannel messages over @a data using key | ||
3332 | * material from @a key. | ||
3333 | * | ||
3334 | * @param key key material (from DH) | ||
3335 | * @param hmac[out] set to the HMAC | ||
3336 | * @param data data to perform HMAC calculation over | ||
3337 | * @param data_size number of bytes in @a data | ||
3338 | */ | ||
3339 | static void | ||
3340 | bc_hmac (const struct BackchannelKeyState *key, | ||
3341 | struct GNUNET_HashCode *hmac, | ||
3342 | const void *data, | ||
3343 | size_t data_size) | ||
3344 | { | ||
3345 | // FIXME! | ||
3346 | } | ||
3347 | |||
3348 | |||
3349 | /** | ||
3350 | * Perform backchannel encryption using symmetric secret in @a key | ||
3351 | * to encrypt data from @a in to @a dst. | ||
3352 | * | ||
3353 | * @param key[in,out] key material to use | ||
3354 | * @param dst where to write the result | ||
3355 | * @param in input data to encrypt (plaintext) | ||
3356 | * @param in_size number of bytes of input in @a in and available at @a dst | ||
3357 | */ | ||
3358 | static void | ||
3359 | bc_encrypt (struct BackchannelKeyState *key, | ||
3360 | void *dst, | ||
3361 | const void *in, | ||
3362 | size_t in_size) | ||
3363 | { | ||
3364 | // FIXME! | ||
3365 | } | ||
3366 | |||
3367 | |||
3368 | /** | ||
3369 | * Perform backchannel encryption using symmetric secret in @a key | ||
3370 | * to encrypt data from @a in to @a dst. | ||
3371 | * | ||
3372 | * @param key[in,out] key material to use | ||
3373 | * @param ciph cipher text to decrypt | ||
3374 | * @param out[out] output data to generate (plaintext) | ||
3375 | * @param out_size number of bytes of input in @a ciph and available in @a out | ||
3376 | */ | ||
3377 | static void | ||
3378 | bc_decrypt (struct BackchannelKeyState *key, | ||
3379 | const void *ciph, | ||
3380 | void *out, | ||
3381 | size_t out_size) | ||
3382 | { | ||
3383 | // FIXME! | ||
3384 | } | ||
3385 | |||
3386 | |||
3387 | /** | ||
3388 | * Clean up key material in @a key. | ||
3389 | * | ||
3390 | * @param key key material to clean up (memory must not be free'd!) | ||
3391 | */ | ||
3392 | static void | ||
3393 | bc_key_clean (struct BackchannelKeyState *key) | ||
3394 | { | ||
3395 | // FIXME! | ||
3396 | } | ||
3397 | |||
3398 | |||
3399 | /** | ||
3167 | * Communicator requests backchannel transmission. Process the request. | 3400 | * Communicator requests backchannel transmission. Process the request. |
3168 | * | 3401 | * |
3169 | * @param cls the client | 3402 | * @param cls the client |
@@ -3178,6 +3411,7 @@ handle_communicator_backchannel (void *cls, | |||
3178 | struct GNUNET_TIME_Absolute ephemeral_validity; | 3411 | struct GNUNET_TIME_Absolute ephemeral_validity; |
3179 | struct TransportBackchannelEncapsulationMessage *enc; | 3412 | struct TransportBackchannelEncapsulationMessage *enc; |
3180 | struct TransportBackchannelRequestPayload ppay; | 3413 | struct TransportBackchannelRequestPayload ppay; |
3414 | struct BackchannelKeyState key; | ||
3181 | char *mpos; | 3415 | char *mpos; |
3182 | uint16_t msize; | 3416 | uint16_t msize; |
3183 | 3417 | ||
@@ -3192,28 +3426,29 @@ handle_communicator_backchannel (void *cls, | |||
3192 | &enc->ephemeral_key, | 3426 | &enc->ephemeral_key, |
3193 | &ppay.sender_sig, | 3427 | &ppay.sender_sig, |
3194 | &ephemeral_validity); | 3428 | &ephemeral_validity); |
3195 | // FIXME: setup 'iv' | 3429 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, |
3196 | #if FIXME | 3430 | &enc->iv, |
3431 | sizeof (enc->iv)); | ||
3197 | dh_key_derive (&private_key, | 3432 | dh_key_derive (&private_key, |
3198 | &cb->pid, | 3433 | &cb->pid, |
3199 | &enc->iv, | 3434 | &enc->iv, |
3200 | &key); | 3435 | &key); |
3201 | #endif | ||
3202 | ppay.ephemeral_validity = GNUNET_TIME_absolute_hton (ephemeral_validity); | 3436 | ppay.ephemeral_validity = GNUNET_TIME_absolute_hton (ephemeral_validity); |
3203 | ppay.monotonic_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (GST_cfg)); | 3437 | ppay.monotonic_time = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (GST_cfg)); |
3204 | mpos = (char *) &enc[1]; | 3438 | mpos = (char *) &enc[1]; |
3205 | #if FIXME | 3439 | bc_encrypt (&key, |
3206 | encrypt (key, | 3440 | &ppay, |
3207 | &ppay, | 3441 | mpos, |
3208 | &mpos, | 3442 | sizeof (ppay)); |
3209 | sizeof (ppay)); | 3443 | bc_encrypt (&key, |
3210 | encrypt (key, | 3444 | &cb[1], |
3211 | &cb[1], | 3445 | &mpos[sizeof (ppay)], |
3212 | &mpos, | 3446 | ntohs (cb->header.size) - sizeof (*cb)); |
3213 | ntohs (cb->header.size) - sizeof (*cb)); | 3447 | bc_hmac (&key, |
3214 | hmac (key, | 3448 | &enc->hmac, |
3215 | &enc->hmac); | 3449 | mpos, |
3216 | #endif | 3450 | sizeof (ppay) + ntohs (cb->header.size) - sizeof (*cb)); |
3451 | bc_key_clean (&key); | ||
3217 | route_message (&cb->pid, | 3452 | route_message (&cb->pid, |
3218 | &enc->header); | 3453 | &enc->header); |
3219 | GNUNET_SERVICE_client_continue (tc->client); | 3454 | GNUNET_SERVICE_client_continue (tc->client); |
@@ -4021,7 +4256,9 @@ check_backchannel_encapsulation (void *cls, | |||
4021 | uint16_t size = ntohs (be->header.size); | 4256 | uint16_t size = ntohs (be->header.size); |
4022 | 4257 | ||
4023 | (void) cls; | 4258 | (void) cls; |
4024 | if (size - sizeof (*be) < sizeof (struct GNUNET_MessageHeader)) | 4259 | if (size - sizeof (*be) < |
4260 | sizeof (struct TransportBackchannelRequestPayload) + | ||
4261 | sizeof (struct GNUNET_MessageHeader) ) | ||
4025 | { | 4262 | { |
4026 | GNUNET_break_op (0); | 4263 | GNUNET_break_op (0); |
4027 | return GNUNET_SYSERR; | 4264 | return GNUNET_SYSERR; |
@@ -4041,21 +4278,64 @@ handle_backchannel_encapsulation (void *cls, | |||
4041 | const struct TransportBackchannelEncapsulationMessage *be) | 4278 | const struct TransportBackchannelEncapsulationMessage *be) |
4042 | { | 4279 | { |
4043 | struct CommunicatorMessageContext *cmc = cls; | 4280 | struct CommunicatorMessageContext *cmc = cls; |
4281 | struct BackchannelKeyState key; | ||
4282 | struct GNUNET_HashCode hmac; | ||
4283 | const char *hdr; | ||
4284 | size_t hrd_len; | ||
4044 | 4285 | ||
4045 | if (0 != GNUNET_memcmp (&be->target, | 4286 | if (0 != GNUNET_memcmp (&be->target, |
4046 | &GST_my_identity)) | 4287 | &GST_my_identity)) |
4047 | { | 4288 | { |
4048 | /* not for me, try to route to target */ | 4289 | /* not for me, try to route to target */ |
4290 | /* FIXME: someone needs to update be->distance! */ | ||
4291 | /* FIXME: BE routing can be special, should we put all of this | ||
4292 | on 'route_message'? Maybe at least pass some more arguments? */ | ||
4049 | route_message (&be->target, | 4293 | route_message (&be->target, |
4050 | GNUNET_copy_message (&be->header)); | 4294 | GNUNET_copy_message (&be->header)); |
4051 | finish_cmc_handling (cmc); | 4295 | finish_cmc_handling (cmc); |
4052 | return; | 4296 | return; |
4053 | } | 4297 | } |
4054 | // FIXME: compute shared secret | 4298 | dh_key_derive_eph_pub (&be->ephemeral_key, |
4055 | // FIXME: check HMAC | 4299 | &be->iv, |
4056 | // FIXME: decrypt payload | 4300 | &key); |
4057 | // FIXME: forward to specified communicator! | 4301 | hdr = (const char *) &be[1]; |
4058 | // (using GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING) | 4302 | hdr_len = ntohs (be->header.size) - sizeof (*be); |
4303 | bc_hmac (&key, | ||
4304 | &hmac, | ||
4305 | hdr, | ||
4306 | hdr_len); | ||
4307 | if (0 != | ||
4308 | GNUNET_memcmp (&hmac, | ||
4309 | &be->hmac)) | ||
4310 | { | ||
4311 | /* HMAC missmatch, disard! */ | ||
4312 | GNUNET_break_op (0); | ||
4313 | finish_cmc_handling (cmc); | ||
4314 | return; | ||
4315 | } | ||
4316 | /* begin actual decryption */ | ||
4317 | { | ||
4318 | struct TransportBackchannelRequestPayload ppay; | ||
4319 | char body[hdr_len - sizeof (ppay)]; | ||
4320 | |||
4321 | GNUNET_assert (hdr_len >= sizeof (ppay) + sizeof (struct GNUNET_MessageHeader)); | ||
4322 | bc_decrypt (&key, | ||
4323 | &ppay, | ||
4324 | hdr, | ||
4325 | sizeof (ppay)); | ||
4326 | bc_decrypt (&key, | ||
4327 | &body, | ||
4328 | &hdr[sizeof (ppay)], | ||
4329 | hdr_len - sizeof (ppay)); | ||
4330 | bc_key_clean (&key); | ||
4331 | // FIXME: verify signatures in ppay! | ||
4332 | // => check if ephemeral key is known & valid, if not | ||
4333 | // => verify sig, cache ephemeral key | ||
4334 | // => update monotonic_time of sender for replay detection | ||
4335 | |||
4336 | // FIXME: forward to specified communicator! | ||
4337 | // (using GNUNET_MESSAGE_TYPE_TRANSPORT_COMMUNICATOR_BACKCHANNEL_INCOMING) | ||
4338 | } | ||
4059 | finish_cmc_handling (cmc); | 4339 | finish_cmc_handling (cmc); |
4060 | } | 4340 | } |
4061 | 4341 | ||