From 3768bfad3207bac5e9106ca04e3ab7d9bc996faf Mon Sep 17 00:00:00 2001 From: Fred Morcos Date: Thu, 3 Nov 2022 10:21:03 +0100 Subject: [PATCH] OpenSSL 3.0: decryptCA6 --- pdns/ipcipher.cc | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/pdns/ipcipher.cc b/pdns/ipcipher.cc index 4cd9b09602..1d64cc902d 100644 --- a/pdns/ipcipher.cc +++ b/pdns/ipcipher.cc @@ -113,10 +113,47 @@ static ComboAddress decryptCA6(const ComboAddress& address, const std::string& k ComboAddress ret = address; +#if OPENSSL_VERSION_MAJOR >= 3 + auto ctx = std::unique_ptr(EVP_CIPHER_CTX_new(), &EVP_CIPHER_CTX_free); + if (ctx == nullptr) { + throw pdns::OpenSSL::error("decryptCA6: Could not initialize cipher context"); + } + + auto aes128cbc = std::unique_ptr(EVP_CIPHER_fetch(nullptr, "AES-128-CBC", nullptr), &EVP_CIPHER_free); + + // NOLINTNEXTLINE(*-cast): Using OpenSSL C APIs. + if (EVP_DecryptInit(ctx.get(), aes128cbc.get(), reinterpret_cast(key.c_str()), nullptr) == 0) { + throw pdns::OpenSSL::error("decryptCA6: Could not initialize decryption algorithm"); + } + + // Disable padding + const auto inSize = sizeof(address.sin6.sin6_addr.s6_addr); + static_assert(inSize == 16, "We disable padding and so we must assume a data size of 16 bytes"); + const auto blockSize = EVP_CIPHER_get_block_size(aes128cbc.get()); + assert(blockSize == 16); + EVP_CIPHER_CTX_set_padding(ctx.get(), 0); + + int updateLen = 0; + // NOLINTNEXTLINE(*-cast): Using OpenSSL C APIs. + const auto* input = reinterpret_cast(&address.sin6.sin6_addr.s6_addr); + // NOLINTNEXTLINE(*-cast): Using OpenSSL C APIs. + auto* output = reinterpret_cast(&ret.sin6.sin6_addr.s6_addr); + if (EVP_DecryptUpdate(ctx.get(), output, &updateLen, input, static_cast(inSize)) == 0) { + throw pdns::OpenSSL::error("decryptCA6: Could not decrypt address"); + } + + int finalLen = 0; + if (EVP_DecryptFinal_ex(ctx.get(), output + updateLen, &finalLen) == 0) { + throw pdns::OpenSSL::error("decryptCA6: Could not finalize address decryption"); + } + + assert(updateLen + finalLen == inSize); +#else AES_KEY wctx; AES_set_decrypt_key((const unsigned char*)key.c_str(), 128, &wctx); AES_decrypt((const unsigned char*)&address.sin6.sin6_addr.s6_addr, (unsigned char*)&ret.sin6.sin6_addr.s6_addr, &wctx); +#endif return ret; } -- 2.47.2