]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
OpenSSL 3.0: decryptCA6 12411/head
authorFred Morcos <fred.morcos@open-xchange.com>
Thu, 3 Nov 2022 09:21:03 +0000 (10:21 +0100)
committerFred Morcos <fred.morcos@open-xchange.com>
Thu, 12 Jan 2023 11:11:45 +0000 (12:11 +0100)
pdns/ipcipher.cc

index 4cd9b09602975526f70f5350b23239538420171c..1d64cc902dd759d6a4f136daba8bb9d5676b68f4 100644 (file)
@@ -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, decltype(&EVP_CIPHER_CTX_free)>(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, decltype(&EVP_CIPHER_free)>(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<const unsigned char*>(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<const unsigned char*>(&address.sin6.sin6_addr.s6_addr);
+  // NOLINTNEXTLINE(*-cast): Using OpenSSL C APIs.
+  auto* output = reinterpret_cast<unsigned char*>(&ret.sin6.sin6_addr.s6_addr);
+  if (EVP_DecryptUpdate(ctx.get(), output, &updateLen, input, static_cast<int>(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;
 }