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

index dc9eff76471fac747b70ef2db7166cd9ae925a72..4cd9b09602975526f70f5350b23239538420171c 100644 (file)
@@ -1,5 +1,6 @@
 #include "ipcipher.hh"
 #include "ext/ipcrypt/ipcrypt.h"
+#include <cassert>
 #include <openssl/aes.h>
 #include <openssl/evp.h>
 
@@ -59,10 +60,47 @@ static ComboAddress encryptCA6(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("encryptCA6: 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_EncryptInit(ctx.get(), aes128cbc.get(), reinterpret_cast<const unsigned char*>(key.c_str()), nullptr) == 0) {
+    throw pdns::OpenSSL::error("encryptCA6: Could not initialize encryption 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_EncryptUpdate(ctx.get(), output, &updateLen, input, static_cast<int>(inSize)) == 0) {
+    throw pdns::OpenSSL::error("encryptCA6: Could not encrypt address");
+  }
+
+  int finalLen = 0;
+  if (EVP_EncryptFinal_ex(ctx.get(), output + updateLen, &finalLen) == 0) {
+    throw pdns::OpenSSL::error("encryptCA6: Could not finalize address encryption");
+  }
+
+  assert(updateLen + finalLen == inSize);
+#else
   AES_KEY wctx;
   AES_set_encrypt_key((const unsigned char*)key.c_str(), 128, &wctx);
   AES_encrypt((const unsigned char*)&address.sin6.sin6_addr.s6_addr,
               (unsigned char*)&ret.sin6.sin6_addr.s6_addr, &wctx);
+#endif
 
   return ret;
 }