xref: /openbsd-src/lib/libcrypto/evp/e_rc2.c (revision 9bac3682a248384cde711fdda825c3b5960b1005)
1*9bac3682Sbeck /* $OpenBSD: e_rc2.c,v 1.29 2024/04/09 13:52:41 beck Exp $ */
2c109e398Sbeck /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3c109e398Sbeck  * All rights reserved.
4c109e398Sbeck  *
5c109e398Sbeck  * This package is an SSL implementation written
6c109e398Sbeck  * by Eric Young (eay@cryptsoft.com).
7c109e398Sbeck  * The implementation was written so as to conform with Netscapes SSL.
8c109e398Sbeck  *
9c109e398Sbeck  * This library is free for commercial and non-commercial use as long as
10c109e398Sbeck  * the following conditions are aheared to.  The following conditions
11c109e398Sbeck  * apply to all code found in this distribution, be it the RC4, RSA,
12c109e398Sbeck  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13c109e398Sbeck  * included with this distribution is covered by the same copyright terms
14c109e398Sbeck  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15c109e398Sbeck  *
16c109e398Sbeck  * Copyright remains Eric Young's, and as such any Copyright notices in
17c109e398Sbeck  * the code are not to be removed.
18c109e398Sbeck  * If this package is used in a product, Eric Young should be given attribution
19c109e398Sbeck  * as the author of the parts of the library used.
20c109e398Sbeck  * This can be in the form of a textual message at program startup or
21c109e398Sbeck  * in documentation (online or textual) provided with the package.
22c109e398Sbeck  *
23c109e398Sbeck  * Redistribution and use in source and binary forms, with or without
24c109e398Sbeck  * modification, are permitted provided that the following conditions
25c109e398Sbeck  * are met:
26c109e398Sbeck  * 1. Redistributions of source code must retain the copyright
27c109e398Sbeck  *    notice, this list of conditions and the following disclaimer.
28c109e398Sbeck  * 2. Redistributions in binary form must reproduce the above copyright
29c109e398Sbeck  *    notice, this list of conditions and the following disclaimer in the
30c109e398Sbeck  *    documentation and/or other materials provided with the distribution.
31c109e398Sbeck  * 3. All advertising materials mentioning features or use of this software
32c109e398Sbeck  *    must display the following acknowledgement:
33c109e398Sbeck  *    "This product includes cryptographic software written by
34c109e398Sbeck  *     Eric Young (eay@cryptsoft.com)"
35c109e398Sbeck  *    The word 'cryptographic' can be left out if the rouines from the library
36c109e398Sbeck  *    being used are not cryptographic related :-).
37c109e398Sbeck  * 4. If you include any Windows specific code (or a derivative thereof) from
38c109e398Sbeck  *    the apps directory (application code) you must include an acknowledgement:
39c109e398Sbeck  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40c109e398Sbeck  *
41c109e398Sbeck  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42c109e398Sbeck  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43c109e398Sbeck  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44c109e398Sbeck  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45c109e398Sbeck  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46c109e398Sbeck  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47c109e398Sbeck  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48c109e398Sbeck  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49c109e398Sbeck  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50c109e398Sbeck  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51c109e398Sbeck  * SUCH DAMAGE.
52c109e398Sbeck  *
53c109e398Sbeck  * The licence and distribution terms for any publically available version or
54c109e398Sbeck  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55c109e398Sbeck  * copied and put under another distribution licence
56c109e398Sbeck  * [including the GNU Public Licence.]
57c109e398Sbeck  */
58c109e398Sbeck 
59b76ab7f9Sjsing #include <limits.h>
60c109e398Sbeck #include <stdio.h>
618cf4d6a6Sjsing 
628cf4d6a6Sjsing #include <openssl/opensslconf.h>
638cf4d6a6Sjsing 
644fcf65c5Sdjm #ifndef OPENSSL_NO_RC2
654fcf65c5Sdjm 
66b6ab114eSjsing #include <openssl/err.h>
67c109e398Sbeck #include <openssl/evp.h>
68c109e398Sbeck #include <openssl/objects.h>
69da347917Sbeck #include <openssl/rc2.h>
70c109e398Sbeck 
71c9675a23Stb #include "evp_local.h"
72b6ab114eSjsing 
73c109e398Sbeck static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
74c109e398Sbeck     const unsigned char *iv, int enc);
75c109e398Sbeck static int rc2_meth_to_magic(EVP_CIPHER_CTX *ctx);
76c109e398Sbeck static int rc2_magic_to_meth(int i);
77c109e398Sbeck static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
78c109e398Sbeck static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
79c109e398Sbeck static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr);
80c109e398Sbeck 
81ba3920edSjsing typedef struct {
82da347917Sbeck 	int key_bits;	/* effective key bits */
83da347917Sbeck 	RC2_KEY ks;	/* key schedule */
84da347917Sbeck } EVP_RC2_KEY;
85da347917Sbeck 
86da347917Sbeck #define data(ctx)	((EVP_RC2_KEY *)(ctx)->cipher_data)
87da347917Sbeck 
888892d6c1Sjsing static int
rc2_cbc_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)898892d6c1Sjsing rc2_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
908892d6c1Sjsing {
91fa590012Sjsing 	size_t chunk = LONG_MAX & ~0xff;
92b76ab7f9Sjsing 
93fa590012Sjsing 	while (inl >= chunk) {
94fa590012Sjsing 		RC2_cbc_encrypt(in, out, (long)chunk, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
95fa590012Sjsing 		inl -= chunk;
96fa590012Sjsing 		in += chunk;
97fa590012Sjsing 		out += chunk;
988892d6c1Sjsing 	}
998892d6c1Sjsing 
1008892d6c1Sjsing 	if (inl)
1018892d6c1Sjsing 		RC2_cbc_encrypt(in, out, (long)inl, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, ctx->encrypt);
1028892d6c1Sjsing 
1038892d6c1Sjsing 	return 1;
1048892d6c1Sjsing }
1058892d6c1Sjsing 
1068892d6c1Sjsing static int
rc2_cfb64_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)1078892d6c1Sjsing rc2_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
1088892d6c1Sjsing {
109fa590012Sjsing 	size_t chunk = LONG_MAX & ~0xff;
110b76ab7f9Sjsing 
1118892d6c1Sjsing 	if (inl < chunk)
1128892d6c1Sjsing 		chunk = inl;
1138892d6c1Sjsing 
1148892d6c1Sjsing 	while (inl && inl >= chunk) {
1157a606269Sjsing 		RC2_cfb64_encrypt(in, out, (long)chunk, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num, ctx->encrypt);
1168892d6c1Sjsing 		inl -= chunk;
1178892d6c1Sjsing 		in += chunk;
1188892d6c1Sjsing 		out += chunk;
1198892d6c1Sjsing 		if (inl < chunk)
1208892d6c1Sjsing 			chunk = inl;
1218892d6c1Sjsing 	}
1228892d6c1Sjsing 
1238892d6c1Sjsing 	return 1;
1248892d6c1Sjsing }
1258892d6c1Sjsing 
1268892d6c1Sjsing static int
rc2_ecb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)1278892d6c1Sjsing rc2_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
1288892d6c1Sjsing {
1298892d6c1Sjsing 	size_t i, bl;
1308892d6c1Sjsing 
1318892d6c1Sjsing 	bl = ctx->cipher->block_size;
1328892d6c1Sjsing 
1338892d6c1Sjsing 	if (inl < bl)
1348892d6c1Sjsing 		return 1;
1358892d6c1Sjsing 
1368892d6c1Sjsing 	inl -= bl;
1378892d6c1Sjsing 
1388892d6c1Sjsing 	for (i = 0; i <= inl; i += bl)
1398892d6c1Sjsing 		RC2_ecb_encrypt(in + i, out + i, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->encrypt);
1408892d6c1Sjsing 
1418892d6c1Sjsing 	return 1;
1428892d6c1Sjsing }
1438892d6c1Sjsing 
1448892d6c1Sjsing static int
rc2_ofb_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)1458892d6c1Sjsing rc2_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl)
1468892d6c1Sjsing {
147fa590012Sjsing 	size_t chunk = LONG_MAX & ~0xff;
148b76ab7f9Sjsing 
149fa590012Sjsing 	while (inl >= chunk) {
150fa590012Sjsing 		RC2_ofb64_encrypt(in, out, (long)chunk, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
151fa590012Sjsing 		inl -= chunk;
152fa590012Sjsing 		in += chunk;
153fa590012Sjsing 		out += chunk;
1548892d6c1Sjsing 	}
1558892d6c1Sjsing 
1568892d6c1Sjsing 	if (inl)
1578892d6c1Sjsing 		RC2_ofb64_encrypt(in, out, (long)inl, &((EVP_RC2_KEY *)ctx->cipher_data)->ks, ctx->iv, &ctx->num);
1588892d6c1Sjsing 
1598892d6c1Sjsing 	return 1;
1608892d6c1Sjsing }
1618892d6c1Sjsing 
1628892d6c1Sjsing static const EVP_CIPHER rc2_cbc = {
1638892d6c1Sjsing 	.nid = NID_rc2_cbc,
1648892d6c1Sjsing 	.block_size = 8,
1658892d6c1Sjsing 	.key_len = RC2_KEY_LENGTH,
1668892d6c1Sjsing 	.iv_len = 8,
1678892d6c1Sjsing 	.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT | EVP_CIPH_CBC_MODE,
1688892d6c1Sjsing 	.init = rc2_init_key,
1698892d6c1Sjsing 	.do_cipher = rc2_cbc_cipher,
1708892d6c1Sjsing 	.cleanup = NULL,
1718892d6c1Sjsing 	.ctx_size = sizeof(EVP_RC2_KEY),
1728892d6c1Sjsing 	.set_asn1_parameters = rc2_set_asn1_type_and_iv,
1738892d6c1Sjsing 	.get_asn1_parameters = rc2_get_asn1_type_and_iv,
1748892d6c1Sjsing 	.ctrl = rc2_ctrl,
1758892d6c1Sjsing };
1768892d6c1Sjsing 
1778892d6c1Sjsing const EVP_CIPHER *
EVP_rc2_cbc(void)1788892d6c1Sjsing EVP_rc2_cbc(void)
1798892d6c1Sjsing {
1808892d6c1Sjsing 	return &rc2_cbc;
1818892d6c1Sjsing }
182*9bac3682Sbeck LCRYPTO_ALIAS(EVP_rc2_cbc);
1838892d6c1Sjsing 
1848892d6c1Sjsing static const EVP_CIPHER rc2_cfb64 = {
1858892d6c1Sjsing 	.nid = NID_rc2_cfb64,
1868892d6c1Sjsing 	.block_size = 1,
1878892d6c1Sjsing 	.key_len = RC2_KEY_LENGTH,
1888892d6c1Sjsing 	.iv_len = 8,
1898892d6c1Sjsing 	.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT | EVP_CIPH_CFB_MODE,
1908892d6c1Sjsing 	.init = rc2_init_key,
1918892d6c1Sjsing 	.do_cipher = rc2_cfb64_cipher,
1928892d6c1Sjsing 	.cleanup = NULL,
1938892d6c1Sjsing 	.ctx_size = sizeof(EVP_RC2_KEY),
1948892d6c1Sjsing 	.set_asn1_parameters = rc2_set_asn1_type_and_iv,
1958892d6c1Sjsing 	.get_asn1_parameters = rc2_get_asn1_type_and_iv,
1968892d6c1Sjsing 	.ctrl = rc2_ctrl,
1978892d6c1Sjsing };
1988892d6c1Sjsing 
1998892d6c1Sjsing const EVP_CIPHER *
EVP_rc2_cfb64(void)2008892d6c1Sjsing EVP_rc2_cfb64(void)
2018892d6c1Sjsing {
2028892d6c1Sjsing 	return &rc2_cfb64;
2038892d6c1Sjsing }
204*9bac3682Sbeck LCRYPTO_ALIAS(EVP_rc2_cfb64);
2058892d6c1Sjsing 
2068892d6c1Sjsing static const EVP_CIPHER rc2_ofb = {
2078892d6c1Sjsing 	.nid = NID_rc2_ofb64,
2088892d6c1Sjsing 	.block_size = 1,
2098892d6c1Sjsing 	.key_len = RC2_KEY_LENGTH,
2108892d6c1Sjsing 	.iv_len = 8,
2118892d6c1Sjsing 	.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT | EVP_CIPH_OFB_MODE,
2128892d6c1Sjsing 	.init = rc2_init_key,
2138892d6c1Sjsing 	.do_cipher = rc2_ofb_cipher,
2148892d6c1Sjsing 	.cleanup = NULL,
2158892d6c1Sjsing 	.ctx_size = sizeof(EVP_RC2_KEY),
2168892d6c1Sjsing 	.set_asn1_parameters = rc2_set_asn1_type_and_iv,
2178892d6c1Sjsing 	.get_asn1_parameters = rc2_get_asn1_type_and_iv,
2188892d6c1Sjsing 	.ctrl = rc2_ctrl,
2198892d6c1Sjsing };
2208892d6c1Sjsing 
2218892d6c1Sjsing const EVP_CIPHER *
EVP_rc2_ofb(void)2228892d6c1Sjsing EVP_rc2_ofb(void)
2238892d6c1Sjsing {
2248892d6c1Sjsing 	return &rc2_ofb;
2258892d6c1Sjsing }
226*9bac3682Sbeck LCRYPTO_ALIAS(EVP_rc2_ofb);
2278892d6c1Sjsing 
2288892d6c1Sjsing static const EVP_CIPHER rc2_ecb = {
2298892d6c1Sjsing 	.nid = NID_rc2_ecb,
2308892d6c1Sjsing 	.block_size = 8,
2318892d6c1Sjsing 	.key_len = RC2_KEY_LENGTH,
2328892d6c1Sjsing 	.iv_len = 0,
2338892d6c1Sjsing 	.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT | EVP_CIPH_ECB_MODE,
2348892d6c1Sjsing 	.init = rc2_init_key,
2358892d6c1Sjsing 	.do_cipher = rc2_ecb_cipher,
2368892d6c1Sjsing 	.cleanup = NULL,
2378892d6c1Sjsing 	.ctx_size = sizeof(EVP_RC2_KEY),
2388892d6c1Sjsing 	.set_asn1_parameters = rc2_set_asn1_type_and_iv,
2398892d6c1Sjsing 	.get_asn1_parameters = rc2_get_asn1_type_and_iv,
2408892d6c1Sjsing 	.ctrl = rc2_ctrl,
2418892d6c1Sjsing };
2428892d6c1Sjsing 
2438892d6c1Sjsing const EVP_CIPHER *
EVP_rc2_ecb(void)2448892d6c1Sjsing EVP_rc2_ecb(void)
2458892d6c1Sjsing {
2468892d6c1Sjsing 	return &rc2_ecb;
2478892d6c1Sjsing }
248*9bac3682Sbeck LCRYPTO_ALIAS(EVP_rc2_ecb);
249c109e398Sbeck 
250c109e398Sbeck #define RC2_40_MAGIC	0xa0
251c109e398Sbeck #define RC2_64_MAGIC	0x78
252c109e398Sbeck #define RC2_128_MAGIC	0x3a
253c109e398Sbeck 
254ba3920edSjsing static const EVP_CIPHER r2_64_cbc_cipher = {
255fd227519Stb 	.nid = NID_rc2_64_cbc,
256fd227519Stb 	.block_size = 8,
257fd227519Stb 	.key_len = 8,
258fd227519Stb 	.iv_len = 8,
259fd227519Stb 	.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
260fd227519Stb 	.init = rc2_init_key,
261fd227519Stb 	.do_cipher = rc2_cbc_cipher,
262fd227519Stb 	.cleanup = NULL,
263fd227519Stb 	.ctx_size = sizeof(EVP_RC2_KEY),
264fd227519Stb 	.set_asn1_parameters = rc2_set_asn1_type_and_iv,
265fd227519Stb 	.get_asn1_parameters = rc2_get_asn1_type_and_iv,
266fd227519Stb 	.ctrl = rc2_ctrl,
267c109e398Sbeck };
268c109e398Sbeck 
269ba3920edSjsing static const EVP_CIPHER r2_40_cbc_cipher = {
270fd227519Stb 	.nid = NID_rc2_40_cbc,
271fd227519Stb 	.block_size = 8,
272fd227519Stb 	.key_len = 5,
273fd227519Stb 	.iv_len = 8,
274fd227519Stb 	.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
275fd227519Stb 	.init = rc2_init_key,
276fd227519Stb 	.do_cipher = rc2_cbc_cipher,
277fd227519Stb 	.cleanup = NULL,
278fd227519Stb 	.ctx_size = sizeof(EVP_RC2_KEY),
279fd227519Stb 	.set_asn1_parameters = rc2_set_asn1_type_and_iv,
280fd227519Stb 	.get_asn1_parameters = rc2_get_asn1_type_and_iv,
281fd227519Stb 	.ctrl = rc2_ctrl,
282c109e398Sbeck };
283c109e398Sbeck 
284ba3920edSjsing const EVP_CIPHER *
EVP_rc2_64_cbc(void)285ba3920edSjsing EVP_rc2_64_cbc(void)
286c109e398Sbeck {
287c109e398Sbeck 	return (&r2_64_cbc_cipher);
288c109e398Sbeck }
289*9bac3682Sbeck LCRYPTO_ALIAS(EVP_rc2_64_cbc);
290c109e398Sbeck 
291ba3920edSjsing const EVP_CIPHER *
EVP_rc2_40_cbc(void)292ba3920edSjsing EVP_rc2_40_cbc(void)
293c109e398Sbeck {
294c109e398Sbeck 	return (&r2_40_cbc_cipher);
295c109e398Sbeck }
296*9bac3682Sbeck LCRYPTO_ALIAS(EVP_rc2_40_cbc);
297c109e398Sbeck 
298ba3920edSjsing static int
rc2_init_key(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)299ba3920edSjsing rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
300c109e398Sbeck     const unsigned char *iv, int enc)
301c109e398Sbeck {
302da347917Sbeck 	RC2_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx),
303da347917Sbeck 	    key, data(ctx)->key_bits);
304c109e398Sbeck 	return 1;
305c109e398Sbeck }
306c109e398Sbeck 
307ba3920edSjsing static int
rc2_meth_to_magic(EVP_CIPHER_CTX * e)308ba3920edSjsing rc2_meth_to_magic(EVP_CIPHER_CTX *e)
309c109e398Sbeck {
310c109e398Sbeck 	int i;
311c109e398Sbeck 
312ae001e8fSinoguchi 	if (EVP_CIPHER_CTX_ctrl(e, EVP_CTRL_GET_RC2_KEY_BITS, 0, &i) <= 0)
313ae001e8fSinoguchi 		return (0);
314ba3920edSjsing 	if (i == 128)
315ba3920edSjsing 		return (RC2_128_MAGIC);
316ba3920edSjsing 	else if (i == 64)
317ba3920edSjsing 		return (RC2_64_MAGIC);
318ba3920edSjsing 	else if (i == 40)
319ba3920edSjsing 		return (RC2_40_MAGIC);
320ba3920edSjsing 	else
321ba3920edSjsing 		return (0);
322c109e398Sbeck }
323c109e398Sbeck 
324ba3920edSjsing static int
rc2_magic_to_meth(int i)325ba3920edSjsing rc2_magic_to_meth(int i)
326c109e398Sbeck {
327ba3920edSjsing 	if (i == RC2_128_MAGIC)
328ba3920edSjsing 		return 128;
329ba3920edSjsing 	else if (i == RC2_64_MAGIC)
330ba3920edSjsing 		return 64;
331ba3920edSjsing 	else if (i == RC2_40_MAGIC)
332ba3920edSjsing 		return 40;
333ba3920edSjsing 	else {
3345067ae9fSbeck 		EVPerror(EVP_R_UNSUPPORTED_KEY_SIZE);
335c109e398Sbeck 		return (0);
336c109e398Sbeck 	}
337c109e398Sbeck }
338c109e398Sbeck 
339ba3920edSjsing static int
rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX * c,ASN1_TYPE * type)340ba3920edSjsing rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
341c109e398Sbeck {
342c109e398Sbeck 	long num = 0;
3434fcf65c5Sdjm 	int i = 0;
344c109e398Sbeck 	int key_bits;
34506f72c83Stb 	int l;
346c109e398Sbeck 	unsigned char iv[EVP_MAX_IV_LENGTH];
347c109e398Sbeck 
348ba3920edSjsing 	if (type != NULL) {
349c109e398Sbeck 		l = EVP_CIPHER_CTX_iv_length(c);
3500a5044deStb 		if (l < 0 || l > sizeof(iv)) {
3515067ae9fSbeck 			EVPerror(EVP_R_IV_TOO_LARGE);
3528ad85bf2Smiod 			return -1;
3538ad85bf2Smiod 		}
354c109e398Sbeck 		i = ASN1_TYPE_get_int_octetstring(type, &num, iv, l);
35506f72c83Stb 		if (i != l)
356c109e398Sbeck 			return (-1);
357c109e398Sbeck 		key_bits = rc2_magic_to_meth((int)num);
358c109e398Sbeck 		if (!key_bits)
359c109e398Sbeck 			return (-1);
3605cdd308eSdjm 		if (i > 0 && !EVP_CipherInit_ex(c, NULL, NULL, NULL, iv, -1))
3615cdd308eSdjm 			return -1;
362ae001e8fSinoguchi 		if (EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_RC2_KEY_BITS,
363ae001e8fSinoguchi 		    key_bits, NULL) <= 0)
364ae001e8fSinoguchi 			return -1;
3655cf727f3Sinoguchi 		if (!EVP_CIPHER_CTX_set_key_length(c, key_bits / 8))
3665cf727f3Sinoguchi 			return -1;
367c109e398Sbeck 	}
368c109e398Sbeck 	return (i);
369c109e398Sbeck }
370c109e398Sbeck 
371ba3920edSjsing static int
rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX * c,ASN1_TYPE * type)372ba3920edSjsing rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
373c109e398Sbeck {
374c109e398Sbeck 	long num;
375c109e398Sbeck 	int i = 0, j;
376c109e398Sbeck 
377ba3920edSjsing 	if (type != NULL) {
378c109e398Sbeck 		num = rc2_meth_to_magic(c);
379c109e398Sbeck 		j = EVP_CIPHER_CTX_iv_length(c);
3800a5044deStb 		if (j < 0 || j > sizeof(c->oiv))
3810a5044deStb 			return 0;
382c109e398Sbeck 		i = ASN1_TYPE_set_int_octetstring(type, num, c->oiv, j);
383c109e398Sbeck 	}
384c109e398Sbeck 	return (i);
385c109e398Sbeck }
386c109e398Sbeck 
387ba3920edSjsing static int
rc2_ctrl(EVP_CIPHER_CTX * c,int type,int arg,void * ptr)388ba3920edSjsing rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
389c109e398Sbeck {
390ba3920edSjsing 	switch (type) {
391c109e398Sbeck 	case EVP_CTRL_INIT:
392b62d6ce7Stb 		data(c)->key_bits = EVP_CIPHER_CTX_key_length(c) * 8;
393c109e398Sbeck 		return 1;
394c109e398Sbeck 
395c109e398Sbeck 	case EVP_CTRL_GET_RC2_KEY_BITS:
396da347917Sbeck 		*(int *)ptr = data(c)->key_bits;
397c109e398Sbeck 		return 1;
398c109e398Sbeck 
399c109e398Sbeck 	case EVP_CTRL_SET_RC2_KEY_BITS:
400ba3920edSjsing 		if (arg > 0) {
401da347917Sbeck 			data(c)->key_bits = arg;
402c109e398Sbeck 			return 1;
403c109e398Sbeck 		}
404c109e398Sbeck 		return 0;
405ba3920edSjsing 
406c109e398Sbeck 	default:
407c109e398Sbeck 		return -1;
408c109e398Sbeck 	}
409c109e398Sbeck }
410c109e398Sbeck 
411c109e398Sbeck #endif
412