| 1 | /* |
| 2 | * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. |
| 3 | * |
| 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
| 5 | * this file except in compliance with the License. You can obtain a copy |
| 6 | * in the file LICENSE in the source distribution or at |
| 7 | * https://www.openssl.org/source/license.html |
| 8 | */ |
| 9 | |
| 10 | /* Dispatch functions for RC2 cipher modes ecb, cbc, ofb, cfb */ |
| 11 | |
| 12 | #include "cipher_rc2.h" |
| 13 | #include "prov/implementations.h" |
| 14 | #include "prov/providercommonerr.h" |
| 15 | |
| 16 | #define RC2_40_MAGIC 0xa0 |
| 17 | #define RC2_64_MAGIC 0x78 |
| 18 | #define RC2_128_MAGIC 0x3a |
| 19 | |
| 20 | static OSSL_OP_cipher_freectx_fn rc2_freectx; |
| 21 | static OSSL_OP_cipher_dupctx_fn rc2_dupctx; |
| 22 | static OSSL_OP_cipher_gettable_ctx_params_fn rc2_gettable_ctx_params; |
| 23 | static OSSL_OP_cipher_settable_ctx_params_fn rc2_settable_ctx_params; |
| 24 | |
| 25 | static void rc2_freectx(void *vctx) |
| 26 | { |
| 27 | PROV_RC2_CTX *ctx = (PROV_RC2_CTX *)vctx; |
| 28 | |
| 29 | OPENSSL_clear_free(ctx, sizeof(*ctx)); |
| 30 | } |
| 31 | |
| 32 | static void *rc2_dupctx(void *ctx) |
| 33 | { |
| 34 | PROV_RC2_CTX *in = (PROV_RC2_CTX *)ctx; |
| 35 | PROV_RC2_CTX *ret = OPENSSL_malloc(sizeof(*ret)); |
| 36 | |
| 37 | if (ret == NULL) { |
| 38 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); |
| 39 | return NULL; |
| 40 | } |
| 41 | *ret = *in; |
| 42 | |
| 43 | return ret; |
| 44 | } |
| 45 | |
| 46 | static int rc2_keybits_to_magic(int keybits) |
| 47 | { |
| 48 | switch (keybits) { |
| 49 | case 128: |
| 50 | return RC2_128_MAGIC; |
| 51 | case 64: |
| 52 | return RC2_64_MAGIC; |
| 53 | case 40: |
| 54 | return RC2_40_MAGIC; |
| 55 | } |
| 56 | ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_KEY_SIZE); |
| 57 | return 0; |
| 58 | } |
| 59 | |
| 60 | static int rc2_magic_to_keybits(int magic) |
| 61 | { |
| 62 | switch (magic) { |
| 63 | case RC2_128_MAGIC: |
| 64 | return 128; |
| 65 | case RC2_64_MAGIC: |
| 66 | return 64; |
| 67 | case RC2_40_MAGIC: |
| 68 | return 40; |
| 69 | } |
| 70 | ERR_raise(ERR_LIB_PROV, PROV_R_UNSUPPORTED_KEY_SIZE); |
| 71 | return 0; |
| 72 | } |
| 73 | |
| 74 | static int rc2_get_ctx_params(void *vctx, OSSL_PARAM params[]) |
| 75 | { |
| 76 | PROV_RC2_CTX *ctx = (PROV_RC2_CTX *)vctx; |
| 77 | OSSL_PARAM *p; |
| 78 | |
| 79 | if (!cipher_generic_get_ctx_params(vctx, params)) |
| 80 | return 0; |
| 81 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_RC2_KEYBITS); |
| 82 | if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->key_bits)) { |
| 83 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); |
| 84 | return 0; |
| 85 | } |
| 86 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_ALG_ID); |
| 87 | if (p != NULL) { |
| 88 | long num; |
| 89 | int i; |
| 90 | ASN1_TYPE *type; |
| 91 | unsigned char *d = p->data; |
| 92 | unsigned char **dd = d == NULL ? NULL : &d; |
| 93 | |
| 94 | if (p->data_type != OSSL_PARAM_OCTET_STRING) { |
| 95 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); |
| 96 | return 0; |
| 97 | } |
| 98 | if ((type = ASN1_TYPE_new()) == NULL) { |
| 99 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); |
| 100 | return 0; |
| 101 | } |
| 102 | |
| 103 | /* Is this the original IV or the running IV? */ |
| 104 | num = rc2_keybits_to_magic(ctx->key_bits); |
| 105 | if (!ASN1_TYPE_set_int_octetstring(type, num, |
| 106 | ctx->base.iv, ctx->base.ivlen)) { |
| 107 | ASN1_TYPE_free(type); |
| 108 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); |
| 109 | return 0; |
| 110 | } |
| 111 | /* |
| 112 | * IF the caller has a buffer, we pray to the gods they got the |
| 113 | * size right. There's no way to tell the i2d functions... |
| 114 | */ |
| 115 | i = i2d_ASN1_TYPE(type, dd); |
| 116 | if (i >= 0) |
| 117 | p->return_size = (size_t)i; |
| 118 | |
| 119 | ASN1_TYPE_free(type); |
| 120 | if (i < 0) { |
| 121 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); |
| 122 | return 0; |
| 123 | } |
| 124 | } |
| 125 | return 1; |
| 126 | } |
| 127 | |
| 128 | static int rc2_set_ctx_params(void *vctx, OSSL_PARAM params[]) |
| 129 | { |
| 130 | PROV_RC2_CTX *ctx = (PROV_RC2_CTX *)vctx; |
| 131 | const OSSL_PARAM *p; |
| 132 | |
| 133 | if (!cipher_var_keylen_set_ctx_params(vctx, params)) |
| 134 | return 0; |
| 135 | p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_RC2_KEYBITS); |
| 136 | if (p != NULL) { |
| 137 | if (!OSSL_PARAM_get_size_t(p, &ctx->key_bits)) { |
| 138 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); |
| 139 | return 0; |
| 140 | } |
| 141 | } |
| 142 | p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_ALG_ID); |
| 143 | if (p != NULL) { |
| 144 | ASN1_TYPE *type = NULL; |
| 145 | long num = 0; |
| 146 | const unsigned char *d = p->data; |
| 147 | int ret = 1; |
| 148 | unsigned char iv[16]; |
| 149 | |
| 150 | if (p->data_type != OSSL_PARAM_OCTET_STRING |
| 151 | || ctx->base.ivlen > sizeof(iv) |
| 152 | || (type = d2i_ASN1_TYPE(NULL, &d, p->data_size)) == NULL |
| 153 | || ((size_t)ASN1_TYPE_get_int_octetstring(type, &num, iv, |
| 154 | ctx->base.ivlen) |
| 155 | != ctx->base.ivlen) |
| 156 | || !cipher_generic_initiv(&ctx->base, iv, ctx->base.ivlen) |
| 157 | || (ctx->key_bits = rc2_magic_to_keybits(num)) == 0) { |
| 158 | ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); |
| 159 | ret = 0; |
| 160 | } |
| 161 | ASN1_TYPE_free(type); |
| 162 | if (ret == 0) |
| 163 | return 0; |
| 164 | /* |
| 165 | * This code assumes that the caller will call |
| 166 | * EVP_CipherInit_ex() with a non NULL key in order to setup a key that |
| 167 | * uses the keylen and keybits that were set here. |
| 168 | */ |
| 169 | ctx->base.keylen = ctx->key_bits / 8; |
| 170 | } |
| 171 | return 1; |
| 172 | } |
| 173 | |
| 174 | CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_START(rc2) |
| 175 | OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_RC2_KEYBITS, NULL), |
| 176 | CIPHER_DEFAULT_GETTABLE_CTX_PARAMS_END(rc2) |
| 177 | |
| 178 | CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_START(rc2) |
| 179 | OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), |
| 180 | OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_RC2_KEYBITS, NULL), |
| 181 | CIPHER_DEFAULT_SETTABLE_CTX_PARAMS_END(rc2) |
| 182 | |
| 183 | #define IMPLEMENT_cipher(alg, UCALG, lcmode, UCMODE, flags, kbits, blkbits, \ |
| 184 | ivbits, typ) \ |
| 185 | static OSSL_OP_cipher_get_params_fn alg##_##kbits##_##lcmode##_get_params; \ |
| 186 | static int alg##_##kbits##_##lcmode##_get_params(OSSL_PARAM params[]) \ |
| 187 | { \ |
| 188 | return cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, flags, \ |
| 189 | kbits, blkbits, ivbits); \ |
| 190 | } \ |
| 191 | static OSSL_OP_cipher_newctx_fn alg##_##kbits##_##lcmode##_newctx; \ |
| 192 | static void * alg##_##kbits##_##lcmode##_newctx(void *provctx) \ |
| 193 | { \ |
| 194 | PROV_##UCALG##_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); \ |
| 195 | if (ctx != NULL) { \ |
| 196 | cipher_generic_initkey(ctx, kbits, blkbits, ivbits, \ |
| 197 | EVP_CIPH_##UCMODE##_MODE, flags, \ |
| 198 | PROV_CIPHER_HW_##alg##_##lcmode(kbits), NULL); \ |
| 199 | ctx->key_bits = kbits; \ |
| 200 | } \ |
| 201 | return ctx; \ |
| 202 | } \ |
| 203 | const OSSL_DISPATCH alg##kbits##lcmode##_functions[] = { \ |
| 204 | { OSSL_FUNC_CIPHER_NEWCTX, \ |
| 205 | (void (*)(void)) alg##_##kbits##_##lcmode##_newctx }, \ |
| 206 | { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void)) alg##_freectx }, \ |
| 207 | { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void)) alg##_dupctx }, \ |
| 208 | { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))cipher_generic_einit }, \ |
| 209 | { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))cipher_generic_dinit }, \ |
| 210 | { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))cipher_generic_##typ##_update },\ |
| 211 | { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))cipher_generic_##typ##_final }, \ |
| 212 | { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))cipher_generic_cipher }, \ |
| 213 | { OSSL_FUNC_CIPHER_GET_PARAMS, \ |
| 214 | (void (*)(void)) alg##_##kbits##_##lcmode##_get_params }, \ |
| 215 | { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, \ |
| 216 | (void (*)(void))cipher_generic_gettable_params }, \ |
| 217 | { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, \ |
| 218 | (void (*)(void))rc2_get_ctx_params }, \ |
| 219 | { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, \ |
| 220 | (void (*)(void))rc2_gettable_ctx_params }, \ |
| 221 | { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, \ |
| 222 | (void (*)(void))rc2_set_ctx_params }, \ |
| 223 | { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, \ |
| 224 | (void (*)(void))rc2_settable_ctx_params }, \ |
| 225 | { 0, NULL } \ |
| 226 | }; |
| 227 | |
| 228 | /* rc2128ecb_functions */ |
| 229 | IMPLEMENT_cipher(rc2, RC2, ecb, ECB, EVP_CIPH_VARIABLE_LENGTH, 128, 64, 0, block) |
| 230 | /* rc2128cbc_functions */ |
| 231 | IMPLEMENT_cipher(rc2, RC2, cbc, CBC, EVP_CIPH_VARIABLE_LENGTH, 128, 64, 64, block) |
| 232 | /* rc240cbc_functions */ |
| 233 | IMPLEMENT_cipher(rc2, RC2, cbc, CBC, EVP_CIPH_VARIABLE_LENGTH, 40, 64, 64, block) |
| 234 | /* rc264cbc_functions */ |
| 235 | IMPLEMENT_cipher(rc2, RC2, cbc, CBC, EVP_CIPH_VARIABLE_LENGTH, 64, 64, 64, block) |
| 236 | |
| 237 | /* rc2128ofb128_functions */ |
| 238 | IMPLEMENT_cipher(rc2, RC2, ofb128, OFB, EVP_CIPH_VARIABLE_LENGTH, 128, 8, 64, stream) |
| 239 | /* rc2128cfb128_functions */ |
| 240 | IMPLEMENT_cipher(rc2, RC2, cfb128, CFB, EVP_CIPH_VARIABLE_LENGTH, 128, 8, 64, stream) |
| 241 | |