From: Anton Ivanov <anton.iva...@cambridgegreys.com> This allows to leverage the openssl implementation which can use hardware crypto on supported platforms.
UUID generation speed is improved by ~ 12% on an AMD Ryzen with support for AES instructions. Signed-off-by: Anton Ivanov <anton.iva...@cambridgegreys.com> --- lib/aes128.c | 79 +++++++++++++++++++++++++++++++++++++++++++-- lib/aes128.h | 13 +++++--- lib/uuid.c | 6 ++-- tests/test-aes128.c | 6 ++-- 4 files changed, 90 insertions(+), 14 deletions(-) diff --git a/lib/aes128.c b/lib/aes128.c index 98447d14b..8236e8ba0 100644 --- a/lib/aes128.c +++ b/lib/aes128.c @@ -28,6 +28,75 @@ #include "util.h" +#ifdef HAVE_OPENSSL + +#include <openssl/conf.h> +#include <openssl/evp.h> +#include <openssl/err.h> +#include <string.h> +#include "entropy.h" +#include "openvswitch/vlog.h" + +VLOG_DEFINE_THIS_MODULE(aes); + +struct aes128 { + EVP_CIPHER_CTX *ctx; +}; + +void *aes128_schedule(const uint8_t key[16]) +{ + uint8_t iv[16]; + + struct aes128 *aes = xmalloc(sizeof *aes); + + aes->ctx = EVP_CIPHER_CTX_new(); + memset(iv, 0, sizeof iv); + if (EVP_EncryptInit_ex(aes->ctx, EVP_aes_128_cbc(), NULL, key, iv) != 1) { + unsigned long ssl_error = ERR_get_error(); + + ERR_load_crypto_strings(); + VLOG_FATAL("Encryption init failed. Error %s", + ERR_error_string(ssl_error, NULL)); + } + return aes; +} + +void aes128_encrypt(void *aes, const void *plain, void *cipher) +{ + int len; + struct aes128 *aes_ctx = aes; + + if (1 != EVP_EncryptUpdate(aes_ctx->ctx, cipher, &len, plain, 16)) { + unsigned long ssl_error = ERR_get_error(); + + ERR_load_crypto_strings(); + VLOG_FATAL("Encryption failed. Error %s", + ERR_error_string(ssl_error, NULL)); + } +} + +#else + +struct aes128 { + uint32_t rk[128/8 + 28]; +}; + +void *aes128_schedule(const uint8_t key[16]) +{ + return ovs_aes128_schedule(key); +} + +void aes128_encrypt(void *aes, const void *input_, void *output_) +{ + ovs_aes128_encrypt(aes, input_, output_); +} + +#endif + +struct ovs_aes128 { + uint32_t rk[128/8 + 28]; +}; + static const uint32_t Te0[256] = { 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, @@ -390,8 +459,9 @@ put_u32(uint8_t *p, uint32_t x) /* Expands 128-bit 'key' into the encryption key 'schedule'. */ void -aes128_schedule(struct aes128 *aes, const uint8_t key[16]) +*ovs_aes128_schedule(const uint8_t key[16]) { + struct ovs_aes128 *aes = xmalloc(sizeof *aes); uint32_t *rk = aes->rk; int i; @@ -412,14 +482,16 @@ aes128_schedule(struct aes128 *aes, const uint8_t key[16]) rk[7] = rk[3] ^ rk[6]; } ovs_assert(rk == &aes->rk[40]); + return aes; } void -aes128_encrypt(const struct aes128 *aes, const void *input_, void *output_) +ovs_aes128_encrypt(void *aes, const void *input_, void *output_) { const uint8_t *input = input_; uint8_t *output = output_; - const uint32_t *rk = aes->rk; + struct ovs_aes128 *ovs_aes = aes; + const uint32_t *rk = ovs_aes->rk; uint32_t s0, s1, s2, s3; uint32_t t0, t1, t2, t3; int r; @@ -507,3 +579,4 @@ aes128_encrypt(const struct aes128 *aes, const void *input_, void *output_) ^ rk[3]); put_u32(output + 12, s3); } + diff --git a/lib/aes128.h b/lib/aes128.h index f0f55d7cf..3e04e00c4 100644 --- a/lib/aes128.h +++ b/lib/aes128.h @@ -27,11 +27,14 @@ #include <stdint.h> -struct aes128 { - uint32_t rk[128/8 + 28]; -}; -void aes128_schedule(struct aes128 *, const uint8_t key[16]); -void aes128_encrypt(const struct aes128 *, const void *, void *); +void *aes128_schedule(const uint8_t key[16]); +void aes128_encrypt(void *, const void *, void *); + +/* These are exposed for unit test purposes. */ + + +void *ovs_aes128_schedule(const uint8_t key[16]); +void ovs_aes128_encrypt(void *, const void *, void *); #endif /* aes128.h */ diff --git a/lib/uuid.c b/lib/uuid.c index 8a16606da..3e14dcb5f 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -36,7 +36,7 @@ VLOG_DEFINE_THIS_MODULE(uuid); -static struct aes128 key; +static void *key; static uint64_t counter[2]; BUILD_ASSERT_DECL(sizeof counter == 16); @@ -164,7 +164,7 @@ uuid_generate(struct uuid *uuid) ovs_mutex_unlock(&mutex); /* AES output is exactly 16 bytes, so we encrypt directly into 'uuid'. */ - aes128_encrypt(&key, copy, uuid); + aes128_encrypt(key, copy, uuid); uuid_set_bits_v4(uuid); @@ -370,7 +370,7 @@ do_init(void) /* Generate key. */ BUILD_ASSERT(sizeof sha1 >= 16); - aes128_schedule(&key, sha1); + key = aes128_schedule(sha1); /* Generate initial counter. */ get_entropy_or_die(counter, sizeof counter); diff --git a/tests/test-aes128.c b/tests/test-aes128.c index 7960551be..8706a7c7c 100644 --- a/tests/test-aes128.c +++ b/tests/test-aes128.c @@ -46,7 +46,7 @@ error: static void test_aes128_main(int argc, char *argv[]) { - struct aes128 aes; + void *aes; uint8_t plaintext[16]; uint8_t ciphertext[16]; uint8_t key[16]; @@ -60,8 +60,8 @@ test_aes128_main(int argc, char *argv[]) hex_to_uint8(argv[1], key, 16); hex_to_uint8(argv[2], plaintext, 16); - aes128_schedule(&aes, key); - aes128_encrypt(&aes, plaintext, ciphertext); + aes = ovs_aes128_schedule(key); + ovs_aes128_encrypt(aes, plaintext, ciphertext); for (i = 0; i < 16; i++) { printf("%02x", ciphertext[i]); } -- 2.20.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev