1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*0Sstevel@tonic-gate  * Use is subject to license terms.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate /*
6*0Sstevel@tonic-gate  * Author: Tatu Ylonen <ylo@cs.hut.fi>
7*0Sstevel@tonic-gate  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
8*0Sstevel@tonic-gate  *                    All rights reserved
9*0Sstevel@tonic-gate  *
10*0Sstevel@tonic-gate  * As far as I am concerned, the code I have written for this software
11*0Sstevel@tonic-gate  * can be used freely for any purpose.  Any derived versions of this
12*0Sstevel@tonic-gate  * software must be clearly marked as such, and if the derived work is
13*0Sstevel@tonic-gate  * incompatible with the protocol description in the RFC file, it must be
14*0Sstevel@tonic-gate  * called by a name other than "ssh" or "Secure Shell".
15*0Sstevel@tonic-gate  *
16*0Sstevel@tonic-gate  *
17*0Sstevel@tonic-gate  * Copyright (c) 1999 Niels Provos.  All rights reserved.
18*0Sstevel@tonic-gate  * Copyright (c) 1999, 2000 Markus Friedl.  All rights reserved.
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
21*0Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
22*0Sstevel@tonic-gate  * are met:
23*0Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
24*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
25*0Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
26*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
27*0Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
28*0Sstevel@tonic-gate  *
29*0Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
30*0Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
31*0Sstevel@tonic-gate  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
32*0Sstevel@tonic-gate  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
33*0Sstevel@tonic-gate  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
34*0Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35*0Sstevel@tonic-gate  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36*0Sstevel@tonic-gate  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37*0Sstevel@tonic-gate  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
38*0Sstevel@tonic-gate  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39*0Sstevel@tonic-gate  */
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate #include "includes.h"
42*0Sstevel@tonic-gate RCSID("$OpenBSD: cipher.c,v 1.61 2002/07/12 15:50:17 markus Exp $");
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate #include "xmalloc.h"
47*0Sstevel@tonic-gate #include "log.h"
48*0Sstevel@tonic-gate #include "cipher.h"
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate #include <openssl/md5.h>
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate #if OPENSSL_VERSION_NUMBER < 0x00906000L
53*0Sstevel@tonic-gate #define SSH_OLD_EVP
54*0Sstevel@tonic-gate #define EVP_CIPHER_CTX_get_app_data(e)          ((e)->app_data)
55*0Sstevel@tonic-gate #endif
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate extern const EVP_CIPHER *evp_aes_128_ctr(void);
58*0Sstevel@tonic-gate extern void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate #if (OPENSSL_VERSION_NUMBER < 0x00907000L)
61*0Sstevel@tonic-gate #include "rijndael.h"
62*0Sstevel@tonic-gate static const EVP_CIPHER *evp_rijndael(void);
63*0Sstevel@tonic-gate #endif
64*0Sstevel@tonic-gate static const EVP_CIPHER *evp_ssh1_3des(void);
65*0Sstevel@tonic-gate static const EVP_CIPHER *evp_ssh1_bf(void);
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate struct Cipher {
68*0Sstevel@tonic-gate 	char	*name;
69*0Sstevel@tonic-gate 	int	number;		/* for ssh1 only */
70*0Sstevel@tonic-gate 	u_int	block_size;
71*0Sstevel@tonic-gate 	u_int	key_len;
72*0Sstevel@tonic-gate 	const EVP_CIPHER	*(*evptype)(void);
73*0Sstevel@tonic-gate } ciphers[] = {
74*0Sstevel@tonic-gate 	{ "none", 		SSH_CIPHER_NONE, 8, 0, EVP_enc_null },
75*0Sstevel@tonic-gate 	{ "des", 		SSH_CIPHER_DES, 8, 8, EVP_des_cbc },
76*0Sstevel@tonic-gate 	{ "3des", 		SSH_CIPHER_3DES, 8, 16, evp_ssh1_3des },
77*0Sstevel@tonic-gate 	{ "blowfish", 		SSH_CIPHER_BLOWFISH, 8, 32, evp_ssh1_bf },
78*0Sstevel@tonic-gate 	{ "3des-cbc", 		SSH_CIPHER_SSH2, 8, 24, EVP_des_ede3_cbc },
79*0Sstevel@tonic-gate 	{ "blowfish-cbc", 	SSH_CIPHER_SSH2, 8, 16, EVP_bf_cbc },
80*0Sstevel@tonic-gate #ifdef SOLARIS_SSH_ENABLE_CAST5_128
81*0Sstevel@tonic-gate 	{ "cast128-cbc", 	SSH_CIPHER_SSH2, 8, 16, EVP_cast5_cbc },
82*0Sstevel@tonic-gate #endif /* SOLARIS_SSH_ENABLE_CAST5_128 */
83*0Sstevel@tonic-gate 	{ "arcfour", 		SSH_CIPHER_SSH2, 8, 16, EVP_rc4 },
84*0Sstevel@tonic-gate #if (OPENSSL_VERSION_NUMBER < 0x00907000L)
85*0Sstevel@tonic-gate 	{ "aes128-cbc", 	SSH_CIPHER_SSH2, 16, 16, evp_rijndael },
86*0Sstevel@tonic-gate #ifdef SOLARIS_SSH_ENABLE_AES192
87*0Sstevel@tonic-gate 	{ "aes192-cbc", 	SSH_CIPHER_SSH2, 16, 24, evp_rijndael },
88*0Sstevel@tonic-gate #endif /* SOLARIS_SSH_ENABLE_AES192 */
89*0Sstevel@tonic-gate #ifdef SOLARIS_SSH_ENABLE_AES256
90*0Sstevel@tonic-gate 	{ "aes256-cbc", 	SSH_CIPHER_SSH2, 16, 32, evp_rijndael },
91*0Sstevel@tonic-gate 	{ "rijndael-cbc@lysator.liu.se",
92*0Sstevel@tonic-gate 				SSH_CIPHER_SSH2, 16, 32, evp_rijndael },
93*0Sstevel@tonic-gate #endif /* SOLARIS_SSH_ENABLE_AES256 */
94*0Sstevel@tonic-gate #else
95*0Sstevel@tonic-gate 	{ "aes128-cbc",		SSH_CIPHER_SSH2, 16, 16, EVP_aes_128_cbc },
96*0Sstevel@tonic-gate #ifdef SOLARIS_SSH_ENABLE_AES192
97*0Sstevel@tonic-gate 	{ "aes192-cbc",		SSH_CIPHER_SSH2, 16, 24, EVP_aes_192_cbc },
98*0Sstevel@tonic-gate #endif /* SOLARIS_SSH_ENABLE_AES192 */
99*0Sstevel@tonic-gate #ifdef SOLARIS_SSH_ENABLE_AES256
100*0Sstevel@tonic-gate 	{ "aes256-cbc",		SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc },
101*0Sstevel@tonic-gate 	{ "rijndael-cbc@lysator.liu.se",
102*0Sstevel@tonic-gate 				SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc },
103*0Sstevel@tonic-gate #endif /* SOLARIS_SSH_ENABLE_AES256 */
104*0Sstevel@tonic-gate #endif
105*0Sstevel@tonic-gate #if OPENSSL_VERSION_NUMBER >= 0x00905000L
106*0Sstevel@tonic-gate         { "aes128-ctr",         SSH_CIPHER_SSH2, 16, 16, evp_aes_128_ctr },
107*0Sstevel@tonic-gate #ifdef SOLARIS_SSH_ENABLE_AES192
108*0Sstevel@tonic-gate         { "aes192-ctr",         SSH_CIPHER_SSH2, 16, 24, evp_aes_128_ctr },
109*0Sstevel@tonic-gate #endif /* SOLARIS_SSH_ENABLE_AES192 */
110*0Sstevel@tonic-gate #ifdef SOLARIS_SSH_ENABLE_AES192
111*0Sstevel@tonic-gate         { "aes256-ctr",         SSH_CIPHER_SSH2, 16, 32, evp_aes_128_ctr },
112*0Sstevel@tonic-gate #endif /* SOLARIS_SSH_ENABLE_AES192 */
113*0Sstevel@tonic-gate #endif
114*0Sstevel@tonic-gate 	{ NULL,			SSH_CIPHER_ILLEGAL, 0, 0, NULL }
115*0Sstevel@tonic-gate };
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate /*--*/
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate u_int
120*0Sstevel@tonic-gate cipher_blocksize(Cipher *c)
121*0Sstevel@tonic-gate {
122*0Sstevel@tonic-gate 	return (c->block_size);
123*0Sstevel@tonic-gate }
124*0Sstevel@tonic-gate 
125*0Sstevel@tonic-gate u_int
126*0Sstevel@tonic-gate cipher_keylen(Cipher *c)
127*0Sstevel@tonic-gate {
128*0Sstevel@tonic-gate 	return (c->key_len);
129*0Sstevel@tonic-gate }
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate u_int
132*0Sstevel@tonic-gate cipher_get_number(Cipher *c)
133*0Sstevel@tonic-gate {
134*0Sstevel@tonic-gate 	return (c->number);
135*0Sstevel@tonic-gate }
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate u_int
138*0Sstevel@tonic-gate cipher_mask_ssh1(int client)
139*0Sstevel@tonic-gate {
140*0Sstevel@tonic-gate 	u_int mask = 0;
141*0Sstevel@tonic-gate 	mask |= 1 << SSH_CIPHER_3DES;		/* Mandatory */
142*0Sstevel@tonic-gate 	mask |= 1 << SSH_CIPHER_BLOWFISH;
143*0Sstevel@tonic-gate 	if (client) {
144*0Sstevel@tonic-gate 		mask |= 1 << SSH_CIPHER_DES;
145*0Sstevel@tonic-gate 	}
146*0Sstevel@tonic-gate 	return mask;
147*0Sstevel@tonic-gate }
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate Cipher *
150*0Sstevel@tonic-gate cipher_by_name(const char *name)
151*0Sstevel@tonic-gate {
152*0Sstevel@tonic-gate 	Cipher *c;
153*0Sstevel@tonic-gate 	for (c = ciphers; c->name != NULL; c++)
154*0Sstevel@tonic-gate 		if (strcasecmp(c->name, name) == 0)
155*0Sstevel@tonic-gate 			return c;
156*0Sstevel@tonic-gate 	return NULL;
157*0Sstevel@tonic-gate }
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate Cipher *
160*0Sstevel@tonic-gate cipher_by_number(int id)
161*0Sstevel@tonic-gate {
162*0Sstevel@tonic-gate 	Cipher *c;
163*0Sstevel@tonic-gate 	for (c = ciphers; c->name != NULL; c++)
164*0Sstevel@tonic-gate 		if (c->number == id)
165*0Sstevel@tonic-gate 			return c;
166*0Sstevel@tonic-gate 	return NULL;
167*0Sstevel@tonic-gate }
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate #define	CIPHER_SEP	","
170*0Sstevel@tonic-gate int
171*0Sstevel@tonic-gate ciphers_valid(const char *names)
172*0Sstevel@tonic-gate {
173*0Sstevel@tonic-gate 	Cipher *c;
174*0Sstevel@tonic-gate 	char *ciphers, *cp;
175*0Sstevel@tonic-gate 	char *p;
176*0Sstevel@tonic-gate 
177*0Sstevel@tonic-gate 	if (names == NULL || strcmp(names, "") == 0)
178*0Sstevel@tonic-gate 		return 0;
179*0Sstevel@tonic-gate 	ciphers = cp = xstrdup(names);
180*0Sstevel@tonic-gate 	for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
181*0Sstevel@tonic-gate 	    (p = strsep(&cp, CIPHER_SEP))) {
182*0Sstevel@tonic-gate 		c = cipher_by_name(p);
183*0Sstevel@tonic-gate 		if (c == NULL || c->number != SSH_CIPHER_SSH2) {
184*0Sstevel@tonic-gate 			debug("bad cipher %s [%s]", p, names);
185*0Sstevel@tonic-gate 			xfree(ciphers);
186*0Sstevel@tonic-gate 			return 0;
187*0Sstevel@tonic-gate 		} else {
188*0Sstevel@tonic-gate 			debug3("cipher ok: %s [%s]", p, names);
189*0Sstevel@tonic-gate 		}
190*0Sstevel@tonic-gate 	}
191*0Sstevel@tonic-gate 	debug3("ciphers ok: [%s]", names);
192*0Sstevel@tonic-gate 	xfree(ciphers);
193*0Sstevel@tonic-gate 	return 1;
194*0Sstevel@tonic-gate }
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate /*
197*0Sstevel@tonic-gate  * Parses the name of the cipher.  Returns the number of the corresponding
198*0Sstevel@tonic-gate  * cipher, or -1 on error.
199*0Sstevel@tonic-gate  */
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate int
202*0Sstevel@tonic-gate cipher_number(const char *name)
203*0Sstevel@tonic-gate {
204*0Sstevel@tonic-gate 	Cipher *c;
205*0Sstevel@tonic-gate 	if (name == NULL)
206*0Sstevel@tonic-gate 		return -1;
207*0Sstevel@tonic-gate 	c = cipher_by_name(name);
208*0Sstevel@tonic-gate 	return (c==NULL) ? -1 : c->number;
209*0Sstevel@tonic-gate }
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate char *
212*0Sstevel@tonic-gate cipher_name(int id)
213*0Sstevel@tonic-gate {
214*0Sstevel@tonic-gate 	Cipher *c = cipher_by_number(id);
215*0Sstevel@tonic-gate 	return (c==NULL) ? "<unknown>" : c->name;
216*0Sstevel@tonic-gate }
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate void
219*0Sstevel@tonic-gate cipher_init(CipherContext *cc, Cipher *cipher,
220*0Sstevel@tonic-gate     const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
221*0Sstevel@tonic-gate     int encrypt)
222*0Sstevel@tonic-gate {
223*0Sstevel@tonic-gate 	static int dowarn = 1;
224*0Sstevel@tonic-gate #ifdef SSH_OLD_EVP
225*0Sstevel@tonic-gate 	EVP_CIPHER *type;
226*0Sstevel@tonic-gate #else
227*0Sstevel@tonic-gate 	const EVP_CIPHER *type;
228*0Sstevel@tonic-gate #endif
229*0Sstevel@tonic-gate 	int klen;
230*0Sstevel@tonic-gate 
231*0Sstevel@tonic-gate 	if (cipher->number == SSH_CIPHER_DES) {
232*0Sstevel@tonic-gate 		if (dowarn) {
233*0Sstevel@tonic-gate 			error("Warning: use of DES is strongly discouraged "
234*0Sstevel@tonic-gate 			    "due to cryptographic weaknesses");
235*0Sstevel@tonic-gate 			dowarn = 0;
236*0Sstevel@tonic-gate 		}
237*0Sstevel@tonic-gate 		if (keylen > 8)
238*0Sstevel@tonic-gate 			keylen = 8;
239*0Sstevel@tonic-gate 	}
240*0Sstevel@tonic-gate 	cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 	if (keylen < cipher->key_len)
243*0Sstevel@tonic-gate 		fatal("cipher_init: key length %d is insufficient for %s.",
244*0Sstevel@tonic-gate 		    keylen, cipher->name);
245*0Sstevel@tonic-gate 	if (iv != NULL && ivlen < cipher->block_size)
246*0Sstevel@tonic-gate 		fatal("cipher_init: iv length %d is insufficient for %s.",
247*0Sstevel@tonic-gate 		    ivlen, cipher->name);
248*0Sstevel@tonic-gate 	cc->cipher = cipher;
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate 	type = (*cipher->evptype)();
251*0Sstevel@tonic-gate 
252*0Sstevel@tonic-gate 	EVP_CIPHER_CTX_init(&cc->evp);
253*0Sstevel@tonic-gate #ifdef SSH_OLD_EVP
254*0Sstevel@tonic-gate 	if (type->key_len > 0 && type->key_len != keylen) {
255*0Sstevel@tonic-gate 		debug("cipher_init: set keylen (%d -> %d)",
256*0Sstevel@tonic-gate 		    type->key_len, keylen);
257*0Sstevel@tonic-gate 		type->key_len = keylen;
258*0Sstevel@tonic-gate 	}
259*0Sstevel@tonic-gate 	EVP_CipherInit(&cc->evp, type, (u_char *)key, (u_char *)iv,
260*0Sstevel@tonic-gate 	    (encrypt == CIPHER_ENCRYPT));
261*0Sstevel@tonic-gate #else
262*0Sstevel@tonic-gate 	if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv,
263*0Sstevel@tonic-gate 	    (encrypt == CIPHER_ENCRYPT)) == 0)
264*0Sstevel@tonic-gate 		fatal("cipher_init: EVP_CipherInit failed for %s",
265*0Sstevel@tonic-gate 		    cipher->name);
266*0Sstevel@tonic-gate 	klen = EVP_CIPHER_CTX_key_length(&cc->evp);
267*0Sstevel@tonic-gate 	if (klen > 0 && keylen != klen) {
268*0Sstevel@tonic-gate 		debug("cipher_init: set keylen (%d -> %d)", klen, keylen);
269*0Sstevel@tonic-gate 		if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0)
270*0Sstevel@tonic-gate 			fatal("cipher_init: set keylen failed (%d -> %d)",
271*0Sstevel@tonic-gate 			    klen, keylen);
272*0Sstevel@tonic-gate 	}
273*0Sstevel@tonic-gate 	if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0)
274*0Sstevel@tonic-gate 		fatal("cipher_init: EVP_CipherInit: set key failed for %s",
275*0Sstevel@tonic-gate 		    cipher->name);
276*0Sstevel@tonic-gate #endif
277*0Sstevel@tonic-gate }
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate void
280*0Sstevel@tonic-gate cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
281*0Sstevel@tonic-gate {
282*0Sstevel@tonic-gate 	if (len % cc->cipher->block_size)
283*0Sstevel@tonic-gate 		fatal("cipher_encrypt: bad plaintext length %d", len);
284*0Sstevel@tonic-gate #ifdef SSH_OLD_EVP
285*0Sstevel@tonic-gate 	EVP_Cipher(&cc->evp, dest, (u_char *)src, len);
286*0Sstevel@tonic-gate #else
287*0Sstevel@tonic-gate 	if (EVP_Cipher(&cc->evp, dest, (u_char *)src, len) == 0)
288*0Sstevel@tonic-gate 		fatal("evp_crypt: EVP_Cipher failed");
289*0Sstevel@tonic-gate #endif
290*0Sstevel@tonic-gate }
291*0Sstevel@tonic-gate 
292*0Sstevel@tonic-gate void
293*0Sstevel@tonic-gate cipher_cleanup(CipherContext *cc)
294*0Sstevel@tonic-gate {
295*0Sstevel@tonic-gate #ifdef SSH_OLD_EVP
296*0Sstevel@tonic-gate 	EVP_CIPHER_CTX_cleanup(&cc->evp);
297*0Sstevel@tonic-gate #else
298*0Sstevel@tonic-gate 	if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
299*0Sstevel@tonic-gate 		error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed");
300*0Sstevel@tonic-gate #endif
301*0Sstevel@tonic-gate }
302*0Sstevel@tonic-gate 
303*0Sstevel@tonic-gate /*
304*0Sstevel@tonic-gate  * Selects the cipher, and keys if by computing the MD5 checksum of the
305*0Sstevel@tonic-gate  * passphrase and using the resulting 16 bytes as the key.
306*0Sstevel@tonic-gate  */
307*0Sstevel@tonic-gate 
308*0Sstevel@tonic-gate void
309*0Sstevel@tonic-gate cipher_set_key_string(CipherContext *cc, Cipher *cipher,
310*0Sstevel@tonic-gate     const char *passphrase, int encrypt)
311*0Sstevel@tonic-gate {
312*0Sstevel@tonic-gate 	MD5_CTX md;
313*0Sstevel@tonic-gate 	u_char digest[16];
314*0Sstevel@tonic-gate 
315*0Sstevel@tonic-gate 	MD5_Init(&md);
316*0Sstevel@tonic-gate 	MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
317*0Sstevel@tonic-gate 	MD5_Final(digest, &md);
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 	cipher_init(cc, cipher, digest, 16, NULL, 0, encrypt);
320*0Sstevel@tonic-gate 
321*0Sstevel@tonic-gate 	memset(digest, 0, sizeof(digest));
322*0Sstevel@tonic-gate 	memset(&md, 0, sizeof(md));
323*0Sstevel@tonic-gate }
324*0Sstevel@tonic-gate 
325*0Sstevel@tonic-gate /* Implementations for other non-EVP ciphers */
326*0Sstevel@tonic-gate 
327*0Sstevel@tonic-gate /*
328*0Sstevel@tonic-gate  * This is used by SSH1:
329*0Sstevel@tonic-gate  *
330*0Sstevel@tonic-gate  * What kind of triple DES are these 2 routines?
331*0Sstevel@tonic-gate  *
332*0Sstevel@tonic-gate  * Why is there a redundant initialization vector?
333*0Sstevel@tonic-gate  *
334*0Sstevel@tonic-gate  * If only iv3 was used, then, this would till effect have been
335*0Sstevel@tonic-gate  * outer-cbc. However, there is also a private iv1 == iv2 which
336*0Sstevel@tonic-gate  * perhaps makes differential analysis easier. On the other hand, the
337*0Sstevel@tonic-gate  * private iv1 probably makes the CRC-32 attack ineffective. This is a
338*0Sstevel@tonic-gate  * result of that there is no longer any known iv1 to use when
339*0Sstevel@tonic-gate  * choosing the X block.
340*0Sstevel@tonic-gate  */
341*0Sstevel@tonic-gate struct ssh1_3des_ctx
342*0Sstevel@tonic-gate {
343*0Sstevel@tonic-gate 	EVP_CIPHER_CTX	k1, k2, k3;
344*0Sstevel@tonic-gate };
345*0Sstevel@tonic-gate 
346*0Sstevel@tonic-gate static int
347*0Sstevel@tonic-gate ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
348*0Sstevel@tonic-gate     int enc)
349*0Sstevel@tonic-gate {
350*0Sstevel@tonic-gate 	struct ssh1_3des_ctx *c;
351*0Sstevel@tonic-gate 	u_char *k1, *k2, *k3;
352*0Sstevel@tonic-gate 
353*0Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
354*0Sstevel@tonic-gate 		c = xmalloc(sizeof(*c));
355*0Sstevel@tonic-gate 		EVP_CIPHER_CTX_set_app_data(ctx, c);
356*0Sstevel@tonic-gate 	}
357*0Sstevel@tonic-gate 	if (key == NULL)
358*0Sstevel@tonic-gate 		return (1);
359*0Sstevel@tonic-gate 	if (enc == -1)
360*0Sstevel@tonic-gate 		enc = ctx->encrypt;
361*0Sstevel@tonic-gate 	k1 = k2 = k3 = (u_char *) key;
362*0Sstevel@tonic-gate 	k2 += 8;
363*0Sstevel@tonic-gate 	if (EVP_CIPHER_CTX_key_length(ctx) >= 16+8) {
364*0Sstevel@tonic-gate 		if (enc)
365*0Sstevel@tonic-gate 			k3 += 16;
366*0Sstevel@tonic-gate 		else
367*0Sstevel@tonic-gate 			k1 += 16;
368*0Sstevel@tonic-gate 	}
369*0Sstevel@tonic-gate 	EVP_CIPHER_CTX_init(&c->k1);
370*0Sstevel@tonic-gate 	EVP_CIPHER_CTX_init(&c->k2);
371*0Sstevel@tonic-gate 	EVP_CIPHER_CTX_init(&c->k3);
372*0Sstevel@tonic-gate #ifdef SSH_OLD_EVP
373*0Sstevel@tonic-gate 	EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc);
374*0Sstevel@tonic-gate 	EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc);
375*0Sstevel@tonic-gate 	EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc);
376*0Sstevel@tonic-gate #else
377*0Sstevel@tonic-gate 	if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
378*0Sstevel@tonic-gate 	    EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
379*0Sstevel@tonic-gate 	    EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
380*0Sstevel@tonic-gate 		memset(c, 0, sizeof(*c));
381*0Sstevel@tonic-gate 		xfree(c);
382*0Sstevel@tonic-gate 		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
383*0Sstevel@tonic-gate 		return (0);
384*0Sstevel@tonic-gate 	}
385*0Sstevel@tonic-gate #endif
386*0Sstevel@tonic-gate 	return (1);
387*0Sstevel@tonic-gate }
388*0Sstevel@tonic-gate 
389*0Sstevel@tonic-gate static int
390*0Sstevel@tonic-gate ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, u_int len)
391*0Sstevel@tonic-gate {
392*0Sstevel@tonic-gate 	struct ssh1_3des_ctx *c;
393*0Sstevel@tonic-gate 
394*0Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
395*0Sstevel@tonic-gate 		error("ssh1_3des_cbc: no context");
396*0Sstevel@tonic-gate 		return (0);
397*0Sstevel@tonic-gate 	}
398*0Sstevel@tonic-gate #ifdef SSH_OLD_EVP
399*0Sstevel@tonic-gate 	EVP_Cipher(&c->k1, dest, (u_char *)src, len);
400*0Sstevel@tonic-gate 	EVP_Cipher(&c->k2, dest, dest, len);
401*0Sstevel@tonic-gate 	EVP_Cipher(&c->k3, dest, dest, len);
402*0Sstevel@tonic-gate #else
403*0Sstevel@tonic-gate 	if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
404*0Sstevel@tonic-gate 	    EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
405*0Sstevel@tonic-gate 	    EVP_Cipher(&c->k3, dest, dest, len) == 0)
406*0Sstevel@tonic-gate 		return (0);
407*0Sstevel@tonic-gate #endif
408*0Sstevel@tonic-gate 	return (1);
409*0Sstevel@tonic-gate }
410*0Sstevel@tonic-gate 
411*0Sstevel@tonic-gate static int
412*0Sstevel@tonic-gate ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
413*0Sstevel@tonic-gate {
414*0Sstevel@tonic-gate 	struct ssh1_3des_ctx *c;
415*0Sstevel@tonic-gate 
416*0Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
417*0Sstevel@tonic-gate 		memset(c, 0, sizeof(*c));
418*0Sstevel@tonic-gate 		xfree(c);
419*0Sstevel@tonic-gate 		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
420*0Sstevel@tonic-gate 	}
421*0Sstevel@tonic-gate 	return (1);
422*0Sstevel@tonic-gate }
423*0Sstevel@tonic-gate 
424*0Sstevel@tonic-gate static const EVP_CIPHER *
425*0Sstevel@tonic-gate evp_ssh1_3des(void)
426*0Sstevel@tonic-gate {
427*0Sstevel@tonic-gate 	static EVP_CIPHER ssh1_3des;
428*0Sstevel@tonic-gate 
429*0Sstevel@tonic-gate 	memset(&ssh1_3des, 0, sizeof(EVP_CIPHER));
430*0Sstevel@tonic-gate 	ssh1_3des.nid = NID_undef;
431*0Sstevel@tonic-gate 	ssh1_3des.block_size = 8;
432*0Sstevel@tonic-gate 	ssh1_3des.iv_len = 0;
433*0Sstevel@tonic-gate 	ssh1_3des.key_len = 16;
434*0Sstevel@tonic-gate 	ssh1_3des.init = ssh1_3des_init;
435*0Sstevel@tonic-gate 	ssh1_3des.cleanup = ssh1_3des_cleanup;
436*0Sstevel@tonic-gate 	ssh1_3des.do_cipher = ssh1_3des_cbc;
437*0Sstevel@tonic-gate #ifndef SSH_OLD_EVP
438*0Sstevel@tonic-gate 	ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
439*0Sstevel@tonic-gate #endif
440*0Sstevel@tonic-gate 	return (&ssh1_3des);
441*0Sstevel@tonic-gate }
442*0Sstevel@tonic-gate 
443*0Sstevel@tonic-gate /*
444*0Sstevel@tonic-gate  * SSH1 uses a variation on Blowfish, all bytes must be swapped before
445*0Sstevel@tonic-gate  * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
446*0Sstevel@tonic-gate  */
447*0Sstevel@tonic-gate static void
448*0Sstevel@tonic-gate swap_bytes(const u_char *src, u_char *dst, int n)
449*0Sstevel@tonic-gate {
450*0Sstevel@tonic-gate 	u_char c[4];
451*0Sstevel@tonic-gate 
452*0Sstevel@tonic-gate 	/* Process 4 bytes every lap. */
453*0Sstevel@tonic-gate 	for (n = n / 4; n > 0; n--) {
454*0Sstevel@tonic-gate 		c[3] = *src++;
455*0Sstevel@tonic-gate 		c[2] = *src++;
456*0Sstevel@tonic-gate 		c[1] = *src++;
457*0Sstevel@tonic-gate 		c[0] = *src++;
458*0Sstevel@tonic-gate 
459*0Sstevel@tonic-gate 		*dst++ = c[0];
460*0Sstevel@tonic-gate 		*dst++ = c[1];
461*0Sstevel@tonic-gate 		*dst++ = c[2];
462*0Sstevel@tonic-gate 		*dst++ = c[3];
463*0Sstevel@tonic-gate 	}
464*0Sstevel@tonic-gate }
465*0Sstevel@tonic-gate 
466*0Sstevel@tonic-gate #ifdef SSH_OLD_EVP
467*0Sstevel@tonic-gate static void bf_ssh1_init (EVP_CIPHER_CTX * ctx, const unsigned char *key,
468*0Sstevel@tonic-gate 			  const unsigned char *iv, int enc)
469*0Sstevel@tonic-gate {
470*0Sstevel@tonic-gate 	if (iv != NULL)
471*0Sstevel@tonic-gate 		memcpy (&(ctx->oiv[0]), iv, 8);
472*0Sstevel@tonic-gate 	memcpy (&(ctx->iv[0]), &(ctx->oiv[0]), 8);
473*0Sstevel@tonic-gate 	if (key != NULL)
474*0Sstevel@tonic-gate 		BF_set_key (&(ctx->c.bf_ks), EVP_CIPHER_CTX_key_length (ctx),
475*0Sstevel@tonic-gate 			    key);
476*0Sstevel@tonic-gate }
477*0Sstevel@tonic-gate #endif
478*0Sstevel@tonic-gate static int (*orig_bf)(EVP_CIPHER_CTX *, u_char *, const u_char *, u_int) = NULL;
479*0Sstevel@tonic-gate 
480*0Sstevel@tonic-gate static int
481*0Sstevel@tonic-gate bf_ssh1_cipher(EVP_CIPHER_CTX *ctx, u_char *out, const u_char *in, u_int len)
482*0Sstevel@tonic-gate {
483*0Sstevel@tonic-gate 	int ret;
484*0Sstevel@tonic-gate 
485*0Sstevel@tonic-gate 	swap_bytes(in, out, len);
486*0Sstevel@tonic-gate 	ret = (*orig_bf)(ctx, out, out, len);
487*0Sstevel@tonic-gate 	swap_bytes(out, out, len);
488*0Sstevel@tonic-gate 	return (ret);
489*0Sstevel@tonic-gate }
490*0Sstevel@tonic-gate 
491*0Sstevel@tonic-gate static const EVP_CIPHER *
492*0Sstevel@tonic-gate evp_ssh1_bf(void)
493*0Sstevel@tonic-gate {
494*0Sstevel@tonic-gate 	static EVP_CIPHER ssh1_bf;
495*0Sstevel@tonic-gate 
496*0Sstevel@tonic-gate 	memcpy(&ssh1_bf, EVP_bf_cbc(), sizeof(EVP_CIPHER));
497*0Sstevel@tonic-gate 	orig_bf = ssh1_bf.do_cipher;
498*0Sstevel@tonic-gate 	ssh1_bf.nid = NID_undef;
499*0Sstevel@tonic-gate #ifdef SSH_OLD_EVP
500*0Sstevel@tonic-gate 	ssh1_bf.init = bf_ssh1_init;
501*0Sstevel@tonic-gate #endif
502*0Sstevel@tonic-gate 	ssh1_bf.do_cipher = bf_ssh1_cipher;
503*0Sstevel@tonic-gate 	ssh1_bf.key_len = 32;
504*0Sstevel@tonic-gate 	return (&ssh1_bf);
505*0Sstevel@tonic-gate }
506*0Sstevel@tonic-gate 
507*0Sstevel@tonic-gate #if (OPENSSL_VERSION_NUMBER < 0x00907000L)
508*0Sstevel@tonic-gate /* RIJNDAEL */
509*0Sstevel@tonic-gate #define RIJNDAEL_BLOCKSIZE 16
510*0Sstevel@tonic-gate struct ssh_rijndael_ctx
511*0Sstevel@tonic-gate {
512*0Sstevel@tonic-gate 	rijndael_ctx	r_ctx;
513*0Sstevel@tonic-gate 	u_char		r_iv[RIJNDAEL_BLOCKSIZE];
514*0Sstevel@tonic-gate };
515*0Sstevel@tonic-gate 
516*0Sstevel@tonic-gate static int
517*0Sstevel@tonic-gate ssh_rijndael_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
518*0Sstevel@tonic-gate     int enc)
519*0Sstevel@tonic-gate {
520*0Sstevel@tonic-gate 	struct ssh_rijndael_ctx *c;
521*0Sstevel@tonic-gate 
522*0Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
523*0Sstevel@tonic-gate 		c = xmalloc(sizeof(*c));
524*0Sstevel@tonic-gate 		EVP_CIPHER_CTX_set_app_data(ctx, c);
525*0Sstevel@tonic-gate 	}
526*0Sstevel@tonic-gate 	if (key != NULL) {
527*0Sstevel@tonic-gate 		if (enc == -1)
528*0Sstevel@tonic-gate 			enc = ctx->encrypt;
529*0Sstevel@tonic-gate 		rijndael_set_key(&c->r_ctx, (u_char *)key,
530*0Sstevel@tonic-gate 		    8*EVP_CIPHER_CTX_key_length(ctx), enc);
531*0Sstevel@tonic-gate 	}
532*0Sstevel@tonic-gate 	if (iv != NULL)
533*0Sstevel@tonic-gate 		memcpy(c->r_iv, iv, RIJNDAEL_BLOCKSIZE);
534*0Sstevel@tonic-gate 	return (1);
535*0Sstevel@tonic-gate }
536*0Sstevel@tonic-gate 
537*0Sstevel@tonic-gate static int
538*0Sstevel@tonic-gate ssh_rijndael_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src,
539*0Sstevel@tonic-gate     u_int len)
540*0Sstevel@tonic-gate {
541*0Sstevel@tonic-gate 	struct ssh_rijndael_ctx *c;
542*0Sstevel@tonic-gate 	u_char buf[RIJNDAEL_BLOCKSIZE];
543*0Sstevel@tonic-gate 	u_char *cprev, *cnow, *plain, *ivp;
544*0Sstevel@tonic-gate 	int i, j, blocks = len / RIJNDAEL_BLOCKSIZE;
545*0Sstevel@tonic-gate 
546*0Sstevel@tonic-gate 	if (len == 0)
547*0Sstevel@tonic-gate 		return (1);
548*0Sstevel@tonic-gate 	if (len % RIJNDAEL_BLOCKSIZE)
549*0Sstevel@tonic-gate 		fatal("ssh_rijndael_cbc: bad len %d", len);
550*0Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
551*0Sstevel@tonic-gate 		error("ssh_rijndael_cbc: no context");
552*0Sstevel@tonic-gate 		return (0);
553*0Sstevel@tonic-gate 	}
554*0Sstevel@tonic-gate 	if (ctx->encrypt) {
555*0Sstevel@tonic-gate 		cnow  = dest;
556*0Sstevel@tonic-gate 		plain = (u_char *)src;
557*0Sstevel@tonic-gate 		cprev = c->r_iv;
558*0Sstevel@tonic-gate 		for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE,
559*0Sstevel@tonic-gate 		    cnow+=RIJNDAEL_BLOCKSIZE) {
560*0Sstevel@tonic-gate 			for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
561*0Sstevel@tonic-gate 				buf[j] = plain[j] ^ cprev[j];
562*0Sstevel@tonic-gate 			rijndael_encrypt(&c->r_ctx, buf, cnow);
563*0Sstevel@tonic-gate 			cprev = cnow;
564*0Sstevel@tonic-gate 		}
565*0Sstevel@tonic-gate 		memcpy(c->r_iv, cprev, RIJNDAEL_BLOCKSIZE);
566*0Sstevel@tonic-gate 	} else {
567*0Sstevel@tonic-gate 		cnow  = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE);
568*0Sstevel@tonic-gate 		plain = dest+len-RIJNDAEL_BLOCKSIZE;
569*0Sstevel@tonic-gate 
570*0Sstevel@tonic-gate 		memcpy(buf, cnow, RIJNDAEL_BLOCKSIZE);
571*0Sstevel@tonic-gate 		for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE,
572*0Sstevel@tonic-gate 		    plain-=RIJNDAEL_BLOCKSIZE) {
573*0Sstevel@tonic-gate 			rijndael_decrypt(&c->r_ctx, cnow, plain);
574*0Sstevel@tonic-gate 			ivp = (i == 1) ? c->r_iv : cnow-RIJNDAEL_BLOCKSIZE;
575*0Sstevel@tonic-gate 			for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
576*0Sstevel@tonic-gate 				plain[j] ^= ivp[j];
577*0Sstevel@tonic-gate 		}
578*0Sstevel@tonic-gate 		memcpy(c->r_iv, buf, RIJNDAEL_BLOCKSIZE);
579*0Sstevel@tonic-gate 	}
580*0Sstevel@tonic-gate 	return (1);
581*0Sstevel@tonic-gate }
582*0Sstevel@tonic-gate 
583*0Sstevel@tonic-gate static int
584*0Sstevel@tonic-gate ssh_rijndael_cleanup(EVP_CIPHER_CTX *ctx)
585*0Sstevel@tonic-gate {
586*0Sstevel@tonic-gate 	struct ssh_rijndael_ctx *c;
587*0Sstevel@tonic-gate 
588*0Sstevel@tonic-gate 	if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) {
589*0Sstevel@tonic-gate 		memset(c, 0, sizeof(*c));
590*0Sstevel@tonic-gate 		xfree(c);
591*0Sstevel@tonic-gate 		EVP_CIPHER_CTX_set_app_data(ctx, NULL);
592*0Sstevel@tonic-gate 	}
593*0Sstevel@tonic-gate 	return (1);
594*0Sstevel@tonic-gate }
595*0Sstevel@tonic-gate 
596*0Sstevel@tonic-gate static const EVP_CIPHER *
597*0Sstevel@tonic-gate evp_rijndael(void)
598*0Sstevel@tonic-gate {
599*0Sstevel@tonic-gate 	static EVP_CIPHER rijndal_cbc;
600*0Sstevel@tonic-gate 
601*0Sstevel@tonic-gate 	memset(&rijndal_cbc, 0, sizeof(EVP_CIPHER));
602*0Sstevel@tonic-gate 	rijndal_cbc.nid = NID_undef;
603*0Sstevel@tonic-gate 	rijndal_cbc.block_size = RIJNDAEL_BLOCKSIZE;
604*0Sstevel@tonic-gate 	rijndal_cbc.iv_len = RIJNDAEL_BLOCKSIZE;
605*0Sstevel@tonic-gate 	rijndal_cbc.key_len = 16;
606*0Sstevel@tonic-gate 	rijndal_cbc.init = ssh_rijndael_init;
607*0Sstevel@tonic-gate 	rijndal_cbc.cleanup = ssh_rijndael_cleanup;
608*0Sstevel@tonic-gate 	rijndal_cbc.do_cipher = ssh_rijndael_cbc;
609*0Sstevel@tonic-gate #ifndef SSH_OLD_EVP
610*0Sstevel@tonic-gate 	rijndal_cbc.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH |
611*0Sstevel@tonic-gate 	    EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV;
612*0Sstevel@tonic-gate #endif
613*0Sstevel@tonic-gate 	return (&rijndal_cbc);
614*0Sstevel@tonic-gate }
615*0Sstevel@tonic-gate #endif
616*0Sstevel@tonic-gate 
617*0Sstevel@tonic-gate /*
618*0Sstevel@tonic-gate  * Exports an IV from the CipherContext required to export the key
619*0Sstevel@tonic-gate  * state back from the unprivileged child to the privileged parent
620*0Sstevel@tonic-gate  * process.
621*0Sstevel@tonic-gate  */
622*0Sstevel@tonic-gate 
623*0Sstevel@tonic-gate int
624*0Sstevel@tonic-gate cipher_get_keyiv_len(CipherContext *cc)
625*0Sstevel@tonic-gate {
626*0Sstevel@tonic-gate 	Cipher *c = cc->cipher;
627*0Sstevel@tonic-gate 	int ivlen;
628*0Sstevel@tonic-gate 
629*0Sstevel@tonic-gate 	if (c->number == SSH_CIPHER_3DES)
630*0Sstevel@tonic-gate 		ivlen = 24;
631*0Sstevel@tonic-gate 	else
632*0Sstevel@tonic-gate 		ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp);
633*0Sstevel@tonic-gate 	return (ivlen);
634*0Sstevel@tonic-gate }
635*0Sstevel@tonic-gate 
636*0Sstevel@tonic-gate void
637*0Sstevel@tonic-gate cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
638*0Sstevel@tonic-gate {
639*0Sstevel@tonic-gate 	Cipher *c = cc->cipher;
640*0Sstevel@tonic-gate 	u_char *civ = NULL;
641*0Sstevel@tonic-gate 	int evplen;
642*0Sstevel@tonic-gate 
643*0Sstevel@tonic-gate 	switch (c->number) {
644*0Sstevel@tonic-gate 	case SSH_CIPHER_SSH2:
645*0Sstevel@tonic-gate 	case SSH_CIPHER_DES:
646*0Sstevel@tonic-gate 	case SSH_CIPHER_BLOWFISH:
647*0Sstevel@tonic-gate 		evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
648*0Sstevel@tonic-gate 		if (evplen == 0)
649*0Sstevel@tonic-gate 			return;
650*0Sstevel@tonic-gate 		if (evplen != len)
651*0Sstevel@tonic-gate 			fatal("%s: wrong iv length %d != %d", __func__,
652*0Sstevel@tonic-gate 			    evplen, len);
653*0Sstevel@tonic-gate 
654*0Sstevel@tonic-gate #if (OPENSSL_VERSION_NUMBER < 0x00907000L)
655*0Sstevel@tonic-gate 		if (c->evptype == evp_rijndael) {
656*0Sstevel@tonic-gate 			struct ssh_rijndael_ctx *aesc;
657*0Sstevel@tonic-gate 
658*0Sstevel@tonic-gate 			aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
659*0Sstevel@tonic-gate 			if (aesc == NULL)
660*0Sstevel@tonic-gate 				fatal("%s: no rijndael context", __func__);
661*0Sstevel@tonic-gate 			civ = aesc->r_iv;
662*0Sstevel@tonic-gate 		} else
663*0Sstevel@tonic-gate #endif
664*0Sstevel@tonic-gate 		if (c->evptype == evp_aes_128_ctr) {
665*0Sstevel@tonic-gate 			ssh_aes_ctr_iv(&cc->evp, 0, iv, len);
666*0Sstevel@tonic-gate 			return;
667*0Sstevel@tonic-gate 		} else {
668*0Sstevel@tonic-gate 			civ = cc->evp.iv;
669*0Sstevel@tonic-gate 		}
670*0Sstevel@tonic-gate 		break;
671*0Sstevel@tonic-gate 	case SSH_CIPHER_3DES: {
672*0Sstevel@tonic-gate 		struct ssh1_3des_ctx *desc;
673*0Sstevel@tonic-gate 		if (len != 24)
674*0Sstevel@tonic-gate 			fatal("%s: bad 3des iv length: %d", __func__, len);
675*0Sstevel@tonic-gate 		desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
676*0Sstevel@tonic-gate 		if (desc == NULL)
677*0Sstevel@tonic-gate 			fatal("%s: no 3des context", __func__);
678*0Sstevel@tonic-gate 		debug3("%s: Copying 3DES IV", __func__);
679*0Sstevel@tonic-gate 		memcpy(iv, desc->k1.iv, 8);
680*0Sstevel@tonic-gate 		memcpy(iv + 8, desc->k2.iv, 8);
681*0Sstevel@tonic-gate 		memcpy(iv + 16, desc->k3.iv, 8);
682*0Sstevel@tonic-gate 		return;
683*0Sstevel@tonic-gate 	}
684*0Sstevel@tonic-gate 	default:
685*0Sstevel@tonic-gate 		fatal("%s: bad cipher %d", __func__, c->number);
686*0Sstevel@tonic-gate 	}
687*0Sstevel@tonic-gate 	memcpy(iv, civ, len);
688*0Sstevel@tonic-gate }
689*0Sstevel@tonic-gate 
690*0Sstevel@tonic-gate void
691*0Sstevel@tonic-gate cipher_set_keyiv(CipherContext *cc, u_char *iv)
692*0Sstevel@tonic-gate {
693*0Sstevel@tonic-gate 	Cipher *c = cc->cipher;
694*0Sstevel@tonic-gate 	u_char *div = NULL;
695*0Sstevel@tonic-gate 	int evplen = 0;
696*0Sstevel@tonic-gate 
697*0Sstevel@tonic-gate 	switch (c->number) {
698*0Sstevel@tonic-gate 	case SSH_CIPHER_SSH2:
699*0Sstevel@tonic-gate 	case SSH_CIPHER_DES:
700*0Sstevel@tonic-gate 	case SSH_CIPHER_BLOWFISH:
701*0Sstevel@tonic-gate 		evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
702*0Sstevel@tonic-gate 		if (evplen == 0)
703*0Sstevel@tonic-gate 			return;
704*0Sstevel@tonic-gate 
705*0Sstevel@tonic-gate #if (OPENSSL_VERSION_NUMBER < 0x00907000L)
706*0Sstevel@tonic-gate 		if (c->evptype == evp_rijndael) {
707*0Sstevel@tonic-gate 			struct ssh_rijndael_ctx *aesc;
708*0Sstevel@tonic-gate 
709*0Sstevel@tonic-gate 			aesc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
710*0Sstevel@tonic-gate 			if (aesc == NULL)
711*0Sstevel@tonic-gate 				fatal("%s: no rijndael context", __func__);
712*0Sstevel@tonic-gate 			div = aesc->r_iv;
713*0Sstevel@tonic-gate 		} else
714*0Sstevel@tonic-gate #endif
715*0Sstevel@tonic-gate 		if (c->evptype == evp_aes_128_ctr) {
716*0Sstevel@tonic-gate 			ssh_aes_ctr_iv(&cc->evp, 1, iv, evplen);
717*0Sstevel@tonic-gate 			return;
718*0Sstevel@tonic-gate 		} else {
719*0Sstevel@tonic-gate 			div = cc->evp.iv;
720*0Sstevel@tonic-gate 		}
721*0Sstevel@tonic-gate 		break;
722*0Sstevel@tonic-gate 	case SSH_CIPHER_3DES: {
723*0Sstevel@tonic-gate 		struct ssh1_3des_ctx *desc;
724*0Sstevel@tonic-gate 		desc = EVP_CIPHER_CTX_get_app_data(&cc->evp);
725*0Sstevel@tonic-gate 		if (desc == NULL)
726*0Sstevel@tonic-gate 			fatal("%s: no 3des context", __func__);
727*0Sstevel@tonic-gate 		debug3("%s: Installed 3DES IV", __func__);
728*0Sstevel@tonic-gate 		memcpy(desc->k1.iv, iv, 8);
729*0Sstevel@tonic-gate 		memcpy(desc->k2.iv, iv + 8, 8);
730*0Sstevel@tonic-gate 		memcpy(desc->k3.iv, iv + 16, 8);
731*0Sstevel@tonic-gate 		return;
732*0Sstevel@tonic-gate 	}
733*0Sstevel@tonic-gate 	default:
734*0Sstevel@tonic-gate 		fatal("%s: bad cipher %d", __func__, c->number);
735*0Sstevel@tonic-gate 	}
736*0Sstevel@tonic-gate 	memcpy(div, iv, evplen);
737*0Sstevel@tonic-gate }
738*0Sstevel@tonic-gate 
739*0Sstevel@tonic-gate #if OPENSSL_VERSION_NUMBER < 0x00907000L
740*0Sstevel@tonic-gate #define EVP_X_STATE(evp)	&(evp).c
741*0Sstevel@tonic-gate #define EVP_X_STATE_LEN(evp)	sizeof((evp).c)
742*0Sstevel@tonic-gate #else
743*0Sstevel@tonic-gate #define EVP_X_STATE(evp)	(evp).cipher_data
744*0Sstevel@tonic-gate #define EVP_X_STATE_LEN(evp)	(evp).cipher->ctx_size
745*0Sstevel@tonic-gate #endif
746*0Sstevel@tonic-gate 
747*0Sstevel@tonic-gate int
748*0Sstevel@tonic-gate cipher_get_keycontext(CipherContext *cc, u_char *dat)
749*0Sstevel@tonic-gate {
750*0Sstevel@tonic-gate 	int plen = 0;
751*0Sstevel@tonic-gate 	Cipher *c = cc->cipher;
752*0Sstevel@tonic-gate 
753*0Sstevel@tonic-gate 	if (c->evptype == EVP_rc4) {
754*0Sstevel@tonic-gate 		plen = EVP_X_STATE_LEN(cc->evp);
755*0Sstevel@tonic-gate 		if (dat == NULL)
756*0Sstevel@tonic-gate 			return (plen);
757*0Sstevel@tonic-gate 		memcpy(dat, EVP_X_STATE(cc->evp), plen);
758*0Sstevel@tonic-gate 	}
759*0Sstevel@tonic-gate 	return (plen);
760*0Sstevel@tonic-gate }
761*0Sstevel@tonic-gate 
762*0Sstevel@tonic-gate void
763*0Sstevel@tonic-gate cipher_set_keycontext(CipherContext *cc, u_char *dat)
764*0Sstevel@tonic-gate {
765*0Sstevel@tonic-gate 	Cipher *c = cc->cipher;
766*0Sstevel@tonic-gate 	int plen;
767*0Sstevel@tonic-gate 
768*0Sstevel@tonic-gate 	if (c->evptype == EVP_rc4) {
769*0Sstevel@tonic-gate 		plen = EVP_X_STATE_LEN(cc->evp);
770*0Sstevel@tonic-gate 		memcpy(EVP_X_STATE(cc->evp), dat, plen);
771*0Sstevel@tonic-gate 	}
772*0Sstevel@tonic-gate }
773