e_rc2.c revision 1.16
1/* $OpenBSD: e_rc2.c,v 1.16 2022/09/04 13:55:39 jsing Exp $ */ 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59#include <stdio.h> 60 61#include <openssl/opensslconf.h> 62 63#ifndef OPENSSL_NO_RC2 64 65#include <openssl/err.h> 66#include <openssl/evp.h> 67#include <openssl/objects.h> 68#include <openssl/rc2.h> 69 70#include "evp_locl.h" 71 72static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, 73 const unsigned char *iv, int enc); 74static int rc2_meth_to_magic(EVP_CIPHER_CTX *ctx); 75static int rc2_magic_to_meth(int i); 76static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); 77static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); 78static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr); 79 80typedef struct { 81 int key_bits; /* effective key bits */ 82 RC2_KEY ks; /* key schedule */ 83} EVP_RC2_KEY; 84 85#define data(ctx) ((EVP_RC2_KEY *)(ctx)->cipher_data) 86 87static int 88rc2_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) 89{ 90 while (inl >= EVP_MAXCHUNK) { 91 RC2_cbc_encrypt(in, out, (long)EVP_MAXCHUNK, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt); 92 inl -= EVP_MAXCHUNK; 93 in += EVP_MAXCHUNK; 94 out += EVP_MAXCHUNK; 95 } 96 97 if (inl) 98 RC2_cbc_encrypt(in, out, (long)inl, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt); 99 100 return 1; 101} 102 103static int 104rc2_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) 105{ 106 size_t chunk = EVP_MAXCHUNK; 107 108 if (inl < chunk) 109 chunk = inl; 110 111 while (inl && inl >= chunk) { 112 RC2_cfb64_encrypt(in, out, (long)inl, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt); 113 inl -= chunk; 114 in += chunk; 115 out += chunk; 116 if (inl < chunk) 117 chunk = inl; 118 } 119 120 return 1; 121} 122 123static int 124rc2_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) 125{ 126 size_t i, bl; 127 128 bl = ctx->cipher->block_size; 129 130 if (inl < bl) 131 return 1; 132 133 inl -= bl; 134 135 for (i = 0; i <= inl; i += bl) 136 RC2_ecb_encrypt(in + i, out + i, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->encrypt); 137 138 return 1; 139} 140 141static int 142rc2_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) 143{ 144 while (inl >= EVP_MAXCHUNK) { 145 RC2_ofb64_encrypt(in, out, (long)EVP_MAXCHUNK, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num); 146 inl -= EVP_MAXCHUNK; 147 in += EVP_MAXCHUNK; 148 out += EVP_MAXCHUNK; 149 } 150 151 if (inl) 152 RC2_ofb64_encrypt(in, out, (long)inl, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num); 153 154 return 1; 155} 156 157static const EVP_CIPHER rc2_cbc = { 158 .nid = NID_rc2_cbc, 159 .block_size = 8, 160 .key_len = RC2_KEY_LENGTH, 161 .iv_len = 8, 162 .flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT | EVP_CIPH_CBC_MODE, 163 .init = rc2_init_key, 164 .do_cipher = rc2_cbc_cipher, 165 .cleanup = NULL, 166 .ctx_size = sizeof(EVP_RC2_KEY), 167 .set_asn1_parameters = rc2_set_asn1_type_and_iv, 168 .get_asn1_parameters = rc2_get_asn1_type_and_iv, 169 .ctrl = rc2_ctrl, 170 .app_data = NULL, 171}; 172 173const EVP_CIPHER * 174EVP_rc2_cbc(void) 175{ 176 return &rc2_cbc; 177} 178 179static const EVP_CIPHER rc2_cfb64 = { 180 .nid = NID_rc2_cfb64, 181 .block_size = 1, 182 .key_len = RC2_KEY_LENGTH, 183 .iv_len = 8, 184 .flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT | EVP_CIPH_CFB_MODE, 185 .init = rc2_init_key, 186 .do_cipher = rc2_cfb64_cipher, 187 .cleanup = NULL, 188 .ctx_size = sizeof(EVP_RC2_KEY), 189 .set_asn1_parameters = rc2_set_asn1_type_and_iv, 190 .get_asn1_parameters = rc2_get_asn1_type_and_iv, 191 .ctrl = rc2_ctrl, 192 .app_data = NULL, 193}; 194 195const EVP_CIPHER * 196EVP_rc2_cfb64(void) 197{ 198 return &rc2_cfb64; 199} 200 201static const EVP_CIPHER rc2_ofb = { 202 .nid = NID_rc2_ofb64, 203 .block_size = 1, 204 .key_len = RC2_KEY_LENGTH, 205 .iv_len = 8, 206 .flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT | EVP_CIPH_OFB_MODE, 207 .init = rc2_init_key, 208 .do_cipher = rc2_ofb_cipher, 209 .cleanup = NULL, 210 .ctx_size = sizeof(EVP_RC2_KEY), 211 .set_asn1_parameters = rc2_set_asn1_type_and_iv, 212 .get_asn1_parameters = rc2_get_asn1_type_and_iv, 213 .ctrl = rc2_ctrl, 214 .app_data = NULL, 215}; 216 217const EVP_CIPHER * 218EVP_rc2_ofb(void) 219{ 220 return &rc2_ofb; 221} 222 223static const EVP_CIPHER rc2_ecb = { 224 .nid = NID_rc2_ecb, 225 .block_size = 8, 226 .key_len = RC2_KEY_LENGTH, 227 .iv_len = 0, 228 .flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT | EVP_CIPH_ECB_MODE, 229 .init = rc2_init_key, 230 .do_cipher = rc2_ecb_cipher, 231 .cleanup = NULL, 232 .ctx_size = sizeof(EVP_RC2_KEY), 233 .set_asn1_parameters = rc2_set_asn1_type_and_iv, 234 .get_asn1_parameters = rc2_get_asn1_type_and_iv, 235 .ctrl = rc2_ctrl, 236 .app_data = NULL, 237}; 238 239const EVP_CIPHER * 240EVP_rc2_ecb(void) 241{ 242 return &rc2_ecb; 243} 244 245#define RC2_40_MAGIC 0xa0 246#define RC2_64_MAGIC 0x78 247#define RC2_128_MAGIC 0x3a 248 249static const EVP_CIPHER r2_64_cbc_cipher = { 250 NID_rc2_64_cbc, 251 8, 8 /* 64 bit */, 8, 252 EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, 253 rc2_init_key, 254 rc2_cbc_cipher, 255 NULL, 256 sizeof(EVP_RC2_KEY), 257 rc2_set_asn1_type_and_iv, 258 rc2_get_asn1_type_and_iv, 259 rc2_ctrl, 260 NULL 261}; 262 263static const EVP_CIPHER r2_40_cbc_cipher = { 264 NID_rc2_40_cbc, 265 8, 5 /* 40 bit */, 8, 266 EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, 267 rc2_init_key, 268 rc2_cbc_cipher, 269 NULL, 270 sizeof(EVP_RC2_KEY), 271 rc2_set_asn1_type_and_iv, 272 rc2_get_asn1_type_and_iv, 273 rc2_ctrl, 274 NULL 275}; 276 277const EVP_CIPHER * 278EVP_rc2_64_cbc(void) 279{ 280 return (&r2_64_cbc_cipher); 281} 282 283const EVP_CIPHER * 284EVP_rc2_40_cbc(void) 285{ 286 return (&r2_40_cbc_cipher); 287} 288 289static int 290rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, 291 const unsigned char *iv, int enc) 292{ 293 RC2_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), 294 key, data(ctx)->key_bits); 295 return 1; 296} 297 298static int 299rc2_meth_to_magic(EVP_CIPHER_CTX *e) 300{ 301 int i; 302 303 if (EVP_CIPHER_CTX_ctrl(e, EVP_CTRL_GET_RC2_KEY_BITS, 0, &i) <= 0) 304 return (0); 305 if (i == 128) 306 return (RC2_128_MAGIC); 307 else if (i == 64) 308 return (RC2_64_MAGIC); 309 else if (i == 40) 310 return (RC2_40_MAGIC); 311 else 312 return (0); 313} 314 315static int 316rc2_magic_to_meth(int i) 317{ 318 if (i == RC2_128_MAGIC) 319 return 128; 320 else if (i == RC2_64_MAGIC) 321 return 64; 322 else if (i == RC2_40_MAGIC) 323 return 40; 324 else { 325 EVPerror(EVP_R_UNSUPPORTED_KEY_SIZE); 326 return (0); 327 } 328} 329 330static int 331rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) 332{ 333 long num = 0; 334 int i = 0; 335 int key_bits; 336 unsigned int l; 337 unsigned char iv[EVP_MAX_IV_LENGTH]; 338 339 if (type != NULL) { 340 l = EVP_CIPHER_CTX_iv_length(c); 341 if (l > sizeof(iv)) { 342 EVPerror(EVP_R_IV_TOO_LARGE); 343 return -1; 344 } 345 i = ASN1_TYPE_get_int_octetstring(type, &num, iv, l); 346 if (i != (int)l) 347 return (-1); 348 key_bits = rc2_magic_to_meth((int)num); 349 if (!key_bits) 350 return (-1); 351 if (i > 0 && !EVP_CipherInit_ex(c, NULL, NULL, NULL, iv, -1)) 352 return -1; 353 if (EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_RC2_KEY_BITS, 354 key_bits, NULL) <= 0) 355 return -1; 356 if (!EVP_CIPHER_CTX_set_key_length(c, key_bits / 8)) 357 return -1; 358 } 359 return (i); 360} 361 362static int 363rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) 364{ 365 long num; 366 int i = 0, j; 367 368 if (type != NULL) { 369 num = rc2_meth_to_magic(c); 370 j = EVP_CIPHER_CTX_iv_length(c); 371 i = ASN1_TYPE_set_int_octetstring(type, num, c->oiv, j); 372 } 373 return (i); 374} 375 376static int 377rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) 378{ 379 switch (type) { 380 case EVP_CTRL_INIT: 381 data(c)->key_bits = EVP_CIPHER_CTX_key_length(c) * 8; 382 return 1; 383 384 case EVP_CTRL_GET_RC2_KEY_BITS: 385 *(int *)ptr = data(c)->key_bits; 386 return 1; 387 388 case EVP_CTRL_SET_RC2_KEY_BITS: 389 if (arg > 0) { 390 data(c)->key_bits = arg; 391 return 1; 392 } 393 return 0; 394 395#ifdef PBE_PRF_TEST 396 case EVP_CTRL_PBE_PRF_NID: 397 *(int *)ptr = NID_hmacWithMD5; 398 return 1; 399#endif 400 401 default: 402 return -1; 403 } 404} 405 406#endif 407