e_rc2.c revision 1.18
1/* $OpenBSD: e_rc2.c,v 1.18 2022/09/10 17:39:47 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 <limits.h> 60#include <stdio.h> 61 62#include <openssl/opensslconf.h> 63 64#ifndef OPENSSL_NO_RC2 65 66#include <openssl/err.h> 67#include <openssl/evp.h> 68#include <openssl/objects.h> 69#include <openssl/rc2.h> 70 71#include "evp_locl.h" 72 73static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, 74 const unsigned char *iv, int enc); 75static int rc2_meth_to_magic(EVP_CIPHER_CTX *ctx); 76static int rc2_magic_to_meth(int i); 77static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); 78static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); 79static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr); 80 81typedef struct { 82 int key_bits; /* effective key bits */ 83 RC2_KEY ks; /* key schedule */ 84} EVP_RC2_KEY; 85 86#define data(ctx) ((EVP_RC2_KEY *)(ctx)->cipher_data) 87 88static int 89rc2_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) 90{ 91 if (inl > LONG_MAX) 92 return 0; 93 94 while (inl >= EVP_MAXCHUNK) { 95 RC2_cbc_encrypt(in, out, (long)EVP_MAXCHUNK, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt); 96 inl -= EVP_MAXCHUNK; 97 in += EVP_MAXCHUNK; 98 out += EVP_MAXCHUNK; 99 } 100 101 if (inl) 102 RC2_cbc_encrypt(in, out, (long)inl, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt); 103 104 return 1; 105} 106 107static int 108rc2_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) 109{ 110 size_t chunk = EVP_MAXCHUNK; 111 112 if (inl > LONG_MAX) 113 return 0; 114 115 if (inl < chunk) 116 chunk = inl; 117 118 while (inl && inl >= chunk) { 119 RC2_cfb64_encrypt(in, out, (long)chunk, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt); 120 inl -= chunk; 121 in += chunk; 122 out += chunk; 123 if (inl < chunk) 124 chunk = inl; 125 } 126 127 return 1; 128} 129 130static int 131rc2_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) 132{ 133 size_t i, bl; 134 135 if (inl > LONG_MAX) 136 return 0; 137 138 bl = ctx->cipher->block_size; 139 140 if (inl < bl) 141 return 1; 142 143 inl -= bl; 144 145 for (i = 0; i <= inl; i += bl) 146 RC2_ecb_encrypt(in + i, out + i, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->encrypt); 147 148 return 1; 149} 150 151static int 152rc2_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) 153{ 154 if (inl > LONG_MAX) 155 return 0; 156 157 while (inl >= EVP_MAXCHUNK) { 158 RC2_ofb64_encrypt(in, out, (long)EVP_MAXCHUNK, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num); 159 inl -= EVP_MAXCHUNK; 160 in += EVP_MAXCHUNK; 161 out += EVP_MAXCHUNK; 162 } 163 164 if (inl) 165 RC2_ofb64_encrypt(in, out, (long)inl, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num); 166 167 return 1; 168} 169 170static const EVP_CIPHER rc2_cbc = { 171 .nid = NID_rc2_cbc, 172 .block_size = 8, 173 .key_len = RC2_KEY_LENGTH, 174 .iv_len = 8, 175 .flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT | EVP_CIPH_CBC_MODE, 176 .init = rc2_init_key, 177 .do_cipher = rc2_cbc_cipher, 178 .cleanup = NULL, 179 .ctx_size = sizeof(EVP_RC2_KEY), 180 .set_asn1_parameters = rc2_set_asn1_type_and_iv, 181 .get_asn1_parameters = rc2_get_asn1_type_and_iv, 182 .ctrl = rc2_ctrl, 183 .app_data = NULL, 184}; 185 186const EVP_CIPHER * 187EVP_rc2_cbc(void) 188{ 189 return &rc2_cbc; 190} 191 192static const EVP_CIPHER rc2_cfb64 = { 193 .nid = NID_rc2_cfb64, 194 .block_size = 1, 195 .key_len = RC2_KEY_LENGTH, 196 .iv_len = 8, 197 .flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT | EVP_CIPH_CFB_MODE, 198 .init = rc2_init_key, 199 .do_cipher = rc2_cfb64_cipher, 200 .cleanup = NULL, 201 .ctx_size = sizeof(EVP_RC2_KEY), 202 .set_asn1_parameters = rc2_set_asn1_type_and_iv, 203 .get_asn1_parameters = rc2_get_asn1_type_and_iv, 204 .ctrl = rc2_ctrl, 205 .app_data = NULL, 206}; 207 208const EVP_CIPHER * 209EVP_rc2_cfb64(void) 210{ 211 return &rc2_cfb64; 212} 213 214static const EVP_CIPHER rc2_ofb = { 215 .nid = NID_rc2_ofb64, 216 .block_size = 1, 217 .key_len = RC2_KEY_LENGTH, 218 .iv_len = 8, 219 .flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT | EVP_CIPH_OFB_MODE, 220 .init = rc2_init_key, 221 .do_cipher = rc2_ofb_cipher, 222 .cleanup = NULL, 223 .ctx_size = sizeof(EVP_RC2_KEY), 224 .set_asn1_parameters = rc2_set_asn1_type_and_iv, 225 .get_asn1_parameters = rc2_get_asn1_type_and_iv, 226 .ctrl = rc2_ctrl, 227 .app_data = NULL, 228}; 229 230const EVP_CIPHER * 231EVP_rc2_ofb(void) 232{ 233 return &rc2_ofb; 234} 235 236static const EVP_CIPHER rc2_ecb = { 237 .nid = NID_rc2_ecb, 238 .block_size = 8, 239 .key_len = RC2_KEY_LENGTH, 240 .iv_len = 0, 241 .flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT | EVP_CIPH_ECB_MODE, 242 .init = rc2_init_key, 243 .do_cipher = rc2_ecb_cipher, 244 .cleanup = NULL, 245 .ctx_size = sizeof(EVP_RC2_KEY), 246 .set_asn1_parameters = rc2_set_asn1_type_and_iv, 247 .get_asn1_parameters = rc2_get_asn1_type_and_iv, 248 .ctrl = rc2_ctrl, 249 .app_data = NULL, 250}; 251 252const EVP_CIPHER * 253EVP_rc2_ecb(void) 254{ 255 return &rc2_ecb; 256} 257 258#define RC2_40_MAGIC 0xa0 259#define RC2_64_MAGIC 0x78 260#define RC2_128_MAGIC 0x3a 261 262static const EVP_CIPHER r2_64_cbc_cipher = { 263 NID_rc2_64_cbc, 264 8, 8 /* 64 bit */, 8, 265 EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, 266 rc2_init_key, 267 rc2_cbc_cipher, 268 NULL, 269 sizeof(EVP_RC2_KEY), 270 rc2_set_asn1_type_and_iv, 271 rc2_get_asn1_type_and_iv, 272 rc2_ctrl, 273 NULL 274}; 275 276static const EVP_CIPHER r2_40_cbc_cipher = { 277 NID_rc2_40_cbc, 278 8, 5 /* 40 bit */, 8, 279 EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, 280 rc2_init_key, 281 rc2_cbc_cipher, 282 NULL, 283 sizeof(EVP_RC2_KEY), 284 rc2_set_asn1_type_and_iv, 285 rc2_get_asn1_type_and_iv, 286 rc2_ctrl, 287 NULL 288}; 289 290const EVP_CIPHER * 291EVP_rc2_64_cbc(void) 292{ 293 return (&r2_64_cbc_cipher); 294} 295 296const EVP_CIPHER * 297EVP_rc2_40_cbc(void) 298{ 299 return (&r2_40_cbc_cipher); 300} 301 302static int 303rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, 304 const unsigned char *iv, int enc) 305{ 306 RC2_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), 307 key, data(ctx)->key_bits); 308 return 1; 309} 310 311static int 312rc2_meth_to_magic(EVP_CIPHER_CTX *e) 313{ 314 int i; 315 316 if (EVP_CIPHER_CTX_ctrl(e, EVP_CTRL_GET_RC2_KEY_BITS, 0, &i) <= 0) 317 return (0); 318 if (i == 128) 319 return (RC2_128_MAGIC); 320 else if (i == 64) 321 return (RC2_64_MAGIC); 322 else if (i == 40) 323 return (RC2_40_MAGIC); 324 else 325 return (0); 326} 327 328static int 329rc2_magic_to_meth(int i) 330{ 331 if (i == RC2_128_MAGIC) 332 return 128; 333 else if (i == RC2_64_MAGIC) 334 return 64; 335 else if (i == RC2_40_MAGIC) 336 return 40; 337 else { 338 EVPerror(EVP_R_UNSUPPORTED_KEY_SIZE); 339 return (0); 340 } 341} 342 343static int 344rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) 345{ 346 long num = 0; 347 int i = 0; 348 int key_bits; 349 unsigned int l; 350 unsigned char iv[EVP_MAX_IV_LENGTH]; 351 352 if (type != NULL) { 353 l = EVP_CIPHER_CTX_iv_length(c); 354 if (l > sizeof(iv)) { 355 EVPerror(EVP_R_IV_TOO_LARGE); 356 return -1; 357 } 358 i = ASN1_TYPE_get_int_octetstring(type, &num, iv, l); 359 if (i != (int)l) 360 return (-1); 361 key_bits = rc2_magic_to_meth((int)num); 362 if (!key_bits) 363 return (-1); 364 if (i > 0 && !EVP_CipherInit_ex(c, NULL, NULL, NULL, iv, -1)) 365 return -1; 366 if (EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_RC2_KEY_BITS, 367 key_bits, NULL) <= 0) 368 return -1; 369 if (!EVP_CIPHER_CTX_set_key_length(c, key_bits / 8)) 370 return -1; 371 } 372 return (i); 373} 374 375static int 376rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) 377{ 378 long num; 379 int i = 0, j; 380 381 if (type != NULL) { 382 num = rc2_meth_to_magic(c); 383 j = EVP_CIPHER_CTX_iv_length(c); 384 i = ASN1_TYPE_set_int_octetstring(type, num, c->oiv, j); 385 } 386 return (i); 387} 388 389static int 390rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) 391{ 392 switch (type) { 393 case EVP_CTRL_INIT: 394 data(c)->key_bits = EVP_CIPHER_CTX_key_length(c) * 8; 395 return 1; 396 397 case EVP_CTRL_GET_RC2_KEY_BITS: 398 *(int *)ptr = data(c)->key_bits; 399 return 1; 400 401 case EVP_CTRL_SET_RC2_KEY_BITS: 402 if (arg > 0) { 403 data(c)->key_bits = arg; 404 return 1; 405 } 406 return 0; 407 408#ifdef PBE_PRF_TEST 409 case EVP_CTRL_PBE_PRF_NID: 410 *(int *)ptr = NID_hmacWithMD5; 411 return 1; 412#endif 413 414 default: 415 return -1; 416 } 417} 418 419#endif 420