aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-04-16 16:42:54 +0200
committerChristian Grothoff <christian@grothoff.org>2019-04-16 16:43:05 +0200
commitf1422cd5bf05ff27cde0c60c1fb16b6d8d6c0452 (patch)
tree037194cb954888e736123091cef82519333acbe3
parent9b84e344cac92456d0d6574b3bf662c2fba4e559 (diff)
downloadgnunet-f1422cd5bf05ff27cde0c60c1fb16b6d8d6c0452.tar.gz
gnunet-f1422cd5bf05ff27cde0c60c1fb16b6d8d6c0452.zip
explain motivations behind signatures better
-rw-r--r--src/transport/gnunet-service-tng.c378
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 */
510struct DvInitPS 545struct 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 */
528struct DvHopPS 590struct 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 */
859struct EphemeralCacheEntry 921struct 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 */
3239struct 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
3259static void
3260setup_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 */
3286static void
3287dh_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 */
3313static void
3314dh_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 */
3339static void
3340bc_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 */
3358static void
3359bc_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 */
3377static void
3378bc_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 */
3392static void
3393bc_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