commit 83b9f63b860efab0473bcfa41c8c12912af2aeca
parent 2f0b83a64d475a7c5572d6bc93c2b41b93dd4e2e
Author: Nick Mathewson <nickm@torproject.org>
Date: Sun, 20 Apr 2025 18:49:40 -0400
aes: Support for replacing an AES key without free+alloc
Diffstat:
3 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/src/lib/crypt_ops/aes.h b/src/lib/crypt_ops/aes.h
@@ -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))
diff --git a/src/lib/crypt_ops/aes_nss.c b/src/lib/crypt_ops/aes_nss.c
@@ -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;
diff --git a/src/lib/crypt_ops/aes_openssl.c b/src/lib/crypt_ops/aes_openssl.c
@@ -422,6 +422,30 @@ aes_raw_new(const uint8_t *key, int key_bits, bool encrypt)
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'.
*/
void