diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index f713d1ce..68dc8f90 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -8,11 +8,14 @@ #include #include "TunnelBase.h" #include -#include "Crypto.h" +#if OPENSSL_HKDF +#include +#endif #if !OPENSSL_AEAD_CHACHA20_POLY1305 #include "ChaCha20.h" #include "Poly1305.h" #endif +#include "Crypto.h" #include "Ed25519.h" #include "I2PEndian.h" #include "Log.h" @@ -1245,6 +1248,30 @@ namespace crypto #endif } + void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, uint8_t * out) + { +#if OPENSSL_HKDF + EVP_PKEY_CTX * pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_HKDF, NULL); + EVP_PKEY_derive_init (pctx); + EVP_PKEY_CTX_set_hkdf_md (pctx, EVP_sha256()); + EVP_PKEY_CTX_set1_hkdf_salt (pctx, salt, 32); + EVP_PKEY_CTX_set1_hkdf_key (pctx, key, keyLen); + if (info.length () > 0) + EVP_PKEY_CTX_add1_hkdf_info (pctx, info.c_str (), info.length ()); + size_t outlen = 64; + EVP_PKEY_derive (pctx, out, &outlen); + EVP_PKEY_CTX_free (pctx); +#else + uint8_t prk[32]; unsigned int len; + HMAC(EVP_sha256(), salt, 32, key, keyLen, prk, &len); + auto l = info.length (); + memcpy (out, info.c_str (), l); out[l] = 0x01; + HMAC(EVP_sha256(), prk, 32, out, l + 1, out, &len); + memcpy (out + 32, info.c_str (), l); out[l + 32] = 0x02; + HMAC(EVP_sha256(), prk, 32, out, l + 33, out + 32, &len); +#endif + } + // init and terminate /* std::vector > m_OpenSSLMutexes; diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index fb1b6fad..5afc4c52 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -27,6 +27,7 @@ # define X509_getm_notAfter X509_get_notAfter #else # define LEGACY_OPENSSL 0 +# define OPENSSL_HKDF 1 # if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1 # define OPENSSL_EDDSA 1 # define OPENSSL_X25519 1 @@ -290,8 +291,13 @@ namespace crypto void AEADChaCha20Poly1305Encrypt (const std::vector >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac); // encrypt multiple buffers with zero ad +// ChaCha20 void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out); +// HKDF + + void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, uint8_t * out); // salt - 32, out - 64, info <= 32 + // init and terminate void InitCrypto (bool precomputation); void TerminateCrypto (); diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 51b885f7..0c0ea35f 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -494,7 +494,7 @@ namespace data // outerSalt = outerCiphertext[0:32] // keys = HKDF(outerSalt, outerInput, "ELS2_L1K", 44) uint8_t keys[64]; // 44 bytes actual data - HKDF (outerCiphertext, {subcredential, 36}, "ELS2_L1K", keys); + i2p::crypto::HKDF (outerCiphertext, subcredential, 36, "ELS2_L1K", keys); // decrypt Layer 1 // outerKey = keys[0:31] // outerIV = keys[32:43] @@ -505,7 +505,7 @@ namespace data // innerSalt = innerCiphertext[0:32] // keys = HKDF(innerSalt, innerInput, "ELS2_L2K", 44) // skip 1 byte flags - HKDF (outerPlainText.data () + 1, {subcredential, 36}, "ELS2_L2K", keys); // no authCookie + i2p::crypto::HKDF (outerPlainText.data () + 1, subcredential, 36, "ELS2_L2K", keys); // no authCookie // decrypt Layer 2 // innerKey = keys[0:31] // innerIV = keys[32:43] @@ -535,24 +535,13 @@ namespace data SHA256_Final (hash, &ctx); } - void LeaseSet2::HKDF (const uint8_t * salt, const std::pair& ikm, const std::string& info, uint8_t * out) - { - uint8_t prk[32]; unsigned int len; - HMAC(EVP_sha256(), salt, 32, ikm.first, ikm.second, prk, &len); - auto l = info.length (); - memcpy (out, info.c_str (), l); out[l] = 0x01; - HMAC(EVP_sha256(), prk, 32, out, l + 1, out, &len); - memcpy (out + 32, info.c_str (), l); out[l + 32] = 0x02; - HMAC(EVP_sha256(), prk, 32, out, l + 33, out + 32, &len); - } - void LeaseSet2::BlindPublicKey (std::shared_ptr identity, const char * date, SigningKeyType blindedKeyType, uint8_t * blindedKey) { uint16_t stA = htobe16 (identity->GetSigningKeyType ()), stA1 = htobe16 (blindedKeyType); uint8_t salt[32], seed[64]; //seed = HKDF(H("I2PGenerateAlpha", keydata), datestring || secret, "i2pblinding1", 64) H ("I2PGenerateAlpha", { {identity->GetSigningPublicKeyBuffer (), identity->GetSigningPublicKeyLen ()}, {(const uint8_t *)&stA, 2}, {(const uint8_t *)&stA1, 2} }, salt); - HKDF (salt, { (const uint8_t *)date, 8 }, "i2pblinding1", seed); + i2p::crypto::HKDF (salt, (const uint8_t *)date, 8, "i2pblinding1", seed); i2p::crypto::GetEd25519 ()->BlindPublicKey (identity->GetSigningPublicKeyBuffer (), seed, blindedKey); } diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index cee5d9d0..d3e7cfc3 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -158,7 +158,6 @@ namespace data // for encrypted LS static void H (const std::string& p, const std::vector >& bufs, uint8_t * hash); - static void HKDF (const uint8_t * salt, const std::pair& ikm, const std::string& info, uint8_t * out); // salt - 32, out - 64, info <= 32 static void BlindPublicKey (std::shared_ptr identity, const char * date, SigningKeyType blindedKeyType, uint8_t * blindedKey); // blinded key 32 bytes, date is 8 chars "YYYYMMDD" private: