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