From: Fred Morcos Date: Thu, 3 Nov 2022 09:21:03 +0000 (+0100) Subject: OpenSSL 3.0: decryptCA6 X-Git-Tag: dnsdist-1.8.0-rc1~121^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F12411%2Fhead;p=thirdparty%2Fpdns.git OpenSSL 3.0: decryptCA6 --- 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; }