From 6a41156c20cbccc56c46bf6a5f7d2ac45cc1679a Mon Sep 17 00:00:00 2001 From: Shane Lontis Date: Thu, 3 Oct 2019 16:05:49 +1000 Subject: [PATCH] Add rc5 ciphers to default provider Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/10006) --- crypto/err/openssl.txt | 1 + crypto/evp/evp_enc.c | 15 +- doc/man7/provider-cipher.pod | 7 +- include/openssl/core_names.h | 1 + providers/common/ciphers/cipher_common.c | 12 +- providers/common/ciphers/cipher_local.h | 16 -- .../include/internal/ciphers/ciphercommon.h | 29 ++++ .../common/include/internal/provider_algs.h | 6 + .../include/internal/providercommonerr.h | 5 +- providers/common/provider_err.c | 4 + providers/default/ciphers/build.info | 5 + providers/default/ciphers/cipher_rc5.c | 145 ++++++++++++++++++ providers/default/ciphers/cipher_rc5.h | 25 +++ providers/default/ciphers/cipher_rc5_hw.c | 35 +++++ providers/default/defltprov.c | 6 + test/evp_test.c | 17 ++ test/recipes/30-test_evp.t | 3 + test/recipes/30-test_evp_data/evpciph_rc5.txt | 86 +++++++++++ 18 files changed, 388 insertions(+), 30 deletions(-) create mode 100644 providers/default/ciphers/cipher_rc5.c create mode 100644 providers/default/ciphers/cipher_rc5.h create mode 100644 providers/default/ciphers/cipher_rc5_hw.c create mode 100644 test/recipes/30-test_evp_data/evpciph_rc5.txt diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index c62728b2ea..520ac1f9a4 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2715,6 +2715,7 @@ PROV_R_UNABLE_TO_LOAD_SHA1:143:unable to load sha1 PROV_R_UNABLE_TO_LOAD_SHA256:147:unable to load sha256 PROV_R_UNSUPPORTED_CEK_ALG:145:unsupported cek alg PROV_R_UNSUPPORTED_MAC_TYPE:137:unsupported mac type +PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS:152:unsupported number of rounds PROV_R_VALUE_ERROR:138:value error PROV_R_WRONG_FINAL_BLOCK_LENGTH:107:wrong final block length PROV_R_WRONG_OUTPUT_BUFFER_SIZE:139:wrong output buffer size diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c index 09c49b6202..eb85b26e5a 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -269,7 +269,11 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, case NID_sm4_ofb128: case NID_rc4: case NID_rc4_40: - break; + case NID_rc5_cbc: + case NID_rc5_ecb: + case NID_rc5_cfb64: + case NID_rc5_ofb64: + break; default: goto legacy; } @@ -1069,6 +1073,7 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) int ret = EVP_CTRL_RET_UNSUPPORTED; int set_params = 1; size_t sz = arg; + unsigned int i; OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; if (ctx == NULL || ctx->cipher == NULL) { @@ -1109,6 +1114,14 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED, ptr, sz); break; + case EVP_CTRL_GET_RC5_ROUNDS: + set_params = 0; /* Fall thru */ + case EVP_CTRL_SET_RC5_ROUNDS: + if (arg < 0) + return 0; + i = (unsigned int)arg; + params[0] = OSSL_PARAM_construct_uint(OSSL_CIPHER_PARAM_ROUNDS, &i); + break; case EVP_CTRL_AEAD_GET_TAG: set_params = 0; /* Fall thru */ case EVP_CTRL_AEAD_SET_TAG: diff --git a/doc/man7/provider-cipher.pod b/doc/man7/provider-cipher.pod index d5766f47a5..3bae345b89 100644 --- a/doc/man7/provider-cipher.pod +++ b/doc/man7/provider-cipher.pod @@ -321,13 +321,18 @@ Gets a implementation specific randomly generated key for the associated cipher ctx. This is currently only supported by 3DES (which sets the key to odd parity). -=item "alg_id_param" (B) (octet string) +=item "alg_id_param" (B) Used to pass the DER encoded AlgorithmIdentifier parameter to or from the cipher implementation. Functions like L and L use this parameter for any implementation that has the flag B set. +=item "rounds" (B) + +Sets or gets the number of rounds to be used for a cipher. +This is used by the RC5 cipher. + =back =head1 RETURN VALUES diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h index 4659d1f08d..837c89b60d 100644 --- a/include/openssl/core_names.h +++ b/include/openssl/core_names.h @@ -59,6 +59,7 @@ extern "C" { #define OSSL_CIPHER_PARAM_IVLEN "ivlen" /* size_t */ #define OSSL_CIPHER_PARAM_IV "iv" /* octet_string OR octet_ptr */ #define OSSL_CIPHER_PARAM_NUM "num" /* uint */ +#define OSSL_CIPHER_PARAM_ROUNDS "rounds" /* uint */ #define OSSL_CIPHER_PARAM_AEAD_TAG "tag" /* octet_string */ #define OSSL_CIPHER_PARAM_AEAD_TLS1_AAD "tlsaad" /* octet_string */ #define OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD "tlsaadpad" /* size_t */ diff --git a/providers/common/ciphers/cipher_common.c b/providers/common/ciphers/cipher_common.c index 34407879e6..bc8776d874 100644 --- a/providers/common/ciphers/cipher_common.c +++ b/providers/common/ciphers/cipher_common.c @@ -68,16 +68,8 @@ int cipher_generic_get_params(OSSL_PARAM params[], unsigned int md, CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(cipher_generic) CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(cipher_generic) -static const OSSL_PARAM cipher_known_settable_ctx_params[] = { - OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), - OSSL_PARAM_uint(OSSL_CIPHER_PARAM_PADDING, NULL), - OSSL_PARAM_uint(OSSL_CIPHER_PARAM_NUM, NULL), - OSSL_PARAM_END -}; -const OSSL_PARAM *cipher_generic_settable_ctx_params(void) -{ - return cipher_known_settable_ctx_params; -} +CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(cipher_generic) +CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(cipher_generic) /*- * AEAD cipher functions for OSSL_PARAM gettables and settables diff --git a/providers/common/ciphers/cipher_local.h b/providers/common/ciphers/cipher_local.h index cc37a348ed..898c99b1d3 100644 --- a/providers/common/ciphers/cipher_local.h +++ b/providers/common/ciphers/cipher_local.h @@ -9,21 +9,5 @@ #include "internal/ciphers/ciphercommon.h" -#define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(name) \ -static const OSSL_PARAM name##_known_gettable_ctx_params[] = { \ - OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), \ - OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), \ - OSSL_PARAM_uint(OSSL_CIPHER_PARAM_PADDING, NULL), \ - OSSL_PARAM_uint(OSSL_CIPHER_PARAM_NUM, NULL), \ - OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0), - -#define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(name) \ - OSSL_PARAM_END \ -}; \ -const OSSL_PARAM * name##_gettable_ctx_params(void) \ -{ \ - return name##_known_gettable_ctx_params; \ -} - void padblock(unsigned char *buf, size_t *buflen, size_t blocksize); int unpadblock(unsigned char *buf, size_t *buflen, size_t blocksize); diff --git a/providers/common/include/internal/ciphers/ciphercommon.h b/providers/common/include/internal/ciphers/ciphercommon.h index 9a01abf6cb..e30af4dfbf 100644 --- a/providers/common/include/internal/ciphers/ciphercommon.h +++ b/providers/common/include/internal/ciphers/ciphercommon.h @@ -225,6 +225,35 @@ static int cipher_hw_##NAME##_##MODE##_cipher(PROV_CIPHER_CTX *ctx, \ return 1; \ } +#define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(name) \ +static const OSSL_PARAM name##_known_gettable_ctx_params[] = { \ + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), \ + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), \ + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_PADDING, NULL), \ + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_NUM, NULL), \ + OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_IV, NULL, 0), + +#define CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(name) \ + OSSL_PARAM_END \ +}; \ +const OSSL_PARAM * name##_gettable_ctx_params(void) \ +{ \ + return name##_known_gettable_ctx_params; \ +} + +#define CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(name) \ +static const OSSL_PARAM name##_known_settable_ctx_params[] = { \ + OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), \ + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_PADDING, NULL), \ + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_NUM, NULL), +#define CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(name) \ + OSSL_PARAM_END \ +}; \ +const OSSL_PARAM * name##_settable_ctx_params(void) \ +{ \ + return name##_known_settable_ctx_params; \ +} + size_t fillblock(unsigned char *buf, size_t *buflen, size_t blocksize, const unsigned char **in, size_t *inlen); int trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize, diff --git a/providers/common/include/internal/provider_algs.h b/providers/common/include/internal/provider_algs.h index 3e23788698..08cc7062da 100644 --- a/providers/common/include/internal/provider_algs.h +++ b/providers/common/include/internal/provider_algs.h @@ -159,6 +159,12 @@ extern const OSSL_DISPATCH sm4128ctr_functions[]; extern const OSSL_DISPATCH sm4128ofb128_functions[]; extern const OSSL_DISPATCH sm4128cfb128_functions[]; #endif /* OPENSSL_NO_SM4 */ +#ifndef OPENSSL_NO_RC5 +extern const OSSL_DISPATCH rc5128ecb_functions[]; +extern const OSSL_DISPATCH rc5128cbc_functions[]; +extern const OSSL_DISPATCH rc5128ofb64_functions[]; +extern const OSSL_DISPATCH rc5128cfb64_functions[]; +#endif /* OPENSSL_NO_RC5 */ #ifndef OPENSSL_NO_DES extern const OSSL_DISPATCH tdes_ede3_ecb_functions[]; diff --git a/providers/common/include/internal/providercommonerr.h b/providers/common/include/internal/providercommonerr.h index 5ce5f32e7d..e813099051 100644 --- a/providers/common/include/internal/providercommonerr.h +++ b/providers/common/include/internal/providercommonerr.h @@ -8,8 +8,8 @@ * https://www.openssl.org/source/license.html */ -#ifndef OSSL_PROVIDERS_PROVIDERCOMMONERR_H -# define OSSL_PROVIDERS_PROVIDERCOMMONERR_H +#ifndef OPENSSL_PROVERR_H +# define OPENSSL_PROVERR_H # include # include @@ -96,6 +96,7 @@ int ERR_load_PROV_strings(void); # define PROV_R_UNABLE_TO_LOAD_SHA256 147 # define PROV_R_UNSUPPORTED_CEK_ALG 145 # define PROV_R_UNSUPPORTED_MAC_TYPE 137 +# define PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS 152 # define PROV_R_VALUE_ERROR 138 # define PROV_R_WRONG_FINAL_BLOCK_LENGTH 107 # define PROV_R_WRONG_OUTPUT_BUFFER_SIZE 139 diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c index 27d6837af3..7d4b1ceb01 100644 --- a/providers/common/provider_err.c +++ b/providers/common/provider_err.c @@ -44,6 +44,7 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEY_LEN), "invalid key len"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_KEY_LENGTH), "invalid key length"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MAC), "invalid mac"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MODE), "invalid mode"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_MODE_INT), "invalid mode int"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_SALT_LENGTH), @@ -52,6 +53,7 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_INVALID_TAGLEN), "invalid taglen"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_CEK_ALG), "missing cek alg"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_KEY), "missing key"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_MAC), "missing mac"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_MESSAGE_DIGEST), "missing message digest"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_MISSING_PASS), "missing pass"}, @@ -78,6 +80,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { "unsupported cek alg"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNSUPPORTED_MAC_TYPE), "unsupported mac type"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS), + "unsupported number of rounds"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_VALUE_ERROR), "value error"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_WRONG_FINAL_BLOCK_LENGTH), "wrong final block length"}, diff --git a/providers/default/ciphers/build.info b/providers/default/ciphers/build.info index 76a5135aac..a42a31325e 100644 --- a/providers/default/ciphers/build.info +++ b/providers/default/ciphers/build.info @@ -55,4 +55,9 @@ IF[{- !$disabled{rc4} -}] cipher_rc4.c cipher_rc4_hw.c ENDIF +IF[{- !$disabled{rc5} -}] + SOURCE[../../../libcrypto]=\ + cipher_rc5.c cipher_rc5_hw.c +ENDIF + INCLUDE[../../../libcrypto]=. ../../../crypto diff --git a/providers/default/ciphers/cipher_rc5.c b/providers/default/ciphers/cipher_rc5.c new file mode 100644 index 0000000000..645a6b8b64 --- /dev/null +++ b/providers/default/ciphers/cipher_rc5.c @@ -0,0 +1,145 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Dispatch functions for RC5 cipher modes ecb, cbc, ofb, cfb */ + +#include "cipher_rc5.h" +#include "internal/provider_algs.h" +#include "internal/providercommonerr.h" + +static OSSL_OP_cipher_freectx_fn rc5_freectx; +static OSSL_OP_cipher_dupctx_fn rc5_dupctx; +OSSL_OP_cipher_gettable_ctx_params_fn rc5_gettable_ctx_params; +OSSL_OP_cipher_settable_ctx_params_fn rc5_settable_ctx_params; + +static void rc5_freectx(void *vctx) +{ + PROV_RC5_CTX *ctx = (PROV_RC5_CTX *)vctx; + + OPENSSL_clear_free(ctx, sizeof(*ctx)); +} + +static void *rc5_dupctx(void *ctx) +{ + PROV_RC5_CTX *in = (PROV_RC5_CTX *)ctx; + PROV_RC5_CTX *ret = OPENSSL_malloc(sizeof(*ret)); + + if (ret == NULL) { + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + return NULL; + } + *ret = *in; + + return ret; +} + +static int rc5_set_ctx_params(void *vctx, const OSSL_PARAM params[]) +{ + PROV_RC5_CTX *ctx = (PROV_RC5_CTX *)vctx; + const OSSL_PARAM *p; + + if (!cipher_generic_set_ctx_params(vctx, params)) + return 0; + + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_ROUNDS); + if (p != NULL) { + unsigned int rounds; + + if (!OSSL_PARAM_get_uint(p, &rounds)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); + return 0; + } + if (rounds != RC5_8_ROUNDS + && rounds != RC5_12_ROUNDS + && rounds != RC5_16_ROUNDS) { + ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS); + return 0; + } + ctx->rounds = rounds; + } + return 1; +} + +CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(rc5) + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_ROUNDS, NULL), +CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(rc5) + +CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(rc5) + OSSL_PARAM_uint(OSSL_CIPHER_PARAM_ROUNDS, NULL), +CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(rc5) + + +static int rc5_get_ctx_params(void *vctx, OSSL_PARAM params[]) +{ + PROV_RC5_CTX *ctx = (PROV_RC5_CTX *)vctx; + OSSL_PARAM *p; + + if (!cipher_generic_get_ctx_params(vctx, params)) + return 0; + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_ROUNDS); + if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->rounds)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + return 1; +} + +#define IMPLEMENT_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, \ + blkbits, ivbits, typ) \ +static OSSL_OP_cipher_get_params_fn alg##_##kbits##_##lcmode##_get_params; \ +static int alg##_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \ +{ \ + return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, flags, \ + kbits, blkbits, ivbits); \ +} \ +static OSSL_OP_cipher_newctx_fn alg##_##kbits##_##lcmode##_newctx; \ +static void * alg##_##kbits##_##lcmode##_newctx(void *provctx) \ +{ \ + PROV_##UCALG##_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); \ + if (ctx != NULL) { \ + cipher_generic_initkey(ctx, kbits, blkbits, ivbits, \ + EVP_CIPH_##UCMODE##_MODE, flags, \ + PROV_CIPHER_HW_##alg##_##lcmode(kbits), NULL); \ + ctx->rounds = RC5_12_ROUNDS; \ + } \ + return ctx; \ +} \ +const OSSL_DISPATCH alg##kbits##lcmode##_functions[] = { \ + { OSSL_FUNC_CIPHER_NEWCTX, \ + (void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \ + { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \ + { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \ + { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))cipher_generic_einit }, \ + { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))cipher_generic_dinit }, \ + { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))cipher_generic_##typ##_update },\ + { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))cipher_generic_##typ##_final }, \ + { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))cipher_generic_cipher }, \ + { OSSL_FUNC_CIPHER_GET_PARAMS, \ + (void (*)(void)) alg##_##kbits##_##lcmode##_get_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ + (void (*)(void))cipher_generic_gettable_params }, \ + { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ + (void (*)(void))rc5_get_ctx_params }, \ + { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ + (void (*)(void))rc5_gettable_ctx_params }, \ + { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ + (void (*)(void))rc5_set_ctx_params }, \ + { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ + (void (*)(void))rc5_settable_ctx_params }, \ + { 0, NULL } \ +}; + +/* rc5128ecb_functions */ +IMPLEMENT_cipher(rc5, RC5, ecb, ECB, EVP_CIPH_VARIABLE_LENGTH, 128, 64, 0, block) +/* rc5128cbc_functions */ +IMPLEMENT_cipher(rc5, RC5, cbc, CBC, EVP_CIPH_VARIABLE_LENGTH, 128, 64, 64, block) +/* rc5128ofb64_functions */ +IMPLEMENT_cipher(rc5, RC5, ofb64, OFB, EVP_CIPH_VARIABLE_LENGTH, 128, 8, 64, stream) +/* rc5128cfb64_functions */ +IMPLEMENT_cipher(rc5, RC5, cfb64, CFB, EVP_CIPH_VARIABLE_LENGTH, 128, 8, 64, stream) diff --git a/providers/default/ciphers/cipher_rc5.h b/providers/default/ciphers/cipher_rc5.h new file mode 100644 index 0000000000..c415e18c59 --- /dev/null +++ b/providers/default/ciphers/cipher_rc5.h @@ -0,0 +1,25 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include +#include "internal/ciphers/ciphercommon.h" + +typedef struct prov_blowfish_ctx_st { + PROV_CIPHER_CTX base; /* Must be first */ + union { + OSSL_UNION_ALIGN; + RC5_32_KEY ks; /* key schedule */ + } ks; + unsigned int rounds; /* number of rounds */ +} PROV_RC5_CTX; + +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc5_cbc(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc5_ecb(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc5_ofb64(size_t keybits); +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc5_cfb64(size_t keybits); diff --git a/providers/default/ciphers/cipher_rc5_hw.c b/providers/default/ciphers/cipher_rc5_hw.c new file mode 100644 index 0000000000..a9a05ba32f --- /dev/null +++ b/providers/default/ciphers/cipher_rc5_hw.c @@ -0,0 +1,35 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "cipher_rc5.h" + +static int cipher_hw_rc5_initkey(PROV_CIPHER_CTX *ctx, + const unsigned char *key, size_t keylen) +{ + PROV_RC5_CTX *rctx = (PROV_RC5_CTX *)ctx; + + return RC5_32_set_key(&rctx->ks.ks, keylen, key, rctx->rounds); +} + +# define PROV_CIPHER_HW_rc5_mode(mode, UCMODE) \ +IMPLEMENT_CIPHER_HW_##UCMODE(mode, rc5, PROV_RC5_CTX, RC5_32_KEY, \ + RC5_32_##mode) \ +static const PROV_CIPHER_HW rc5_##mode = { \ + cipher_hw_rc5_initkey, \ + cipher_hw_rc5_##mode##_cipher \ +}; \ +const PROV_CIPHER_HW *PROV_CIPHER_HW_rc5_##mode(size_t keybits) \ +{ \ + return &rc5_##mode; \ +} + +PROV_CIPHER_HW_rc5_mode(cbc, CBC) +PROV_CIPHER_HW_rc5_mode(ecb, ECB) +PROV_CIPHER_HW_rc5_mode(ofb64, OFB) +PROV_CIPHER_HW_rc5_mode(cfb64, CFB) diff --git a/providers/default/defltprov.c b/providers/default/defltprov.c index 7cfec618ce..bcb897ba1c 100644 --- a/providers/default/defltprov.c +++ b/providers/default/defltprov.c @@ -241,6 +241,12 @@ static const OSSL_ALGORITHM deflt_ciphers[] = { { "RC4", "default=yes", rc4128_functions }, { "RC4-40", "default=yes", rc440_functions }, #endif /* OPENSSL_NO_RC4 */ +#ifndef OPENSSL_NO_RC5 + { "RC5-ECB", "default=yes", rc5128ecb_functions }, + { "RC5-CBC", "default=yes", rc5128cbc_functions }, + { "RC5-OFB", "default=yes", rc5128ofb64_functions }, + { "RC5-CFB", "default=yes", rc5128cfb64_functions }, +#endif /* OPENSSL_NO_RC5 */ { NULL, NULL, NULL } }; diff --git a/test/evp_test.c b/test/evp_test.c index 03581ff447..04519545f1 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -486,6 +486,7 @@ typedef struct cipher_data_st { unsigned char *key; size_t key_len; unsigned char *iv; + unsigned int rounds; size_t iv_len; unsigned char *plaintext; size_t plaintext_len; @@ -559,6 +560,13 @@ static int cipher_test_parse(EVP_TEST *t, const char *keyword, if (strcmp(keyword, "Key") == 0) return parse_bin(value, &cdat->key, &cdat->key_len); + if (strcmp(keyword, "Rounds") == 0) { + i = atoi(value); + if (i < 0) + return -1; + cdat->rounds = (unsigned int)i; + return 1; + } if (strcmp(keyword, "IV") == 0) return parse_bin(value, &cdat->iv, &cdat->iv_len); if (strcmp(keyword, "Plaintext") == 0) @@ -683,6 +691,15 @@ static int cipher_test_enc(EVP_TEST *t, int enc, } } + if (expected->rounds > 0) { + int rounds = (int)expected->rounds; + + if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC5_ROUNDS, rounds, NULL)) { + t->err = "INVALID_ROUNDS"; + goto err; + } + } + if (!EVP_CIPHER_CTX_set_key_length(ctx, expected->key_len)) { t->err = "INVALID_KEY_LENGTH"; goto err; diff --git a/test/recipes/30-test_evp.t b/test/recipes/30-test_evp.t index e60f82415b..7ff3a14e3e 100644 --- a/test/recipes/30-test_evp.t +++ b/test/recipes/30-test_evp.t @@ -53,6 +53,9 @@ push @defltfiles, @desfiles unless disabled("des"); my @rc4files = qw( evpciph_rc4.txt ); push @defltfiles, @rc4files unless disabled("rc4"); +my @rc5files = qw( evpciph_rc5.txt ); +push @defltfiles, @rc5files unless disabled("rc5"); + plan tests => ($no_fips ? 0 : 1) # FIPS install test + (scalar(@configs) * scalar(@files)) diff --git a/test/recipes/30-test_evp_data/evpciph_rc5.txt b/test/recipes/30-test_evp_data/evpciph_rc5.txt new file mode 100644 index 0000000000..300201b7cb --- /dev/null +++ b/test/recipes/30-test_evp_data/evpciph_rc5.txt @@ -0,0 +1,86 @@ +# +# Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the Apache License 2.0 (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +#The following tests were generated using legacy code, to ensure that the +#provider ciphers have identical results. +Title = RC5 Tests + +Cipher = RC5-ECB +Key = 00000000000000000000000000000000 +Plaintext = 0000000000000000 +Ciphertext = 21a5dbee154b8f6d + +Cipher = RC5-ECB +Key = 00000000000000000000000000000000 +Plaintext = 000102030405060708090A0B0C0D0E0F +Ciphertext = d9d37019aec1161b27d7ad56b21f0f42 + +Cipher = RC5-CBC +Key = 00000000000000000000000000000000 +IV = 0000000000000000 +Plaintext = 0000000000000000 +Ciphertext = 21a5dbee154b8f6d + +Cipher = RC5-CBC +Key = 0102030405060708090A0B0C0D0E0F10 +IV = 0102030405060708 +Plaintext = 000102030405060708090A0B0C0D0E0F +Ciphertext = eeebae12d768ac9e5b3d6072a9c76c65 + +Cipher = RC5-OFB +Key = 00000000000000000000000000000000 +IV = 0000000000000000 +Plaintext = 0000000000000000 +Ciphertext = 21a5dbee154b8f6d + +Cipher = RC5-OFB +Key = 0102030405060708090A0B0C0D0E0F10 +IV = 0102030405060708 +Plaintext = 000102030405060708090A0B0C0D0E0F +Ciphertext = c0ad101b40fc7ffdfc386ea5ecf458b7 + +Cipher = RC5-CFB +Key = 00000000000000000000000000000000 +IV = 0000000000000000 +Plaintext = 0000000000000000 +Ciphertext = 21a5dbee154b8f6d + +Cipher = RC5-CFB +Key = 0102030405060708090A0B0C0D0E0F10 +IV = 0102030405060708 +Plaintext = 000102030405060708090A0B0C0D0E0F +Ciphertext = c0ad101b40fc7ffdeb97c6173bf2987e + +Cipher = RC5-CFB +Key = 0102030405060708090A0B0C0D0E0F10 +IV = 0102030405060708 +Rounds = 8 +Plaintext = 000102030405060708090A0B0C0D0E0F +Ciphertext = 439945301dfa830885ac2f3cf5e61d0e + +Cipher = RC5-CFB +Key = 0102030405060708090A0B0C0D0E0F10 +IV = 0102030405060708 +Rounds = 16 +Plaintext = 000102030405060708090A0B0C0D0E0F +Ciphertext = 5ad80530f4a19e622d03cd4f2b165730 + +#Bad rounds +Cipher = RC5-CFB +Key = 0102030405060708090A0B0C0D0E0F10 +IV = 0102030405060708 +Rounds = 9 +Plaintext = 000102030405060708090A0B0C0D0E0F +Result = INVALID_ROUNDS + +#bigger key +Cipher = RC5-CFB +Key = 0102030405060708090A0B0C0D0E0F101213141516 +IV = 0102030405060708 +Plaintext = 000102030405060708090A0B0C0D0E0F +Ciphertext = b3724d2d9d1b9285e1338fd266c2277d -- 2.25.1