From 3266ea560ea1b243810dce4d46ee2889da7b4f6c Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 16 Apr 2019 19:57:15 +0200 Subject: implement backchannel encryption/decryption --- src/include/gnunet_crypto_lib.h | 20 ++++++++-- src/transport/Makefile.am | 1 + src/transport/gnunet-communicator-tcp.c | 10 ++--- src/transport/gnunet-service-tng.c | 68 ++++++++++++++++++++++++--------- src/util/crypto_random.c | 39 +++++++++++++++++-- 5 files changed, 108 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index 6822de2f1..45da5f6ba 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h @@ -456,6 +456,18 @@ int32_t GNUNET_CRYPTO_crc32_n (const void *buf, size_t len); +/** + * @ingroup crypto + * Zero out @a buffer, securely against compiler optimizations. + * Used to delete key material. + * + * @param buffer the buffer to zap + * @param length buffer length + */ +void +GNUNET_CRYPTO_zero_keys (void *buffer, + size_t length); + /** * @ingroup crypto @@ -721,8 +733,8 @@ GNUNET_CRYPTO_hash_context_abort (struct GNUNET_HashContext *hc); */ void GNUNET_CRYPTO_hmac_raw (const void *key, size_t key_len, - const void *plaintext, size_t plaintext_len, - struct GNUNET_HashCode *hmac); + const void *plaintext, size_t plaintext_len, + struct GNUNET_HashCode *hmac); /** @@ -1866,7 +1878,7 @@ GNUNET_CRYPTO_rsa_private_key_free (struct GNUNET_CRYPTO_RsaPrivateKey *key); */ size_t GNUNET_CRYPTO_rsa_private_key_encode (const struct GNUNET_CRYPTO_RsaPrivateKey *key, - char **buffer); + char **buffer); /** @@ -1879,7 +1891,7 @@ GNUNET_CRYPTO_rsa_private_key_encode (const struct GNUNET_CRYPTO_RsaPrivateKey * */ struct GNUNET_CRYPTO_RsaPrivateKey * GNUNET_CRYPTO_rsa_private_key_decode (const char *buf, - size_t len); + size_t len); /** diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index f83fa669c..53fd9c973 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -374,6 +374,7 @@ gnunet_service_tng_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la \ + $(LIBGCRYPT_LIBS) \ $(GN_LIBINTL) plugin_LTLIBRARIES = \ diff --git a/src/transport/gnunet-communicator-tcp.c b/src/transport/gnunet-communicator-tcp.c index a8f88c5e4..e9223401f 100644 --- a/src/transport/gnunet-communicator-tcp.c +++ b/src/transport/gnunet-communicator-tcp.c @@ -814,9 +814,9 @@ pass_plaintext_to_core (struct Queue *queue, */ static void setup_cipher (const struct GNUNET_HashCode *dh, - const struct GNUNET_PeerIdentity *pid, - gcry_cipher_hd_t *cipher, - struct GNUNET_HashCode *hmac_key) + const struct GNUNET_PeerIdentity *pid, + gcry_cipher_hd_t *cipher, + struct GNUNET_HashCode *hmac_key) { char key[256/8]; char ctr[128/8]; @@ -872,7 +872,7 @@ setup_cipher (const struct GNUNET_HashCode *dh, */ static void setup_in_cipher (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral, - struct Queue *queue) + struct Queue *queue) { struct GNUNET_HashCode dh; @@ -896,7 +896,7 @@ setup_in_cipher (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral, */ static void do_rekey (struct Queue *queue, - const struct TCPRekey *rekey) + const struct TCPRekey *rekey) { struct TcpHandshakeSignature thp; diff --git a/src/transport/gnunet-service-tng.c b/src/transport/gnunet-service-tng.c index bb1656876..53b9ba0c8 100644 --- a/src/transport/gnunet-service-tng.c +++ b/src/transport/gnunet-service-tng.c @@ -33,7 +33,6 @@ * transport-to-transport traffic) * * Implement next: - * - backchannel message encryption & decryption * - DV data structures: * + using DV routes! * - handling of DV-boxed messages that need to be forwarded @@ -59,7 +58,6 @@ * FIXME (without marks in the code!): * - proper use/initialization of timestamps in messages exchanged * during DV learning - * - * * Optimizations: * - use shorthashmap on msg_uuid's when matching reliability/fragment ACKs @@ -3238,21 +3236,32 @@ route_message (const struct GNUNET_PeerIdentity *target, */ struct BackchannelKeyState { - // FIXME: actual data types in this struct are likely still totally wrong /** - * + * State of our block cipher. */ - char hdr_key[128]; + gcry_cipher_hd_t cipher; /** - * + * Actual key material. */ - char body_key[128]; + struct { - /** - * - */ - char hmac_key[128]; + /** + * Key used for HMAC calculations (via #GNUNET_CRYPTO_hmac()). + */ + struct GNUNET_CRYPTO_AuthKey hmac_key; + + /** + * Symmetric key to use for encryption. + */ + char aes_key[256/8]; + + /** + * Counter value to use during setup. + */ + char aes_ctr[128/8]; + + } material; }; @@ -3263,14 +3272,24 @@ bc_setup_key_state_from_km (const struct GNUNET_HashCode *km, { /* must match #dh_key_derive_eph_pub */ GNUNET_assert (GNUNET_YES == - GNUNET_CRYPTO_kdf (key, - sizeof (*key), + GNUNET_CRYPTO_kdf (&key->material, + sizeof (key->material), "transport-backchannel-key", strlen ("transport-backchannel-key"), &km, sizeof (km), iv, sizeof (*iv))); + gcry_cipher_open (&key->cipher, + GCRY_CIPHER_AES256 /* low level: go for speed */, + GCRY_CIPHER_MODE_CTR, + 0 /* flags */); + gcry_cipher_setkey (key->cipher, + &key->material.aes_key, + sizeof (key->material.aes_key)); + gcry_cipher_setctr (key->cipher, + &key->material.aes_ctr, + sizeof (key->material.aes_ctr)); } @@ -3342,7 +3361,10 @@ bc_hmac (const struct BackchannelKeyState *key, const void *data, size_t data_size) { - // FIXME! + GNUNET_CRYPTO_hmac (&key->material.hmac_key, + data, + data_size, + hmac); } @@ -3361,7 +3383,12 @@ bc_encrypt (struct BackchannelKeyState *key, void *dst, size_t in_size) { - // FIXME! + GNUNET_assert (0 == + gcry_cipher_encrypt (key->cipher, + dst, + in_size, + in, + in_size)); } @@ -3380,7 +3407,12 @@ bc_decrypt (struct BackchannelKeyState *key, const void *ciph, size_t out_size) { - // FIXME! + GNUNET_assert (0 == + gcry_cipher_decrypt (key->cipher, + out, + out_size, + ciph, + out_size)); } @@ -3392,7 +3424,9 @@ bc_decrypt (struct BackchannelKeyState *key, static void bc_key_clean (struct BackchannelKeyState *key) { - // FIXME! + gcry_cipher_close (key->cipher); + GNUNET_CRYPTO_zero_keys (&key->material, + sizeof (key->material)); } diff --git a/src/util/crypto_random.c b/src/util/crypto_random.c index 54bea58e1..8bb5f0587 100644 --- a/src/util/crypto_random.c +++ b/src/util/crypto_random.c @@ -96,6 +96,34 @@ GNUNET_CRYPTO_seed_weak_random (int32_t seed) } +/** + * @ingroup crypto + * Zero out @a buffer, securely against compiler optimizations. + * Used to delete key material. + * + * @param buffer the buffer to zap + * @param length buffer length + */ +void +GNUNET_CRYPTO_zero_keys (void *buffer, + size_t length) +{ +#if HAVE_MEMSET_S + memset_s (buffer, + length, + 0, + length); +#elif HAVE_EXPLICIT_BZERO + explicit_bzero (buffer, + length); +#else + volatile unsigned char *p = buffer; + while (length--) + *p++ = 0; +#endif +} + + /** * @ingroup crypto * Fill block with a random values. @@ -105,7 +133,9 @@ GNUNET_CRYPTO_seed_weak_random (int32_t seed) * @param length buffer length */ void -GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length) +GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode, + void *buffer, + size_t length) { #ifdef gcry_fast_random_poll static unsigned int invokeCount; @@ -146,7 +176,7 @@ GNUNET_CRYPTO_random_block (enum GNUNET_CRYPTO_Quality mode, void *buffer, size_ */ uint32_t GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, - uint32_t i) + uint32_t i) { #ifdef gcry_fast_random_poll static unsigned int invokeCount; @@ -202,7 +232,7 @@ GNUNET_CRYPTO_random_u32 (enum GNUNET_CRYPTO_Quality mode, */ unsigned int * GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, - unsigned int n) + unsigned int n) { unsigned int *ret; unsigned int i; @@ -232,7 +262,8 @@ GNUNET_CRYPTO_random_permute (enum GNUNET_CRYPTO_Quality mode, * @return random 64-bit number */ uint64_t -GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, uint64_t max) +GNUNET_CRYPTO_random_u64 (enum GNUNET_CRYPTO_Quality mode, + uint64_t max) { uint64_t ret; uint64_t ul; -- cgit v1.2.3