diff options
author | t3sserakt <t3ss@posteo.de> | 2021-01-25 15:47:10 +0100 |
---|---|---|
committer | t3sserakt <t3ss@posteo.de> | 2021-01-25 15:47:10 +0100 |
commit | ac71165822501c42b00980db2fb7f5e2144f3d20 (patch) | |
tree | cb62e4f7af0f91bdcf50c69bfc0bb901d3059358 /src/transport/gnunet-communicator-tcp.c | |
parent | 438aca2f666f0e0648f389774adee01c131da25c (diff) | |
download | gnunet-ac71165822501c42b00980db2fb7f5e2144f3d20.tar.gz gnunet-ac71165822501c42b00980db2fb7f5e2144f3d20.zip |
- fixed bug in tcp com challenge logic. added test case for bidirectional test.
Diffstat (limited to 'src/transport/gnunet-communicator-tcp.c')
-rw-r--r-- | src/transport/gnunet-communicator-tcp.c | 654 |
1 files changed, 338 insertions, 316 deletions
diff --git a/src/transport/gnunet-communicator-tcp.c b/src/transport/gnunet-communicator-tcp.c index 0c79fc1b4..ed82dba9f 100644 --- a/src/transport/gnunet-communicator-tcp.c +++ b/src/transport/gnunet-communicator-tcp.c | |||
@@ -590,6 +590,11 @@ struct Queue | |||
590 | struct ChallengeNonceP challenge; | 590 | struct ChallengeNonceP challenge; |
591 | 591 | ||
592 | /** | 592 | /** |
593 | * Challenge value received. In case of inbound connection we have to remember the value, because we send the challenge back later after we received the GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK. | ||
594 | */ | ||
595 | struct ChallengeNonceP challenge_received; | ||
596 | |||
597 | /** | ||
593 | * Iteration Context for retrieving the monotonic time send with key for rekeying. | 598 | * Iteration Context for retrieving the monotonic time send with key for rekeying. |
594 | */ | 599 | */ |
595 | struct GNUNET_PEERSTORE_IterateContext *rekey_monotime_get; | 600 | struct GNUNET_PEERSTORE_IterateContext *rekey_monotime_get; |
@@ -834,7 +839,7 @@ int addrs_lens; | |||
834 | * Size of data received without KX challenge played back. | 839 | * Size of data received without KX challenge played back. |
835 | */ | 840 | */ |
836 | // TODO remove? | 841 | // TODO remove? |
837 | // size_t unverified_size; | 842 | size_t unverified_size; |
838 | 843 | ||
839 | /** | 844 | /** |
840 | * Database for peer's HELLOs. | 845 | * Database for peer's HELLOs. |
@@ -1188,23 +1193,6 @@ setup_cipher (const struct GNUNET_HashCode *dh, | |||
1188 | 0)); | 1193 | 0)); |
1189 | } | 1194 | } |
1190 | 1195 | ||
1191 | |||
1192 | /** | ||
1193 | * Setup cipher of @a queue for decryption. | ||
1194 | * | ||
1195 | * @param ephemeral ephemeral key we received from the other peer | ||
1196 | * @param queue[in,out] queue to initialize decryption cipher for | ||
1197 | */ | ||
1198 | static void | ||
1199 | setup_in_cipher (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral, | ||
1200 | struct Queue *queue) | ||
1201 | { | ||
1202 | struct GNUNET_HashCode dh; | ||
1203 | |||
1204 | GNUNET_CRYPTO_eddsa_ecdh (my_private_key, ephemeral, &dh); | ||
1205 | setup_cipher (&dh, &my_identity, &queue->in_cipher, &queue->in_hmac); | ||
1206 | } | ||
1207 | |||
1208 | /** | 1196 | /** |
1209 | * Callback called when peerstore store operation for rekey monotime value is finished. | 1197 | * Callback called when peerstore store operation for rekey monotime value is finished. |
1210 | * @param cls Queue context the store operation was executed. | 1198 | * @param cls Queue context the store operation was executed. |
@@ -1279,6 +1267,23 @@ rekey_monotime_cb (void *cls, | |||
1279 | } | 1267 | } |
1280 | 1268 | ||
1281 | /** | 1269 | /** |
1270 | * Setup cipher of @a queue for decryption. | ||
1271 | * | ||
1272 | * @param ephemeral ephemeral key we received from the other peer | ||
1273 | * @param queue[in,out] queue to initialize decryption cipher for | ||
1274 | */ | ||
1275 | static void | ||
1276 | setup_in_cipher (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral, | ||
1277 | struct Queue *queue) | ||
1278 | { | ||
1279 | struct GNUNET_HashCode dh; | ||
1280 | |||
1281 | GNUNET_CRYPTO_eddsa_ecdh (my_private_key, ephemeral, &dh); | ||
1282 | setup_cipher (&dh, &my_identity, &queue->in_cipher, &queue->in_hmac); | ||
1283 | } | ||
1284 | |||
1285 | |||
1286 | /** | ||
1282 | * Handle @a rekey message on @a queue. The message was already | 1287 | * Handle @a rekey message on @a queue. The message was already |
1283 | * HMAC'ed, but we should additionally still check the signature. | 1288 | * HMAC'ed, but we should additionally still check the signature. |
1284 | * Then we need to stop the old cipher and start afresh. | 1289 | * Then we need to stop the old cipher and start afresh. |
@@ -1416,6 +1421,220 @@ handshake_ack_monotime_cb (void *cls, | |||
1416 | } | 1421 | } |
1417 | 1422 | ||
1418 | /** | 1423 | /** |
1424 | * Sending challenge with TcpConfirmationAck back to sender of ephemeral key. | ||
1425 | * | ||
1426 | * @param tc The TCPConfirmation originally send. | ||
1427 | * @param queue The queue context. | ||
1428 | */ | ||
1429 | static void | ||
1430 | send_challenge (struct ChallengeNonceP challenge, struct Queue *queue) | ||
1431 | { | ||
1432 | struct TCPConfirmationAck tca; | ||
1433 | struct TcpHandshakeAckSignature thas; | ||
1434 | |||
1435 | GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG, | ||
1436 | "transport", | ||
1437 | "sending challenge\n"); | ||
1438 | |||
1439 | tca.header.type = ntohs ( | ||
1440 | GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK); | ||
1441 | tca.header.size = ntohs (sizeof(tca)); | ||
1442 | tca.challenge = challenge; | ||
1443 | tca.sender = my_identity; | ||
1444 | tca.monotonic_time = | ||
1445 | GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg)); | ||
1446 | thas.purpose.purpose = htonl ( | ||
1447 | GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE_ACK); | ||
1448 | thas.purpose.size = htonl (sizeof(thas)); | ||
1449 | thas.sender = my_identity; | ||
1450 | thas.receiver = queue->target; | ||
1451 | thas.monotonic_time = tca.monotonic_time; | ||
1452 | thas.challenge = tca.challenge; | ||
1453 | GNUNET_CRYPTO_eddsa_sign (my_private_key, | ||
1454 | &thas, | ||
1455 | &tca.sender_sig); | ||
1456 | GNUNET_assert (0 == | ||
1457 | gcry_cipher_encrypt (queue->out_cipher, | ||
1458 | &queue->cwrite_buf[queue->cwrite_off], | ||
1459 | sizeof(tca), | ||
1460 | &tca, | ||
1461 | sizeof(tca))); | ||
1462 | queue->cwrite_off += sizeof(tca); | ||
1463 | GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG, | ||
1464 | "transport", | ||
1465 | "sending challenge done\n"); | ||
1466 | } | ||
1467 | |||
1468 | /** | ||
1469 | * Setup cipher for outgoing data stream based on target and | ||
1470 | * our ephemeral private key. | ||
1471 | * | ||
1472 | * @param queue queue to setup outgoing (encryption) cipher for | ||
1473 | */ | ||
1474 | static void | ||
1475 | setup_out_cipher (struct Queue *queue) | ||
1476 | { | ||
1477 | struct GNUNET_HashCode dh; | ||
1478 | |||
1479 | GNUNET_CRYPTO_ecdh_eddsa (&queue->ephemeral, &queue->target.public_key, &dh); | ||
1480 | /* we don't need the private key anymore, drop it! */ | ||
1481 | memset (&queue->ephemeral, 0, sizeof(queue->ephemeral)); | ||
1482 | setup_cipher (&dh, &queue->target, &queue->out_cipher, &queue->out_hmac); | ||
1483 | queue->rekey_time = GNUNET_TIME_relative_to_absolute (rekey_interval); | ||
1484 | queue->rekey_left_bytes = | ||
1485 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, REKEY_MAX_BYTES); | ||
1486 | } | ||
1487 | |||
1488 | |||
1489 | /** | ||
1490 | * Inject a `struct TCPRekey` message into the queue's plaintext | ||
1491 | * buffer. | ||
1492 | * | ||
1493 | * @param queue queue to perform rekeying on | ||
1494 | */ | ||
1495 | static void | ||
1496 | inject_rekey (struct Queue *queue) | ||
1497 | { | ||
1498 | struct TCPRekey rekey; | ||
1499 | struct TcpRekeySignature thp; | ||
1500 | |||
1501 | GNUNET_assert (0 == queue->pwrite_off); | ||
1502 | memset (&rekey, 0, sizeof(rekey)); | ||
1503 | GNUNET_CRYPTO_ecdhe_key_create (&queue->ephemeral); | ||
1504 | rekey.header.type = ntohs (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY); | ||
1505 | rekey.header.size = ntohs (sizeof(rekey)); | ||
1506 | GNUNET_CRYPTO_ecdhe_key_get_public (&queue->ephemeral, &rekey.ephemeral); | ||
1507 | rekey.monotonic_time = | ||
1508 | GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg)); | ||
1509 | thp.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY); | ||
1510 | thp.purpose.size = htonl (sizeof(thp)); | ||
1511 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1512 | "inject_rekey size %u\n", | ||
1513 | thp.purpose.size); | ||
1514 | thp.sender = my_identity; | ||
1515 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1516 | "sender %s\n", | ||
1517 | GNUNET_p2s (&thp.sender.public_key)); | ||
1518 | thp.receiver = queue->target; | ||
1519 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1520 | "receiver %s\n", | ||
1521 | GNUNET_p2s (&thp.receiver.public_key)); | ||
1522 | thp.ephemeral = rekey.ephemeral; | ||
1523 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1524 | "ephemeral %s\n", | ||
1525 | GNUNET_e2s (&thp.ephemeral)); | ||
1526 | thp.monotonic_time = rekey.monotonic_time; | ||
1527 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1528 | "time %s\n", | ||
1529 | GNUNET_STRINGS_absolute_time_to_string ( | ||
1530 | GNUNET_TIME_absolute_ntoh (thp.monotonic_time))); | ||
1531 | GNUNET_CRYPTO_eddsa_sign (my_private_key, | ||
1532 | &thp, | ||
1533 | &rekey.sender_sig); | ||
1534 | calculate_hmac (&queue->out_hmac, &rekey, sizeof(rekey), &rekey.hmac); | ||
1535 | /* Encrypt rekey message with 'old' cipher */ | ||
1536 | GNUNET_assert (0 == | ||
1537 | gcry_cipher_encrypt (queue->out_cipher, | ||
1538 | &queue->cwrite_buf[queue->cwrite_off], | ||
1539 | sizeof(rekey), | ||
1540 | &rekey, | ||
1541 | sizeof(rekey))); | ||
1542 | queue->cwrite_off += sizeof(rekey); | ||
1543 | /* Setup new cipher for successive messages */ | ||
1544 | gcry_cipher_close (queue->out_cipher); | ||
1545 | setup_out_cipher (queue); | ||
1546 | } | ||
1547 | |||
1548 | /** | ||
1549 | * We have been notified that our socket is ready to write. | ||
1550 | * Then reschedule this function to be called again once more is available. | ||
1551 | * | ||
1552 | * @param cls a `struct Queue` | ||
1553 | */ | ||
1554 | static void | ||
1555 | queue_write (void *cls) | ||
1556 | { | ||
1557 | struct Queue *queue = cls; | ||
1558 | ssize_t sent; | ||
1559 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In queue write\n"); | ||
1560 | queue->write_task = NULL; | ||
1561 | if (0 != queue->cwrite_off) | ||
1562 | { | ||
1563 | sent = GNUNET_NETWORK_socket_send (queue->sock, | ||
1564 | queue->cwrite_buf, | ||
1565 | queue->cwrite_off); | ||
1566 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1567 | "Sent %lu bytes to TCP queue\n", sent); | ||
1568 | if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno)) | ||
1569 | { | ||
1570 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send"); | ||
1571 | queue_destroy (queue); | ||
1572 | return; | ||
1573 | } | ||
1574 | if (sent > 0) | ||
1575 | { | ||
1576 | size_t usent = (size_t) sent; | ||
1577 | queue->cwrite_off -= usent; | ||
1578 | memmove (queue->cwrite_buf, | ||
1579 | &queue->cwrite_buf[usent], | ||
1580 | queue->cwrite_off); | ||
1581 | reschedule_queue_timeout (queue); | ||
1582 | } | ||
1583 | } | ||
1584 | /* can we encrypt more? (always encrypt full messages, needed | ||
1585 | such that #mq_cancel() can work!) */ | ||
1586 | if ((0 < queue->rekey_left_bytes) && | ||
1587 | (queue->pwrite_off > 0) && | ||
1588 | (queue->cwrite_off + queue->pwrite_off <= BUF_SIZE)) | ||
1589 | { | ||
1590 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1591 | "Encrypting %lu bytes\n", queue->pwrite_off); | ||
1592 | GNUNET_assert (0 == | ||
1593 | gcry_cipher_encrypt (queue->out_cipher, | ||
1594 | &queue->cwrite_buf[queue->cwrite_off], | ||
1595 | queue->pwrite_off, | ||
1596 | queue->pwrite_buf, | ||
1597 | queue->pwrite_off)); | ||
1598 | if (queue->rekey_left_bytes > queue->pwrite_off) | ||
1599 | queue->rekey_left_bytes -= queue->pwrite_off; | ||
1600 | else | ||
1601 | queue->rekey_left_bytes = 0; | ||
1602 | queue->cwrite_off += queue->pwrite_off; | ||
1603 | queue->pwrite_off = 0; | ||
1604 | } | ||
1605 | // if ((-1 != unverified_size)&& ((0 == queue->pwrite_off) && | ||
1606 | if (((0 == queue->pwrite_off) && | ||
1607 | ((0 == queue->rekey_left_bytes) || | ||
1608 | (0 == | ||
1609 | GNUNET_TIME_absolute_get_remaining ( | ||
1610 | queue->rekey_time).rel_value_us)))) | ||
1611 | { | ||
1612 | inject_rekey (queue); | ||
1613 | } | ||
1614 | if ((0 == queue->pwrite_off) && (! queue->finishing) && | ||
1615 | (GNUNET_YES == queue->mq_awaits_continue)) | ||
1616 | { | ||
1617 | queue->mq_awaits_continue = GNUNET_NO; | ||
1618 | GNUNET_MQ_impl_send_continue (queue->mq); | ||
1619 | } | ||
1620 | /* did we just finish writing 'finish'? */ | ||
1621 | if ((0 == queue->cwrite_off) && (GNUNET_YES == queue->finishing)) | ||
1622 | { | ||
1623 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1624 | "Finishing queue\n"); | ||
1625 | queue_destroy (queue); | ||
1626 | return; | ||
1627 | } | ||
1628 | /* do we care to write more? */ | ||
1629 | if ((0 < queue->cwrite_off) || (0 < queue->pwrite_off)) | ||
1630 | queue->write_task = | ||
1631 | GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, | ||
1632 | queue->sock, | ||
1633 | &queue_write, | ||
1634 | queue); | ||
1635 | } | ||
1636 | |||
1637 | /** | ||
1419 | * Test if we have received a full message in plaintext. | 1638 | * Test if we have received a full message in plaintext. |
1420 | * If so, handle it. | 1639 | * If so, handle it. |
1421 | * | 1640 | * |
@@ -1450,16 +1669,16 @@ try_handle_plaintext (struct Queue *queue) | |||
1450 | return 0; /* not even a header */ | 1669 | return 0; /* not even a header */ |
1451 | } | 1670 | } |
1452 | 1671 | ||
1453 | /* if ((-1 != unverified_size) && (unverified_size > INITIAL_CORE_KX_SIZE)) */ | 1672 | if ((-1 != unverified_size) && (unverified_size > INITIAL_CORE_KX_SIZE)) |
1454 | /* { */ | 1673 | { |
1455 | /* GNUNET_log (GNUNET_ERROR_TYPE_ERROR, */ | 1674 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
1456 | /* "Already received data of size %lu bigger than KX size %lu!\n", */ | 1675 | "Already received data of size %lu bigger than KX size %lu!\n", |
1457 | /* unverified_size, */ | 1676 | unverified_size, |
1458 | /* INITIAL_CORE_KX_SIZE); */ | 1677 | INITIAL_CORE_KX_SIZE); |
1459 | /* GNUNET_break_op (0); */ | 1678 | GNUNET_break_op (0); |
1460 | /* queue_finish (queue); */ | 1679 | queue_finish (queue); |
1461 | /* return 0; */ | 1680 | return 0; |
1462 | /* } */ | 1681 | } |
1463 | 1682 | ||
1464 | type = ntohs (hdr->type); | 1683 | type = ntohs (hdr->type); |
1465 | switch (type) | 1684 | switch (type) |
@@ -1520,43 +1739,53 @@ try_handle_plaintext (struct Queue *queue) | |||
1520 | queue); | 1739 | queue); |
1521 | 1740 | ||
1522 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1741 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1523 | "Handling plaintext, ack processed!"); | 1742 | "Handling plaintext, ack processed!\n"); |
1524 | 1743 | ||
1525 | // unverified_size = -1; | 1744 | if (GNUNET_TRANSPORT_CS_INBOUND == queue->cs) |
1526 | 1745 | { | |
1527 | /* char *foreign_addr; */ | 1746 | send_challenge (queue->challenge_received, queue); |
1528 | 1747 | queue->write_task = | |
1529 | /* switch (queue->address->sa_family) */ | 1748 | GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, |
1530 | /* { */ | 1749 | queue->sock, |
1531 | /* case AF_INET: */ | 1750 | &queue_write, |
1532 | /* GNUNET_asprintf (&foreign_addr, */ | 1751 | queue); |
1533 | /* "%s-%s", */ | 1752 | } |
1534 | /* COMMUNICATOR_ADDRESS_PREFIX, */ | 1753 | |
1535 | /* GNUNET_a2s (queue->address, queue->address_len)); */ | 1754 | unverified_size = -1; |
1536 | /* break; */ | 1755 | |
1537 | 1756 | char *foreign_addr; | |
1538 | /* case AF_INET6: */ | 1757 | |
1539 | /* GNUNET_asprintf (&foreign_addr, */ | 1758 | switch (queue->address->sa_family) |
1540 | /* "%s-%s", */ | 1759 | { |
1541 | /* COMMUNICATOR_ADDRESS_PREFIX, */ | 1760 | case AF_INET: |
1542 | /* GNUNET_a2s (queue->address, queue->address_len)); */ | 1761 | GNUNET_asprintf (&foreign_addr, |
1543 | /* break; */ | 1762 | "%s-%s", |
1544 | 1763 | COMMUNICATOR_ADDRESS_PREFIX, | |
1545 | /* default: */ | 1764 | GNUNET_a2s (queue->address, queue->address_len)); |
1546 | /* GNUNET_assert (0); */ | 1765 | break; |
1547 | /* } */ | 1766 | |
1548 | 1767 | case AF_INET6: | |
1549 | /* queue->qh = GNUNET_TRANSPORT_communicator_mq_add (ch, */ | 1768 | GNUNET_asprintf (&foreign_addr, |
1550 | /* &queue->target, */ | 1769 | "%s-%s", |
1551 | /* foreign_addr, */ | 1770 | COMMUNICATOR_ADDRESS_PREFIX, |
1552 | /* 0 /\* no MTU *\/, */ | 1771 | GNUNET_a2s (queue->address, queue->address_len)); |
1553 | /* GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED, */ | 1772 | break; |
1554 | /* 0, /\* Priority *\/ */ | 1773 | |
1555 | /* queue->nt, */ | 1774 | default: |
1556 | /* queue->cs, */ | 1775 | GNUNET_assert (0); |
1557 | /* queue->mq); */ | 1776 | } |
1558 | 1777 | ||
1559 | /* GNUNET_free (foreign_addr); */ | 1778 | queue->qh = GNUNET_TRANSPORT_communicator_mq_add (ch, |
1779 | &queue->target, | ||
1780 | foreign_addr, | ||
1781 | 0 /* no MTU */, | ||
1782 | GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED, | ||
1783 | 0, /* Priority */ | ||
1784 | queue->nt, | ||
1785 | queue->cs, | ||
1786 | queue->mq); | ||
1787 | |||
1788 | GNUNET_free (foreign_addr); | ||
1560 | 1789 | ||
1561 | size = ntohs (hdr->size); | 1790 | size = ntohs (hdr->size); |
1562 | break; | 1791 | break; |
@@ -1633,8 +1862,8 @@ try_handle_plaintext (struct Queue *queue) | |||
1633 | return 0; | 1862 | return 0; |
1634 | } | 1863 | } |
1635 | GNUNET_assert (0 != size); | 1864 | GNUNET_assert (0 != size); |
1636 | /* if (-1 != unverified_size) */ | 1865 | if (-1 != unverified_size) |
1637 | /* unverified_size += size; */ | 1866 | unverified_size += size; |
1638 | return size; | 1867 | return size; |
1639 | } | 1868 | } |
1640 | 1869 | ||
@@ -2043,178 +2272,6 @@ tcp_address_to_sockaddr (const char *bindto, socklen_t *sock_len) | |||
2043 | return in; | 2272 | return in; |
2044 | } | 2273 | } |
2045 | 2274 | ||
2046 | |||
2047 | /** | ||
2048 | * Setup cipher for outgoing data stream based on target and | ||
2049 | * our ephemeral private key. | ||
2050 | * | ||
2051 | * @param queue queue to setup outgoing (encryption) cipher for | ||
2052 | */ | ||
2053 | static void | ||
2054 | setup_out_cipher (struct Queue *queue) | ||
2055 | { | ||
2056 | struct GNUNET_HashCode dh; | ||
2057 | |||
2058 | GNUNET_CRYPTO_ecdh_eddsa (&queue->ephemeral, &queue->target.public_key, &dh); | ||
2059 | /* we don't need the private key anymore, drop it! */ | ||
2060 | memset (&queue->ephemeral, 0, sizeof(queue->ephemeral)); | ||
2061 | setup_cipher (&dh, &queue->target, &queue->out_cipher, &queue->out_hmac); | ||
2062 | queue->rekey_time = GNUNET_TIME_relative_to_absolute (rekey_interval); | ||
2063 | queue->rekey_left_bytes = | ||
2064 | GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, REKEY_MAX_BYTES); | ||
2065 | } | ||
2066 | |||
2067 | |||
2068 | /** | ||
2069 | * Inject a `struct TCPRekey` message into the queue's plaintext | ||
2070 | * buffer. | ||
2071 | * | ||
2072 | * @param queue queue to perform rekeying on | ||
2073 | */ | ||
2074 | static void | ||
2075 | inject_rekey (struct Queue *queue) | ||
2076 | { | ||
2077 | struct TCPRekey rekey; | ||
2078 | struct TcpRekeySignature thp; | ||
2079 | |||
2080 | GNUNET_assert (0 == queue->pwrite_off); | ||
2081 | memset (&rekey, 0, sizeof(rekey)); | ||
2082 | GNUNET_CRYPTO_ecdhe_key_create (&queue->ephemeral); | ||
2083 | rekey.header.type = ntohs (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY); | ||
2084 | rekey.header.size = ntohs (sizeof(rekey)); | ||
2085 | GNUNET_CRYPTO_ecdhe_key_get_public (&queue->ephemeral, &rekey.ephemeral); | ||
2086 | rekey.monotonic_time = | ||
2087 | GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg)); | ||
2088 | thp.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY); | ||
2089 | thp.purpose.size = htonl (sizeof(thp)); | ||
2090 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2091 | "inject_rekey size %u\n", | ||
2092 | thp.purpose.size); | ||
2093 | thp.sender = my_identity; | ||
2094 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2095 | "sender %s\n", | ||
2096 | GNUNET_p2s (&thp.sender.public_key)); | ||
2097 | thp.receiver = queue->target; | ||
2098 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2099 | "receiver %s\n", | ||
2100 | GNUNET_p2s (&thp.receiver.public_key)); | ||
2101 | thp.ephemeral = rekey.ephemeral; | ||
2102 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2103 | "ephemeral %s\n", | ||
2104 | GNUNET_e2s (&thp.ephemeral)); | ||
2105 | thp.monotonic_time = rekey.monotonic_time; | ||
2106 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2107 | "time %s\n", | ||
2108 | GNUNET_STRINGS_absolute_time_to_string ( | ||
2109 | GNUNET_TIME_absolute_ntoh (thp.monotonic_time))); | ||
2110 | GNUNET_CRYPTO_eddsa_sign (my_private_key, | ||
2111 | &thp, | ||
2112 | &rekey.sender_sig); | ||
2113 | calculate_hmac (&queue->out_hmac, &rekey, sizeof(rekey), &rekey.hmac); | ||
2114 | /* Encrypt rekey message with 'old' cipher */ | ||
2115 | GNUNET_assert (0 == | ||
2116 | gcry_cipher_encrypt (queue->out_cipher, | ||
2117 | &queue->cwrite_buf[queue->cwrite_off], | ||
2118 | sizeof(rekey), | ||
2119 | &rekey, | ||
2120 | sizeof(rekey))); | ||
2121 | queue->cwrite_off += sizeof(rekey); | ||
2122 | /* Setup new cipher for successive messages */ | ||
2123 | gcry_cipher_close (queue->out_cipher); | ||
2124 | setup_out_cipher (queue); | ||
2125 | } | ||
2126 | |||
2127 | |||
2128 | /** | ||
2129 | * We have been notified that our socket is ready to write. | ||
2130 | * Then reschedule this function to be called again once more is available. | ||
2131 | * | ||
2132 | * @param cls a `struct Queue` | ||
2133 | */ | ||
2134 | static void | ||
2135 | queue_write (void *cls) | ||
2136 | { | ||
2137 | struct Queue *queue = cls; | ||
2138 | ssize_t sent; | ||
2139 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "In queue write\n"); | ||
2140 | queue->write_task = NULL; | ||
2141 | if (0 != queue->cwrite_off) | ||
2142 | { | ||
2143 | sent = GNUNET_NETWORK_socket_send (queue->sock, | ||
2144 | queue->cwrite_buf, | ||
2145 | queue->cwrite_off); | ||
2146 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2147 | "Sent %lu bytes to TCP queue\n", sent); | ||
2148 | if ((-1 == sent) && (EAGAIN != errno) && (EINTR != errno)) | ||
2149 | { | ||
2150 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "send"); | ||
2151 | queue_destroy (queue); | ||
2152 | return; | ||
2153 | } | ||
2154 | if (sent > 0) | ||
2155 | { | ||
2156 | size_t usent = (size_t) sent; | ||
2157 | queue->cwrite_off -= usent; | ||
2158 | memmove (queue->cwrite_buf, | ||
2159 | &queue->cwrite_buf[usent], | ||
2160 | queue->cwrite_off); | ||
2161 | reschedule_queue_timeout (queue); | ||
2162 | } | ||
2163 | } | ||
2164 | /* can we encrypt more? (always encrypt full messages, needed | ||
2165 | such that #mq_cancel() can work!) */ | ||
2166 | if ((0 < queue->rekey_left_bytes) && | ||
2167 | (queue->pwrite_off > 0) && | ||
2168 | (queue->cwrite_off + queue->pwrite_off <= BUF_SIZE)) | ||
2169 | { | ||
2170 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2171 | "Encrypting %lu bytes\n", queue->pwrite_off); | ||
2172 | GNUNET_assert (0 == | ||
2173 | gcry_cipher_encrypt (queue->out_cipher, | ||
2174 | &queue->cwrite_buf[queue->cwrite_off], | ||
2175 | queue->pwrite_off, | ||
2176 | queue->pwrite_buf, | ||
2177 | queue->pwrite_off)); | ||
2178 | if (queue->rekey_left_bytes > queue->pwrite_off) | ||
2179 | queue->rekey_left_bytes -= queue->pwrite_off; | ||
2180 | else | ||
2181 | queue->rekey_left_bytes = 0; | ||
2182 | queue->cwrite_off += queue->pwrite_off; | ||
2183 | queue->pwrite_off = 0; | ||
2184 | } | ||
2185 | // if ((-1 != unverified_size)&& ((0 == queue->pwrite_off) && | ||
2186 | if (((0 == queue->pwrite_off) && | ||
2187 | ((0 == queue->rekey_left_bytes) || | ||
2188 | (0 == | ||
2189 | GNUNET_TIME_absolute_get_remaining ( | ||
2190 | queue->rekey_time).rel_value_us)))) | ||
2191 | { | ||
2192 | inject_rekey (queue); | ||
2193 | } | ||
2194 | if ((0 == queue->pwrite_off) && (! queue->finishing) && | ||
2195 | (GNUNET_YES == queue->mq_awaits_continue)) | ||
2196 | { | ||
2197 | queue->mq_awaits_continue = GNUNET_NO; | ||
2198 | GNUNET_MQ_impl_send_continue (queue->mq); | ||
2199 | } | ||
2200 | /* did we just finish writing 'finish'? */ | ||
2201 | if ((0 == queue->cwrite_off) && (GNUNET_YES == queue->finishing)) | ||
2202 | { | ||
2203 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2204 | "Finishing queue\n"); | ||
2205 | queue_destroy (queue); | ||
2206 | return; | ||
2207 | } | ||
2208 | /* do we care to write more? */ | ||
2209 | if ((0 < queue->cwrite_off) || (0 < queue->pwrite_off)) | ||
2210 | queue->write_task = | ||
2211 | GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, | ||
2212 | queue->sock, | ||
2213 | &queue_write, | ||
2214 | queue); | ||
2215 | } | ||
2216 | |||
2217 | |||
2218 | /** | 2275 | /** |
2219 | * Signature of functions implementing the sending functionality of a | 2276 | * Signature of functions implementing the sending functionality of a |
2220 | * message queue. | 2277 | * message queue. |
@@ -2348,39 +2405,39 @@ boot_queue (struct Queue *queue) | |||
2348 | NULL, | 2405 | NULL, |
2349 | &mq_error, | 2406 | &mq_error, |
2350 | queue); | 2407 | queue); |
2351 | { | 2408 | /* { */ |
2352 | char *foreign_addr; | 2409 | /* char *foreign_addr; */ |
2353 | 2410 | ||
2354 | switch (queue->address->sa_family) | 2411 | /* switch (queue->address->sa_family) */ |
2355 | { | 2412 | /* { */ |
2356 | case AF_INET: | 2413 | /* case AF_INET: */ |
2357 | GNUNET_asprintf (&foreign_addr, | 2414 | /* GNUNET_asprintf (&foreign_addr, */ |
2358 | "%s-%s", | 2415 | /* "%s-%s", */ |
2359 | COMMUNICATOR_ADDRESS_PREFIX, | 2416 | /* COMMUNICATOR_ADDRESS_PREFIX, */ |
2360 | GNUNET_a2s (queue->address, queue->address_len)); | 2417 | /* GNUNET_a2s (queue->address, queue->address_len)); */ |
2361 | break; | 2418 | /* break; */ |
2362 | 2419 | ||
2363 | case AF_INET6: | 2420 | /* case AF_INET6: */ |
2364 | GNUNET_asprintf (&foreign_addr, | 2421 | /* GNUNET_asprintf (&foreign_addr, */ |
2365 | "%s-%s", | 2422 | /* "%s-%s", */ |
2366 | COMMUNICATOR_ADDRESS_PREFIX, | 2423 | /* COMMUNICATOR_ADDRESS_PREFIX, */ |
2367 | GNUNET_a2s (queue->address, queue->address_len)); | 2424 | /* GNUNET_a2s (queue->address, queue->address_len)); */ |
2368 | break; | 2425 | /* break; */ |
2369 | 2426 | ||
2370 | default: | 2427 | /* default: */ |
2371 | GNUNET_assert (0); | 2428 | /* GNUNET_assert (0); */ |
2372 | } | 2429 | /* } */ |
2373 | queue->qh = GNUNET_TRANSPORT_communicator_mq_add (ch, | 2430 | /* queue->qh = GNUNET_TRANSPORT_communicator_mq_add (ch, */ |
2374 | &queue->target, | 2431 | /* &queue->target, */ |
2375 | foreign_addr, | 2432 | /* foreign_addr, */ |
2376 | 0 /* no MTU */, | 2433 | /* 0 /\* no MTU *\/, */ |
2377 | GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED, | 2434 | /* GNUNET_TRANSPORT_QUEUE_LENGTH_UNLIMITED, */ |
2378 | 0, /* Priority */ | 2435 | /* 0, /\* Priority *\/ */ |
2379 | queue->nt, | 2436 | /* queue->nt, */ |
2380 | queue->cs, | 2437 | /* queue->cs, */ |
2381 | queue->mq); | 2438 | /* queue->mq); */ |
2382 | GNUNET_free (foreign_addr); | 2439 | /* GNUNET_free (foreign_addr); */ |
2383 | } | 2440 | /* } */ |
2384 | } | 2441 | } |
2385 | 2442 | ||
2386 | 2443 | ||
@@ -2595,48 +2652,6 @@ free_proto_queue (struct ProtoQueue *pq) | |||
2595 | } | 2652 | } |
2596 | 2653 | ||
2597 | /** | 2654 | /** |
2598 | * Sending challenge with TcpConfirmationAck back to sender of ephemeral key. | ||
2599 | * | ||
2600 | * @param tc The TCPConfirmation originally send. | ||
2601 | * @param queue The queue context. | ||
2602 | */ | ||
2603 | static void | ||
2604 | send_challenge (struct ChallengeNonceP challenge, struct Queue *queue) | ||
2605 | { | ||
2606 | struct TCPConfirmationAck tca; | ||
2607 | struct TcpHandshakeAckSignature thas; | ||
2608 | |||
2609 | GNUNET_log_from_nocheck (GNUNET_ERROR_TYPE_DEBUG, | ||
2610 | "transport", | ||
2611 | "sending challenge\n"); | ||
2612 | |||
2613 | tca.header.type = ntohs ( | ||
2614 | GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_CONFIRMATION_ACK); | ||
2615 | tca.header.size = ntohs (sizeof(tca)); | ||
2616 | tca.challenge = challenge; | ||
2617 | tca.sender = my_identity; | ||
2618 | tca.monotonic_time = | ||
2619 | GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get_monotonic (cfg)); | ||
2620 | thas.purpose.purpose = htonl ( | ||
2621 | GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE_ACK); | ||
2622 | thas.purpose.size = htonl (sizeof(thas)); | ||
2623 | thas.sender = my_identity; | ||
2624 | thas.receiver = queue->target; | ||
2625 | thas.monotonic_time = tca.monotonic_time; | ||
2626 | thas.challenge = tca.challenge; | ||
2627 | GNUNET_CRYPTO_eddsa_sign (my_private_key, | ||
2628 | &thas, | ||
2629 | &tca.sender_sig); | ||
2630 | GNUNET_assert (0 == | ||
2631 | gcry_cipher_encrypt (queue->out_cipher, | ||
2632 | &queue->cwrite_buf[queue->cwrite_off], | ||
2633 | sizeof(tca), | ||
2634 | &tca, | ||
2635 | sizeof(tca))); | ||
2636 | queue->cwrite_off += sizeof(tca); | ||
2637 | } | ||
2638 | |||
2639 | /** | ||
2640 | * Read from the socket of the proto queue until we have enough data | 2655 | * Read from the socket of the proto queue until we have enough data |
2641 | * to upgrade to full queue. | 2656 | * to upgrade to full queue. |
2642 | * | 2657 | * |
@@ -2722,7 +2737,8 @@ proto_read_kx (void *cls) | |||
2722 | &queue_write, | 2737 | &queue_write, |
2723 | queue); | 2738 | queue); |
2724 | // TODO To early! Move it somewhere else. | 2739 | // TODO To early! Move it somewhere else. |
2725 | // send_challenge (tc, queue); | 2740 | // send_challenge (tc.challenge, queue); |
2741 | queue->challenge_received = tc.challenge; | ||
2726 | 2742 | ||
2727 | GNUNET_CONTAINER_DLL_remove (proto_head, proto_tail, pq); | 2743 | GNUNET_CONTAINER_DLL_remove (proto_head, proto_tail, pq); |
2728 | GNUNET_free (pq); | 2744 | GNUNET_free (pq); |
@@ -2853,6 +2869,12 @@ queue_read_kx (void *cls) | |||
2853 | return; | 2869 | return; |
2854 | } | 2870 | } |
2855 | send_challenge (tc.challenge, queue); | 2871 | send_challenge (tc.challenge, queue); |
2872 | queue->write_task = | ||
2873 | GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL, | ||
2874 | queue->sock, | ||
2875 | &queue_write, | ||
2876 | queue); | ||
2877 | |||
2856 | /* update queue timeout */ | 2878 | /* update queue timeout */ |
2857 | reschedule_queue_timeout (queue); | 2879 | reschedule_queue_timeout (queue); |
2858 | /* prepare to continue with regular read task immediately */ | 2880 | /* prepare to continue with regular read task immediately */ |
@@ -2866,7 +2888,7 @@ queue_read_kx (void *cls) | |||
2866 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2888 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
2867 | "cread_off set to %lu bytes\n", | 2889 | "cread_off set to %lu bytes\n", |
2868 | queue->cread_off); | 2890 | queue->cread_off); |
2869 | if (0 < queue->cread_off) | 2891 | if (0 <= queue->cread_off) |
2870 | queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read, queue); | 2892 | queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read, queue); |
2871 | } | 2893 | } |
2872 | 2894 | ||