Add rc5 ciphers to default provider
authorShane Lontis <shane.lontis@oracle.com>
Thu, 3 Oct 2019 06:05:49 +0000 (16:05 +1000)
committerShane Lontis <shane.lontis@oracle.com>
Thu, 3 Oct 2019 06:05:49 +0000 (16:05 +1000)
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10006)

18 files changed:
crypto/err/openssl.txt
crypto/evp/evp_enc.c
doc/man7/provider-cipher.pod
include/openssl/core_names.h
providers/common/ciphers/cipher_common.c
providers/common/ciphers/cipher_local.h
providers/common/include/internal/ciphers/ciphercommon.h
providers/common/include/internal/provider_algs.h
providers/common/include/internal/providercommonerr.h
providers/common/provider_err.c
providers/default/ciphers/build.info
providers/default/ciphers/cipher_rc5.c [new file with mode: 0644]
providers/default/ciphers/cipher_rc5.h [new file with mode: 0644]
providers/default/ciphers/cipher_rc5_hw.c [new file with mode: 0644]
providers/default/defltprov.c
test/evp_test.c
test/recipes/30-test_evp.t
test/recipes/30-test_evp_data/evpciph_rc5.txt [new file with mode: 0644]

index c62728b..520ac1f 100644 (file)
@@ -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
index 09c49b6..eb85b26 100644 (file)
@@ -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:
index d5766f4..3bae345 100644 (file)
@@ -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<OSSL_CIPHER_PARAM_ALG_ID>) (octet string)
+=item "alg_id_param" (B<OSSL_CIPHER_PARAM_ALG_ID>) <octet string>
 
 Used to pass the DER encoded AlgorithmIdentifier parameter to or from
 the cipher implementation.  Functions like L<EVP_CIPHER_param_to_asn1(3)>
 and L<EVP_CIPHER_asn1_to_param(3)> use this parameter for any implementation
 that has the flag B<EVP_CIPH_FLAG_CUSTOM_ASN1> set.
 
+=item "rounds" (B<OSSL_CIPHER_PARAM_ROUNDS>) <unsigned integer>
+
+Sets or gets the number of rounds to be used for a cipher.
+This is used by the RC5 cipher.
+
 =back
 
 =head1 RETURN VALUES
index 4659d1f..837c89b 100644 (file)
@@ -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 */
index 3440787..bc8776d 100644 (file)
@@ -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
index cc37a34..898c99b 100644 (file)
@@ -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);
index 9a01abf..e30af4d 100644 (file)
@@ -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,
index 3e23788..08cc706 100644 (file)
@@ -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[];
index 5ce5f32..e813099 100644 (file)
@@ -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 <openssl/opensslconf.h>
 # include <openssl/symhacks.h>
@@ -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
index 27d6837..7d4b1ce 100644 (file)
@@ -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"},
index 76a5135..a42a313 100644 (file)
@@ -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 (file)
index 0000000..645a6b8
--- /dev/null
@@ -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 (file)
index 0000000..c415e18
--- /dev/null
@@ -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 <openssl/rc5.h>
+#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 (file)
index 0000000..a9a05ba
--- /dev/null
@@ -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)
index 7cfec61..bcb897b 100644 (file)
@@ -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 }
 };
 
index 03581ff..0451954 100644 (file)
@@ -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;
index e60f824..7ff3a14 100644 (file)
@@ -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 (file)
index 0000000..300201b
--- /dev/null
@@ -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