From: Nick Mathewson Date: Sun, 20 Apr 2025 22:49:40 +0000 (-0400) Subject: aes: Support for replacing an AES key without free+alloc X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=83b9f63b860efab0473bcfa41c8c12912af2aeca;p=thirdparty%2Ftor.git aes: Support for replacing an AES key without free+alloc --- diff --git a/src/lib/crypt_ops/aes.h b/src/lib/crypt_ops/aes.h index f9e95ccd0d..d6844d9b9d 100644 --- 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 index 55ac5a2edf..f2550e91c1 100644 --- 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 index f28b9211c2..7a03024440 100644 --- a/src/lib/crypt_ops/aes_openssl.c +++ b/src/lib/crypt_ops/aes_openssl.c @@ -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'. */