1323134Sdes/* $OpenBSD: cipher.c,v 1.102 2016/08/03 05:41:57 djm Exp $ */
257429Smarkm/*
357429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi>
457429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
557429Smarkm *                    All rights reserved
660576Skris *
765674Skris * As far as I am concerned, the code I have written for this software
865674Skris * can be used freely for any purpose.  Any derived versions of this
965674Skris * software must be clearly marked as such, and if the derived work is
1065674Skris * incompatible with the protocol description in the RFC file, it must be
1165674Skris * called by a name other than "ssh" or "Secure Shell".
1260576Skris *
1365674Skris *
1465674Skris * Copyright (c) 1999 Niels Provos.  All rights reserved.
1592559Sdes * Copyright (c) 1999, 2000 Markus Friedl.  All rights reserved.
1665674Skris *
1765674Skris * Redistribution and use in source and binary forms, with or without
1865674Skris * modification, are permitted provided that the following conditions
1965674Skris * are met:
2065674Skris * 1. Redistributions of source code must retain the above copyright
2165674Skris *    notice, this list of conditions and the following disclaimer.
2265674Skris * 2. Redistributions in binary form must reproduce the above copyright
2365674Skris *    notice, this list of conditions and the following disclaimer in the
2465674Skris *    documentation and/or other materials provided with the distribution.
2565674Skris *
2665674Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2765674Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2865674Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2965674Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
3065674Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
3165674Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3265674Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3365674Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3465674Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3565674Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3657429Smarkm */
3757429Smarkm
3857429Smarkm#include "includes.h"
3957429Smarkm
40162856Sdes#include <sys/types.h>
41162856Sdes
42162856Sdes#include <string.h>
43162856Sdes#include <stdarg.h>
44261320Sdes#include <stdio.h>
45162856Sdes
46294328Sdes#include "cipher.h"
47261320Sdes#include "misc.h"
48294328Sdes#include "sshbuf.h"
49294328Sdes#include "ssherr.h"
50263712Sdes#include "digest.h"
5157429Smarkm
52149753Sdes#include "openbsd-compat/openssl-compat.h"
5398941Sdes
54294328Sdes#ifdef WITH_SSH1
55124211Sdesextern const EVP_CIPHER *evp_ssh1_bf(void);
56124211Sdesextern const EVP_CIPHER *evp_ssh1_3des(void);
57294328Sdesextern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
58294328Sdes#endif
5957429Smarkm
60323134Sdesstruct sshcipher_ctx {
61323134Sdes	int	plaintext;
62323134Sdes	int	encrypt;
63323134Sdes	EVP_CIPHER_CTX *evp;
64323134Sdes	struct chachapoly_ctx cp_ctx; /* XXX union with evp? */
65323134Sdes	struct aesctr_ctx ac_ctx; /* XXX union with evp? */
66323134Sdes	const struct sshcipher *cipher;
67323134Sdes};
68323134Sdes
69294328Sdesstruct sshcipher {
7092559Sdes	char	*name;
7192559Sdes	int	number;		/* for ssh1 only */
7292559Sdes	u_int	block_size;
7392559Sdes	u_int	key_len;
74248619Sdes	u_int	iv_len;		/* defaults to block_size */
75248619Sdes	u_int	auth_len;
76149753Sdes	u_int	discard_len;
77261320Sdes	u_int	flags;
78261320Sdes#define CFLAG_CBC		(1<<0)
79261320Sdes#define CFLAG_CHACHAPOLY	(1<<1)
80294328Sdes#define CFLAG_AESCTR		(1<<2)
81294328Sdes#define CFLAG_NONE		(1<<3)
82294328Sdes#ifdef WITH_OPENSSL
8398684Sdes	const EVP_CIPHER	*(*evptype)(void);
84294328Sdes#else
85294328Sdes	void	*ignored;
86294328Sdes#endif
87255767Sdes};
88255767Sdes
89294328Sdesstatic const struct sshcipher ciphers[] = {
90294328Sdes#ifdef WITH_SSH1
91248619Sdes	{ "des",	SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc },
92248619Sdes	{ "3des",	SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des },
93323129Sdes# ifndef OPENSSL_NO_BF
94248619Sdes	{ "blowfish",	SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf },
95323129Sdes# endif /* OPENSSL_NO_BF */
96294328Sdes#endif /* WITH_SSH1 */
97294328Sdes#ifdef WITH_OPENSSL
98294328Sdes	{ "none",	SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null },
99248619Sdes	{ "3des-cbc",	SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc },
100323129Sdes# ifndef OPENSSL_NO_BF
101248619Sdes	{ "blowfish-cbc",
102248619Sdes			SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc },
103323129Sdes# endif /* OPENSSL_NO_BF */
104323129Sdes# ifndef OPENSSL_NO_CAST
105248619Sdes	{ "cast128-cbc",
106248619Sdes			SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_cast5_cbc },
107323129Sdes# endif /* OPENSSL_NO_CAST */
108323129Sdes# ifndef OPENSSL_NO_RC4
109248619Sdes	{ "arcfour",	SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 0, EVP_rc4 },
110248619Sdes	{ "arcfour128",	SSH_CIPHER_SSH2, 8, 16, 0, 0, 1536, 0, EVP_rc4 },
111248619Sdes	{ "arcfour256",	SSH_CIPHER_SSH2, 8, 32, 0, 0, 1536, 0, EVP_rc4 },
112323129Sdes# endif /* OPENSSL_NO_RC4 */
113248619Sdes	{ "aes128-cbc",	SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 1, EVP_aes_128_cbc },
114248619Sdes	{ "aes192-cbc",	SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 1, EVP_aes_192_cbc },
115248619Sdes	{ "aes256-cbc",	SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc },
11698684Sdes	{ "rijndael-cbc@lysator.liu.se",
117248619Sdes			SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc },
118248619Sdes	{ "aes128-ctr",	SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr },
119248619Sdes	{ "aes192-ctr",	SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr },
120248619Sdes	{ "aes256-ctr",	SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr },
121294328Sdes# ifdef OPENSSL_HAVE_EVPGCM
122248619Sdes	{ "aes128-gcm@openssh.com",
123248619Sdes			SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm },
124248619Sdes	{ "aes256-gcm@openssh.com",
125248619Sdes			SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm },
126294328Sdes# endif /* OPENSSL_HAVE_EVPGCM */
127294328Sdes#else /* WITH_OPENSSL */
128294328Sdes	{ "aes128-ctr",	SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, CFLAG_AESCTR, NULL },
129294328Sdes	{ "aes192-ctr",	SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, CFLAG_AESCTR, NULL },
130294328Sdes	{ "aes256-ctr",	SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, CFLAG_AESCTR, NULL },
131294328Sdes	{ "none",	SSH_CIPHER_NONE, 8, 0, 0, 0, 0, CFLAG_NONE, NULL },
132294328Sdes#endif /* WITH_OPENSSL */
133261320Sdes	{ "chacha20-poly1305@openssh.com",
134261320Sdes			SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL },
135294328Sdes
136248619Sdes	{ NULL,		SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL }
13792559Sdes};
13869591Sgreen
13992559Sdes/*--*/
14057429Smarkm
141294328Sdes/* Returns a comma-separated list of supported ciphers. */
142255767Sdeschar *
143261320Sdescipher_alg_list(char sep, int auth_only)
144255767Sdes{
145294328Sdes	char *tmp, *ret = NULL;
146255767Sdes	size_t nlen, rlen = 0;
147294328Sdes	const struct sshcipher *c;
148255767Sdes
149255767Sdes	for (c = ciphers; c->name != NULL; c++) {
150255767Sdes		if (c->number != SSH_CIPHER_SSH2)
151255767Sdes			continue;
152261320Sdes		if (auth_only && c->auth_len == 0)
153261320Sdes			continue;
154255767Sdes		if (ret != NULL)
155261320Sdes			ret[rlen++] = sep;
156255767Sdes		nlen = strlen(c->name);
157294328Sdes		if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
158294328Sdes			free(ret);
159294328Sdes			return NULL;
160294328Sdes		}
161294328Sdes		ret = tmp;
162255767Sdes		memcpy(ret + rlen, c->name, nlen + 1);
163255767Sdes		rlen += nlen;
164255767Sdes	}
165255767Sdes	return ret;
166255767Sdes}
167255767Sdes
16898684Sdesu_int
169294328Sdescipher_blocksize(const struct sshcipher *c)
17057429Smarkm{
17192559Sdes	return (c->block_size);
17257429Smarkm}
17399063Sdes
17498684Sdesu_int
175294328Sdescipher_keylen(const struct sshcipher *c)
17669591Sgreen{
17792559Sdes	return (c->key_len);
17869591Sgreen}
17999063Sdes
18098684Sdesu_int
181294328Sdescipher_seclen(const struct sshcipher *c)
182261320Sdes{
183261320Sdes	if (strcmp("3des-cbc", c->name) == 0)
184261320Sdes		return 14;
185261320Sdes	return cipher_keylen(c);
186261320Sdes}
187261320Sdes
188261320Sdesu_int
189294328Sdescipher_authlen(const struct sshcipher *c)
190248619Sdes{
191248619Sdes	return (c->auth_len);
192248619Sdes}
193248619Sdes
194248619Sdesu_int
195294328Sdescipher_ivlen(const struct sshcipher *c)
196248619Sdes{
197261320Sdes	/*
198261320Sdes	 * Default is cipher block size, except for chacha20+poly1305 that
199261320Sdes	 * needs no IV. XXX make iv_len == -1 default?
200261320Sdes	 */
201261320Sdes	return (c->iv_len != 0 || (c->flags & CFLAG_CHACHAPOLY) != 0) ?
202261320Sdes	    c->iv_len : c->block_size;
203248619Sdes}
204248619Sdes
205248619Sdesu_int
206294328Sdescipher_get_number(const struct sshcipher *c)
20798684Sdes{
20898684Sdes	return (c->number);
20998684Sdes}
21069591Sgreen
21176262Sgreenu_int
212294328Sdescipher_is_cbc(const struct sshcipher *c)
213192595Sdes{
214261320Sdes	return (c->flags & CFLAG_CBC) != 0;
215192595Sdes}
216192595Sdes
217192595Sdesu_int
218323134Sdescipher_ctx_is_plaintext(struct sshcipher_ctx *cc)
219323134Sdes{
220323134Sdes	return cc->plaintext;
221323134Sdes}
222323134Sdes
223323134Sdesu_int
224323134Sdescipher_ctx_get_number(struct sshcipher_ctx *cc)
225323134Sdes{
226323134Sdes	return cc->cipher->number;
227323134Sdes}
228323134Sdes
229323134Sdesu_int
23069591Sgreencipher_mask_ssh1(int client)
23157429Smarkm{
23276262Sgreen	u_int mask = 0;
23392559Sdes	mask |= 1 << SSH_CIPHER_3DES;		/* Mandatory */
23457429Smarkm	mask |= 1 << SSH_CIPHER_BLOWFISH;
23569591Sgreen	if (client) {
23669591Sgreen		mask |= 1 << SSH_CIPHER_DES;
23769591Sgreen	}
23857429Smarkm	return mask;
23957429Smarkm}
24069591Sgreen
241294328Sdesconst struct sshcipher *
24269591Sgreencipher_by_name(const char *name)
24360576Skris{
244294328Sdes	const struct sshcipher *c;
24569591Sgreen	for (c = ciphers; c->name != NULL; c++)
246147005Sdes		if (strcmp(c->name, name) == 0)
24769591Sgreen			return c;
24869591Sgreen	return NULL;
24960576Skris}
25057429Smarkm
251294328Sdesconst struct sshcipher *
25269591Sgreencipher_by_number(int id)
25357429Smarkm{
254294328Sdes	const struct sshcipher *c;
25569591Sgreen	for (c = ciphers; c->name != NULL; c++)
25669591Sgreen		if (c->number == id)
25769591Sgreen			return c;
25869591Sgreen	return NULL;
25957429Smarkm}
26057429Smarkm
26160576Skris#define	CIPHER_SEP	","
26260576Skrisint
26360576Skrisciphers_valid(const char *names)
26460576Skris{
265294328Sdes	const struct sshcipher *c;
266137019Sdes	char *cipher_list, *cp;
26760576Skris	char *p;
26860576Skris
26961212Skris	if (names == NULL || strcmp(names, "") == 0)
27060576Skris		return 0;
271294328Sdes	if ((cipher_list = cp = strdup(names)) == NULL)
272294328Sdes		return 0;
27369591Sgreen	for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
27492559Sdes	    (p = strsep(&cp, CIPHER_SEP))) {
27569591Sgreen		c = cipher_by_name(p);
276291198Sdes		if (c == NULL || c->number != SSH_CIPHER_SSH2) {
277255767Sdes			free(cipher_list);
27860576Skris			return 0;
27960576Skris		}
28060576Skris	}
281255767Sdes	free(cipher_list);
28260576Skris	return 1;
28360576Skris}
28460576Skris
28557429Smarkm/*
28657429Smarkm * Parses the name of the cipher.  Returns the number of the corresponding
28757429Smarkm * cipher, or -1 on error.
28857429Smarkm */
28957429Smarkm
29057429Smarkmint
29157429Smarkmcipher_number(const char *name)
29257429Smarkm{
293294328Sdes	const struct sshcipher *c;
29461212Skris	if (name == NULL)
29561212Skris		return -1;
296147005Sdes	for (c = ciphers; c->name != NULL; c++)
297147005Sdes		if (strcasecmp(c->name, name) == 0)
298147005Sdes			return c->number;
299147005Sdes	return -1;
30057429Smarkm}
30157429Smarkm
30269591Sgreenchar *
30369591Sgreencipher_name(int id)
30457429Smarkm{
305294328Sdes	const struct sshcipher *c = cipher_by_number(id);
30669591Sgreen	return (c==NULL) ? "<unknown>" : c->name;
30757429Smarkm}
30857429Smarkm
309294328Sdesconst char *
310294328Sdescipher_warning_message(const struct sshcipher_ctx *cc)
311294328Sdes{
312294328Sdes	if (cc == NULL || cc->cipher == NULL)
313294328Sdes		return NULL;
314294328Sdes	if (cc->cipher->number == SSH_CIPHER_DES)
315294328Sdes		return "use of DES is strongly discouraged due to "
316294328Sdes		    "cryptographic weaknesses";
317294328Sdes	return NULL;
318294328Sdes}
319294328Sdes
320294328Sdesint
321323134Sdescipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher,
32292559Sdes    const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
323137019Sdes    int do_encrypt)
32457429Smarkm{
325323134Sdes	struct sshcipher_ctx *cc = NULL;
326323134Sdes	int ret = SSH_ERR_INTERNAL_ERROR;
327294328Sdes#ifdef WITH_OPENSSL
32892559Sdes	const EVP_CIPHER *type;
329149753Sdes	int klen;
330149753Sdes	u_char *junk, *discard;
331323134Sdes#endif
33292559Sdes
333323134Sdes	*ccp = NULL;
334323134Sdes	if ((cc = calloc(sizeof(*cc), 1)) == NULL)
335323134Sdes		return SSH_ERR_ALLOC_FAIL;
336323134Sdes
33792559Sdes	if (cipher->number == SSH_CIPHER_DES) {
33892559Sdes		if (keylen > 8)
33992559Sdes			keylen = 8;
34092559Sdes	}
341323134Sdes
34292559Sdes	cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
343248619Sdes	cc->encrypt = do_encrypt;
34492559Sdes
345294328Sdes	if (keylen < cipher->key_len ||
346323134Sdes	    (iv != NULL && ivlen < cipher_ivlen(cipher))) {
347323134Sdes		ret = SSH_ERR_INVALID_ARGUMENT;
348323134Sdes		goto out;
349323134Sdes	}
350294328Sdes
35169591Sgreen	cc->cipher = cipher;
352261320Sdes	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
353323134Sdes		ret = chachapoly_init(&cc->cp_ctx, key, keylen);
354323134Sdes		goto out;
355261320Sdes	}
356294328Sdes#ifndef WITH_OPENSSL
357294328Sdes	if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
358294328Sdes		aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen);
359294328Sdes		aesctr_ivsetup(&cc->ac_ctx, iv);
360323134Sdes		ret = 0;
361323134Sdes		goto out;
362294328Sdes	}
363323134Sdes	if ((cc->cipher->flags & CFLAG_NONE) != 0) {
364323134Sdes		ret = 0;
365323134Sdes		goto out;
366323134Sdes	}
367323134Sdes	ret = SSH_ERR_INVALID_ARGUMENT;
368323134Sdes	goto out;
369323134Sdes#else /* WITH_OPENSSL */
37092559Sdes	type = (*cipher->evptype)();
371323134Sdes	if ((cc->evp = EVP_CIPHER_CTX_new()) == NULL) {
372323134Sdes		ret = SSH_ERR_ALLOC_FAIL;
373323134Sdes		goto out;
374323134Sdes	}
375323134Sdes	if (EVP_CipherInit(cc->evp, type, NULL, (u_char *)iv,
376294328Sdes	    (do_encrypt == CIPHER_ENCRYPT)) == 0) {
377294328Sdes		ret = SSH_ERR_LIBCRYPTO_ERROR;
378323134Sdes		goto out;
37998941Sdes	}
380248619Sdes	if (cipher_authlen(cipher) &&
381323134Sdes	    !EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_IV_FIXED,
382294328Sdes	    -1, (u_char *)iv)) {
383294328Sdes		ret = SSH_ERR_LIBCRYPTO_ERROR;
384323134Sdes		goto out;
385294328Sdes	}
386323134Sdes	klen = EVP_CIPHER_CTX_key_length(cc->evp);
387149753Sdes	if (klen > 0 && keylen != (u_int)klen) {
388323134Sdes		if (EVP_CIPHER_CTX_set_key_length(cc->evp, keylen) == 0) {
389294328Sdes			ret = SSH_ERR_LIBCRYPTO_ERROR;
390323134Sdes			goto out;
391294328Sdes		}
39292559Sdes	}
393323134Sdes	if (EVP_CipherInit(cc->evp, NULL, (u_char *)key, NULL, -1) == 0) {
394294328Sdes		ret = SSH_ERR_LIBCRYPTO_ERROR;
395323134Sdes		goto out;
396294328Sdes	}
397149753Sdes
398149753Sdes	if (cipher->discard_len > 0) {
399294328Sdes		if ((junk = malloc(cipher->discard_len)) == NULL ||
400294328Sdes		    (discard = malloc(cipher->discard_len)) == NULL) {
401296633Sdes			free(junk);
402294328Sdes			ret = SSH_ERR_ALLOC_FAIL;
403323134Sdes			goto out;
404294328Sdes		}
405323134Sdes		ret = EVP_Cipher(cc->evp, discard, junk, cipher->discard_len);
406263712Sdes		explicit_bzero(discard, cipher->discard_len);
407255767Sdes		free(junk);
408255767Sdes		free(discard);
409294328Sdes		if (ret != 1) {
410294328Sdes			ret = SSH_ERR_LIBCRYPTO_ERROR;
411323134Sdes			goto out;
412294328Sdes		}
413149753Sdes	}
414323134Sdes	ret = 0;
415323134Sdes#endif /* WITH_OPENSSL */
416323134Sdes out:
417323134Sdes	if (ret == 0) {
418323134Sdes		/* success */
419323134Sdes		*ccp = cc;
420323134Sdes	} else {
421323134Sdes		if (cc != NULL) {
422323134Sdes#ifdef WITH_OPENSSL
423323134Sdes			if (cc->evp != NULL)
424323134Sdes				EVP_CIPHER_CTX_free(cc->evp);
425323134Sdes#endif /* WITH_OPENSSL */
426323134Sdes			explicit_bzero(cc, sizeof(*cc));
427323134Sdes			free(cc);
428323134Sdes		}
429323134Sdes	}
430323134Sdes	return ret;
43157429Smarkm}
43257429Smarkm
433248619Sdes/*
434248619Sdes * cipher_crypt() operates as following:
435248619Sdes * Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'.
436248619Sdes * Theses bytes are treated as additional authenticated data for
437248619Sdes * authenticated encryption modes.
438248619Sdes * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'.
439248619Sdes * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag.
440248619Sdes * This tag is written on encryption and verified on decryption.
441248619Sdes * Both 'aadlen' and 'authlen' can be set to 0.
442248619Sdes */
443261320Sdesint
444294328Sdescipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest,
445294328Sdes   const u_char *src, u_int len, u_int aadlen, u_int authlen)
44660576Skris{
447294328Sdes	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
448294328Sdes		return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src,
449294328Sdes		    len, aadlen, authlen, cc->encrypt);
450294328Sdes	}
451294328Sdes#ifndef WITH_OPENSSL
452294328Sdes	if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
453294328Sdes		if (aadlen)
454294328Sdes			memcpy(dest, src, aadlen);
455294328Sdes		aesctr_encrypt_bytes(&cc->ac_ctx, src + aadlen,
456294328Sdes		    dest + aadlen, len);
457294328Sdes		return 0;
458294328Sdes	}
459294328Sdes	if ((cc->cipher->flags & CFLAG_NONE) != 0) {
460294328Sdes		memcpy(dest, src, aadlen + len);
461294328Sdes		return 0;
462294328Sdes	}
463294328Sdes	return SSH_ERR_INVALID_ARGUMENT;
464294328Sdes#else
465248619Sdes	if (authlen) {
466248619Sdes		u_char lastiv[1];
467248619Sdes
468248619Sdes		if (authlen != cipher_authlen(cc->cipher))
469294328Sdes			return SSH_ERR_INVALID_ARGUMENT;
470248619Sdes		/* increment IV */
471323134Sdes		if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN,
472248619Sdes		    1, lastiv))
473294328Sdes			return SSH_ERR_LIBCRYPTO_ERROR;
474248619Sdes		/* set tag on decyption */
475248619Sdes		if (!cc->encrypt &&
476323134Sdes		    !EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_TAG,
477248619Sdes		    authlen, (u_char *)src + aadlen + len))
478294328Sdes			return SSH_ERR_LIBCRYPTO_ERROR;
479248619Sdes	}
480248619Sdes	if (aadlen) {
481248619Sdes		if (authlen &&
482323134Sdes		    EVP_Cipher(cc->evp, NULL, (u_char *)src, aadlen) < 0)
483294328Sdes			return SSH_ERR_LIBCRYPTO_ERROR;
484248619Sdes		memcpy(dest, src, aadlen);
485248619Sdes	}
48669591Sgreen	if (len % cc->cipher->block_size)
487294328Sdes		return SSH_ERR_INVALID_ARGUMENT;
488323134Sdes	if (EVP_Cipher(cc->evp, dest + aadlen, (u_char *)src + aadlen,
489248619Sdes	    len) < 0)
490294328Sdes		return SSH_ERR_LIBCRYPTO_ERROR;
491248619Sdes	if (authlen) {
492248619Sdes		/* compute tag (on encrypt) or verify tag (on decrypt) */
493323134Sdes		if (EVP_Cipher(cc->evp, NULL, NULL, 0) < 0)
494294328Sdes			return cc->encrypt ?
495294328Sdes			    SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID;
496248619Sdes		if (cc->encrypt &&
497323134Sdes		    !EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_GET_TAG,
498248619Sdes		    authlen, dest + aadlen + len))
499294328Sdes			return SSH_ERR_LIBCRYPTO_ERROR;
500248619Sdes	}
501261320Sdes	return 0;
502294328Sdes#endif
50360576Skris}
50460576Skris
505261320Sdes/* Extract the packet length, including any decryption necessary beforehand */
506261320Sdesint
507294328Sdescipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr,
508261320Sdes    const u_char *cp, u_int len)
509261320Sdes{
510261320Sdes	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
511261320Sdes		return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr,
512261320Sdes		    cp, len);
513261320Sdes	if (len < 4)
514294328Sdes		return SSH_ERR_MESSAGE_INCOMPLETE;
515261320Sdes	*plenp = get_u32(cp);
516261320Sdes	return 0;
517261320Sdes}
518261320Sdes
519323134Sdesvoid
520323134Sdescipher_free(struct sshcipher_ctx *cc)
52157429Smarkm{
522323134Sdes	if (cc == NULL)
523323134Sdes		return;
524261320Sdes	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
525263712Sdes		explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx));
526294328Sdes	else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
527294328Sdes		explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx));
528294328Sdes#ifdef WITH_OPENSSL
529323134Sdes	if (cc->evp != NULL) {
530323134Sdes		EVP_CIPHER_CTX_free(cc->evp);
531323134Sdes		cc->evp = NULL;
532323134Sdes	}
533294328Sdes#endif
534323134Sdes	explicit_bzero(cc, sizeof(*cc));
535323134Sdes	free(cc);
53657429Smarkm}
53757429Smarkm
53869591Sgreen/*
53969591Sgreen * Selects the cipher, and keys if by computing the MD5 checksum of the
54069591Sgreen * passphrase and using the resulting 16 bytes as the key.
54169591Sgreen */
542294328Sdesint
543323134Sdescipher_set_key_string(struct sshcipher_ctx **ccp,
544323134Sdes    const struct sshcipher *cipher, const char *passphrase, int do_encrypt)
54557429Smarkm{
54676262Sgreen	u_char digest[16];
547294328Sdes	int r = SSH_ERR_INTERNAL_ERROR;
54857429Smarkm
549294328Sdes	if ((r = ssh_digest_memory(SSH_DIGEST_MD5,
550294328Sdes	    passphrase, strlen(passphrase),
551294328Sdes	    digest, sizeof(digest))) != 0)
552294328Sdes		goto out;
55357429Smarkm
554323134Sdes	r = cipher_init(ccp, cipher, digest, 16, NULL, 0, do_encrypt);
555294328Sdes out:
556263712Sdes	explicit_bzero(digest, sizeof(digest));
557294328Sdes	return r;
55857429Smarkm}
55992559Sdes
56092559Sdes/*
561294328Sdes * Exports an IV from the sshcipher_ctx required to export the key
56298684Sdes * state back from the unprivileged child to the privileged parent
56398684Sdes * process.
56498684Sdes */
56598684Sdesint
566294328Sdescipher_get_keyiv_len(const struct sshcipher_ctx *cc)
56798684Sdes{
568294328Sdes	const struct sshcipher *c = cc->cipher;
569294328Sdes	int ivlen = 0;
57098684Sdes
57198684Sdes	if (c->number == SSH_CIPHER_3DES)
57298684Sdes		ivlen = 24;
573261320Sdes	else if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
574261320Sdes		ivlen = 0;
575294332Sdes	else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
576294332Sdes		ivlen = sizeof(cc->ac_ctx.ctr);
577294328Sdes#ifdef WITH_OPENSSL
57898684Sdes	else
579323134Sdes		ivlen = EVP_CIPHER_CTX_iv_length(cc->evp);
580294328Sdes#endif /* WITH_OPENSSL */
58198684Sdes	return (ivlen);
58298684Sdes}
58398684Sdes
584294328Sdesint
585294328Sdescipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
58698684Sdes{
587294328Sdes	const struct sshcipher *c = cc->cipher;
588294328Sdes#ifdef WITH_OPENSSL
589294328Sdes 	int evplen;
590294328Sdes#endif
59198684Sdes
592261320Sdes	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
593261320Sdes		if (len != 0)
594294328Sdes			return SSH_ERR_INVALID_ARGUMENT;
595294328Sdes		return 0;
596261320Sdes	}
597294332Sdes	if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
598294332Sdes		if (len != sizeof(cc->ac_ctx.ctr))
599294332Sdes			return SSH_ERR_INVALID_ARGUMENT;
600294332Sdes		memcpy(iv, cc->ac_ctx.ctr, len);
601294332Sdes		return 0;
602294332Sdes	}
603294328Sdes	if ((cc->cipher->flags & CFLAG_NONE) != 0)
604294328Sdes		return 0;
605261320Sdes
60698684Sdes	switch (c->number) {
607294328Sdes#ifdef WITH_OPENSSL
60898684Sdes	case SSH_CIPHER_SSH2:
60998684Sdes	case SSH_CIPHER_DES:
61098684Sdes	case SSH_CIPHER_BLOWFISH:
611323134Sdes		evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
612294328Sdes		if (evplen == 0)
613294328Sdes			return 0;
614294328Sdes		else if (evplen < 0)
615294328Sdes			return SSH_ERR_LIBCRYPTO_ERROR;
616149753Sdes		if ((u_int)evplen != len)
617294328Sdes			return SSH_ERR_INVALID_ARGUMENT;
618248619Sdes#ifndef OPENSSL_HAVE_EVPCTR
619124211Sdes		if (c->evptype == evp_aes_128_ctr)
620323134Sdes			ssh_aes_ctr_iv(cc->evp, 0, iv, len);
621124211Sdes		else
622248619Sdes#endif
623294328Sdes		if (cipher_authlen(c)) {
624323134Sdes			if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN,
625294328Sdes			   len, iv))
626294328Sdes			       return SSH_ERR_LIBCRYPTO_ERROR;
627294328Sdes		} else
628323134Sdes			memcpy(iv, cc->evp->iv, len);
62998684Sdes		break;
630294328Sdes#endif
631294328Sdes#ifdef WITH_SSH1
632124211Sdes	case SSH_CIPHER_3DES:
633323134Sdes		return ssh1_3des_iv(cc->evp, 0, iv, 24);
634294328Sdes#endif
63598684Sdes	default:
636294328Sdes		return SSH_ERR_INVALID_ARGUMENT;
63798684Sdes	}
638294328Sdes	return 0;
63998684Sdes}
64098684Sdes
641294328Sdesint
642294328Sdescipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
64398684Sdes{
644294328Sdes	const struct sshcipher *c = cc->cipher;
645294328Sdes#ifdef WITH_OPENSSL
646294328Sdes 	int evplen = 0;
647294328Sdes#endif
64898684Sdes
649261320Sdes	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
650294328Sdes		return 0;
651294328Sdes	if ((cc->cipher->flags & CFLAG_NONE) != 0)
652294328Sdes		return 0;
653261320Sdes
65498684Sdes	switch (c->number) {
655294328Sdes#ifdef WITH_OPENSSL
65698684Sdes	case SSH_CIPHER_SSH2:
65798684Sdes	case SSH_CIPHER_DES:
65898684Sdes	case SSH_CIPHER_BLOWFISH:
659323134Sdes		evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
660294328Sdes		if (evplen <= 0)
661294328Sdes			return SSH_ERR_LIBCRYPTO_ERROR;
662323134Sdes#ifndef OPENSSL_HAVE_EVPCTR
663323134Sdes		/* XXX iv arg is const, but ssh_aes_ctr_iv isn't */
664323134Sdes		if (c->evptype == evp_aes_128_ctr)
665323134Sdes			ssh_aes_ctr_iv(cc->evp, 1, (u_char *)iv, evplen);
666323134Sdes		else
667323134Sdes#endif
668294328Sdes		if (cipher_authlen(c)) {
669294328Sdes			/* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */
670323134Sdes			if (!EVP_CIPHER_CTX_ctrl(cc->evp,
671294328Sdes			    EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv))
672294328Sdes				return SSH_ERR_LIBCRYPTO_ERROR;
673294328Sdes		} else
674323134Sdes			memcpy(cc->evp->iv, iv, evplen);
675294328Sdes		break;
67698684Sdes#endif
677294328Sdes#ifdef WITH_SSH1
678294328Sdes	case SSH_CIPHER_3DES:
679323134Sdes		return ssh1_3des_iv(cc->evp, 1, (u_char *)iv, 24);
680248619Sdes#endif
68198684Sdes	default:
682294328Sdes		return SSH_ERR_INVALID_ARGUMENT;
68398684Sdes	}
684294328Sdes	return 0;
68598684Sdes}
68698684Sdes
687294328Sdes#ifdef WITH_OPENSSL
688323134Sdes#define EVP_X_STATE(evp)	(evp)->cipher_data
689323134Sdes#define EVP_X_STATE_LEN(evp)	(evp)->cipher->ctx_size
690294328Sdes#endif
691294328Sdes
69298684Sdesint
693294328Sdescipher_get_keycontext(const struct sshcipher_ctx *cc, u_char *dat)
69498684Sdes{
695323129Sdes#if defined(WITH_OPENSSL) && !defined(OPENSSL_NO_RC4)
696294328Sdes	const struct sshcipher *c = cc->cipher;
69798684Sdes	int plen = 0;
69898684Sdes
699248619Sdes	if (c->evptype == EVP_rc4) {
70098684Sdes		plen = EVP_X_STATE_LEN(cc->evp);
70198684Sdes		if (dat == NULL)
70298684Sdes			return (plen);
70398684Sdes		memcpy(dat, EVP_X_STATE(cc->evp), plen);
70498684Sdes	}
70598684Sdes	return (plen);
706294328Sdes#else
707294328Sdes	return 0;
708294328Sdes#endif
70998684Sdes}
71098684Sdes
71198684Sdesvoid
712294328Sdescipher_set_keycontext(struct sshcipher_ctx *cc, const u_char *dat)
71398684Sdes{
714323129Sdes#if defined(WITH_OPENSSL) && !defined(OPENSSL_NO_RC4)
715294328Sdes	const struct sshcipher *c = cc->cipher;
71698684Sdes	int plen;
71798684Sdes
718248619Sdes	if (c->evptype == EVP_rc4) {
71998684Sdes		plen = EVP_X_STATE_LEN(cc->evp);
72098684Sdes		memcpy(EVP_X_STATE(cc->evp), dat, plen);
72198684Sdes	}
722294328Sdes#endif
72398684Sdes}
724