From 1f58b09c897cadde4e472bd9cb482883a09bceaa Mon Sep 17 00:00:00 2001 From: =?utf8?q?Niels=20M=C3=B6ller?= Date: Wed, 8 Sep 2021 21:30:43 +0200 Subject: [PATCH] Add specialized functions for cbc-aes. --- ChangeLog | 19 ++++++++++ Makefile.in | 3 +- cbc-aes128-encrypt.c | 42 ++++++++++++++++++++ cbc-aes192-encrypt.c | 42 ++++++++++++++++++++ cbc-aes256-encrypt.c | 42 ++++++++++++++++++++ cbc.h | 16 ++++++++ examples/nettle-benchmark.c | 29 +++++++------- nettle-internal.c | 76 ++++++++++++++++++++++++++++++++++++- nettle-internal.h | 8 ++++ testsuite/cbc-test.c | 45 ++++++++++++++++++++++ testsuite/testutils.c | 51 ++++++++++++++----------- 11 files changed, 336 insertions(+), 37 deletions(-) create mode 100644 cbc-aes128-encrypt.c create mode 100644 cbc-aes192-encrypt.c create mode 100644 cbc-aes256-encrypt.c diff --git a/ChangeLog b/ChangeLog index e59aa4c7..e6f95784 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2021-09-08 Niels Möller + + * cbc-aes128-encrypt.c (nettle_cbc_aes128_encrypt): New file and + function. + * cbc-aes192-encrypt.c (cbc_aes192_set_encrypt_key): New file. + * cbc-aes256-encrypt.c (cbc_aes256_set_encrypt_key): New file. + * cbc.h (cbc_aes128_ctx, struct cbc_aes192_ctx, cbc_aes256_ctx): + New context structs. Declare new functions. + * Makefile.in (nettle_SOURCES): Add new files. + * nettle-internal.c (nettle_cbc_aes128, nettle_cbc_aes192) + (nettle_cbc_aes256): New algorithm structs, for tests and + benchmarking. + * testsuite/testutils.c (test_aead): Skip tests of decryption and + authentication, if corresponding function pointers are NULL. + * testsuite/cbc-test.c (test_main): Add tests of new cbc + functions. + * examples/nettle-benchmark.c (time_aead): Skip decrypt benchmark, + if corresponding function pointer is NULL. + 2021-08-16 Niels Möller S390x functions for sha1, sha256 and sha512, from Mamone Tarsha: diff --git a/Makefile.in b/Makefile.in index fe2de5a8..2edafd67 100644 --- a/Makefile.in +++ b/Makefile.in @@ -102,7 +102,8 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c aes-decrypt-table.c \ camellia256-set-encrypt-key.c camellia256-crypt.c \ camellia256-set-decrypt-key.c \ camellia256-meta.c \ - cast128.c cast128-meta.c cbc.c \ + cast128.c cast128-meta.c \ + cbc.c cbc-aes128-encrypt.c cbc-aes192-encrypt.c cbc-aes256-encrypt.c \ ccm.c ccm-aes128.c ccm-aes192.c ccm-aes256.c cfb.c \ siv-cmac.c siv-cmac-aes128.c siv-cmac-aes256.c \ cnd-memcpy.c \ diff --git a/cbc-aes128-encrypt.c b/cbc-aes128-encrypt.c new file mode 100644 index 00000000..7b86645c --- /dev/null +++ b/cbc-aes128-encrypt.c @@ -0,0 +1,42 @@ +/* cbc-aes128-encrypt.c + + Copyright (C) 2021 Niels Möller + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "cbc.h" + +void +cbc_aes128_encrypt(struct cbc_aes128_ctx *ctx, size_t length, uint8_t *dst, const uint8_t *src) +{ + CBC_ENCRYPT(ctx, aes128_encrypt, length, dst, src); +} diff --git a/cbc-aes192-encrypt.c b/cbc-aes192-encrypt.c new file mode 100644 index 00000000..6226e360 --- /dev/null +++ b/cbc-aes192-encrypt.c @@ -0,0 +1,42 @@ +/* cbc-aes192-encrypt.c + + Copyright (C) 2021 Niels Möller + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "cbc.h" + +void +cbc_aes192_encrypt(struct cbc_aes192_ctx *ctx, size_t length, uint8_t *dst, const uint8_t *src) +{ + CBC_ENCRYPT(ctx, aes192_encrypt, length, dst, src); +} diff --git a/cbc-aes256-encrypt.c b/cbc-aes256-encrypt.c new file mode 100644 index 00000000..49240b3d --- /dev/null +++ b/cbc-aes256-encrypt.c @@ -0,0 +1,42 @@ +/* cbc-aes256-encrypt.c + + Copyright (C) 2021 Niels Möller + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + or both in parallel, as here. + + GNU Nettle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#include "cbc.h" + +void +cbc_aes256_encrypt(struct cbc_aes256_ctx *ctx, size_t length, uint8_t *dst, const uint8_t *src) +{ + CBC_ENCRYPT(ctx, aes256_encrypt, length, dst, src); +} diff --git a/cbc.h b/cbc.h index 93b2e739..5fa670f3 100644 --- a/cbc.h +++ b/cbc.h @@ -35,6 +35,7 @@ #define NETTLE_CBC_H_INCLUDED #include "nettle-types.h" +#include "aes.h" #ifdef __cplusplus extern "C" { @@ -43,6 +44,9 @@ extern "C" { /* Name mangling */ #define cbc_encrypt nettle_cbc_encrypt #define cbc_decrypt nettle_cbc_decrypt +#define cbc_aes128_encrypt nettle_cbc_aes128_encrypt +#define cbc_aes192_encrypt nettle_cbc_aes192_encrypt +#define cbc_aes256_encrypt nettle_cbc_aes256_encrypt void cbc_encrypt(const void *ctx, nettle_cipher_func *f, @@ -79,6 +83,18 @@ memcpy((ctx)->iv, (data), sizeof((ctx)->iv)) sizeof((self)->iv), (self)->iv, \ (length), (dst), (src))) +struct cbc_aes128_ctx CBC_CTX(struct aes128_ctx, AES_BLOCK_SIZE); +void +cbc_aes128_encrypt(struct cbc_aes128_ctx *ctx, size_t length, uint8_t *dst, const uint8_t *src); + +struct cbc_aes192_ctx CBC_CTX(struct aes192_ctx, AES_BLOCK_SIZE); +void +cbc_aes192_encrypt(struct cbc_aes192_ctx *ctx, size_t length, uint8_t *dst, const uint8_t *src); + +struct cbc_aes256_ctx CBC_CTX(struct aes256_ctx, AES_BLOCK_SIZE); +void +cbc_aes256_encrypt(struct cbc_aes256_ctx *ctx, size_t length, uint8_t *dst, const uint8_t *src); + #ifdef __cplusplus } #endif diff --git a/examples/nettle-benchmark.c b/examples/nettle-benchmark.c index 9ce3a733..50a5815a 100644 --- a/examples/nettle-benchmark.c +++ b/examples/nettle-benchmark.c @@ -769,21 +769,22 @@ time_aead(const struct nettle_aead *aead) display(aead->name, "encrypt", aead->block_size, time_function(bench_aead_crypt, &info)); } - - { - struct bench_aead_info info; - info.ctx = ctx; - info.crypt = aead->decrypt; - info.data = data; + + if (aead->decrypt) + { + struct bench_aead_info info; + info.ctx = ctx; + info.crypt = aead->decrypt; + info.data = data; - init_key(aead->key_size, key); - aead->set_decrypt_key(ctx, key); - if (aead->set_nonce) - aead->set_nonce (ctx, nonce); + init_key(aead->key_size, key); + aead->set_decrypt_key(ctx, key); + if (aead->set_nonce) + aead->set_nonce (ctx, nonce); - display(aead->name, "decrypt", aead->block_size, - time_function(bench_aead_crypt, &info)); - } + display(aead->name, "decrypt", aead->block_size, + time_function(bench_aead_crypt, &info)); + } if (aead->update) { @@ -933,6 +934,8 @@ main(int argc, char **argv) /* Stream ciphers */ &nettle_arcfour128, &nettle_salsa20, &nettle_salsa20r12, &nettle_chacha, + /* CBC encrypt */ + &nettle_cbc_aes128, &nettle_cbc_aes192, &nettle_cbc_aes256, /* Proper AEAD algorithme. */ &nettle_gcm_aes128, &nettle_gcm_aes192, diff --git a/nettle-internal.c b/nettle-internal.c index 2a809472..e2422a5b 100644 --- a/nettle-internal.c +++ b/nettle-internal.c @@ -38,12 +38,14 @@ #include #include +#include #include "nettle-internal.h" #include "arcfour.h" #include "blowfish.h" -#include "des.h" +#include "cbc.h" #include "chacha.h" +#include "des.h" #include "salsa20.h" /* Wrapper functions discarding the return value. Needed for the @@ -149,3 +151,75 @@ nettle_salsa20r12 = { (nettle_crypt_func *) salsa20r12_crypt, NULL, }; + +static void +cbc_aes128_set_encrypt_key(struct cbc_aes128_ctx *ctx, const uint8_t *key) +{ + aes128_set_encrypt_key(&ctx->ctx, key); +} +static void +cbc_aes128_set_iv(struct cbc_aes128_ctx *ctx, const uint8_t *iv) +{ + CBC_SET_IV(ctx, iv); +} +const struct nettle_aead +nettle_cbc_aes128 = { + "cbc_aes128", sizeof(struct cbc_aes128_ctx), + AES_BLOCK_SIZE, AES128_KEY_SIZE, + AES_BLOCK_SIZE, 0, + (nettle_set_key_func*) cbc_aes128_set_encrypt_key, + NULL, + (nettle_set_key_func*) cbc_aes128_set_iv, + NULL, + (nettle_crypt_func *) cbc_aes128_encrypt, + NULL, + NULL, +}; + +static void +cbc_aes192_set_encrypt_key(struct cbc_aes192_ctx *ctx, const uint8_t *key) +{ + aes192_set_encrypt_key(&ctx->ctx, key); +} +static void +cbc_aes192_set_iv(struct cbc_aes192_ctx *ctx, const uint8_t *iv) +{ + CBC_SET_IV(ctx, iv); +} +const struct nettle_aead +nettle_cbc_aes192 = { + "cbc_aes192", sizeof(struct cbc_aes192_ctx), + AES_BLOCK_SIZE, AES192_KEY_SIZE, + AES_BLOCK_SIZE, 0, + (nettle_set_key_func*) cbc_aes192_set_encrypt_key, + NULL, + (nettle_set_key_func*) cbc_aes192_set_iv, + NULL, + (nettle_crypt_func *) cbc_aes192_encrypt, + NULL, + NULL, +}; + +static void +cbc_aes256_set_encrypt_key(struct cbc_aes256_ctx *ctx, const uint8_t *key) +{ + aes256_set_encrypt_key(&ctx->ctx, key); +} +static void +cbc_aes256_set_iv(struct cbc_aes256_ctx *ctx, const uint8_t *iv) +{ + CBC_SET_IV(ctx, iv); +} +const struct nettle_aead +nettle_cbc_aes256 = { + "cbc_aes256", sizeof(struct cbc_aes256_ctx), + AES_BLOCK_SIZE, AES256_KEY_SIZE, + AES_BLOCK_SIZE, 0, + (nettle_set_key_func*) cbc_aes256_set_encrypt_key, + NULL, + (nettle_set_key_func*) cbc_aes256_set_iv, + NULL, + (nettle_crypt_func *) cbc_aes256_encrypt, + NULL, + NULL, +}; diff --git a/nettle-internal.h b/nettle-internal.h index 9203a232..ddc483de 100644 --- a/nettle-internal.h +++ b/nettle-internal.h @@ -97,10 +97,18 @@ extern const struct nettle_aead nettle_arcfour128; extern const struct nettle_aead nettle_chacha; extern const struct nettle_aead nettle_salsa20; extern const struct nettle_aead nettle_salsa20r12; + +/* All-in-one CBC encrypt fucntinos treated as AEAD with no + authentication and no decrypt method. */ +extern const struct nettle_aead nettle_cbc_aes128; +extern const struct nettle_aead nettle_cbc_aes192; +extern const struct nettle_aead nettle_cbc_aes256; + extern const struct nettle_aead nettle_openssl_gcm_aes128; extern const struct nettle_aead nettle_openssl_gcm_aes192; extern const struct nettle_aead nettle_openssl_gcm_aes256; + /* Glue to openssl, for comparative benchmarking. Code in * examples/nettle-openssl.c. */ extern void nettle_openssl_init(void); diff --git a/testsuite/cbc-test.c b/testsuite/cbc-test.c index 9394f1cb..d83b108b 100644 --- a/testsuite/cbc-test.c +++ b/testsuite/cbc-test.c @@ -2,6 +2,7 @@ #include "aes.h" #include "cbc.h" #include "knuth-lfib.h" +#include "nettle-internal.h" /* Test with more data and inplace decryption, to check that the * cbc_decrypt buffering works. */ @@ -114,6 +115,20 @@ test_main(void) "73bed6b8e3c1743b7116e69e22229516" "3ff1caa1681fac09120eca307586e1a7"), SHEX("000102030405060708090a0b0c0d0e0f")); + + test_aead(&nettle_cbc_aes128, NULL, + SHEX("2b7e151628aed2a6abf7158809cf4f3c"), + NULL, + SHEX("6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710"), + SHEX("7649abac8119b246cee98e9b12e9197d" + "5086cb9b507219ee95db113a917678b2" + "73bed6b8e3c1743b7116e69e22229516" + "3ff1caa1681fac09120eca307586e1a7"), + SHEX("000102030405060708090a0b0c0d0e0f"), + NULL); /* F.2.3 CBC-AES192.Encrypt */ @@ -137,6 +152,21 @@ test_main(void) "571b242012fb7ae07fa9baac3df102e0" "08b0e27988598881d920a9e64f5615cd"), SHEX("000102030405060708090a0b0c0d0e0f")); + + test_aead(&nettle_cbc_aes192, NULL, + SHEX("8e73b0f7da0e6452c810f32b809079e5" + "62f8ead2522c6b7b"), + NULL, + SHEX("6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710"), + SHEX("4f021db243bc633d7178183a9fa071e8" + "b4d9ada9ad7dedf4e5e738763f69145a" + "571b242012fb7ae07fa9baac3df102e0" + "08b0e27988598881d920a9e64f5615cd"), + SHEX("000102030405060708090a0b0c0d0e0f"), + NULL); /* F.2.5 CBC-AES256.Encrypt */ @@ -161,6 +191,21 @@ test_main(void) "b2eb05e2c39be9fcda6c19078c6a9d1b"), SHEX("000102030405060708090a0b0c0d0e0f")); + test_aead(&nettle_cbc_aes256, NULL, + SHEX("603deb1015ca71be2b73aef0857d7781" + "1f352c073b6108d72d9810a30914dff4"), + NULL, + SHEX("6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710"), + SHEX("f58c4c04d6e5f1ba779eabfb5f7bfbd6" + "9cfc4e967edb808d679f777bc6702c7d" + "39f23369a9d9bacfa530e26304231461" + "b2eb05e2c39be9fcda6c19078c6a9d1b"), + SHEX("000102030405060708090a0b0c0d0e0f"), + NULL); + test_cbc_bulk(); } diff --git a/testsuite/testutils.c b/testsuite/testutils.c index 2c6cac40..b46a6abf 100644 --- a/testsuite/testutils.c +++ b/testsuite/testutils.c @@ -804,7 +804,6 @@ test_aead(const struct nettle_aead *aead, length = cleartext->length; ASSERT (key->length == aead->key_size); - ASSERT (digest->length <= aead->digest_size); data = xalloc(length); @@ -820,41 +819,49 @@ test_aead(const struct nettle_aead *aead, else aead->set_nonce(ctx, nonce->data); - if (authtext->length) + if (aead->update && authtext->length) aead->update(ctx, authtext->length, authtext->data); - + if (length) aead->encrypt(ctx, length, data, cleartext->data); - aead->digest(ctx, digest->length, buffer); + if (digest) + { + ASSERT (digest->length <= aead->digest_size); + aead->digest(ctx, digest->length, buffer); + ASSERT(MEMEQ(digest->length, buffer, digest->data)); + } + else + ASSERT(!aead->digest); ASSERT(MEMEQ(length, data, ciphertext->data)); - ASSERT(MEMEQ(digest->length, buffer, digest->data)); /* decryption */ - memset(buffer, 0, aead->digest_size); + if (aead->set_decrypt_key) + { + memset(buffer, 0, aead->digest_size); - aead->set_decrypt_key(ctx, key->data); + aead->set_decrypt_key(ctx, key->data); - if (nonce->length != aead->nonce_size) - { - ASSERT (set_nonce); - set_nonce (ctx, nonce->length, nonce->data); - } - else - aead->set_nonce(ctx, nonce->data); + if (nonce->length != aead->nonce_size) + { + ASSERT (set_nonce); + set_nonce (ctx, nonce->length, nonce->data); + } + else + aead->set_nonce(ctx, nonce->data); - if (authtext->length) - aead->update(ctx, authtext->length, authtext->data); + if (authtext->length) + aead->update(ctx, authtext->length, authtext->data); - if (length) - aead->decrypt(ctx, length, data, data); + if (length) + aead->decrypt(ctx, length, data, data); - aead->digest(ctx, digest->length, buffer); - - ASSERT(MEMEQ(length, data, cleartext->data)); - ASSERT(MEMEQ(digest->length, buffer, digest->data)); + aead->digest(ctx, digest->length, buffer); + ASSERT(MEMEQ(length, data, cleartext->data)); + ASSERT(MEMEQ(digest->length, buffer, digest->data)); + } free(ctx); free(data); free(buffer); -- 2.47.2