aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-communicator-udp.c
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2023-07-29 13:42:03 +0200
committerMartin Schanzenbach <schanzen@gnunet.org>2023-07-29 13:42:03 +0200
commit6c9229f7a8266ea13cff1aff25269b41ce9f3b03 (patch)
treefbfb45406e234618fab38e35f42badef1603e29f /src/transport/gnunet-communicator-udp.c
parentaa2c53087ae6eab738a93abfa8401be03ad923d7 (diff)
downloadgnunet-6c9229f7a8266ea13cff1aff25269b41ce9f3b03.tar.gz
gnunet-6c9229f7a8266ea13cff1aff25269b41ce9f3b03.zip
NEWS: -
TNG: Simplify rekey message and incorporate into regular boxed message.
Diffstat (limited to 'src/transport/gnunet-communicator-udp.c')
-rw-r--r--src/transport/gnunet-communicator-udp.c338
1 files changed, 110 insertions, 228 deletions
diff --git a/src/transport/gnunet-communicator-udp.c b/src/transport/gnunet-communicator-udp.c
index 5a6d8f1f9..c69fb233c 100644
--- a/src/transport/gnunet-communicator-udp.c
+++ b/src/transport/gnunet-communicator-udp.c
@@ -350,23 +350,14 @@ struct UDPBox
350struct UDPRekey 350struct UDPRekey
351{ 351{
352 /** 352 /**
353 * Key and IV identification code. KDF applied to an acknowledged 353 * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_REKEY.
354 * base key and a sequence number. Sequence numbers must be used
355 * monotonically increasing up to the maximum specified in
356 * `struct UDPAck`. Without further `struct UDPAck`s, the sender
357 * must fall back to sending handshakes!
358 */ 354 */
359 struct GNUNET_ShortHashCode kid; 355 struct GNUNET_MessageHeader header;
360 356
361 /** 357 /**
362 * 128-bit authentication tag for the following encrypted message, 358 * Ephemeral key to rekey with.
363 * from GCM. MAC starts at the @e body_start that follows and
364 * extends until the end of the UDP payload. If the @e hmac is
365 * wrong, the receiver should check if the message might be a
366 * `struct UdpHandshakeSignature`.
367 */ 359 */
368 uint8_t gcm_tag[GCM_TAG_SIZE]; 360 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
369
370}; 361};
371 362
372GNUNET_NETWORK_STRUCT_END 363GNUNET_NETWORK_STRUCT_END
@@ -1658,76 +1649,6 @@ handle_ack (void *cls, const struct GNUNET_PeerIdentity *pid, void *value)
1658} 1649}
1659 1650
1660 1651
1661/**
1662 * Test if we have received a valid message in plaintext.
1663 * If so, handle it.
1664 *
1665 * @param sender peer to process inbound plaintext for
1666 * @param buf buffer we received
1667 * @param buf_size number of bytes in @a buf
1668 * @return rekey_indication GNUNET_YES if a rekey is signalled
1669 */
1670static uint16_t
1671try_handle_plaintext (struct SenderAddress *sender,
1672 const void *buf,
1673 size_t buf_size)
1674{
1675 const struct GNUNET_MessageHeader *hdr;
1676 const struct UDPAck *ack;
1677 const char *buf_pos = buf;
1678 size_t bytes_remaining = buf_size;
1679 uint16_t type;
1680 uint16_t rekey;
1681
1682 if (sizeof (uint16_t) > buf_size)
1683 {
1684 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Plaintext too short, dropping...\n");
1685 rekey = ntohs (*(uint16_t*) buf);
1686 return GNUNET_NO;
1687 }
1688 bytes_remaining -= sizeof (uint16_t);
1689 buf_pos += sizeof (uint16_t);
1690 hdr = (struct GNUNET_MessageHeader*) buf_pos;
1691 if (sizeof(*hdr) > bytes_remaining)
1692 {
1693 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Plaintext too short, dropping...\n");
1694 return rekey; /* no data left */
1695 }
1696 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1697 "try_handle_plaintext of size %lu (%u %lu) and type %u\n",
1698 bytes_remaining,
1699 ntohs (hdr->size),
1700 sizeof(*hdr),
1701 ntohs (hdr->type));
1702 if (ntohs (hdr->size) > bytes_remaining)
1703 return GNUNET_NO; /* buffer too short for indicated message length */
1704 type = ntohs (hdr->type);
1705 switch (type)
1706 {
1707 case GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK:
1708 /* lookup master secret by 'cmac', then update sequence_max */
1709 ack = (struct UDPAck*) buf_pos;
1710 GNUNET_CONTAINER_multipeermap_get_multiple (receivers,
1711 &sender->target,
1712 &handle_ack,
1713 (void *) ack);
1714 /* There could be more messages after the ACK, handle those as well */
1715 buf_pos += ntohs (hdr->size);
1716 bytes_remaining -= ntohs (hdr->size);
1717 pass_plaintext_to_core (sender, buf_pos, bytes_remaining);
1718 break;
1719
1720 case GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_PAD:
1721 /* skip padding */
1722 break;
1723
1724 default:
1725 pass_plaintext_to_core (sender, buf_pos, bytes_remaining);
1726 }
1727 return rekey;
1728}
1729
1730
1731static void 1652static void
1732kce_generate_cb (void *cls) 1653kce_generate_cb (void *cls)
1733{ 1654{
@@ -1908,6 +1829,93 @@ consider_ss_ack (struct SharedSecret *ss, int initial)
1908 1829
1909 1830
1910/** 1831/**
1832 * Test if we have received a valid message in plaintext.
1833 * If so, handle it.
1834 *
1835 * @param sender peer to process inbound plaintext for
1836 * @param buf buffer we received
1837 * @param buf_size number of bytes in @a buf
1838 */
1839static void
1840try_handle_plaintext (struct SenderAddress *sender,
1841 const void *buf,
1842 size_t buf_size)
1843{
1844 const struct GNUNET_MessageHeader *hdr;
1845 const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral_pubkey;
1846 const struct UDPAck *ack;
1847 struct SharedSecret *ss_rekey;
1848 const char *buf_pos = buf;
1849 size_t bytes_remaining = buf_size;
1850 uint16_t type;
1851
1852 buf_pos += sizeof (uint16_t);
1853 hdr = (struct GNUNET_MessageHeader*) buf_pos;
1854 if (sizeof(*hdr) > bytes_remaining)
1855 {
1856 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Plaintext too short, dropping...\n");
1857 return; /* no data left */
1858 }
1859 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1860 "try_handle_plaintext of size %lu (%u %lu) and type %u\n",
1861 bytes_remaining,
1862 ntohs (hdr->size),
1863 sizeof(*hdr),
1864 ntohs (hdr->type));
1865 if (ntohs (hdr->size) > bytes_remaining)
1866 return; /* buffer too short for indicated message length */
1867 type = ntohs (hdr->type);
1868 switch (type)
1869 {
1870 case GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_REKEY:
1871 ephemeral_pubkey = (struct GNUNET_CRYPTO_EcdhePublicKey *) buf_pos;
1872 ss_rekey = setup_shared_secret_dec (ephemeral_pubkey);
1873 ss_rekey->sender = sender;
1874 GNUNET_CONTAINER_DLL_insert (sender->ss_head, sender->ss_tail, ss_rekey);
1875 sender->ss_rekey = ss_rekey;
1876 sender->num_secrets++;
1877 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1878 "Received secret with cmac %s\n",
1879 GNUNET_h2s (&(ss_rekey->cmac)));
1880 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1881 "Received secret with master %s.\n",
1882 GNUNET_h2s (&(ss_rekey->master)));
1883 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1884 "We have %u sequence_allowed.\n",
1885 ss_rekey->sequence_allowed);
1886 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1887 "We have a sender %p\n",
1888 ss_rekey->sender);
1889 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1890 "We have %u acks available.\n",
1891 ss_rekey->sender->acks_available);
1892 consider_ss_ack (ss_rekey, GNUNET_YES);
1893 break;
1894 case GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_ACK:
1895 /* lookup master secret by 'cmac', then update sequence_max */
1896 ack = (struct UDPAck*) buf_pos;
1897 GNUNET_CONTAINER_multipeermap_get_multiple (receivers,
1898 &sender->target,
1899 &handle_ack,
1900 (void *) ack);
1901 /* There could be more messages after the ACK, handle those as well */
1902 buf_pos += ntohs (hdr->size);
1903 bytes_remaining -= ntohs (hdr->size);
1904 pass_plaintext_to_core (sender, buf_pos, bytes_remaining);
1905 break;
1906
1907 case GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_PAD:
1908 /* skip padding */
1909 break;
1910
1911 default:
1912 pass_plaintext_to_core (sender, buf_pos, bytes_remaining);
1913 }
1914 return;
1915}
1916
1917
1918/**
1911 * We received a @a box with matching @a kce. Decrypt and process it. 1919 * We received a @a box with matching @a kce. Decrypt and process it.
1912 * 1920 *
1913 * @param box the data we received 1921 * @param box the data we received
@@ -1950,94 +1958,7 @@ decrypt_box (const struct UDPBox *box,
1950 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1958 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1951 "decrypted UDPBox with kid %s\n", 1959 "decrypted UDPBox with kid %s\n",
1952 GNUNET_sh2s (&box->kid)); 1960 GNUNET_sh2s (&box->kid));
1953 rekeying = try_handle_plaintext (ss->sender, out_buf, sizeof(out_buf)); 1961 try_handle_plaintext (ss->sender, out_buf, sizeof(out_buf));
1954 if ((GNUNET_NO == rekeying) && (GNUNET_YES == ss->sender->rekeying))
1955 {
1956 ss->sender->rekeying = GNUNET_NO;
1957 ss->sender->ss_rekey = NULL;
1958 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1959 "Receiver stopped rekeying.\n");
1960 }
1961 else if (GNUNET_YES == rekeying)
1962 {
1963 ss->sender->rekeying = GNUNET_YES;
1964 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1965 "Got Box: Receiver doing rekeying.\n");
1966 }
1967}
1968
1969
1970/**
1971 * We received a @a rekey with matching @a kce. Decrypt and process it.
1972 *
1973 * @param rekey the data we received
1974 * @param rekey_len number of bytes in @a rekey
1975 * @param kce key index to decrypt @a rekey
1976 */
1977static void
1978decrypt_rekey (const struct UDPRekey *rekey,
1979 size_t rekey_len,
1980 struct KeyCacheEntry *kce)
1981{
1982 struct SharedSecret *ss = kce->ss;
1983 struct SharedSecret *ss_rekey;
1984 char out_buf[rekey_len - sizeof(*rekey)];
1985 struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral_pubkey;
1986 struct SenderAddress *sender;
1987
1988 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1989 "decrypt_rekey.\n");
1990
1991 GNUNET_assert (NULL != ss->sender);
1992 sender = ss->sender;
1993 if (GNUNET_OK != try_decrypt (ss,
1994 rekey->gcm_tag,
1995 kce->sequence_number,
1996 (const char *) &rekey[1],
1997 sizeof(out_buf),
1998 out_buf))
1999 {
2000 GNUNET_STATISTICS_update (stats,
2001 "# Decryption failures with valid KCE",
2002 1,
2003 GNUNET_NO);
2004 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2005 "Decryption with kid %s failed\n",
2006 GNUNET_sh2s (&rekey->kid));
2007 kce_destroy (kce);
2008 return;
2009 }
2010 kce_destroy (kce);
2011 GNUNET_STATISTICS_update (stats,
2012 "# bytes decrypted with Rekey",
2013 sizeof(out_buf),
2014 GNUNET_NO);
2015 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2016 "decrypted UDPRekey with kid %s\n",
2017 GNUNET_sh2s (&rekey->kid));
2018 ephemeral_pubkey = (struct GNUNET_CRYPTO_EcdhePublicKey *) out_buf;
2019 ss_rekey = setup_shared_secret_dec (ephemeral_pubkey);
2020 ss_rekey->sender = sender;
2021 GNUNET_CONTAINER_DLL_insert (sender->ss_head, sender->ss_tail, ss_rekey);
2022 sender->ss_rekey = ss_rekey;
2023 sender->num_secrets++;
2024 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2025 "Received secret with cmac %s\n",
2026 GNUNET_h2s (&(ss_rekey->cmac)));
2027 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2028 "Received secret with master %s.\n",
2029 GNUNET_h2s (&(ss_rekey->master)));
2030 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2031 "We have %u sequence_allowed.\n",
2032 ss_rekey->sequence_allowed);
2033 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2034 "We have a sender %p\n",
2035 ss_rekey->sender);
2036 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2037 "We have %u acks available.\n",
2038 ss_rekey->sender->acks_available);
2039 consider_ss_ack (ss_rekey, GNUNET_YES);
2040
2041} 1962}
2042 1963
2043 1964
@@ -2245,26 +2166,6 @@ sock_read (void *cls)
2245 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2166 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2246 "Read %lu bytes\n", rcvd); 2167 "Read %lu bytes\n", rcvd);
2247 2168
2248 if (rcvd > sizeof(struct UDPRekey))
2249 {
2250 const struct UDPRekey *rekey;
2251 const struct UDPBox *box;
2252 struct KeyCacheEntry *kce;
2253 int do_decrypt = GNUNET_NO;
2254
2255 rekey = (const struct UDPRekey *) buf;
2256 kce = GNUNET_CONTAINER_multishortmap_get (key_cache, &rekey->kid);
2257
2258 if ((NULL != kce) && (GNUNET_YES == kce->ss->sender->rekeying))
2259 {
2260 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2261 "UDPRekey with kid %s\n",
2262 GNUNET_sh2s (&rekey->kid));
2263 decrypt_rekey (rekey, (size_t) rcvd, kce);
2264 return;
2265 }
2266 }
2267
2268 /* first, see if it is a UDPBox */ 2169 /* first, see if it is a UDPBox */
2269 if (rcvd > sizeof(struct UDPBox)) 2170 if (rcvd > sizeof(struct UDPBox))
2270 { 2171 {
@@ -2420,24 +2321,7 @@ sock_read (void *cls)
2420 "# messages decrypted without BOX", 2321 "# messages decrypted without BOX",
2421 1, 2322 1,
2422 GNUNET_NO); 2323 GNUNET_NO);
2423 rekeying = try_handle_plaintext (sender, &uc[1], sizeof(pbuf) 2324 try_handle_plaintext (sender, &uc[1], sizeof(pbuf) - sizeof(*uc));
2424 - sizeof(*uc));
2425 if ((GNUNET_NO == rekeying) && (GNUNET_YES == ss->sender->rekeying))
2426 {
2427 ss->sender->rekeying = GNUNET_NO;
2428 sender->ss_rekey = NULL;
2429 // destroy_all_secrets (ss, GNUNET_NO);
2430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2431 "Receiver stopped rekeying.\n");
2432 }
2433 else if (GNUNET_NO == rekeying)
2434 consider_ss_ack (ss, GNUNET_YES);
2435 else
2436 {
2437 ss->sender->rekeying = GNUNET_YES;
2438 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2439 "Got KX: Receiver doing rekeying.\n");
2440 }
2441 } 2325 }
2442 } 2326 }
2443} 2327}
@@ -2757,11 +2641,13 @@ send_UDPRekey (struct ReceiverAddress *receiver, struct SharedSecret *ss)
2757 uint8_t is_acks_available_below = GNUNET_NO; 2641 uint8_t is_acks_available_below = GNUNET_NO;
2758 uint8_t send_rekey = GNUNET_NO; 2642 uint8_t send_rekey = GNUNET_NO;
2759 uint16_t not_below; 2643 uint16_t not_below;
2760 struct UDPRekey *rekey; 2644 struct UDPBox *box;
2645 struct UDPRekey rekey;
2761 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_pubkey; 2646 struct GNUNET_CRYPTO_EcdhePublicKey ephemeral_pubkey;
2762 size_t dpos; 2647 size_t dpos;
2763 2648
2764 char rekey_dgram[sizeof(struct UDPRekey) + receiver->d_mtu]; 2649 char rekey_dgram[sizeof (struct UDPBox) + sizeof(struct UDPRekey)
2650 + receiver->d_mtu];
2765 2651
2766 if (NULL == receiver->ss_rekey) 2652 if (NULL == receiver->ss_rekey)
2767 { 2653 {
@@ -2776,6 +2662,7 @@ send_UDPRekey (struct ReceiverAddress *receiver, struct SharedSecret *ss)
2776 "Setup secret with master %s.\n", 2662 "Setup secret with master %s.\n",
2777 GNUNET_h2s (&(receiver->ss_rekey->master))); 2663 GNUNET_h2s (&(receiver->ss_rekey->master)));
2778 } 2664 }
2665 /* WTF is this */
2779 not_below = (receiver->rekey_acks_available 2666 not_below = (receiver->rekey_acks_available
2780 - (receiver->rekey_acks_available % 3)) / 3; 2667 - (receiver->rekey_acks_available % 3)) / 3;
2781 is_ss_rekey_sequence_allowed_zero = (0 == 2668 is_ss_rekey_sequence_allowed_zero = (0 ==
@@ -2801,30 +2688,31 @@ send_UDPRekey (struct ReceiverAddress *receiver, struct SharedSecret *ss)
2801 2688
2802 if (NULL != ss) 2689 if (NULL != ss)
2803 { 2690 {
2804 rekey = (struct UDPRekey *) rekey_dgram; 2691 box = (struct UDPBox *) rekey_dgram;
2805 ss->sequence_used++; 2692 ss->sequence_used++;
2806 get_kid (&ss->master, ss->sequence_used, &rekey->kid); 2693 get_kid (&ss->master, ss->sequence_used, &box->kid);
2807 receiver->number_rekeying_kce--; 2694 receiver->number_rekeying_kce--;
2808 setup_cipher (&ss->master, ss->sequence_used, &rekey_out_cipher); 2695 setup_cipher (&ss->master, ss->sequence_used, &rekey_out_cipher);
2809 /* Append encrypted payload to dgram */ 2696 /* Append encrypted payload to dgram */
2810 dpos = sizeof(struct UDPRekey); 2697 rekey.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_UDP_REKEY);
2698 rekey.header.size = htons (sizeof (struct UDPRekey));
2811 2699
2812 GNUNET_assert ( 2700 GNUNET_assert (
2813 0 == gcry_cipher_encrypt (rekey_out_cipher, &rekey_dgram[dpos], 2701 0 == gcry_cipher_encrypt (rekey_out_cipher, &rekey,
2814 sizeof(ephemeral_pubkey), 2702 sizeof(struct UDPRekey),
2815 &ephemeral_pubkey, 2703 &box[1],
2816 sizeof(ephemeral_pubkey))); 2704 sizeof(struct UDPRekey)));
2817 dpos += sizeof(ephemeral_pubkey); 2705 dpos = sizeof(struct UDPRekey) + sizeof (struct UDPBox);
2818 do_pad (rekey_out_cipher, &rekey_dgram[dpos], sizeof(rekey_dgram) 2706 do_pad (rekey_out_cipher, &rekey_dgram[dpos], sizeof(rekey_dgram)
2819 - dpos); 2707 - dpos);
2820 GNUNET_assert (0 == gcry_cipher_gettag (rekey_out_cipher, 2708 GNUNET_assert (0 == gcry_cipher_gettag (rekey_out_cipher,
2821 rekey->gcm_tag, 2709 box->gcm_tag,
2822 sizeof(rekey->gcm_tag))); 2710 sizeof(box->gcm_tag)));
2823 gcry_cipher_close (rekey_out_cipher); 2711 gcry_cipher_close (rekey_out_cipher);
2824 2712
2825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2713 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2826 "Sending rekey with kid %s and new pubkey\n", 2714 "Sending rekey with kid %s and new pubkey\n",
2827 GNUNET_sh2s (&rekey->kid)); 2715 GNUNET_sh2s (&box->kid));
2828 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2716 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2829 "Sending rekey with cmac %s\n", 2717 "Sending rekey with cmac %s\n",
2830 GNUNET_h2s (&(receiver->ss_rekey->cmac))); 2718 GNUNET_h2s (&(receiver->ss_rekey->cmac)));
@@ -2901,7 +2789,6 @@ mq_send_d (struct GNUNET_MQ_Handle *mq,
2901 struct UDPBox *box; 2789 struct UDPBox *box;
2902 gcry_cipher_hd_t out_cipher; 2790 gcry_cipher_hd_t out_cipher;
2903 size_t dpos; 2791 size_t dpos;
2904 uint16_t rekey_nbo;
2905 2792
2906 box = (struct UDPBox *) dgram; 2793 box = (struct UDPBox *) dgram;
2907 ss->sequence_used++; 2794 ss->sequence_used++;
@@ -2909,11 +2796,6 @@ mq_send_d (struct GNUNET_MQ_Handle *mq,
2909 setup_cipher (&ss->master, ss->sequence_used, &out_cipher); 2796 setup_cipher (&ss->master, ss->sequence_used, &out_cipher);
2910 /* Append encrypted payload to dgram */ 2797 /* Append encrypted payload to dgram */
2911 dpos = sizeof(struct UDPBox); 2798 dpos = sizeof(struct UDPBox);
2912 rekey_nbo = htons (receiver->rekeying);
2913 GNUNET_assert (
2914 0 == gcry_cipher_encrypt (out_cipher, &dgram[dpos], sizeof (uint16_t),
2915 &rekey_nbo, sizeof (uint16_t)));
2916 dpos += sizeof (uint16_t);
2917 GNUNET_assert ( 2799 GNUNET_assert (
2918 0 == gcry_cipher_encrypt (out_cipher, &dgram[dpos], msize, msg, msize)); 2800 0 == gcry_cipher_encrypt (out_cipher, &dgram[dpos], msize, msg, msize));
2919 dpos += msize; 2801 dpos += msize;