10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * Author: Tatu Ylonen <ylo@cs.hut.fi>
30Sstevel@tonic-gate  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
40Sstevel@tonic-gate  *                    All rights reserved
50Sstevel@tonic-gate  *
60Sstevel@tonic-gate  * As far as I am concerned, the code I have written for this software
70Sstevel@tonic-gate  * can be used freely for any purpose.  Any derived versions of this
80Sstevel@tonic-gate  * software must be clearly marked as such, and if the derived work is
90Sstevel@tonic-gate  * incompatible with the protocol description in the RFC file, it must be
100Sstevel@tonic-gate  * called by a name other than "ssh" or "Secure Shell".
110Sstevel@tonic-gate  *
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * Copyright (c) 1999 Niels Provos.  All rights reserved.
140Sstevel@tonic-gate  * Copyright (c) 1999, 2000 Markus Friedl.  All rights reserved.
150Sstevel@tonic-gate  *
160Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
170Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
180Sstevel@tonic-gate  * are met:
190Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
200Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
210Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
220Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
230Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
260Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
270Sstevel@tonic-gate  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
280Sstevel@tonic-gate  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
290Sstevel@tonic-gate  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
300Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
310Sstevel@tonic-gate  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
320Sstevel@tonic-gate  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
330Sstevel@tonic-gate  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
340Sstevel@tonic-gate  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
350Sstevel@tonic-gate  */
360Sstevel@tonic-gate 
37*6288Sjp161948 /*
38*6288Sjp161948  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
39*6288Sjp161948  * Use is subject to license terms.
40*6288Sjp161948  */
41*6288Sjp161948 
420Sstevel@tonic-gate #include "includes.h"
430Sstevel@tonic-gate RCSID("$OpenBSD: cipher.c,v 1.61 2002/07/12 15:50:17 markus Exp $");
440Sstevel@tonic-gate 
450Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
460Sstevel@tonic-gate 
470Sstevel@tonic-gate #include "xmalloc.h"
480Sstevel@tonic-gate #include "log.h"
490Sstevel@tonic-gate #include "cipher.h"
500Sstevel@tonic-gate 
510Sstevel@tonic-gate #include <openssl/md5.h>
520Sstevel@tonic-gate 
530Sstevel@tonic-gate #if OPENSSL_VERSION_NUMBER < 0x00906000L
540Sstevel@tonic-gate #define SSH_OLD_EVP
550Sstevel@tonic-gate #define EVP_CIPHER_CTX_get_app_data(e)          ((e)->app_data)
560Sstevel@tonic-gate #endif
570Sstevel@tonic-gate 
580Sstevel@tonic-gate extern const EVP_CIPHER *evp_aes_128_ctr(void);
590Sstevel@tonic-gate extern void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
600Sstevel@tonic-gate 
610Sstevel@tonic-gate static const EVP_CIPHER *evp_ssh1_3des(void);
620Sstevel@tonic-gate static const EVP_CIPHER *evp_ssh1_bf(void);
630Sstevel@tonic-gate 
640Sstevel@tonic-gate struct Cipher {
650Sstevel@tonic-gate 	char	*name;
660Sstevel@tonic-gate 	int	number;		/* for ssh1 only */
670Sstevel@tonic-gate 	u_int	block_size;
680Sstevel@tonic-gate 	u_int	key_len;
690Sstevel@tonic-gate 	const EVP_CIPHER	*(*evptype)(void);
700Sstevel@tonic-gate } ciphers[] = {
710Sstevel@tonic-gate 	{ "none", 		SSH_CIPHER_NONE, 8, 0, EVP_enc_null },
720Sstevel@tonic-gate 	{ "des", 		SSH_CIPHER_DES, 8, 8, EVP_des_cbc },
730Sstevel@tonic-gate 	{ "3des", 		SSH_CIPHER_3DES, 8, 16, evp_ssh1_3des },
740Sstevel@tonic-gate 	{ "blowfish", 		SSH_CIPHER_BLOWFISH, 8, 32, evp_ssh1_bf },
750Sstevel@tonic-gate 	{ "3des-cbc", 		SSH_CIPHER_SSH2, 8, 24, EVP_des_ede3_cbc },
760Sstevel@tonic-gate 	{ "blowfish-cbc", 	SSH_CIPHER_SSH2, 8, 16, EVP_bf_cbc },
770Sstevel@tonic-gate #ifdef SOLARIS_SSH_ENABLE_CAST5_128
780Sstevel@tonic-gate 	{ "cast128-cbc", 	SSH_CIPHER_SSH2, 8, 16, EVP_cast5_cbc },
790Sstevel@tonic-gate #endif /* SOLARIS_SSH_ENABLE_CAST5_128 */
800Sstevel@tonic-gate 	{ "arcfour", 		SSH_CIPHER_SSH2, 8, 16, EVP_rc4 },
810Sstevel@tonic-gate 	{ "aes128-cbc",		SSH_CIPHER_SSH2, 16, 16, EVP_aes_128_cbc },
820Sstevel@tonic-gate 	{ "aes192-cbc",		SSH_CIPHER_SSH2, 16, 24, EVP_aes_192_cbc },
830Sstevel@tonic-gate 	{ "aes256-cbc",		SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc },
840Sstevel@tonic-gate         { "aes128-ctr",         SSH_CIPHER_SSH2, 16, 16, evp_aes_128_ctr },
850Sstevel@tonic-gate         { "aes192-ctr",         SSH_CIPHER_SSH2, 16, 24, evp_aes_128_ctr },
860Sstevel@tonic-gate         { "aes256-ctr",         SSH_CIPHER_SSH2, 16, 32, evp_aes_128_ctr },
870Sstevel@tonic-gate 	{ NULL,			SSH_CIPHER_ILLEGAL, 0, 0, NULL }
880Sstevel@tonic-gate };
890Sstevel@tonic-gate 
900Sstevel@tonic-gate /*--*/
910Sstevel@tonic-gate 
920Sstevel@tonic-gate u_int
930Sstevel@tonic-gate cipher_blocksize(Cipher *c)
940Sstevel@tonic-gate {
950Sstevel@tonic-gate 	return (c->block_size);
960Sstevel@tonic-gate }
970Sstevel@tonic-gate 
980Sstevel@tonic-gate u_int
990Sstevel@tonic-gate cipher_keylen(Cipher *c)
1000Sstevel@tonic-gate {
1010Sstevel@tonic-gate 	return (c->key_len);
1020Sstevel@tonic-gate }
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate u_int
1050Sstevel@tonic-gate cipher_get_number(Cipher *c)
1060Sstevel@tonic-gate {
1070Sstevel@tonic-gate 	return (c->number);
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate u_int
1110Sstevel@tonic-gate cipher_mask_ssh1(int client)
1120Sstevel@tonic-gate {
1130Sstevel@tonic-gate 	u_int mask = 0;
1140Sstevel@tonic-gate 	mask |= 1 << SSH_CIPHER_3DES;		/* Mandatory */
1150Sstevel@tonic-gate 	mask |= 1 << SSH_CIPHER_BLOWFISH;
1160Sstevel@tonic-gate 	if (client) {
1170Sstevel@tonic-gate 		mask |= 1 << SSH_CIPHER_DES;
1180Sstevel@tonic-gate 	}
1190Sstevel@tonic-gate 	return mask;
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate Cipher *
1230Sstevel@tonic-gate cipher_by_name(const char *name)
1240Sstevel@tonic-gate {
1250Sstevel@tonic-gate 	Cipher *c;
1260Sstevel@tonic-gate 	for (c = ciphers; c->name != NULL; c++)
1270Sstevel@tonic-gate 		if (strcasecmp(c->name, name) == 0)
1280Sstevel@tonic-gate 			return c;
1290Sstevel@tonic-gate 	return NULL;
1300Sstevel@tonic-gate }
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate Cipher *
1330Sstevel@tonic-gate cipher_by_number(int id)
1340Sstevel@tonic-gate {
1350Sstevel@tonic-gate 	Cipher *c;
1360Sstevel@tonic-gate 	for (c = ciphers; c->name != NULL; c++)
1370Sstevel@tonic-gate 		if (c->number == id)
1380Sstevel@tonic-gate 			return c;
1390Sstevel@tonic-gate 	return NULL;
1400Sstevel@tonic-gate }
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate #define	CIPHER_SEP	","
1430Sstevel@tonic-gate int
1440Sstevel@tonic-gate ciphers_valid(const char *names)
1450Sstevel@tonic-gate {
1460Sstevel@tonic-gate 	Cipher *c;
1470Sstevel@tonic-gate 	char *ciphers, *cp;
1480Sstevel@tonic-gate 	char *p;
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	if (names == NULL || strcmp(names, "") == 0)
1510Sstevel@tonic-gate 		return 0;
1520Sstevel@tonic-gate 	ciphers = cp = xstrdup(names);
1530Sstevel@tonic-gate 	for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
1540Sstevel@tonic-gate 	    (p = strsep(&cp, CIPHER_SEP))) {
1550Sstevel@tonic-gate 		c = cipher_by_name(p);
1560Sstevel@tonic-gate 		if (c == NULL || c->number != SSH_CIPHER_SSH2) {
1570Sstevel@tonic-gate 			debug("bad cipher %s [%s]", p, names);
1580Sstevel@tonic-gate 			xfree(ciphers);
1590Sstevel@tonic-gate 			return 0;
1600Sstevel@tonic-gate 		} else {
1610Sstevel@tonic-gate 			debug3("cipher ok: %s [%s]", p, names);
1620Sstevel@tonic-gate 		}
1630Sstevel@tonic-gate 	}
1640Sstevel@tonic-gate 	debug3("ciphers ok: [%s]", names);
1650Sstevel@tonic-gate 	xfree(ciphers);
1660Sstevel@tonic-gate 	return 1;
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate /*
1700Sstevel@tonic-gate  * Parses the name of the cipher.  Returns the number of the corresponding
1710Sstevel@tonic-gate  * cipher, or -1 on error.
1720Sstevel@tonic-gate  */
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate int
1750Sstevel@tonic-gate cipher_number(const char *name)
1760Sstevel@tonic-gate {
1770Sstevel@tonic-gate 	Cipher *c;
1780Sstevel@tonic-gate 	if (name == NULL)
1790Sstevel@tonic-gate 		return -1;
1800Sstevel@tonic-gate 	c = cipher_by_name(name);
1810Sstevel@tonic-gate 	return (c==NULL) ? -1 : c->number;
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate char *
1850Sstevel@tonic-gate cipher_name(int id)
1860Sstevel@tonic-gate {
1870Sstevel@tonic-gate 	Cipher *c = cipher_by_number(id);
1880Sstevel@tonic-gate 	return (c==NULL) ? "<unknown>" : c->name;
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate void
1920Sstevel@tonic-gate cipher_init(CipherContext *cc, Cipher *cipher,
1930Sstevel@tonic-gate     const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
1940Sstevel@tonic-gate     int encrypt)
1950Sstevel@tonic-gate {
1960Sstevel@tonic-gate 	static int dowarn = 1;
1970Sstevel@tonic-gate #ifdef SSH_OLD_EVP
1980Sstevel@tonic-gate 	EVP_CIPHER *type;
1990Sstevel@tonic-gate #else
2000Sstevel@tonic-gate 	const EVP_CIPHER *type;
2010Sstevel@tonic-gate #endif
2020Sstevel@tonic-gate 	int klen;
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 	if (cipher->number == SSH_CIPHER_DES) {
2050Sstevel@tonic-gate 		if (dowarn) {
2060Sstevel@tonic-gate 			error("Warning: use of DES is strongly discouraged "
2070Sstevel@tonic-gate 			    "due to cryptographic weaknesses");
2080Sstevel@tonic-gate 			dowarn = 0;
2090Sstevel@tonic-gate 		}
2100Sstevel@tonic-gate 		if (keylen > 8)
2110Sstevel@tonic-gate 			keylen = 8;
2120Sstevel@tonic-gate 	}
2130Sstevel@tonic-gate 	cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	if (keylen < cipher->key_len)
2160Sstevel@tonic-gate 		fatal("cipher_init: key length %d is insufficient for %s.",
2170Sstevel@tonic-gate 		    keylen, cipher->name);
2180Sstevel@tonic-gate 	if (iv != NULL && ivlen < cipher->block_size)
2190Sstevel@tonic-gate 		fatal("cipher_init: iv length %d is insufficient for %s.",
2200Sstevel@tonic-gate 		    ivlen, cipher->name);
2210Sstevel@tonic-gate 	cc->cipher = cipher;
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 	type = (*cipher->evptype)();
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	EVP_CIPHER_CTX_init(&cc->evp);
2260Sstevel@tonic-gate #ifdef SSH_OLD_EVP
2270Sstevel@tonic-gate 	if (type->key_len > 0 && type->key_len != keylen) {
2280Sstevel@tonic-gate 		debug("cipher_init: set keylen (%d -> %d)",
2290Sstevel@tonic-gate 		    type->key_len, keylen);
2300Sstevel@tonic-gate 		type->key_len = keylen;
2310Sstevel@tonic-gate 	}
2320Sstevel@tonic-gate 	EVP_CipherInit(&cc->evp, type, (u_char *)key, (u_char *)iv,
2330Sstevel@tonic-gate 	    (encrypt == CIPHER_ENCRYPT));
2340Sstevel@tonic-gate #else
2350Sstevel@tonic-gate 	if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv,
2360Sstevel@tonic-gate 	    (encrypt == CIPHER_ENCRYPT)) == 0)
2370Sstevel@tonic-gate 		fatal("cipher_init: EVP_CipherInit failed for %s",
2380Sstevel@tonic-gate 		    cipher->name);
2390Sstevel@tonic-gate 	klen = EVP_CIPHER_CTX_key_length(&cc->evp);
2400Sstevel@tonic-gate 	if (klen > 0 && keylen != klen) {
2410Sstevel@tonic-gate 		debug("cipher_init: set keylen (%d -> %d)", klen, keylen);
2420Sstevel@tonic-gate 		if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0)
2430Sstevel@tonic-gate 			fatal("cipher_init: set keylen failed (%d -> %d)",
2440Sstevel@tonic-gate 			    klen, keylen);
2450Sstevel@tonic-gate 	}
2460Sstevel@tonic-gate 	if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0)
2470Sstevel@tonic-gate 		fatal("cipher_init: EVP_CipherInit: set key failed for %s",
2480Sstevel@tonic-gate 		    cipher->name);
2490Sstevel@tonic-gate #endif
2500Sstevel@tonic-gate }
2510Sstevel@tonic-gate 
2520Sstevel@tonic-gate void
2530Sstevel@tonic-gate cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
2540Sstevel@tonic-gate {
2550Sstevel@tonic-gate 	if (len % cc->cipher->block_size)
2560Sstevel@tonic-gate 		fatal("cipher_encrypt: bad plaintext length %d", len);
2570Sstevel@tonic-gate #ifdef SSH_OLD_EVP
2580Sstevel@tonic-gate 	EVP_Cipher(&cc->evp, dest, (u_char *)src, len);
2590Sstevel@tonic-gate #else
2600Sstevel@tonic-gate 	if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0)
2610Sstevel@tonic-gate 		fatal("evp_crypt: EVP_Cipher failed");
2620Sstevel@tonic-gate #endif
2630Sstevel@tonic-gate }
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate void
2660Sstevel@tonic-gate cipher_cleanup(CipherContext *cc)
2670Sstevel@tonic-gate {
2680Sstevel@tonic-gate #ifdef SSH_OLD_EVP
2690Sstevel@tonic-gate 	EVP_CIPHER_CTX_cleanup(&cc->evp);
2700Sstevel@tonic-gate #else
2710Sstevel@tonic-gate 	if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
2720Sstevel@tonic-gate 		error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed");
2730Sstevel@tonic-gate #endif
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate /*
2770Sstevel@tonic-gate  * Selects the cipher, and keys if by computing the MD5 checksum of the
2780Sstevel@tonic-gate  * passphrase and using the resulting 16 bytes as the key.
2790Sstevel@tonic-gate  */
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate void
2820Sstevel@tonic-gate cipher_set_key_string(CipherContext *cc, Cipher *cipher,
2830Sstevel@tonic-gate     const char *passphrase, int encrypt)
2840Sstevel@tonic-gate {
2850Sstevel@tonic-gate 	MD5_CTX md;
2860Sstevel@tonic-gate 	u_char digest[16];
2870Sstevel@tonic-gate 
2880Sstevel@tonic-gate 	MD5_Init(&md);
2890Sstevel@tonic-gate 	MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
2900Sstevel@tonic-gate 	MD5_Final(digest, &md);
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	cipher_init(cc, cipher, digest, 16, NULL, 0, encrypt);
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	memset(digest, 0, sizeof(digest));
2950Sstevel@tonic-gate 	memset(&md, 0, sizeof(md));
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate /* Implementations for other non-EVP ciphers */
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate /*
3010Sstevel@tonic-gate  * This is used by SSH1:
3020Sstevel@tonic-gate  *
3030Sstevel@tonic-gate  * What kind of triple DES are these 2 routines?
3040Sstevel@tonic-gate  *
3050Sstevel@tonic-gate  * Why is there a redundant initialization vector?
3060Sstevel@tonic-gate  *
3070Sstevel@tonic-gate  * If only iv3 was used, then, this would till effect have been
3080Sstevel@tonic-gate  * outer-cbc. However, there is also a private iv1 == iv2 which
3090Sstevel@tonic-gate  * perhaps makes differential analysis easier. On the other hand, the
3100Sstevel@tonic-gate  * private iv1 probably makes the CRC-32 attack ineffective. This is a
3110Sstevel@tonic-gate  * result of that there is no longer any known iv1 to use when
3120Sstevel@tonic-gate  * choosing the X block.
3130Sstevel@tonic-gate  */
3140Sstevel@tonic-gate struct ssh1_3des_ctx
3150Sstevel@tonic-gate {
3160Sstevel@tonic-gate 	EVP_CIPHER_CTX	k1, k2, k3;
3170Sstevel@tonic-gate };
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate static int
3200Sstevel@tonic-gate ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
3210Sstevel@tonic-gate     int enc)
3220Sstevel@tonic-gate {
3230Sstevel@tonic-gate 	struct ssh1_3des_ctx *c;
3240Sstevel@tonic-gate 	u_char *k1, *k2, *k3;
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
3270Sstevel@tonic-gate 		c = xmalloc(sizeof(*c));
3280Sstevel@tonic-gate 		EVP_CIPHER_CTX_set_app_data(ctx, c);
3290Sstevel@tonic-gate 	}
3300Sstevel@tonic-gate 	if (key == NULL)
3310Sstevel@tonic-gate 		return (1);
3320Sstevel@tonic-gate 	if (enc == -1)
3330Sstevel@tonic-gate 		enc = ctx->encrypt;
3340Sstevel@tonic-gate 	k1 = k2 = k3 = (u_char *) key;
3350Sstevel@tonic-gate 	k2 += 8;
3360Sstevel@tonic-gate 	if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
3370Sstevel@tonic-gate 		if (enc)
3380Sstevel@tonic-gate 			k3 += 16;
3390Sstevel@tonic-gate 		else
3400Sstevel@tonic-gate 			k1 += 16;
3410Sstevel@tonic-gate 	}
3420Sstevel@tonic-gate 	EVP_CIPHER_CTX_init(&c->k1);
3430Sstevel@tonic-gate 	EVP_CIPHER_CTX_init(&c->k2);
3440Sstevel@tonic-gate 	EVP_CIPHER_CTX_init(&c->k3);
3450Sstevel@tonic-gate #ifdef SSH_OLD_EVP
3460Sstevel@tonic-gate 	EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc);
3470Sstevel@tonic-gate 	EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc);
3480Sstevel@tonic-gate 	EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc);
3490Sstevel@tonic-gate #else
3500Sstevel@tonic-gate 	if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
3510Sstevel@tonic-gate 	    EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
3520Sstevel@tonic-gate 	    EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
3530Sstevel@tonic-gate 		memset(c, 0, sizeof(*c));
3540Sstevel@tonic-gate 		xfree(c);
3550Sstevel@tonic-gate 		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
3560Sstevel@tonic-gate 		return (0);
3570Sstevel@tonic-gate 	}
3580Sstevel@tonic-gate #endif
3590Sstevel@tonic-gate 	return (1);
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate static int
3630Sstevel@tonic-gate ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
3640Sstevel@tonic-gate {
3650Sstevel@tonic-gate 	struct ssh1_3des_ctx *c;
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
3680Sstevel@tonic-gate 		error("ssh1_3des_cbc: no context");
3690Sstevel@tonic-gate 		return (0);
3700Sstevel@tonic-gate 	}
3710Sstevel@tonic-gate #ifdef SSH_OLD_EVP
3720Sstevel@tonic-gate 	EVP_Cipher(&c->k1, dest, (u_char *)src, len);
3730Sstevel@tonic-gate 	EVP_Cipher(&c->k2, dest, dest, len);
3740Sstevel@tonic-gate 	EVP_Cipher(&c->k3, dest, dest, len);
3750Sstevel@tonic-gate #else
3760Sstevel@tonic-gate 	if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
3770Sstevel@tonic-gate 	    EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
3780Sstevel@tonic-gate 	    EVP_Cipher(&c->k3, dest, dest, len) == 0)
3790Sstevel@tonic-gate 		return (0);
3800Sstevel@tonic-gate #endif
3810Sstevel@tonic-gate 	return (1);
3820Sstevel@tonic-gate }
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate static int
3850Sstevel@tonic-gate ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
3860Sstevel@tonic-gate {
3870Sstevel@tonic-gate 	struct ssh1_3des_ctx *c;
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
3900Sstevel@tonic-gate 		memset(c, 0, sizeof(*c));
3910Sstevel@tonic-gate 		xfree(c);
3920Sstevel@tonic-gate 		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
3930Sstevel@tonic-gate 	}
3940Sstevel@tonic-gate 	return (1);
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate static const EVP_CIPHER *
3980Sstevel@tonic-gate evp_ssh1_3des(void)
3990Sstevel@tonic-gate {
4000Sstevel@tonic-gate 	static EVP_CIPHER ssh1_3des;
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 	memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
4030Sstevel@tonic-gate 	ssh1_3des.nid = NID_undef;
4040Sstevel@tonic-gate 	ssh1_3des.block_size = 8;
4050Sstevel@tonic-gate 	ssh1_3des.iv_len = 0;
4060Sstevel@tonic-gate 	ssh1_3des.key_len = 16;
4070Sstevel@tonic-gate 	ssh1_3des.init = ssh1_3des_init;
4080Sstevel@tonic-gate 	ssh1_3des.cleanup = ssh1_3des_cleanup;
4090Sstevel@tonic-gate 	ssh1_3des.do_cipher = ssh1_3des_cbc;
4100Sstevel@tonic-gate #ifndef SSH_OLD_EVP
4110Sstevel@tonic-gate 	ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
4120Sstevel@tonic-gate #endif
4130Sstevel@tonic-gate 	return (&ssh1_3des);
4140Sstevel@tonic-gate }
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate /*
4170Sstevel@tonic-gate  * SSH1 uses a variation on Blowfish, all bytes must be swapped before
4180Sstevel@tonic-gate  * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
4190Sstevel@tonic-gate  */
4200Sstevel@tonic-gate static void
4210Sstevel@tonic-gate swap_bytes(const u_char *src, u_char *dst, int n)
4220Sstevel@tonic-gate {
4230Sstevel@tonic-gate 	u_char c[4];
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 	/* Process 4 bytes every lap. */
4260Sstevel@tonic-gate 	for (n = n / 4; n > 0; n--) {
4270Sstevel@tonic-gate 		c[3] = *src++;
4280Sstevel@tonic-gate 		c[2] = *src++;
4290Sstevel@tonic-gate 		c[1] = *src++;
4300Sstevel@tonic-gate 		c[0] = *src++;
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 		*dst++ = c[0];
4330Sstevel@tonic-gate 		*dst++ = c[1];
4340Sstevel@tonic-gate 		*dst++ = c[2];
4350Sstevel@tonic-gate 		*dst++ = c[3];
4360Sstevel@tonic-gate 	}
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate #ifdef SSH_OLD_EVP
4400Sstevel@tonic-gate static void bf_ssh1_init (EVP_CIPHER_CTX * ctx, const unsigned char *key,
4410Sstevel@tonic-gate 			  const unsigned char *iv, int enc)
4420Sstevel@tonic-gate {
4430Sstevel@tonic-gate 	if (iv != NULL)
4440Sstevel@tonic-gate 		memcpy (&(ctx->oiv[0]), iv, 8);
4450Sstevel@tonic-gate 	memcpy (&(ctx->iv[0]), &(ctx->oiv[0]), 8);
4460Sstevel@tonic-gate 	if (key != NULL)
4470Sstevel@tonic-gate 		BF_set_key (&(ctx->c.bf_ks), EVP_CIPHER_CTX_key_length (ctx),
4480Sstevel@tonic-gate 			    key);
4490Sstevel@tonic-gate }
4500Sstevel@tonic-gate #endif
4510Sstevel@tonic-gate static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, const u_char *, u_int) = NULL;
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate static int
4540Sstevel@tonic-gate bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len)
4550Sstevel@tonic-gate {
4560Sstevel@tonic-gate 	int ret;
4570Sstevel@tonic-gate 
4580Sstevel@tonic-gate 	swap_bytes(in, out, len);
4590Sstevel@tonic-gate 	ret = (*orig_bf)(ctx, out, out, len);
4600Sstevel@tonic-gate 	swap_bytes(out, out, len);
4610Sstevel@tonic-gate 	return (ret);
4620Sstevel@tonic-gate }
4630Sstevel@tonic-gate 
4640Sstevel@tonic-gate static const EVP_CIPHER *
4650Sstevel@tonic-gate evp_ssh1_bf(void)
4660Sstevel@tonic-gate {
4670Sstevel@tonic-gate 	static EVP_CIPHER ssh1_bf;
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 	memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER));
4700Sstevel@tonic-gate 	orig_bf = ssh1_bf.do_cipher;
4710Sstevel@tonic-gate 	ssh1_bf.nid = NID_undef;
4720Sstevel@tonic-gate #ifdef SSH_OLD_EVP
4730Sstevel@tonic-gate 	ssh1_bf.init = bf_ssh1_init;
4740Sstevel@tonic-gate #endif
4750Sstevel@tonic-gate 	ssh1_bf.do_cipher = bf_ssh1_cipher;
4760Sstevel@tonic-gate 	ssh1_bf.key_len = 32;
4770Sstevel@tonic-gate 	return (&ssh1_bf);
4780Sstevel@tonic-gate }
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate #if (OPENSSL_VERSION_NUMBER < 0x00907000L)
4810Sstevel@tonic-gate /* RIJNDAEL */
4820Sstevel@tonic-gate #define RIJNDAEL_BLOCKSIZE 16
4830Sstevel@tonic-gate struct ssh_rijndael_ctx
4840Sstevel@tonic-gate {
4850Sstevel@tonic-gate 	rijndael_ctx	r_ctx;
4860Sstevel@tonic-gate 	u_char		r_iv[RIJNDAEL_BLOCKSIZE];
4870Sstevel@tonic-gate };
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate static int
4900Sstevel@tonic-gate ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
4910Sstevel@tonic-gate     int enc)
4920Sstevel@tonic-gate {
4930Sstevel@tonic-gate 	struct ssh_rijndael_ctx *c;
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
4960Sstevel@tonic-gate 		c = xmalloc(sizeof(*c));
4970Sstevel@tonic-gate 		EVP_CIPHER_CTX_set_app_data(ctx, c);
4980Sstevel@tonic-gate 	}
4990Sstevel@tonic-gate 	if (key != NULL) {
5000Sstevel@tonic-gate 		if (enc == -1)
5010Sstevel@tonic-gate 			enc = ctx->encrypt;
5020Sstevel@tonic-gate 		rijndael_set_key(&c->r_ctx, (u_char *)key,
5030Sstevel@tonic-gate 		    8*EVP_CIPHER_CTX_key_length(ctx), enc);
5040Sstevel@tonic-gate 	}
5050Sstevel@tonic-gate 	if (iv != NULL)
5060Sstevel@tonic-gate 		memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE);
5070Sstevel@tonic-gate 	return (1);
5080Sstevel@tonic-gate }
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate static int
5110Sstevel@tonic-gate ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
5120Sstevel@tonic-gate     u_int len)
5130Sstevel@tonic-gate {
5140Sstevel@tonic-gate 	struct ssh_rijndael_ctx *c;
5150Sstevel@tonic-gate 	u_char buf[RIJNDAEL_BLOCKSIZE];
5160Sstevel@tonic-gate 	u_char *cprev, *cnow, *plain, *ivp;
5170Sstevel@tonic-gate 	int i, j, blocks = len / RIJNDAEL_BLOCKSIZE;
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate 	if (len == 0)
5200Sstevel@tonic-gate 		return (1);
5210Sstevel@tonic-gate 	if (len % RIJNDAEL_BLOCKSIZE)
5220Sstevel@tonic-gate 		fatal("ssh_rijndael_cbc: bad len %d", len);
5230Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
5240Sstevel@tonic-gate 		error("ssh_rijndael_cbc: no context");
5250Sstevel@tonic-gate 		return (0);
5260Sstevel@tonic-gate 	}
5270Sstevel@tonic-gate 	if (ctx->encrypt) {
5280Sstevel@tonic-gate 		cnow  = dest;
5290Sstevel@tonic-gate 		plain = (u_char *)src;
5300Sstevel@tonic-gate 		cprev = c->r_iv;
5310Sstevel@tonic-gate 		for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE,
5320Sstevel@tonic-gate 		    cnow+=RIJNDAEL_BLOCKSIZE) {
5330Sstevel@tonic-gate 			for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
5340Sstevel@tonic-gate 				buf[j] = plain[j] ^ cprev[j];
5350Sstevel@tonic-gate 			rijndael_encrypt(&c->r_ctx, buf, cnow);
5360Sstevel@tonic-gate 			cprev = cnow;
5370Sstevel@tonic-gate 		}
5380Sstevel@tonic-gate 		memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE);
5390Sstevel@tonic-gate 	} else {
5400Sstevel@tonic-gate 		cnow  = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE);
5410Sstevel@tonic-gate 		plain = dest+len-RIJNDAEL_BLOCKSIZE;
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate 		memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE);
5440Sstevel@tonic-gate 		for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE,
5450Sstevel@tonic-gate 		    plain-=RIJNDAEL_BLOCKSIZE) {
5460Sstevel@tonic-gate 			rijndael_decrypt(&c->r_ctx, cnow, plain);
5470Sstevel@tonic-gate 			ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE;
5480Sstevel@tonic-gate 			for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
5490Sstevel@tonic-gate 				plain[j] ^= ivp[j];
5500Sstevel@tonic-gate 		}
5510Sstevel@tonic-gate 		memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE);
5520Sstevel@tonic-gate 	}
5530Sstevel@tonic-gate 	return (1);
5540Sstevel@tonic-gate }
5550Sstevel@tonic-gate 
5560Sstevel@tonic-gate static int
5570Sstevel@tonic-gate ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx)
5580Sstevel@tonic-gate {
5590Sstevel@tonic-gate 	struct ssh_rijndael_ctx *c;
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
5620Sstevel@tonic-gate 		memset(c, 0, sizeof(*c));
5630Sstevel@tonic-gate 		xfree(c);
5640Sstevel@tonic-gate 		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
5650Sstevel@tonic-gate 	}
5660Sstevel@tonic-gate 	return (1);
5670Sstevel@tonic-gate }
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate static const EVP_CIPHER *
5700Sstevel@tonic-gate evp_rijndael(void)
5710Sstevel@tonic-gate {
5720Sstevel@tonic-gate 	static EVP_CIPHER rijndal_cbc;
5730Sstevel@tonic-gate 
5740Sstevel@tonic-gate 	memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER));
5750Sstevel@tonic-gate 	rijndal_cbc.nid = NID_undef;
5760Sstevel@tonic-gate 	rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE;
5770Sstevel@tonic-gate 	rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE;
5780Sstevel@tonic-gate 	rijndal_cbc.key_len = 16;
5790Sstevel@tonic-gate 	rijndal_cbc.init = ssh_rijndael_init;
5800Sstevel@tonic-gate 	rijndal_cbc.cleanup = ssh_rijndael_cleanup;
5810Sstevel@tonic-gate 	rijndal_cbc.do_cipher = ssh_rijndael_cbc;
5820Sstevel@tonic-gate #ifndef SSH_OLD_EVP
5830Sstevel@tonic-gate 	rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
5840Sstevel@tonic-gate 	    EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
5850Sstevel@tonic-gate #endif
5860Sstevel@tonic-gate 	return (&rijndal_cbc);
5870Sstevel@tonic-gate }
5880Sstevel@tonic-gate #endif
5890Sstevel@tonic-gate 
5900Sstevel@tonic-gate /*
5910Sstevel@tonic-gate  * Exports an IV from the CipherContext required to export the key
5920Sstevel@tonic-gate  * state back from the unprivileged child to the privileged parent
5930Sstevel@tonic-gate  * process.
5940Sstevel@tonic-gate  */
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate int
5970Sstevel@tonic-gate cipher_get_keyiv_len(CipherContext *cc)
5980Sstevel@tonic-gate {
5990Sstevel@tonic-gate 	Cipher *c = cc->cipher;
6000Sstevel@tonic-gate 	int ivlen;
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 	if (c->number == SSH_CIPHER_3DES)
6030Sstevel@tonic-gate 		ivlen = 24;
6040Sstevel@tonic-gate 	else
6050Sstevel@tonic-gate 		ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp);
6060Sstevel@tonic-gate 	return (ivlen);
6070Sstevel@tonic-gate }
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate void
6100Sstevel@tonic-gate cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
6110Sstevel@tonic-gate {
6120Sstevel@tonic-gate 	Cipher *c = cc->cipher;
6130Sstevel@tonic-gate 	u_char *civ = NULL;
6140Sstevel@tonic-gate 	int evplen;
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 	switch (c->number) {
6170Sstevel@tonic-gate 	case SSH_CIPHER_SSH2:
6180Sstevel@tonic-gate 	case SSH_CIPHER_DES:
6190Sstevel@tonic-gate 	case SSH_CIPHER_BLOWFISH:
6200Sstevel@tonic-gate 		evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
6210Sstevel@tonic-gate 		if (evplen == 0)
6220Sstevel@tonic-gate 			return;
6230Sstevel@tonic-gate 		if (evplen != len)
6240Sstevel@tonic-gate 			fatal("%s: wrong iv length %d != %d", __func__,
6250Sstevel@tonic-gate 			    evplen, len);
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate #if (OPENSSL_VERSION_NUMBER < 0x00907000L)
6280Sstevel@tonic-gate 		if (c->evptype == evp_rijndael) {
6290Sstevel@tonic-gate 			struct ssh_rijndael_ctx *aesc;
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 			aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
6320Sstevel@tonic-gate 			if (aesc == NULL)
6330Sstevel@tonic-gate 				fatal("%s: no rijndael context", __func__);
6340Sstevel@tonic-gate 			civ = aesc->r_iv;
6350Sstevel@tonic-gate 		} else
6360Sstevel@tonic-gate #endif
6370Sstevel@tonic-gate 		if (c->evptype == evp_aes_128_ctr) {
6380Sstevel@tonic-gate 			ssh_aes_ctr_iv(&cc->evp, 0, iv, len);
6390Sstevel@tonic-gate 			return;
6400Sstevel@tonic-gate 		} else {
6410Sstevel@tonic-gate 			civ = cc->evp.iv;
6420Sstevel@tonic-gate 		}
6430Sstevel@tonic-gate 		break;
6440Sstevel@tonic-gate 	case SSH_CIPHER_3DES: {
6450Sstevel@tonic-gate 		struct ssh1_3des_ctx *desc;
6460Sstevel@tonic-gate 		if (len != 24)
6470Sstevel@tonic-gate 			fatal("%s: bad 3des iv length: %d", __func__, len);
6480Sstevel@tonic-gate 		desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
6490Sstevel@tonic-gate 		if (desc == NULL)
6500Sstevel@tonic-gate 			fatal("%s: no 3des context", __func__);
6510Sstevel@tonic-gate 		debug3("%s: Copying 3DES IV", __func__);
6520Sstevel@tonic-gate 		memcpy(iv, desc->k1.iv, 8);
6530Sstevel@tonic-gate 		memcpy(iv + 8, desc->k2.iv, 8);
6540Sstevel@tonic-gate 		memcpy(iv + 16, desc->k3.iv, 8);
6550Sstevel@tonic-gate 		return;
6560Sstevel@tonic-gate 	}
6570Sstevel@tonic-gate 	default:
6580Sstevel@tonic-gate 		fatal("%s: bad cipher %d", __func__, c->number);
6590Sstevel@tonic-gate 	}
6600Sstevel@tonic-gate 	memcpy(iv, civ, len);
6610Sstevel@tonic-gate }
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate void
6640Sstevel@tonic-gate cipher_set_keyiv(CipherContext *cc, u_char *iv)
6650Sstevel@tonic-gate {
6660Sstevel@tonic-gate 	Cipher *c = cc->cipher;
6670Sstevel@tonic-gate 	u_char *div = NULL;
6680Sstevel@tonic-gate 	int evplen = 0;
6690Sstevel@tonic-gate 
6700Sstevel@tonic-gate 	switch (c->number) {
6710Sstevel@tonic-gate 	case SSH_CIPHER_SSH2:
6720Sstevel@tonic-gate 	case SSH_CIPHER_DES:
6730Sstevel@tonic-gate 	case SSH_CIPHER_BLOWFISH:
6740Sstevel@tonic-gate 		evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
6750Sstevel@tonic-gate 		if (evplen == 0)
6760Sstevel@tonic-gate 			return;
6770Sstevel@tonic-gate 
6780Sstevel@tonic-gate #if (OPENSSL_VERSION_NUMBER < 0x00907000L)
6790Sstevel@tonic-gate 		if (c->evptype == evp_rijndael) {
6800Sstevel@tonic-gate 			struct ssh_rijndael_ctx *aesc;
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 			aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
6830Sstevel@tonic-gate 			if (aesc == NULL)
6840Sstevel@tonic-gate 				fatal("%s: no rijndael context", __func__);
6850Sstevel@tonic-gate 			div = aesc->r_iv;
6860Sstevel@tonic-gate 		} else
6870Sstevel@tonic-gate #endif
6880Sstevel@tonic-gate 		if (c->evptype == evp_aes_128_ctr) {
6890Sstevel@tonic-gate 			ssh_aes_ctr_iv(&cc->evp, 1, iv, evplen);
6900Sstevel@tonic-gate 			return;
6910Sstevel@tonic-gate 		} else {
6920Sstevel@tonic-gate 			div = cc->evp.iv;
6930Sstevel@tonic-gate 		}
6940Sstevel@tonic-gate 		break;
6950Sstevel@tonic-gate 	case SSH_CIPHER_3DES: {
6960Sstevel@tonic-gate 		struct ssh1_3des_ctx *desc;
6970Sstevel@tonic-gate 		desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
6980Sstevel@tonic-gate 		if (desc == NULL)
6990Sstevel@tonic-gate 			fatal("%s: no 3des context", __func__);
7000Sstevel@tonic-gate 		debug3("%s: Installed 3DES IV", __func__);
7010Sstevel@tonic-gate 		memcpy(desc->k1.iv, iv, 8);
7020Sstevel@tonic-gate 		memcpy(desc->k2.iv, iv + 8, 8);
7030Sstevel@tonic-gate 		memcpy(desc->k3.iv, iv + 16, 8);
7040Sstevel@tonic-gate 		return;
7050Sstevel@tonic-gate 	}
7060Sstevel@tonic-gate 	default:
7070Sstevel@tonic-gate 		fatal("%s: bad cipher %d", __func__, c->number);
7080Sstevel@tonic-gate 	}
7090Sstevel@tonic-gate 	memcpy(div, iv, evplen);
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate 
7120Sstevel@tonic-gate #if OPENSSL_VERSION_NUMBER < 0x00907000L
7130Sstevel@tonic-gate #define EVP_X_STATE(evp)	&(evp).c
7140Sstevel@tonic-gate #define EVP_X_STATE_LEN(evp)	sizeof((evp).c)
7150Sstevel@tonic-gate #else
7160Sstevel@tonic-gate #define EVP_X_STATE(evp)	(evp).cipher_data
7170Sstevel@tonic-gate #define EVP_X_STATE_LEN(evp)	(evp).cipher->ctx_size
7180Sstevel@tonic-gate #endif
7190Sstevel@tonic-gate 
7200Sstevel@tonic-gate int
7210Sstevel@tonic-gate cipher_get_keycontext(CipherContext *cc, u_char *dat)
7220Sstevel@tonic-gate {
7230Sstevel@tonic-gate 	int plen = 0;
7240Sstevel@tonic-gate 	Cipher *c = cc->cipher;
7250Sstevel@tonic-gate 
7260Sstevel@tonic-gate 	if (c->evptype == EVP_rc4) {
7270Sstevel@tonic-gate 		plen = EVP_X_STATE_LEN(cc->evp);
7280Sstevel@tonic-gate 		if (dat == NULL)
7290Sstevel@tonic-gate 			return (plen);
7300Sstevel@tonic-gate 		memcpy(dat, EVP_X_STATE(cc->evp), plen);
7310Sstevel@tonic-gate 	}
7320Sstevel@tonic-gate 	return (plen);
7330Sstevel@tonic-gate }
7340Sstevel@tonic-gate 
7350Sstevel@tonic-gate void
7360Sstevel@tonic-gate cipher_set_keycontext(CipherContext *cc, u_char *dat)
7370Sstevel@tonic-gate {
7380Sstevel@tonic-gate 	Cipher *c = cc->cipher;
7390Sstevel@tonic-gate 	int plen;
7400Sstevel@tonic-gate 
7410Sstevel@tonic-gate 	if (c->evptype == EVP_rc4) {
7420Sstevel@tonic-gate 		plen = EVP_X_STATE_LEN(cc->evp);
7430Sstevel@tonic-gate 		memcpy(EVP_X_STATE(cc->evp), dat, plen);
7440Sstevel@tonic-gate 	}
7450Sstevel@tonic-gate }
746