]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
aes: Support for replacing an AES key without free+alloc
authorNick Mathewson <nickm@torproject.org>
Sun, 20 Apr 2025 22:49:40 +0000 (18:49 -0400)
committerNick Mathewson <nickm@torproject.org>
Wed, 21 May 2025 13:43:51 +0000 (09:43 -0400)
src/lib/crypt_ops/aes.h
src/lib/crypt_ops/aes_nss.c
src/lib/crypt_ops/aes_openssl.c

index f9e95ccd0d5898beb91a0c48fdc9ff5ae0992854..d6844d9b9d0d48b80491ea9dac6fe7b50a7f61f9 100644 (file)
@@ -33,6 +33,8 @@ int evaluate_ctr_for_aes(void);
 typedef struct aes_raw_t aes_raw_t;
 
 aes_raw_t *aes_raw_new(const uint8_t *key, int key_bits, bool encrypt);
+void aes_raw_set_key(aes_raw_t **cipher, const uint8_t *key,
+                     int key_bits, bool encrypt);
 void aes_raw_free_(aes_raw_t *cipher);
 #define aes_raw_free(cipher) \
   FREE_AND_NULL(aes_raw_t, aes_raw_free_, (cipher))
index 55ac5a2edfc777263a760e4aea3be937bb23ec48..f2550e91c1fa1e87b15b6cc2eb082522b5aadd4e 100644 (file)
@@ -162,6 +162,15 @@ aes_raw_free_(aes_raw_t *cipher_)
   PK11_DestroyContext(ctx, PR_TRUE);
 }
 void
+aes_raw_set_key(aes_raw_t **cipher, const uint8_t *key,
+                int key_bits, bool encrypt)
+{
+  // For NSS, I could not find a method to change the key
+  // of an existing context.
+  aes_raw_free(*cipher);
+  *cipher = aes_raw_new(key, key_bits, encrypt);
+}
+void
 aes_raw_encrypt(const aes_raw_t *cipher, uint8_t *block)
 {
   SECStatus s;
index f28b9211c2529f1cc87071542a0c9e646f249c4b..7a03024440fcee7ae11579bfbda7c83b6e546dd9 100644 (file)
@@ -421,6 +421,30 @@ aes_raw_new(const uint8_t *key, int key_bits, bool encrypt)
   EVP_CIPHER_CTX_set_padding(cipher, 0);
   return (aes_raw_t *)cipher;
 }
+/**
+ * Replace the key on an existing aes_raw_t.
+ *
+ * This may be faster than freeing and reallocating.
+ */
+void
+aes_raw_set_key(aes_raw_t **cipher_, const uint8_t *key,
+                int key_bits, bool encrypt)
+{
+  const EVP_CIPHER *c = *(EVP_CIPHER**) cipher_;
+  switch (key_bits) {
+    case 128: c = EVP_aes_128_ecb(); break;
+    case 192: c = EVP_aes_192_ecb(); break;
+    case 256: c = EVP_aes_256_ecb(); break;
+    default: tor_assert_unreached();
+  }
+  aes_raw_t *cipherp = *cipher_;
+  EVP_CIPHER_CTX *cipher = (EVP_CIPHER_CTX *)cipherp;
+  EVP_CIPHER_CTX_reset(cipher);
+  int r = EVP_CipherInit(cipher, c, key, NULL, encrypt);
+  tor_assert(r == 1);
+  EVP_CIPHER_CTX_set_padding(cipher, 0);
+}
+
 /**
  * Release storage held by 'cipher'.
  */