diff options
author | Bart Polot <bart@net.in.tum.de> | 2015-10-02 03:37:52 +0000 |
---|---|---|
committer | Bart Polot <bart@net.in.tum.de> | 2015-10-02 03:37:52 +0000 |
commit | a101e9b37474e82102637b09de03c5d602201983 (patch) | |
tree | 46e33de632aafc73d7c3b5fc30f64ecf55e5e2b6 /src/cadet | |
parent | cef0009520797f29eefb74e68a0020e4cdb3d5a8 (diff) | |
download | gnunet-a101e9b37474e82102637b09de03c5d602201983.tar.gz gnunet-a101e9b37474e82102637b09de03c5d602201983.zip |
Fix try_old_keys, in order to use it for data with the same Header key but out-of-order message number
Diffstat (limited to 'src/cadet')
-rw-r--r-- | src/cadet/cadet_protocol.h | 4 | ||||
-rw-r--r-- | src/cadet/gnunet-service-cadet_tunnel.c | 92 |
2 files changed, 70 insertions, 26 deletions
diff --git a/src/cadet/cadet_protocol.h b/src/cadet/cadet_protocol.h index 0e0030986..cba574c08 100644 --- a/src/cadet/cadet_protocol.h +++ b/src/cadet/cadet_protocol.h | |||
@@ -319,6 +319,8 @@ struct GNUNET_CADET_AX | |||
319 | */ | 319 | */ |
320 | struct GNUNET_CADET_Hash hmac; | 320 | struct GNUNET_CADET_Hash hmac; |
321 | 321 | ||
322 | /**************** AX_HEADER start ****************/ | ||
323 | |||
322 | /** | 324 | /** |
323 | * Number of messages sent with the current ratchet key. | 325 | * Number of messages sent with the current ratchet key. |
324 | */ | 326 | */ |
@@ -334,6 +336,8 @@ struct GNUNET_CADET_AX | |||
334 | */ | 336 | */ |
335 | struct GNUNET_CRYPTO_EcdhePublicKey DHRs; | 337 | struct GNUNET_CRYPTO_EcdhePublicKey DHRs; |
336 | 338 | ||
339 | /**************** AX_HEADER end ****************/ | ||
340 | |||
337 | /** | 341 | /** |
338 | * Encrypted content follows. | 342 | * Encrypted content follows. |
339 | */ | 343 | */ |
diff --git a/src/cadet/gnunet-service-cadet_tunnel.c b/src/cadet/gnunet-service-cadet_tunnel.c index be99f4b47..67f770246 100644 --- a/src/cadet/gnunet-service-cadet_tunnel.c +++ b/src/cadet/gnunet-service-cadet_tunnel.c | |||
@@ -188,6 +188,11 @@ struct CadetTunnelSkippedKey | |||
188 | * Message key. | 188 | * Message key. |
189 | */ | 189 | */ |
190 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; | 190 | struct GNUNET_CRYPTO_SymmetricSessionKey MK; |
191 | |||
192 | /** | ||
193 | * Key number for a given HK. | ||
194 | */ | ||
195 | unsigned int Kn; | ||
191 | }; | 196 | }; |
192 | 197 | ||
193 | 198 | ||
@@ -1325,38 +1330,60 @@ t_decrypt_and_validate (struct CadetTunnel *t, | |||
1325 | * @return Size of the decrypted data, -1 if an error was encountered. | 1330 | * @return Size of the decrypted data, -1 if an error was encountered. |
1326 | */ | 1331 | */ |
1327 | static int | 1332 | static int |
1328 | try_old_ax_keys (struct CadetTunnel *t, struct GNUNET_CADET_AX *dst, | 1333 | try_old_ax_keys (struct CadetTunnel *t, void *dst, |
1329 | const struct GNUNET_CADET_AX *src, size_t size) | 1334 | const struct GNUNET_CADET_AX *src, size_t size) |
1330 | { | 1335 | { |
1331 | struct CadetTunnelSkippedKey *key; | 1336 | struct CadetTunnelSkippedKey *key; |
1332 | struct GNUNET_CADET_Hash hmac; | 1337 | struct GNUNET_CADET_Hash *hmac; |
1333 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | 1338 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; |
1339 | struct GNUNET_CADET_AX plaintext_header; | ||
1340 | size_t esize; | ||
1334 | size_t res; | 1341 | size_t res; |
1335 | size_t len; | 1342 | size_t len; |
1336 | 1343 | ||
1337 | 1344 | hmac = &plaintext_header.hmac; | |
1345 | esize = size - sizeof (struct GNUNET_CADET_AX); | ||
1338 | for (key = t->ax->skipped_head; NULL != key; key = key->next) | 1346 | for (key = t->ax->skipped_head; NULL != key; key = key->next) |
1339 | { | 1347 | { |
1340 | t_hmac (&src->Ns, AX_HEADER_SIZE, 0, &key->HK, &hmac); | 1348 | t_hmac (&src->Ns, AX_HEADER_SIZE + esize, 0, &key->HK, hmac); |
1341 | if (0 != memcmp (&hmac, &src->hmac, sizeof (hmac))) | 1349 | if (0 == memcmp (hmac, &src->hmac, sizeof (*hmac))) |
1350 | { | ||
1342 | break; | 1351 | break; |
1352 | } | ||
1343 | } | 1353 | } |
1344 | if (NULL == key) | 1354 | if (NULL == key) |
1345 | return -1; | 1355 | return -1; |
1346 | 1356 | ||
1347 | #if DUMP_KEYS_TO_STDERR | 1357 | #if DUMP_KEYS_TO_STDERR |
1348 | LOG (GNUNET_ERROR_TYPE_INFO, " AX_DEC with skipped key %s\n", | 1358 | LOG (GNUNET_ERROR_TYPE_INFO, " AX_DEC_H with skipped key %s\n", |
1349 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->MK)); | 1359 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->HK)); |
1360 | LOG (GNUNET_ERROR_TYPE_INFO, " AX_DEC with skipped key %u: %s\n", | ||
1361 | key->Kn, GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->MK)); | ||
1350 | #endif | 1362 | #endif |
1351 | 1363 | ||
1364 | /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */ | ||
1352 | GNUNET_assert (size > sizeof (struct GNUNET_CADET_AX)); | 1365 | GNUNET_assert (size > sizeof (struct GNUNET_CADET_AX)); |
1353 | len = size - sizeof (struct GNUNET_CADET_AX); | 1366 | len = size - sizeof (struct GNUNET_CADET_AX); |
1367 | GNUNET_assert (len >= sizeof (struct GNUNET_MessageHeader)); | ||
1368 | |||
1369 | /* Decrypt header */ | ||
1370 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, &key->HK, NULL, 0, NULL); | ||
1371 | res = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns, AX_HEADER_SIZE, | ||
1372 | &key->HK, &iv, &plaintext_header.Ns); | ||
1373 | GNUNET_assert (AX_HEADER_SIZE == res); | ||
1374 | LOG (GNUNET_ERROR_TYPE_INFO, " Message %u, previous: %u\n", | ||
1375 | ntohl (plaintext_header.Ns), ntohl (plaintext_header.PNs)); | ||
1376 | |||
1377 | // FIXME find correct key | ||
1378 | |||
1379 | /* Decrypt payload */ | ||
1354 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, &key->MK, NULL, 0, NULL); | 1380 | GNUNET_CRYPTO_symmetric_derive_iv (&iv, &key->MK, NULL, 0, NULL); |
1355 | res = GNUNET_CRYPTO_symmetric_decrypt (&src[1], len, &key->MK, &iv, &dst[1]); | 1381 | res = GNUNET_CRYPTO_symmetric_decrypt (&src[1], len, &key->MK, &iv, dst); |
1356 | 1382 | ||
1383 | /* Remove key */ | ||
1357 | GNUNET_CONTAINER_DLL_remove (t->ax->skipped_head, t->ax->skipped_tail, key); | 1384 | GNUNET_CONTAINER_DLL_remove (t->ax->skipped_head, t->ax->skipped_tail, key); |
1358 | t->ax->skipped--; | 1385 | t->ax->skipped--; |
1359 | GNUNET_free (key); | 1386 | GNUNET_free (key); /* GNUNET_free overwrites memory with 0xbaadf00d */ |
1360 | 1387 | ||
1361 | return res; | 1388 | return res; |
1362 | } | 1389 | } |
@@ -1376,11 +1403,12 @@ store_skipped_key (struct CadetTunnel *t, | |||
1376 | 1403 | ||
1377 | key = GNUNET_new (struct CadetTunnelSkippedKey); | 1404 | key = GNUNET_new (struct CadetTunnelSkippedKey); |
1378 | key->timestamp = GNUNET_TIME_absolute_get (); | 1405 | key->timestamp = GNUNET_TIME_absolute_get (); |
1406 | key->Kn = t->ax->Nr; | ||
1379 | key->HK = t->ax->HKr; | 1407 | key->HK = t->ax->HKr; |
1380 | t_hmac_derive_key (&t->ax->CKr, &key->MK, "0", 1); | 1408 | t_hmac_derive_key (&t->ax->CKr, &key->MK, "0", 1); |
1381 | #if DUMP_KEYS_TO_STDERR | 1409 | #if DUMP_KEYS_TO_STDERR |
1382 | LOG (GNUNET_ERROR_TYPE_INFO, " storing MK for Nr %u: %s\n", | 1410 | LOG (GNUNET_ERROR_TYPE_INFO, " storing MK for Nr %u: %s\n", |
1383 | t->ax->Nr, GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->MK)); | 1411 | key->Kn, GNUNET_i2s ((struct GNUNET_PeerIdentity *) &key->MK)); |
1384 | LOG (GNUNET_ERROR_TYPE_INFO, " for CKr: %s\n", | 1412 | LOG (GNUNET_ERROR_TYPE_INFO, " for CKr: %s\n", |
1385 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &t->ax->CKr)); | 1413 | GNUNET_i2s ((struct GNUNET_PeerIdentity *) &t->ax->CKr)); |
1386 | #endif | 1414 | #endif |
@@ -1414,23 +1442,32 @@ delete_skipped_key (struct CadetTunnel *t, struct CadetTunnelSkippedKey *key) | |||
1414 | * @param t Tunnel where to stage the keys. | 1442 | * @param t Tunnel where to stage the keys. |
1415 | * @param HKr Header key. | 1443 | * @param HKr Header key. |
1416 | * @param Np Received meesage number. | 1444 | * @param Np Received meesage number. |
1445 | * | ||
1446 | * @return GNUNET_OK if keys were stored. | ||
1447 | * GNUNET_SYSERR if an error ocurred (Np not expected). | ||
1417 | */ | 1448 | */ |
1418 | static void | 1449 | static int |
1419 | store_ax_keys (struct CadetTunnel *t, | 1450 | store_ax_keys (struct CadetTunnel *t, |
1420 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr, | 1451 | const struct GNUNET_CRYPTO_SymmetricSessionKey *HKr, |
1421 | uint32_t Np) | 1452 | uint32_t Np) |
1422 | { | 1453 | { |
1423 | int gap; | 1454 | int gap; |
1424 | 1455 | ||
1456 | |||
1425 | gap = Np - t->ax->Nr; | 1457 | gap = Np - t->ax->Nr; |
1426 | if (MAX_KEY_GAP < gap || 0 > gap) | 1458 | if (MAX_KEY_GAP < gap) |
1427 | { | 1459 | { |
1428 | /* Avoid DoS (forcing peer to do 2*33 chain HMAC operations) */ | 1460 | /* Avoid DoS (forcing peer to do 2*33 chain HMAC operations) */ |
1429 | /* TODO: start new key exchange on return */ | 1461 | /* TODO: start new key exchange on return */ |
1430 | GNUNET_break_op (0); | 1462 | GNUNET_break_op (0); |
1431 | LOG (GNUNET_ERROR_TYPE_WARNING, "Got message %u, expected %u+\n", | 1463 | LOG (GNUNET_ERROR_TYPE_WARNING, "Got message %u, expected %u+\n", |
1432 | Np, t->ax->Nr); | 1464 | Np, t->ax->Nr); |
1433 | return; | 1465 | return GNUNET_SYSERR; |
1466 | } | ||
1467 | if (0 > gap) | ||
1468 | { | ||
1469 | /* Delayed message: don't store keys, flag to try old keys. */ | ||
1470 | return GNUNET_SYSERR; | ||
1434 | } | 1471 | } |
1435 | 1472 | ||
1436 | while (t->ax->Nr < Np) | 1473 | while (t->ax->Nr < Np) |
@@ -1438,6 +1475,8 @@ store_ax_keys (struct CadetTunnel *t, | |||
1438 | 1475 | ||
1439 | while (t->ax->skipped > MAX_SKIPPED_KEYS) | 1476 | while (t->ax->skipped > MAX_SKIPPED_KEYS) |
1440 | delete_skipped_key (t, t->ax->skipped_tail); | 1477 | delete_skipped_key (t, t->ax->skipped_tail); |
1478 | |||
1479 | return GNUNET_OK; | ||
1441 | } | 1480 | } |
1442 | 1481 | ||
1443 | 1482 | ||
@@ -1459,14 +1498,13 @@ t_ax_decrypt_and_validate (struct CadetTunnel *t, void *dst, | |||
1459 | struct CadetTunnelAxolotl *ax; | 1498 | struct CadetTunnelAxolotl *ax; |
1460 | struct GNUNET_CADET_Hash msg_hmac; | 1499 | struct GNUNET_CADET_Hash msg_hmac; |
1461 | struct GNUNET_HashCode hmac; | 1500 | struct GNUNET_HashCode hmac; |
1462 | struct GNUNET_CADET_AX *dstmsg; | 1501 | struct GNUNET_CADET_AX plaintext_header; |
1463 | uint32_t Np; | 1502 | uint32_t Np; |
1464 | uint32_t PNp; | 1503 | uint32_t PNp; |
1465 | size_t esize; | 1504 | size_t esize; |
1466 | size_t osize; | 1505 | size_t osize; |
1467 | 1506 | ||
1468 | ax = t->ax; | 1507 | ax = t->ax; |
1469 | dstmsg = dst; | ||
1470 | esize = size - sizeof (struct GNUNET_CADET_AX); | 1508 | esize = size - sizeof (struct GNUNET_CADET_AX); |
1471 | 1509 | ||
1472 | if (NULL == ax) | 1510 | if (NULL == ax) |
@@ -1489,14 +1527,14 @@ t_ax_decrypt_and_validate (struct CadetTunnel *t, void *dst, | |||
1489 | /* Try the skipped keys, if that fails, we're out of luck. */ | 1527 | /* Try the skipped keys, if that fails, we're out of luck. */ |
1490 | return try_old_ax_keys (t, dst, src, size); | 1528 | return try_old_ax_keys (t, dst, src, size); |
1491 | } | 1529 | } |
1492 | LOG (GNUNET_ERROR_TYPE_INFO, "next HK\n"); | 1530 | LOG (GNUNET_ERROR_TYPE_INFO, "next HK worked\n"); |
1493 | 1531 | ||
1494 | HK = ax->HKr; | 1532 | HK = ax->HKr; |
1495 | ax->HKr = ax->NHKr; | 1533 | ax->HKr = ax->NHKr; |
1496 | t_h_decrypt (t, src, dstmsg); | 1534 | t_h_decrypt (t, src, &plaintext_header); |
1497 | Np = ntohl (dstmsg->Ns); | 1535 | Np = ntohl (plaintext_header.Ns); |
1498 | PNp = ntohl (dstmsg->PNs); | 1536 | PNp = ntohl (plaintext_header.PNs); |
1499 | DHRp = &dstmsg->DHRs; | 1537 | DHRp = &plaintext_header.DHRs; |
1500 | store_ax_keys (t, &HK, PNp); | 1538 | store_ax_keys (t, &HK, PNp); |
1501 | 1539 | ||
1502 | /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */ | 1540 | /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */ |
@@ -1516,13 +1554,15 @@ t_ax_decrypt_and_validate (struct CadetTunnel *t, void *dst, | |||
1516 | else | 1554 | else |
1517 | { | 1555 | { |
1518 | LOG (GNUNET_ERROR_TYPE_DEBUG, "current HK\n"); | 1556 | LOG (GNUNET_ERROR_TYPE_DEBUG, "current HK\n"); |
1519 | t_h_decrypt (t, src, dstmsg); | 1557 | t_h_decrypt (t, src, &plaintext_header); |
1520 | Np = ntohl (dstmsg->Ns); | 1558 | Np = ntohl (plaintext_header.Ns); |
1521 | PNp = ntohl (dstmsg->PNs); | 1559 | PNp = ntohl (plaintext_header.PNs); |
1522 | } | 1560 | } |
1523 | 1561 | LOG (GNUNET_ERROR_TYPE_INFO, " got AX Nr %u\n", Np); | |
1524 | if (Np > ax->Nr) | 1562 | if (Np != ax->Nr) |
1525 | store_ax_keys (t, &ax->HKr, Np); | 1563 | if (GNUNET_OK != store_ax_keys (t, &ax->HKr, Np)) |
1564 | /* Try the skipped keys, if that fails, we're out of luck. */ | ||
1565 | return try_old_ax_keys (t, dst, src, size); | ||
1526 | 1566 | ||
1527 | osize = t_ax_decrypt (t, dst, &src[1], esize); | 1567 | osize = t_ax_decrypt (t, dst, &src[1], esize); |
1528 | ax->Nr = Np + 1; | 1568 | ax->Nr = Np + 1; |