xref: /onnv-gate/usr/src/cmd/ssh/libssh/common/cipher.c (revision 8805:e32f9c722e63)
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 /*
38*8805SJan.Pechanec@Sun.COM  * Copyright 2009 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 
517574SJan.Pechanec@Sun.COM /*
527574SJan.Pechanec@Sun.COM  * Symmetric ciphers can be offloaded to any engine through the EVP API only.
537574SJan.Pechanec@Sun.COM  * However, OpenSSL doesn't offer AES in counter mode through EVP. So, we must
547574SJan.Pechanec@Sun.COM  * define our own EVP functions.
557574SJan.Pechanec@Sun.COM  */
560Sstevel@tonic-gate extern const EVP_CIPHER *evp_aes_128_ctr(void);
577574SJan.Pechanec@Sun.COM extern const EVP_CIPHER *evp_aes_192_ctr(void);
587574SJan.Pechanec@Sun.COM extern const EVP_CIPHER *evp_aes_256_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;
69*8805SJan.Pechanec@Sun.COM 	u_int	discard_len;
700Sstevel@tonic-gate 	const EVP_CIPHER	*(*evptype)(void);
710Sstevel@tonic-gate } ciphers[] = {
72*8805SJan.Pechanec@Sun.COM 	{ "none",	  SSH_CIPHER_NONE,	8,  0,	  0, EVP_enc_null },
73*8805SJan.Pechanec@Sun.COM 	{ "des",	  SSH_CIPHER_DES,	8,  8,	  0, EVP_des_cbc },
74*8805SJan.Pechanec@Sun.COM 	{ "3des",	  SSH_CIPHER_3DES,	8, 16,	  0, evp_ssh1_3des },
75*8805SJan.Pechanec@Sun.COM 	{ "blowfish",	  SSH_CIPHER_BLOWFISH,  8, 32,	  0, evp_ssh1_bf },
76*8805SJan.Pechanec@Sun.COM 	{ "3des-cbc",	  SSH_CIPHER_SSH2,	8, 24,	  0, EVP_des_ede3_cbc },
77*8805SJan.Pechanec@Sun.COM 	{ "blowfish-cbc", SSH_CIPHER_SSH2,	8, 16,	  0, EVP_bf_cbc },
780Sstevel@tonic-gate #ifdef SOLARIS_SSH_ENABLE_CAST5_128
79*8805SJan.Pechanec@Sun.COM 	{ "cast128-cbc",  SSH_CIPHER_SSH2,	8, 16,	  0, EVP_cast5_cbc },
800Sstevel@tonic-gate #endif /* SOLARIS_SSH_ENABLE_CAST5_128 */
81*8805SJan.Pechanec@Sun.COM 	{ "arcfour",	  SSH_CIPHER_SSH2,	8, 16,	  0, EVP_rc4 },
82*8805SJan.Pechanec@Sun.COM 	{ "arcfour128",	  SSH_CIPHER_SSH2,	8, 16, 1536, EVP_rc4 },
83*8805SJan.Pechanec@Sun.COM 	{ "arcfour256",	  SSH_CIPHER_SSH2,	8, 32, 1536, EVP_rc4 },
84*8805SJan.Pechanec@Sun.COM 	{ "aes128-cbc",	  SSH_CIPHER_SSH2,     16, 16,	  0, EVP_aes_128_cbc },
85*8805SJan.Pechanec@Sun.COM 	{ "aes192-cbc",	  SSH_CIPHER_SSH2,     16, 24,	  0, EVP_aes_192_cbc },
86*8805SJan.Pechanec@Sun.COM 	{ "aes256-cbc",	  SSH_CIPHER_SSH2,     16, 32,	  0, EVP_aes_256_cbc },
87*8805SJan.Pechanec@Sun.COM 	{ "aes128-ctr",	  SSH_CIPHER_SSH2,     16, 16,	  0, evp_aes_128_ctr },
88*8805SJan.Pechanec@Sun.COM 	{ "aes192-ctr",	  SSH_CIPHER_SSH2,     16, 24,	  0, evp_aes_192_ctr },
89*8805SJan.Pechanec@Sun.COM 	{ "aes256-ctr",	  SSH_CIPHER_SSH2,     16, 32,	  0, evp_aes_256_ctr },
90*8805SJan.Pechanec@Sun.COM 	{ NULL,		  SSH_CIPHER_ILLEGAL,	0,  0,	  0, NULL }
910Sstevel@tonic-gate };
920Sstevel@tonic-gate 
930Sstevel@tonic-gate /*--*/
940Sstevel@tonic-gate 
950Sstevel@tonic-gate u_int
cipher_blocksize(Cipher * c)960Sstevel@tonic-gate cipher_blocksize(Cipher *c)
970Sstevel@tonic-gate {
980Sstevel@tonic-gate 	return (c->block_size);
990Sstevel@tonic-gate }
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate u_int
cipher_keylen(Cipher * c)1020Sstevel@tonic-gate cipher_keylen(Cipher *c)
1030Sstevel@tonic-gate {
1040Sstevel@tonic-gate 	return (c->key_len);
1050Sstevel@tonic-gate }
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate u_int
cipher_get_number(Cipher * c)1080Sstevel@tonic-gate cipher_get_number(Cipher *c)
1090Sstevel@tonic-gate {
1100Sstevel@tonic-gate 	return (c->number);
1110Sstevel@tonic-gate }
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate u_int
cipher_mask_ssh1(int client)1140Sstevel@tonic-gate cipher_mask_ssh1(int client)
1150Sstevel@tonic-gate {
1160Sstevel@tonic-gate 	u_int mask = 0;
1170Sstevel@tonic-gate 	mask |= 1 << SSH_CIPHER_3DES;		/* Mandatory */
1180Sstevel@tonic-gate 	mask |= 1 << SSH_CIPHER_BLOWFISH;
1190Sstevel@tonic-gate 	if (client) {
1200Sstevel@tonic-gate 		mask |= 1 << SSH_CIPHER_DES;
1210Sstevel@tonic-gate 	}
1220Sstevel@tonic-gate 	return mask;
1230Sstevel@tonic-gate }
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate Cipher *
cipher_by_name(const char * name)1260Sstevel@tonic-gate cipher_by_name(const char *name)
1270Sstevel@tonic-gate {
1280Sstevel@tonic-gate 	Cipher *c;
1290Sstevel@tonic-gate 	for (c = ciphers; c->name != NULL; c++)
1300Sstevel@tonic-gate 		if (strcasecmp(c->name, name) == 0)
1310Sstevel@tonic-gate 			return c;
1320Sstevel@tonic-gate 	return NULL;
1330Sstevel@tonic-gate }
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate Cipher *
cipher_by_number(int id)1360Sstevel@tonic-gate cipher_by_number(int id)
1370Sstevel@tonic-gate {
1380Sstevel@tonic-gate 	Cipher *c;
1390Sstevel@tonic-gate 	for (c = ciphers; c->name != NULL; c++)
1400Sstevel@tonic-gate 		if (c->number == id)
1410Sstevel@tonic-gate 			return c;
1420Sstevel@tonic-gate 	return NULL;
1430Sstevel@tonic-gate }
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate #define	CIPHER_SEP	","
1460Sstevel@tonic-gate int
ciphers_valid(const char * names)1470Sstevel@tonic-gate ciphers_valid(const char *names)
1480Sstevel@tonic-gate {
1490Sstevel@tonic-gate 	Cipher *c;
1500Sstevel@tonic-gate 	char *ciphers, *cp;
1510Sstevel@tonic-gate 	char *p;
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 	if (names == NULL || strcmp(names, "") == 0)
1540Sstevel@tonic-gate 		return 0;
1550Sstevel@tonic-gate 	ciphers = cp = xstrdup(names);
1560Sstevel@tonic-gate 	for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
1570Sstevel@tonic-gate 	    (p = strsep(&cp, CIPHER_SEP))) {
1580Sstevel@tonic-gate 		c = cipher_by_name(p);
1590Sstevel@tonic-gate 		if (c == NULL || c->number != SSH_CIPHER_SSH2) {
1600Sstevel@tonic-gate 			debug("bad cipher %s [%s]", p, names);
1610Sstevel@tonic-gate 			xfree(ciphers);
1620Sstevel@tonic-gate 			return 0;
1630Sstevel@tonic-gate 		} else {
1640Sstevel@tonic-gate 			debug3("cipher ok: %s [%s]", p, names);
1650Sstevel@tonic-gate 		}
1660Sstevel@tonic-gate 	}
1670Sstevel@tonic-gate 	debug3("ciphers ok: [%s]", names);
1680Sstevel@tonic-gate 	xfree(ciphers);
1690Sstevel@tonic-gate 	return 1;
1700Sstevel@tonic-gate }
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate /*
1730Sstevel@tonic-gate  * Parses the name of the cipher.  Returns the number of the corresponding
1740Sstevel@tonic-gate  * cipher, or -1 on error.
1750Sstevel@tonic-gate  */
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate int
cipher_number(const char * name)1780Sstevel@tonic-gate cipher_number(const char *name)
1790Sstevel@tonic-gate {
1800Sstevel@tonic-gate 	Cipher *c;
1810Sstevel@tonic-gate 	if (name == NULL)
1820Sstevel@tonic-gate 		return -1;
1830Sstevel@tonic-gate 	c = cipher_by_name(name);
1840Sstevel@tonic-gate 	return (c==NULL) ? -1 : c->number;
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate char *
cipher_name(int id)1880Sstevel@tonic-gate cipher_name(int id)
1890Sstevel@tonic-gate {
1900Sstevel@tonic-gate 	Cipher *c = cipher_by_number(id);
1910Sstevel@tonic-gate 	return (c==NULL) ? "<unknown>" : c->name;
1920Sstevel@tonic-gate }
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate void
cipher_init(CipherContext * cc,Cipher * cipher,const u_char * key,u_int keylen,const u_char * iv,u_int ivlen,int encrypt)1950Sstevel@tonic-gate cipher_init(CipherContext *cc, Cipher *cipher,
1960Sstevel@tonic-gate     const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
1970Sstevel@tonic-gate     int encrypt)
1980Sstevel@tonic-gate {
1990Sstevel@tonic-gate 	static int dowarn = 1;
2000Sstevel@tonic-gate 	const EVP_CIPHER *type;
2010Sstevel@tonic-gate 	int klen;
202*8805SJan.Pechanec@Sun.COM 	u_char *junk, *discard;
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);
226*8805SJan.Pechanec@Sun.COM 	/*
227*8805SJan.Pechanec@Sun.COM 	 * cc->evp is of type EVP_CIPHER_CTX and its key_len will be set to the
228*8805SJan.Pechanec@Sun.COM 	 * default value here for the cipher type. If the requested key length
229*8805SJan.Pechanec@Sun.COM 	 * is different from the default value we will call EVP_CipherInit()
230*8805SJan.Pechanec@Sun.COM 	 * again, see below.
231*8805SJan.Pechanec@Sun.COM 	 */
2320Sstevel@tonic-gate 	if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv,
2330Sstevel@tonic-gate 	    (encrypt == CIPHER_ENCRYPT)) == 0)
2340Sstevel@tonic-gate 		fatal("cipher_init: EVP_CipherInit failed for %s",
2350Sstevel@tonic-gate 		    cipher->name);
2360Sstevel@tonic-gate 	klen = EVP_CIPHER_CTX_key_length(&cc->evp);
2370Sstevel@tonic-gate 	if (klen > 0 && keylen != klen) {
2380Sstevel@tonic-gate 		debug("cipher_init: set keylen (%d -> %d)", klen, keylen);
2390Sstevel@tonic-gate 		if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0)
2400Sstevel@tonic-gate 			fatal("cipher_init: set keylen failed (%d -> %d)",
2410Sstevel@tonic-gate 			    klen, keylen);
2420Sstevel@tonic-gate 	}
2430Sstevel@tonic-gate 	if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0)
2440Sstevel@tonic-gate 		fatal("cipher_init: EVP_CipherInit: set key failed for %s",
2450Sstevel@tonic-gate 		    cipher->name);
246*8805SJan.Pechanec@Sun.COM 
247*8805SJan.Pechanec@Sun.COM 	if (cipher->discard_len > 0) {
248*8805SJan.Pechanec@Sun.COM 		junk = xmalloc(cipher->discard_len);
249*8805SJan.Pechanec@Sun.COM 		discard = xmalloc(cipher->discard_len);
250*8805SJan.Pechanec@Sun.COM 		if (EVP_Cipher(&cc->evp, discard, junk,
251*8805SJan.Pechanec@Sun.COM 		    cipher->discard_len) == 0)
252*8805SJan.Pechanec@Sun.COM 			fatal("cipher_init: EVP_Cipher failed during discard");
253*8805SJan.Pechanec@Sun.COM 		memset(discard, 0, cipher->discard_len);
254*8805SJan.Pechanec@Sun.COM 		xfree(junk);
255*8805SJan.Pechanec@Sun.COM 		xfree(discard);
256*8805SJan.Pechanec@Sun.COM 	}
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate void
cipher_crypt(CipherContext * cc,u_char * dest,const u_char * src,u_int len)2600Sstevel@tonic-gate cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
2610Sstevel@tonic-gate {
2620Sstevel@tonic-gate 	if (len % cc->cipher->block_size)
2630Sstevel@tonic-gate 		fatal("cipher_encrypt: bad plaintext length %d", len);
2640Sstevel@tonic-gate 	if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0)
2650Sstevel@tonic-gate 		fatal("evp_crypt: EVP_Cipher failed");
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate void
cipher_cleanup(CipherContext * cc)2690Sstevel@tonic-gate cipher_cleanup(CipherContext *cc)
2700Sstevel@tonic-gate {
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 }
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate /*
2760Sstevel@tonic-gate  * Selects the cipher, and keys if by computing the MD5 checksum of the
2770Sstevel@tonic-gate  * passphrase and using the resulting 16 bytes as the key.
2780Sstevel@tonic-gate  */
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate void
cipher_set_key_string(CipherContext * cc,Cipher * cipher,const char * passphrase,int encrypt)2810Sstevel@tonic-gate cipher_set_key_string(CipherContext *cc, Cipher *cipher,
2820Sstevel@tonic-gate     const char *passphrase, int encrypt)
2830Sstevel@tonic-gate {
2840Sstevel@tonic-gate 	MD5_CTX md;
2850Sstevel@tonic-gate 	u_char digest[16];
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	MD5_Init(&md);
2880Sstevel@tonic-gate 	MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
2890Sstevel@tonic-gate 	MD5_Final(digest, &md);
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	cipher_init(cc, cipher, digest, 16, NULL, 0, encrypt);
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 	memset(digest, 0, sizeof(digest));
2940Sstevel@tonic-gate 	memset(&md, 0, sizeof(md));
2950Sstevel@tonic-gate }
2960Sstevel@tonic-gate 
2970Sstevel@tonic-gate /* Implementations for other non-EVP ciphers */
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate /*
3000Sstevel@tonic-gate  * This is used by SSH1:
3010Sstevel@tonic-gate  *
3020Sstevel@tonic-gate  * What kind of triple DES are these 2 routines?
3030Sstevel@tonic-gate  *
3040Sstevel@tonic-gate  * Why is there a redundant initialization vector?
3050Sstevel@tonic-gate  *
3060Sstevel@tonic-gate  * If only iv3 was used, then, this would till effect have been
3070Sstevel@tonic-gate  * outer-cbc. However, there is also a private iv1 == iv2 which
3080Sstevel@tonic-gate  * perhaps makes differential analysis easier. On the other hand, the
3090Sstevel@tonic-gate  * private iv1 probably makes the CRC-32 attack ineffective. This is a
3100Sstevel@tonic-gate  * result of that there is no longer any known iv1 to use when
3110Sstevel@tonic-gate  * choosing the X block.
3120Sstevel@tonic-gate  */
3130Sstevel@tonic-gate struct ssh1_3des_ctx
3140Sstevel@tonic-gate {
3150Sstevel@tonic-gate 	EVP_CIPHER_CTX	k1, k2, k3;
3160Sstevel@tonic-gate };
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate static int
ssh1_3des_init(EVP_CIPHER_CTX * ctx,const u_char * key,const u_char * iv,int enc)3190Sstevel@tonic-gate ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
3200Sstevel@tonic-gate     int enc)
3210Sstevel@tonic-gate {
3220Sstevel@tonic-gate 	struct ssh1_3des_ctx *c;
3230Sstevel@tonic-gate 	u_char *k1, *k2, *k3;
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
3260Sstevel@tonic-gate 		c = xmalloc(sizeof(*c));
3270Sstevel@tonic-gate 		EVP_CIPHER_CTX_set_app_data(ctx, c);
3280Sstevel@tonic-gate 	}
3290Sstevel@tonic-gate 	if (key == NULL)
3300Sstevel@tonic-gate 		return (1);
3310Sstevel@tonic-gate 	if (enc == -1)
3320Sstevel@tonic-gate 		enc = ctx->encrypt;
3330Sstevel@tonic-gate 	k1 = k2 = k3 = (u_char *) key;
3340Sstevel@tonic-gate 	k2 += 8;
3350Sstevel@tonic-gate 	if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
3360Sstevel@tonic-gate 		if (enc)
3370Sstevel@tonic-gate 			k3 += 16;
3380Sstevel@tonic-gate 		else
3390Sstevel@tonic-gate 			k1 += 16;
3400Sstevel@tonic-gate 	}
3410Sstevel@tonic-gate 	EVP_CIPHER_CTX_init(&c->k1);
3420Sstevel@tonic-gate 	EVP_CIPHER_CTX_init(&c->k2);
3430Sstevel@tonic-gate 	EVP_CIPHER_CTX_init(&c->k3);
3440Sstevel@tonic-gate 	if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
3450Sstevel@tonic-gate 	    EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
3460Sstevel@tonic-gate 	    EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
3470Sstevel@tonic-gate 		memset(c, 0, sizeof(*c));
3480Sstevel@tonic-gate 		xfree(c);
3490Sstevel@tonic-gate 		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
3500Sstevel@tonic-gate 		return (0);
3510Sstevel@tonic-gate 	}
3520Sstevel@tonic-gate 	return (1);
3530Sstevel@tonic-gate }
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate static int
ssh1_3des_cbc(EVP_CIPHER_CTX * ctx,u_char * dest,const u_char * src,u_int len)3560Sstevel@tonic-gate ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
3570Sstevel@tonic-gate {
3580Sstevel@tonic-gate 	struct ssh1_3des_ctx *c;
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
3610Sstevel@tonic-gate 		error("ssh1_3des_cbc: no context");
3620Sstevel@tonic-gate 		return (0);
3630Sstevel@tonic-gate 	}
3640Sstevel@tonic-gate 	if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
3650Sstevel@tonic-gate 	    EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
3660Sstevel@tonic-gate 	    EVP_Cipher(&c->k3, dest, dest, len) == 0)
3670Sstevel@tonic-gate 		return (0);
3680Sstevel@tonic-gate 	return (1);
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate static int
ssh1_3des_cleanup(EVP_CIPHER_CTX * ctx)3720Sstevel@tonic-gate ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
3730Sstevel@tonic-gate {
3740Sstevel@tonic-gate 	struct ssh1_3des_ctx *c;
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
3770Sstevel@tonic-gate 		memset(c, 0, sizeof(*c));
3780Sstevel@tonic-gate 		xfree(c);
3790Sstevel@tonic-gate 		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
3800Sstevel@tonic-gate 	}
3810Sstevel@tonic-gate 	return (1);
3820Sstevel@tonic-gate }
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate static const EVP_CIPHER *
evp_ssh1_3des(void)3850Sstevel@tonic-gate evp_ssh1_3des(void)
3860Sstevel@tonic-gate {
3870Sstevel@tonic-gate 	static EVP_CIPHER ssh1_3des;
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 	memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
3900Sstevel@tonic-gate 	ssh1_3des.nid = NID_undef;
3910Sstevel@tonic-gate 	ssh1_3des.block_size = 8;
3920Sstevel@tonic-gate 	ssh1_3des.iv_len = 0;
3930Sstevel@tonic-gate 	ssh1_3des.key_len = 16;
3940Sstevel@tonic-gate 	ssh1_3des.init = ssh1_3des_init;
3950Sstevel@tonic-gate 	ssh1_3des.cleanup = ssh1_3des_cleanup;
3960Sstevel@tonic-gate 	ssh1_3des.do_cipher = ssh1_3des_cbc;
3970Sstevel@tonic-gate 	ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
3980Sstevel@tonic-gate 	return (&ssh1_3des);
3990Sstevel@tonic-gate }
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate /*
4020Sstevel@tonic-gate  * SSH1 uses a variation on Blowfish, all bytes must be swapped before
4030Sstevel@tonic-gate  * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
4040Sstevel@tonic-gate  */
4050Sstevel@tonic-gate static void
swap_bytes(const u_char * src,u_char * dst,int n)4060Sstevel@tonic-gate swap_bytes(const u_char *src, u_char *dst, int n)
4070Sstevel@tonic-gate {
4080Sstevel@tonic-gate 	u_char c[4];
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 	/* Process 4 bytes every lap. */
4110Sstevel@tonic-gate 	for (n = n / 4; n > 0; n--) {
4120Sstevel@tonic-gate 		c[3] = *src++;
4130Sstevel@tonic-gate 		c[2] = *src++;
4140Sstevel@tonic-gate 		c[1] = *src++;
4150Sstevel@tonic-gate 		c[0] = *src++;
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 		*dst++ = c[0];
4180Sstevel@tonic-gate 		*dst++ = c[1];
4190Sstevel@tonic-gate 		*dst++ = c[2];
4200Sstevel@tonic-gate 		*dst++ = c[3];
4210Sstevel@tonic-gate 	}
4220Sstevel@tonic-gate }
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, const u_char *, u_int) = NULL;
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate static int
bf_ssh1_cipher(EVP_CIPHER_CTX * ctx,u_char * out,const u_char * in,u_int len)4270Sstevel@tonic-gate bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len)
4280Sstevel@tonic-gate {
4290Sstevel@tonic-gate 	int ret;
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	swap_bytes(in, out, len);
4320Sstevel@tonic-gate 	ret = (*orig_bf)(ctx, out, out, len);
4330Sstevel@tonic-gate 	swap_bytes(out, out, len);
4340Sstevel@tonic-gate 	return (ret);
4350Sstevel@tonic-gate }
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate static const EVP_CIPHER *
evp_ssh1_bf(void)4380Sstevel@tonic-gate evp_ssh1_bf(void)
4390Sstevel@tonic-gate {
4400Sstevel@tonic-gate 	static EVP_CIPHER ssh1_bf;
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER));
4430Sstevel@tonic-gate 	orig_bf = ssh1_bf.do_cipher;
4440Sstevel@tonic-gate 	ssh1_bf.nid = NID_undef;
4450Sstevel@tonic-gate 	ssh1_bf.do_cipher = bf_ssh1_cipher;
4460Sstevel@tonic-gate 	ssh1_bf.key_len = 32;
4470Sstevel@tonic-gate 	return (&ssh1_bf);
4480Sstevel@tonic-gate }
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate /*
4510Sstevel@tonic-gate  * Exports an IV from the CipherContext required to export the key
4520Sstevel@tonic-gate  * state back from the unprivileged child to the privileged parent
4530Sstevel@tonic-gate  * process.
4540Sstevel@tonic-gate  */
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate int
cipher_get_keyiv_len(CipherContext * cc)4570Sstevel@tonic-gate cipher_get_keyiv_len(CipherContext *cc)
4580Sstevel@tonic-gate {
4590Sstevel@tonic-gate 	Cipher *c = cc->cipher;
4600Sstevel@tonic-gate 	int ivlen;
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 	if (c->number == SSH_CIPHER_3DES)
4630Sstevel@tonic-gate 		ivlen = 24;
4640Sstevel@tonic-gate 	else
4650Sstevel@tonic-gate 		ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp);
4660Sstevel@tonic-gate 	return (ivlen);
4670Sstevel@tonic-gate }
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate void
cipher_get_keyiv(CipherContext * cc,u_char * iv,u_int len)4700Sstevel@tonic-gate cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
4710Sstevel@tonic-gate {
4720Sstevel@tonic-gate 	Cipher *c = cc->cipher;
4730Sstevel@tonic-gate 	u_char *civ = NULL;
4740Sstevel@tonic-gate 	int evplen;
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 	switch (c->number) {
4770Sstevel@tonic-gate 	case SSH_CIPHER_SSH2:
4780Sstevel@tonic-gate 	case SSH_CIPHER_DES:
4790Sstevel@tonic-gate 	case SSH_CIPHER_BLOWFISH:
4800Sstevel@tonic-gate 		evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
4810Sstevel@tonic-gate 		if (evplen == 0)
4820Sstevel@tonic-gate 			return;
4830Sstevel@tonic-gate 		if (evplen != len)
4840Sstevel@tonic-gate 			fatal("%s: wrong iv length %d != %d", __func__,
4850Sstevel@tonic-gate 			    evplen, len);
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 		if (c->evptype == evp_aes_128_ctr) {
4880Sstevel@tonic-gate 			ssh_aes_ctr_iv(&cc->evp, 0, iv, len);
4890Sstevel@tonic-gate 			return;
4900Sstevel@tonic-gate 		} else {
4910Sstevel@tonic-gate 			civ = cc->evp.iv;
4920Sstevel@tonic-gate 		}
4930Sstevel@tonic-gate 		break;
4940Sstevel@tonic-gate 	case SSH_CIPHER_3DES: {
4950Sstevel@tonic-gate 		struct ssh1_3des_ctx *desc;
4960Sstevel@tonic-gate 		if (len != 24)
4970Sstevel@tonic-gate 			fatal("%s: bad 3des iv length: %d", __func__, len);
4980Sstevel@tonic-gate 		desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
4990Sstevel@tonic-gate 		if (desc == NULL)
5000Sstevel@tonic-gate 			fatal("%s: no 3des context", __func__);
5010Sstevel@tonic-gate 		debug3("%s: Copying 3DES IV", __func__);
5020Sstevel@tonic-gate 		memcpy(iv, desc->k1.iv, 8);
5030Sstevel@tonic-gate 		memcpy(iv + 8, desc->k2.iv, 8);
5040Sstevel@tonic-gate 		memcpy(iv + 16, desc->k3.iv, 8);
5050Sstevel@tonic-gate 		return;
5060Sstevel@tonic-gate 	}
5070Sstevel@tonic-gate 	default:
5080Sstevel@tonic-gate 		fatal("%s: bad cipher %d", __func__, c->number);
5090Sstevel@tonic-gate 	}
5100Sstevel@tonic-gate 	memcpy(iv, civ, len);
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate void
cipher_set_keyiv(CipherContext * cc,u_char * iv)5140Sstevel@tonic-gate cipher_set_keyiv(CipherContext *cc, u_char *iv)
5150Sstevel@tonic-gate {
5160Sstevel@tonic-gate 	Cipher *c = cc->cipher;
5170Sstevel@tonic-gate 	u_char *div = NULL;
5180Sstevel@tonic-gate 	int evplen = 0;
5190Sstevel@tonic-gate 
5200Sstevel@tonic-gate 	switch (c->number) {
5210Sstevel@tonic-gate 	case SSH_CIPHER_SSH2:
5220Sstevel@tonic-gate 	case SSH_CIPHER_DES:
5230Sstevel@tonic-gate 	case SSH_CIPHER_BLOWFISH:
5240Sstevel@tonic-gate 		evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
5250Sstevel@tonic-gate 		if (evplen == 0)
5260Sstevel@tonic-gate 			return;
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate 		if (c->evptype == evp_aes_128_ctr) {
5290Sstevel@tonic-gate 			ssh_aes_ctr_iv(&cc->evp, 1, iv, evplen);
5300Sstevel@tonic-gate 			return;
5310Sstevel@tonic-gate 		} else {
5320Sstevel@tonic-gate 			div = cc->evp.iv;
5330Sstevel@tonic-gate 		}
5340Sstevel@tonic-gate 		break;
5350Sstevel@tonic-gate 	case SSH_CIPHER_3DES: {
5360Sstevel@tonic-gate 		struct ssh1_3des_ctx *desc;
5370Sstevel@tonic-gate 		desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
5380Sstevel@tonic-gate 		if (desc == NULL)
5390Sstevel@tonic-gate 			fatal("%s: no 3des context", __func__);
5400Sstevel@tonic-gate 		debug3("%s: Installed 3DES IV", __func__);
5410Sstevel@tonic-gate 		memcpy(desc->k1.iv, iv, 8);
5420Sstevel@tonic-gate 		memcpy(desc->k2.iv, iv + 8, 8);
5430Sstevel@tonic-gate 		memcpy(desc->k3.iv, iv + 16, 8);
5440Sstevel@tonic-gate 		return;
5450Sstevel@tonic-gate 	}
5460Sstevel@tonic-gate 	default:
5470Sstevel@tonic-gate 		fatal("%s: bad cipher %d", __func__, c->number);
5480Sstevel@tonic-gate 	}
5490Sstevel@tonic-gate 	memcpy(div, iv, evplen);
5500Sstevel@tonic-gate }
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate #if OPENSSL_VERSION_NUMBER < 0x00907000L
5530Sstevel@tonic-gate #define EVP_X_STATE(evp)	&(evp).c
5540Sstevel@tonic-gate #define EVP_X_STATE_LEN(evp)	sizeof((evp).c)
5550Sstevel@tonic-gate #else
5560Sstevel@tonic-gate #define EVP_X_STATE(evp)	(evp).cipher_data
5570Sstevel@tonic-gate #define EVP_X_STATE_LEN(evp)	(evp).cipher->ctx_size
5580Sstevel@tonic-gate #endif
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate int
cipher_get_keycontext(CipherContext * cc,u_char * dat)5610Sstevel@tonic-gate cipher_get_keycontext(CipherContext *cc, u_char *dat)
5620Sstevel@tonic-gate {
5630Sstevel@tonic-gate 	int plen = 0;
5640Sstevel@tonic-gate 	Cipher *c = cc->cipher;
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate 	if (c->evptype == EVP_rc4) {
5670Sstevel@tonic-gate 		plen = EVP_X_STATE_LEN(cc->evp);
5680Sstevel@tonic-gate 		if (dat == NULL)
5690Sstevel@tonic-gate 			return (plen);
5700Sstevel@tonic-gate 		memcpy(dat, EVP_X_STATE(cc->evp), plen);
5710Sstevel@tonic-gate 	}
5720Sstevel@tonic-gate 	return (plen);
5730Sstevel@tonic-gate }
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate void
cipher_set_keycontext(CipherContext * cc,u_char * dat)5760Sstevel@tonic-gate cipher_set_keycontext(CipherContext *cc, u_char *dat)
5770Sstevel@tonic-gate {
5780Sstevel@tonic-gate 	Cipher *c = cc->cipher;
5790Sstevel@tonic-gate 	int plen;
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 	if (c->evptype == EVP_rc4) {
5820Sstevel@tonic-gate 		plen = EVP_X_STATE_LEN(cc->evp);
5830Sstevel@tonic-gate 		memcpy(EVP_X_STATE(cc->evp), dat, plen);
5840Sstevel@tonic-gate 	}
5850Sstevel@tonic-gate }
586