From 8e8abf7a11c70c8dbe79e80c375ab6e133bf35e2 Mon Sep 17 00:00:00 2001 From: Mark Atwood Date: Wed, 7 Oct 2026 18:44:10 +0000 Subject: [PATCH] aes: add AES-128/192/256-OFB --- README.md | 2 +- include/wolfprovider/alg_funcs.h | 8 + include/wolfprovider/settings.h | 3 + src/wp_aes_stream.c | 56 ++++++- src/wp_wolfprov.c | 10 ++ test/test_cipher.c | 268 ++++++++++++++++++++++++++++++- test/unit.c | 6 + test/unit.h | 9 ++ 8 files changed, 353 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 3db632e3..2425c88c 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Information on how to configure, build, and test wolfProvider can be found here: ### Symmetric Ciphers * AES (128, 192, 256-bit keys) - * ECB, CBC, CTR, CFB, CTS + * ECB, CBC, CTR, CFB, OFB, CTS * GCM, CCM (AEAD) * Key Wrap * 3DES-CBC diff --git a/include/wolfprovider/alg_funcs.h b/include/wolfprovider/alg_funcs.h index 771a1a76..5ed7f9d7 100644 --- a/include/wolfprovider/alg_funcs.h +++ b/include/wolfprovider/alg_funcs.h @@ -114,6 +114,10 @@ typedef void (*DFUNC)(void); #define WP_NAMES_AES_192_CFB "AES-192-CFB:2.16.840.1.101.3.4.1.24" #define WP_NAMES_AES_128_CFB "AES-128-CFB:2.16.840.1.101.3.4.1.4" +#define WP_NAMES_AES_256_OFB "AES-256-OFB:2.16.840.1.101.3.4.1.43" +#define WP_NAMES_AES_192_OFB "AES-192-OFB:2.16.840.1.101.3.4.1.23" +#define WP_NAMES_AES_128_OFB "AES-128-OFB:2.16.840.1.101.3.4.1.3" + #define WP_NAMES_AES_256_WRAP \ "AES-256-WRAP:id-aes256-wrap:AES256-WRAP:2.16.840.1.101.3.4.1.45" #define WP_NAMES_AES_192_WRAP \ @@ -423,6 +427,10 @@ extern const OSSL_DISPATCH wp_aes256cfb_functions[]; extern const OSSL_DISPATCH wp_aes192cfb_functions[]; extern const OSSL_DISPATCH wp_aes128cfb_functions[]; +extern const OSSL_DISPATCH wp_aes256ofb_functions[]; +extern const OSSL_DISPATCH wp_aes192ofb_functions[]; +extern const OSSL_DISPATCH wp_aes128ofb_functions[]; + extern const OSSL_DISPATCH wp_aes256wrap_functions[]; extern const OSSL_DISPATCH wp_aes192wrap_functions[]; extern const OSSL_DISPATCH wp_aes128wrap_functions[]; diff --git a/include/wolfprovider/settings.h b/include/wolfprovider/settings.h index cdda021c..9d7d295d 100644 --- a/include/wolfprovider/settings.h +++ b/include/wolfprovider/settings.h @@ -134,6 +134,9 @@ #ifdef WOLFSSL_AES_CFB #define WP_HAVE_AESCFB #endif +#ifdef WOLFSSL_AES_OFB + #define WP_HAVE_AESOFB +#endif #ifndef WC_NO_RNG #define WP_HAVE_RANDOM diff --git a/src/wp_aes_stream.c b/src/wp_aes_stream.c index 0d159535..e1c6b83a 100644 --- a/src/wp_aes_stream.c +++ b/src/wp_aes_stream.c @@ -29,7 +29,8 @@ #include #include -#if defined(WP_HAVE_AESCTR) || defined(WP_HAVE_AESCFB) || defined(WP_HAVE_AESCTS) +#if defined(WP_HAVE_AESCTR) || defined(WP_HAVE_AESCFB) || \ + defined(WP_HAVE_AESOFB) || defined(WP_HAVE_AESCTS) /** * Data structure for AES ciphers that are streaming. @@ -38,7 +39,7 @@ typedef struct wp_AesStreamCtx { /** wolfSSL AES object. */ Aes aes; - /** Cipher mode - CTR, CFB or CTS. */ + /** Cipher mode - CTR, CFB, OFB or CTS. */ int mode; /** Length of key in bytes. */ @@ -323,7 +324,8 @@ static int wp_aes_stream_init(wp_AesStreamCtx *ctx, const unsigned char *key, } if (ok && (iv == NULL) && ctx->ivSet && ((ctx->mode == EVP_CIPH_CBC_MODE) || - (ctx->mode == EVP_CIPH_CFB_MODE))) { + (ctx->mode == EVP_CIPH_CFB_MODE) || + (ctx->mode == EVP_CIPH_OFB_MODE))) { if (!wp_aes_init_iv(ctx, ctx->oiv, ctx->ivLen)) { ok = 0; } @@ -586,7 +588,7 @@ static int wp_aes_cts_decrypt(wp_AesStreamCtx *ctx, unsigned char *out, #endif /* ifdef WP_HAVE_AESCTS */ /** - * Encrypt/decrypt using AES-CTR, AES-CFB or AES-CTS with wolfSSL. + * Encrypt/decrypt using AES-CTR, AES-CFB, AES-OFB or AES-CTS with wolfSSL. * * Assumes out has inLen bytes available. * Assumes whole blocks only. @@ -657,6 +659,35 @@ static int wp_aes_stream_doit(wp_AesStreamCtx *ctx, unsigned char *out, } else #endif +#ifdef WP_HAVE_AESOFB + if (ctx->mode == EVP_CIPH_OFB_MODE) { + XMEMCPY(&ctx->aes.reg, ctx->iv, ctx->ivLen); + while (ok && (inLen > 0)) { + /* Cap chunk to largest word32 multiple of AES_BLOCK_SIZE so the + * IV state is consistent across chunk boundaries. */ + word32 chunk = (inLen > 0xFFFFFFF0U) ? 0xFFFFFFF0U : (word32)inLen; + int rc; + if (ctx->enc) { + rc = wc_AesOfbEncrypt(&ctx->aes, out, in, chunk); + } + else { + rc = wc_AesOfbDecrypt(&ctx->aes, out, in, chunk); + } + if (rc != 0) { + WOLFPROV_MSG_DEBUG_RETCODE(WP_LOG_LEVEL_DEBUG, + "wc_AesOfbEncrypt/wc_AesOfbDecrypt", rc); + ok = 0; + } + in += chunk; + out += chunk; + inLen -= chunk; + } + if (ok) { + XMEMCPY(ctx->iv, ctx->aes.reg, ctx->ivLen); + } + } + else +#endif #ifdef WP_HAVE_AESCTS if (ctx->mode == EVP_CIPH_CBC_MODE) { if (ctx->updated) { @@ -923,7 +954,7 @@ static int wp_aes_stream_set_ctx_params(wp_AesStreamCtx *ctx, * @param [in, out] ctx AES stream context object. * @param [in] kBits Number of bits in a valid key. * @param [in] ivBits Number of bits in a valid IV. 0 indicates no IV. - * @param [in] mode AES stream mode: CTR, CFB or CTS. + * @param [in] mode AES stream mode: CTR, CFB, OFB or CTS. * @return 1 on success. * @return 0 on failure. */ @@ -1031,6 +1062,18 @@ IMPLEMENT_AES_STREAM(cfb, CFB, 0, 192, 128) IMPLEMENT_AES_STREAM(cfb, CFB, 0, 128, 128) #endif /* WP_HAVE_AESCFB */ +/* + * AES OFB + */ +#ifdef WP_HAVE_AESOFB +/** wp_aes256ofb_functions */ +IMPLEMENT_AES_STREAM(ofb, OFB, 0, 256, 128) +/** wp_aes192ofb_functions */ +IMPLEMENT_AES_STREAM(ofb, OFB, 0, 192, 128) +/** wp_aes128ofb_functions */ +IMPLEMENT_AES_STREAM(ofb, OFB, 0, 128, 128) +#endif /* WP_HAVE_AESOFB */ + /* * AES CTS * @@ -1046,5 +1089,6 @@ IMPLEMENT_AES_STREAM(cts, CBC, EVP_CIPH_FLAG_CTS, 192, 128) IMPLEMENT_AES_STREAM(cts, CBC, EVP_CIPH_FLAG_CTS, 128, 128) #endif /* WP_HAVE_AESCTS */ -#endif /* WP_HAVE_AESCTR || WP_HAVE_AESCFB || WP_HAVE_AESCTS */ +#endif /* WP_HAVE_AESCTR || WP_HAVE_AESCFB || WP_HAVE_AESOFB || + * WP_HAVE_AESCTS */ diff --git a/src/wp_wolfprov.c b/src/wp_wolfprov.c index 69446838..3dc3730b 100644 --- a/src/wp_wolfprov.c +++ b/src/wp_wolfprov.c @@ -531,6 +531,16 @@ static const OSSL_ALGORITHM wolfprov_ciphers[] = { "" }, #endif +#ifdef WP_HAVE_AESOFB + /* AES-OFB */ + { WP_NAMES_AES_256_OFB, WOLFPROV_PROPERTIES, wp_aes256ofb_functions, + "" }, + { WP_NAMES_AES_192_OFB, WOLFPROV_PROPERTIES, wp_aes192ofb_functions, + "" }, + { WP_NAMES_AES_128_OFB, WOLFPROV_PROPERTIES, wp_aes128ofb_functions, + "" }, +#endif + #ifdef WP_HAVE_AESCTS /* AES-CTS */ { WP_NAMES_AES_256_CTS, WOLFPROV_PROPERTIES, wp_aes256cts_functions, diff --git a/test/test_cipher.c b/test/test_cipher.c index f0172569..9c0238f0 100644 --- a/test/test_cipher.c +++ b/test/test_cipher.c @@ -22,7 +22,8 @@ #if defined(WP_HAVE_DES3CBC) || defined(WP_HAVE_AESCBC) || \ defined(WP_HAVE_AESECB) || defined(WP_HAVE_AESCTR) || \ - defined(WP_HAVE_AESCFB) || defined(WP_HAVE_AESCTS) + defined(WP_HAVE_AESCFB) || defined(WP_HAVE_AESOFB) || \ + defined(WP_HAVE_AESCTS) static int test_cipher_enc(const EVP_CIPHER *cipher, unsigned char *key, unsigned char *iv, @@ -181,7 +182,8 @@ static int test_cipher_enc_dec(void *data, const char *cipher, int keyLen, #if defined(WP_HAVE_DES3CBC) || defined(WP_HAVE_AESCBC) || \ defined(WP_HAVE_AESECB) || defined(WP_HAVE_AESCTR) || \ - defined(WP_HAVE_AESCFB) || defined(WP_HAVE_AESCTS) + defined(WP_HAVE_AESCFB) || defined(WP_HAVE_AESOFB) || \ + defined(WP_HAVE_AESCTS) /******************************************************************************/ @@ -1026,6 +1028,268 @@ int test_aes128_cfb_reinit(void *data) #endif /* WP_HAVE_AESCFB */ +#ifdef WP_HAVE_AESOFB + +int test_aes128_ofb_stream(void *data) +{ + int err; + + err = test_stream_enc_dec(data, "AES-128-OFB", 16, 16, 16, 0); + if (err == 0) + err = test_stream_enc_dec(data, "AES-128-OFB", 16, 16, 1, 0); + + return err; +} + +/******************************************************************************/ + +int test_aes192_ofb_stream(void *data) +{ + int err; + + err = test_stream_enc_dec(data, "AES-192-OFB", 24, 16, 15, 0); + if (err == 0) + err = test_stream_enc_dec(data, "AES-192-OFB", 24, 16, 2, 0); + + return err; +} + +/******************************************************************************/ + +int test_aes256_ofb_stream(void *data) +{ + int err; + + err = test_stream_enc_dec(data, "AES-256-OFB", 32, 16, 14, 0); + if (err == 0) + err = test_stream_enc_dec(data, "AES-256-OFB", 32, 16, 3, 0); + + return err; +} + +/******************************************************************************/ + +/* NIST CAVP AESAVS multi-block message test vectors for OFB, from aesmmt.zip + * (OFBMMT128.rsp, OFBMMT192.rsp, OFBMMT256.rsp), COUNT = 2 of each + * [ENCRYPT] and [DECRYPT] section. */ +static const struct { + const char *cipher; + int keyLen; + unsigned char key[32]; + unsigned char iv[16]; + unsigned char pt[48]; + unsigned char ct[48]; +} ofbKat[] = { + /* OFBMMT128.rsp [ENCRYPT] COUNT = 2 */ + { "AES-128-OFB", 16, + { + 0x7a, 0x70, 0xcc, 0x6b, 0x26, 0x1e, 0xec, 0xcb, 0x05, 0xc5, 0x71, 0x17, + 0xd5, 0x76, 0x31, 0x97 + }, + { + 0xbb, 0x7b, 0x96, 0x67, 0xfb, 0xd7, 0x6d, 0x5e, 0xe2, 0x04, 0x82, 0x87, + 0x69, 0xa3, 0x41, 0xb1 + }, + { + 0x82, 0x3c, 0xba, 0xae, 0x37, 0x60, 0xc8, 0x55, 0x12, 0xa3, 0xc8, 0x3f, + 0xd6, 0x0b, 0xb5, 0x4b, 0x7c, 0xfc, 0x73, 0x9b, 0x29, 0x5b, 0x63, 0xe0, + 0x5e, 0xf4, 0x35, 0xd8, 0x6e, 0x19, 0xfd, 0x15, 0x36, 0x8c, 0x89, 0xff, + 0x08, 0xa0, 0xf2, 0x1c, 0xe8, 0x9a, 0x72, 0x8f, 0xfb, 0x5d, 0x75, 0xdf + }, + { + 0xf5, 0xc4, 0x9a, 0xae, 0x8a, 0x02, 0x6b, 0xf0, 0x5e, 0x52, 0x5a, 0x12, + 0xab, 0x7e, 0x19, 0x5e, 0xea, 0x8a, 0x1b, 0x71, 0xa8, 0xd3, 0x2a, 0x51, + 0x13, 0xaa, 0x89, 0x74, 0x85, 0x8f, 0x2c, 0xfc, 0x03, 0x39, 0x80, 0x50, + 0x03, 0xa0, 0xcb, 0x1a, 0x7b, 0xe1, 0x9f, 0x37, 0x6d, 0x46, 0x04, 0xeb + } }, + /* OFBMMT128.rsp [DECRYPT] COUNT = 2 */ + { "AES-128-OFB", 16, + { + 0x6a, 0x8f, 0x64, 0x87, 0xe7, 0x60, 0x58, 0xbc, 0x5a, 0x12, 0x62, 0x76, + 0xe4, 0x8f, 0xdd, 0x77 + }, + { + 0x6e, 0x75, 0xd8, 0xb8, 0xac, 0x09, 0x76, 0x14, 0x3e, 0xa1, 0x03, 0xa7, + 0x10, 0xca, 0xec, 0x02 + }, + { + 0x42, 0x4d, 0xdc, 0x34, 0x30, 0x67, 0x61, 0x2f, 0xdb, 0x42, 0x69, 0x20, + 0xf4, 0x0a, 0xb4, 0xd8, 0x2e, 0x3d, 0x4f, 0x94, 0x85, 0xb0, 0x7f, 0xef, + 0x91, 0x61, 0x75, 0x56, 0xd3, 0x09, 0x38, 0x74, 0x84, 0x0e, 0x81, 0x10, + 0xff, 0x37, 0x5b, 0x7a, 0x68, 0xf9, 0x8c, 0x47, 0x1c, 0xa1, 0x0a, 0xcc + }, + { + 0x29, 0xc3, 0x60, 0xfa, 0xc9, 0xb3, 0x61, 0xc4, 0x49, 0xe1, 0x12, 0x41, + 0x5e, 0x3a, 0x7a, 0xef, 0xe1, 0x49, 0xca, 0xcb, 0x2d, 0x08, 0xe2, 0xc2, + 0xc9, 0xf6, 0x17, 0x68, 0x47, 0x69, 0x34, 0xec, 0x6b, 0x26, 0xbe, 0x4c, + 0x90, 0x2f, 0x7d, 0xc5, 0x48, 0xdc, 0x37, 0x8e, 0x43, 0x2d, 0xbf, 0xc5 + } }, + /* OFBMMT192.rsp [ENCRYPT] COUNT = 2 */ + { "AES-192-OFB", 24, + { + 0x15, 0x5f, 0x12, 0x74, 0x4f, 0x6c, 0xf7, 0xe1, 0xf1, 0x08, 0xdf, 0x34, + 0x1c, 0x5e, 0x9c, 0x02, 0xdd, 0xd4, 0x48, 0x12, 0xb2, 0x85, 0xe4, 0x6f + }, + { + 0x85, 0x5a, 0x58, 0x99, 0x18, 0x04, 0x72, 0x42, 0x7a, 0x10, 0x02, 0xc0, + 0xba, 0x5a, 0x3d, 0xff + }, + { + 0xe7, 0xef, 0xcd, 0x84, 0xd5, 0x2e, 0x30, 0x37, 0x6d, 0x96, 0xac, 0xe9, + 0x21, 0x60, 0xe2, 0xce, 0x24, 0x7e, 0x4b, 0x82, 0x74, 0x8c, 0x67, 0x9d, + 0x18, 0x04, 0x18, 0x87, 0xa6, 0xb1, 0x48, 0x8e, 0x09, 0x66, 0xd2, 0x35, + 0x81, 0xef, 0xa0, 0xcf, 0xeb, 0x48, 0x11, 0x4d, 0x43, 0x0d, 0x9d, 0x55 + }, + { + 0xd6, 0x07, 0x9c, 0x22, 0xd7, 0x40, 0x63, 0x7b, 0x24, 0xfd, 0x80, 0x1e, + 0xb0, 0x2a, 0xb2, 0x4e, 0x6d, 0x0f, 0x32, 0xa9, 0xae, 0x7c, 0x0e, 0xaf, + 0xb1, 0x3b, 0x5f, 0xcf, 0xdf, 0x05, 0xe1, 0x81, 0x1c, 0x2e, 0xd7, 0xf3, + 0x37, 0xe1, 0xb9, 0x64, 0xed, 0x0d, 0xa1, 0x09, 0x90, 0xb5, 0x0d, 0xe6 + } }, + /* OFBMMT192.rsp [DECRYPT] COUNT = 2 */ + { "AES-192-OFB", 24, + { + 0x67, 0x06, 0x98, 0x82, 0x10, 0xf6, 0x4a, 0x2a, 0x22, 0xe3, 0x59, 0xbc, + 0x73, 0x1a, 0x6c, 0x90, 0x0b, 0x5a, 0xdf, 0xe8, 0x32, 0x90, 0x71, 0xd3 + }, + { + 0x74, 0x01, 0x4d, 0x44, 0xbd, 0x6a, 0x85, 0x7b, 0xb5, 0xe1, 0x3e, 0x35, + 0x19, 0x45, 0xab, 0x68 + }, + { + 0x1d, 0x5c, 0xff, 0xc8, 0x09, 0x87, 0xda, 0xe1, 0xc5, 0x4a, 0xc1, 0x24, + 0x8b, 0x0b, 0xd6, 0x2c, 0x3e, 0x11, 0x61, 0x63, 0x68, 0xd5, 0xb3, 0x65, + 0xfc, 0xc8, 0xba, 0x3c, 0x22, 0x28, 0xce, 0x4c, 0xbc, 0x6f, 0x0b, 0x22, + 0xd7, 0xd9, 0x0b, 0x7c, 0x9f, 0xd2, 0x04, 0xca, 0x69, 0xa5, 0xa8, 0x3f + }, + { + 0x2d, 0xde, 0x0b, 0xb7, 0x4a, 0x3e, 0x0f, 0x81, 0xa8, 0x2f, 0x54, 0xaa, + 0x86, 0xcb, 0x1c, 0xbb, 0x58, 0x84, 0xa4, 0x4e, 0x60, 0x66, 0x55, 0x74, + 0x7e, 0x9c, 0x3e, 0x55, 0x49, 0x36, 0xc2, 0x16, 0x5e, 0x29, 0x8e, 0x00, + 0xf9, 0x97, 0xcf, 0xde, 0xc2, 0x51, 0xa1, 0xa6, 0xe9, 0x9b, 0xca, 0x5c + } }, + /* OFBMMT256.rsp [ENCRYPT] COUNT = 2 */ + { "AES-256-OFB", 32, + { + 0xc4, 0xc7, 0xfa, 0xd6, 0x53, 0x5c, 0xb8, 0x71, 0x4a, 0x5c, 0x40, 0x77, + 0x9a, 0x8b, 0xa1, 0xd2, 0x53, 0x3e, 0x23, 0xb4, 0xb2, 0x58, 0x73, 0x2a, + 0x5b, 0x78, 0x01, 0xf4, 0xe3, 0x71, 0xa7, 0x94 + }, + { + 0x5e, 0xb9, 0x33, 0x13, 0xb8, 0x71, 0xff, 0x16, 0xb9, 0x8a, 0x9b, 0xcb, + 0x43, 0x33, 0x0d, 0x6f + }, + { + 0x6d, 0x0b, 0xb0, 0x79, 0x63, 0x84, 0x71, 0xe9, 0x39, 0xd4, 0x53, 0x14, + 0x86, 0xc1, 0x4c, 0x25, 0x9a, 0xee, 0xc6, 0xf3, 0xc0, 0x0d, 0xfd, 0xd6, + 0xc0, 0x50, 0xa8, 0xba, 0xa8, 0x20, 0xdb, 0x71, 0xcc, 0x12, 0x2c, 0x4e, + 0x0c, 0x17, 0x15, 0xef, 0x55, 0xf3, 0x99, 0x5a, 0x6b, 0xf0, 0x2a, 0x4c + }, + { + 0x0f, 0x54, 0x61, 0x71, 0x59, 0xd0, 0x3f, 0xfc, 0x1b, 0xfa, 0xfb, 0x60, + 0x29, 0x30, 0xd7, 0x00, 0xf4, 0xa4, 0xa8, 0xe6, 0xdd, 0x93, 0x94, 0x46, + 0x64, 0xd2, 0x19, 0xc4, 0xc5, 0x4d, 0xde, 0x1b, 0x04, 0x53, 0xe1, 0x73, + 0xf5, 0x18, 0x74, 0xae, 0xfd, 0x64, 0xa2, 0xe1, 0xe2, 0x76, 0x13, 0xb0 + } }, + /* OFBMMT256.rsp [DECRYPT] COUNT = 2 */ + { "AES-256-OFB", 32, + { + 0x61, 0x65, 0xcf, 0x1d, 0xc4, 0x8c, 0xad, 0xcc, 0x1b, 0xa0, 0x68, 0xf5, + 0xcf, 0x35, 0xd6, 0x69, 0x7e, 0x42, 0xa0, 0x77, 0x4e, 0x25, 0x3d, 0x0d, + 0x81, 0xe7, 0x21, 0x21, 0x4a, 0xc2, 0x31, 0x4f + }, + { + 0x0c, 0x47, 0xe4, 0x90, 0xb3, 0xc8, 0x3d, 0x32, 0x03, 0x6e, 0xc2, 0x7b, + 0xe7, 0xcc, 0xcf, 0x22 + }, + { + 0xc3, 0xce, 0x73, 0x8b, 0x5a, 0xab, 0xab, 0x83, 0x0c, 0xcd, 0xd8, 0x2e, + 0x3c, 0x58, 0x8e, 0x0a, 0xbd, 0xd0, 0xc7, 0x9c, 0x22, 0x6a, 0x92, 0xdd, + 0xb7, 0x4f, 0x16, 0x36, 0x9c, 0x70, 0x59, 0x3c, 0x93, 0x39, 0xb7, 0xba, + 0x77, 0x0f, 0x60, 0x7a, 0x44, 0xc2, 0x3f, 0xaf, 0xa9, 0xd9, 0x19, 0x23 + }, + { + 0x33, 0x96, 0xe3, 0x0d, 0x12, 0x6a, 0x59, 0x1a, 0xdf, 0x64, 0x89, 0x71, + 0x65, 0x74, 0xb3, 0x23, 0xfd, 0xe0, 0x16, 0x43, 0x01, 0xe7, 0x06, 0xa5, + 0x83, 0xa5, 0x3f, 0xe6, 0x3f, 0x36, 0x79, 0xac, 0xcf, 0x1e, 0x3c, 0x2f, + 0x1e, 0xe8, 0xf6, 0xf9, 0x1f, 0x0e, 0x4b, 0xea, 0xbf, 0x19, 0xac, 0x7e + } }, +}; + +/* Encrypt or decrypt in with wolfProvider: two updates split at an odd + * offset, then re-initialize with a NULL key and IV and do it again in one + * update. Both results must equal exp. */ +static int test_aes_ofb_kat_dir(EVP_CIPHER *cipher, const unsigned char *key, + const unsigned char *iv, const unsigned char *in, + const unsigned char *exp, int len, int enc) +{ + int err; + int outLen; + int fLen; + unsigned char out[48]; + EVP_CIPHER_CTX *ctx; + + err = (ctx = EVP_CIPHER_CTX_new()) == NULL; + if (err == 0) { + err = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc) != 1 + || EVP_CipherUpdate(ctx, out, &outLen, in, 17) != 1 + || EVP_CipherUpdate(ctx, out + outLen, &fLen, in + 17, + len - 17) != 1 + || EVP_CipherFinal_ex(ctx, out + outLen + fLen, &fLen) != 1; + } + if (err == 0 && memcmp(out, exp, len) != 0) { + PRINT_BUFFER("Expected", exp, len); + PRINT_BUFFER("Got", out, len); + err = 1; + } + if (err == 0) { + err = EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, enc) != 1 + || EVP_CipherUpdate(ctx, out, &outLen, in, len) != 1 + || outLen != len; + } + if (err == 0 && memcmp(out, exp, len) != 0) { + PRINT_MSG("OFB reinit with NULL IV did not restore the IV"); + err = 1; + } + + EVP_CIPHER_CTX_free(ctx); + return err; +} + +int test_aes_ofb_kat(void *data) +{ + int err = 0; + size_t i; + EVP_CIPHER *cipher; + + (void)data; + + for (i = 0; (err == 0) && (i < sizeof(ofbKat) / sizeof(*ofbKat)); i++) { + PRINT_MSG("%s", ofbKat[i].cipher); + cipher = EVP_CIPHER_fetch(wpLibCtx, ofbKat[i].cipher, ""); + if (cipher == NULL) { + PRINT_ERR_MSG("Failed to fetch cipher from wolfProvider"); + err = 1; + } + if (err == 0) { + err = EVP_CIPHER_get_key_length(cipher) != ofbKat[i].keyLen; + } + if (err == 0) { + err = test_aes_ofb_kat_dir(cipher, ofbKat[i].key, ofbKat[i].iv, + ofbKat[i].pt, ofbKat[i].ct, sizeof(ofbKat[i].pt), 1); + } + if (err == 0) { + err = test_aes_ofb_kat_dir(cipher, ofbKat[i].key, ofbKat[i].iv, + ofbKat[i].ct, ofbKat[i].pt, sizeof(ofbKat[i].ct), 0); + } + EVP_CIPHER_free(cipher); + } + + return err; +} + +#endif /* WP_HAVE_AESOFB */ + #ifdef WP_HAVE_AESCTS static int test_cipher_cts_enc_err_cases(const EVP_CIPHER *cipher, diff --git a/test/unit.c b/test/unit.c index 2db3f5a0..381df4b6 100644 --- a/test/unit.c +++ b/test/unit.c @@ -307,6 +307,12 @@ TEST_CASE test_case[] = { TEST_DECL(test_aes128_cfb_reinit, NULL), TEST_DECL(test_aes_cfb_large_update, NULL), #endif +#ifdef WP_HAVE_AESOFB + TEST_DECL(test_aes128_ofb_stream, NULL), + TEST_DECL(test_aes192_ofb_stream, NULL), + TEST_DECL(test_aes256_ofb_stream, NULL), + TEST_DECL(test_aes_ofb_kat, NULL), +#endif #ifdef WP_HAVE_AESCTS TEST_DECL(test_aes128_cts, NULL), TEST_DECL(test_aes256_cts, NULL), diff --git a/test/unit.h b/test/unit.h index a315c3a0..7f3c2fc0 100644 --- a/test/unit.h +++ b/test/unit.h @@ -274,6 +274,15 @@ int test_aes_cfb_large_update(void *data); #endif +#ifdef WP_HAVE_AESOFB + +int test_aes128_ofb_stream(void *data); +int test_aes192_ofb_stream(void *data); +int test_aes256_ofb_stream(void *data); +int test_aes_ofb_kat(void *data); + +#endif + int test_cipher_null_zero(void *data); #ifdef WP_HAVE_AESGCM