Home | History | Annotate | Line # | Download | only in dist
      1  1.26       nia /*	$NetBSD: cipher.c,v 1.26 2025/12/28 09:39:35 nia Exp $	*/
      2  1.25  christos /* $OpenBSD: cipher.c,v 1.125 2025/09/02 11:08:34 djm Exp $ */
      3  1.19  christos 
      4   1.1  christos /*
      5   1.1  christos  * Author: Tatu Ylonen <ylo (at) cs.hut.fi>
      6   1.1  christos  * Copyright (c) 1995 Tatu Ylonen <ylo (at) cs.hut.fi>, Espoo, Finland
      7   1.1  christos  *                    All rights reserved
      8   1.1  christos  *
      9   1.1  christos  * As far as I am concerned, the code I have written for this software
     10   1.1  christos  * can be used freely for any purpose.  Any derived versions of this
     11   1.1  christos  * software must be clearly marked as such, and if the derived work is
     12   1.1  christos  * incompatible with the protocol description in the RFC file, it must be
     13   1.1  christos  * called by a name other than "ssh" or "Secure Shell".
     14   1.1  christos  *
     15   1.1  christos  *
     16   1.1  christos  * Copyright (c) 1999 Niels Provos.  All rights reserved.
     17   1.1  christos  * Copyright (c) 1999, 2000 Markus Friedl.  All rights reserved.
     18   1.1  christos  *
     19   1.1  christos  * Redistribution and use in source and binary forms, with or without
     20   1.1  christos  * modification, are permitted provided that the following conditions
     21   1.1  christos  * are met:
     22   1.1  christos  * 1. Redistributions of source code must retain the above copyright
     23   1.1  christos  *    notice, this list of conditions and the following disclaimer.
     24   1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     25   1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     26   1.1  christos  *    documentation and/or other materials provided with the distribution.
     27   1.1  christos  *
     28   1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     29   1.1  christos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     30   1.1  christos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     31   1.1  christos  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     32   1.1  christos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     33   1.1  christos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     34   1.1  christos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     35   1.1  christos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     36   1.1  christos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     37   1.1  christos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     38   1.1  christos  */
     39   1.1  christos 
     40   1.2  christos #include "includes.h"
     41  1.26       nia __RCSID("$NetBSD: cipher.c,v 1.26 2025/12/28 09:39:35 nia Exp $");
     42   1.1  christos #include <sys/types.h>
     43   1.1  christos 
     44   1.1  christos #include <string.h>
     45   1.1  christos #include <stdarg.h>
     46   1.6  christos #include <stdio.h>
     47   1.1  christos 
     48   1.1  christos #include "cipher.h"
     49   1.6  christos #include "misc.h"
     50   1.6  christos #include "sshbuf.h"
     51   1.6  christos #include "ssherr.h"
     52   1.6  christos #include "digest.h"
     53   1.1  christos 
     54  1.16  christos #ifndef WITH_OPENSSL
     55  1.16  christos #define EVP_CIPHER_CTX void
     56  1.16  christos #endif
     57   1.1  christos 
     58  1.20  christos // XXX: from libressl
     59  1.26       nia #ifdef WITH_OPENSSL
     60  1.20  christos #define HAVE_EVP_CIPHER_CTX_IV
     61  1.20  christos 
     62  1.20  christos static int
     63  1.20  christos EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx, unsigned char *iv, size_t len)
     64  1.20  christos {
     65  1.20  christos 	if (ctx == NULL)
     66  1.20  christos 		return 0;
     67  1.20  christos 	if (EVP_CIPHER_CTX_iv_length(ctx) < 0)
     68  1.20  christos 		return 0;
     69  1.20  christos 	if (len != (size_t)EVP_CIPHER_CTX_iv_length(ctx))
     70  1.20  christos 		return 0;
     71  1.20  christos 	if (len > EVP_MAX_IV_LENGTH)
     72  1.20  christos 		return 0; /* sanity check; shouldn't happen */
     73  1.20  christos 	/*
     74  1.20  christos 	 * Skip the memcpy entirely when the requested IV length is zero,
     75  1.20  christos 	 * since the iv pointer may be NULL or invalid.
     76  1.20  christos 	 */
     77  1.20  christos 	if (len != 0) {
     78  1.20  christos 		if (iv == NULL)
     79  1.20  christos 			return 0;
     80  1.20  christos # ifdef HAVE_EVP_CIPHER_CTX_IV
     81  1.20  christos 		memcpy(iv, EVP_CIPHER_CTX_iv(ctx), len);
     82  1.20  christos # else
     83  1.20  christos 		memcpy(iv, ctx->iv, len);
     84  1.20  christos # endif /* HAVE_EVP_CIPHER_CTX_IV */
     85  1.20  christos 	}
     86  1.20  christos 	return 1;
     87  1.20  christos }
     88  1.26       nia #endif
     89  1.20  christos // XXX: end
     90  1.20  christos 
     91   1.9  christos struct sshcipher_ctx {
     92   1.9  christos 	int	plaintext;
     93   1.9  christos 	int	encrypt;
     94   1.9  christos 	EVP_CIPHER_CTX *evp;
     95  1.18  christos 	struct chachapoly_ctx *cp_ctx;
     96   1.9  christos 	struct aesctr_ctx ac_ctx; /* XXX union with evp? */
     97   1.9  christos 	const struct sshcipher *cipher;
     98   1.9  christos };
     99   1.9  christos 
    100   1.6  christos struct sshcipher {
    101   1.3  christos 	const char	*name;
    102   1.1  christos 	u_int	block_size;
    103   1.1  christos 	u_int	key_len;
    104   1.4  christos 	u_int	iv_len;		/* defaults to block_size */
    105   1.4  christos 	u_int	auth_len;
    106   1.6  christos 	u_int	flags;
    107   1.6  christos #define CFLAG_CBC		(1<<0)
    108   1.6  christos #define CFLAG_CHACHAPOLY	(1<<1)
    109   1.6  christos #define CFLAG_AESCTR		(1<<2)
    110   1.6  christos #define CFLAG_NONE		(1<<3)
    111  1.11  christos #define CFLAG_INTERNAL		CFLAG_NONE /* Don't use "none" for packets */
    112   1.6  christos #ifdef WITH_OPENSSL
    113   1.1  christos 	const EVP_CIPHER	*(*evptype)(void);
    114   1.6  christos #else
    115   1.6  christos 	void	*ignored;
    116   1.6  christos #endif
    117   1.5  christos };
    118   1.5  christos 
    119   1.6  christos static const struct sshcipher ciphers[] = {
    120   1.6  christos #ifdef WITH_OPENSSL
    121  1.11  christos 	{ "3des-cbc",		8, 24, 0, 0, CFLAG_CBC, EVP_des_ede3_cbc },
    122  1.11  christos 	{ "aes128-cbc",		16, 16, 0, 0, CFLAG_CBC, EVP_aes_128_cbc },
    123  1.11  christos 	{ "aes192-cbc",		16, 24, 0, 0, CFLAG_CBC, EVP_aes_192_cbc },
    124  1.11  christos 	{ "aes256-cbc",		16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc },
    125  1.11  christos 	{ "aes128-ctr",		16, 16, 0, 0, 0, EVP_aes_128_ctr },
    126  1.11  christos 	{ "aes192-ctr",		16, 24, 0, 0, 0, EVP_aes_192_ctr },
    127  1.11  christos 	{ "aes256-ctr",		16, 32, 0, 0, 0, EVP_aes_256_ctr },
    128   1.4  christos 	{ "aes128-gcm (at) openssh.com",
    129  1.11  christos 				16, 16, 12, 16, 0, EVP_aes_128_gcm },
    130   1.4  christos 	{ "aes256-gcm (at) openssh.com",
    131  1.11  christos 				16, 32, 12, 16, 0, EVP_aes_256_gcm },
    132   1.6  christos #else
    133  1.11  christos 	{ "aes128-ctr",		16, 16, 0, 0, CFLAG_AESCTR, NULL },
    134  1.11  christos 	{ "aes192-ctr",		16, 24, 0, 0, CFLAG_AESCTR, NULL },
    135  1.11  christos 	{ "aes256-ctr",		16, 32, 0, 0, CFLAG_AESCTR, NULL },
    136   1.6  christos #endif
    137   1.6  christos 	{ "chacha20-poly1305 (at) openssh.com",
    138  1.11  christos 				8, 64, 0, 16, CFLAG_CHACHAPOLY, NULL },
    139  1.11  christos 	{ "none",		8, 0, 0, 0, CFLAG_NONE, NULL },
    140   1.6  christos 
    141  1.11  christos 	{ NULL,			0, 0, 0, 0, 0, NULL }
    142   1.1  christos };
    143   1.1  christos 
    144   1.1  christos /*--*/
    145   1.1  christos 
    146   1.5  christos /* Returns a comma-separated list of supported ciphers. */
    147   1.5  christos char *
    148   1.6  christos cipher_alg_list(char sep, int auth_only)
    149   1.5  christos {
    150  1.25  christos 	char *ret = NULL;
    151   1.6  christos 	const struct sshcipher *c;
    152  1.25  christos 	char sep_str[2] = {sep, '\0'};
    153   1.5  christos 
    154   1.5  christos 	for (c = ciphers; c->name != NULL; c++) {
    155  1.11  christos 		if ((c->flags & CFLAG_INTERNAL) != 0)
    156   1.5  christos 			continue;
    157   1.6  christos 		if (auth_only && c->auth_len == 0)
    158   1.6  christos 			continue;
    159  1.25  christos 		xextendf(&ret, sep_str, "%s", c->name);
    160   1.5  christos 	}
    161   1.5  christos 	return ret;
    162   1.5  christos }
    163   1.5  christos 
    164  1.17  christos const char *
    165  1.17  christos compression_alg_list(int compression)
    166  1.17  christos {
    167  1.17  christos #ifdef WITH_ZLIB
    168  1.23  christos 	return compression ? "zlib (at) openssh.com,none" :
    169  1.23  christos 	    "none,zlib (at) openssh.com";
    170  1.17  christos #else
    171  1.17  christos 	return "none";
    172  1.17  christos #endif
    173  1.17  christos }
    174  1.17  christos 
    175   1.1  christos u_int
    176   1.6  christos cipher_blocksize(const struct sshcipher *c)
    177   1.1  christos {
    178   1.1  christos 	return (c->block_size);
    179   1.1  christos }
    180   1.1  christos 
    181   1.1  christos u_int
    182   1.6  christos cipher_keylen(const struct sshcipher *c)
    183   1.1  christos {
    184   1.1  christos 	return (c->key_len);
    185   1.1  christos }
    186   1.1  christos 
    187   1.1  christos u_int
    188   1.6  christos cipher_seclen(const struct sshcipher *c)
    189   1.6  christos {
    190   1.6  christos 	if (strcmp("3des-cbc", c->name) == 0)
    191   1.6  christos 		return 14;
    192   1.6  christos 	return cipher_keylen(c);
    193   1.6  christos }
    194   1.6  christos 
    195   1.6  christos u_int
    196   1.6  christos cipher_authlen(const struct sshcipher *c)
    197   1.4  christos {
    198   1.4  christos 	return (c->auth_len);
    199   1.4  christos }
    200   1.4  christos 
    201   1.4  christos u_int
    202   1.6  christos cipher_ivlen(const struct sshcipher *c)
    203   1.4  christos {
    204   1.6  christos 	/*
    205   1.6  christos 	 * Default is cipher block size, except for chacha20+poly1305 that
    206   1.6  christos 	 * needs no IV. XXX make iv_len == -1 default?
    207   1.6  christos 	 */
    208   1.6  christos 	return (c->iv_len != 0 || (c->flags & CFLAG_CHACHAPOLY) != 0) ?
    209   1.6  christos 	    c->iv_len : c->block_size;
    210   1.4  christos }
    211   1.4  christos 
    212   1.4  christos u_int
    213   1.6  christos cipher_is_cbc(const struct sshcipher *c)
    214   1.1  christos {
    215   1.6  christos 	return (c->flags & CFLAG_CBC) != 0;
    216   1.1  christos }
    217   1.1  christos 
    218   1.1  christos u_int
    219   1.9  christos cipher_ctx_is_plaintext(struct sshcipher_ctx *cc)
    220   1.9  christos {
    221   1.9  christos 	return cc->plaintext;
    222   1.9  christos }
    223   1.9  christos 
    224   1.6  christos const struct sshcipher *
    225   1.1  christos cipher_by_name(const char *name)
    226   1.1  christos {
    227   1.6  christos 	const struct sshcipher *c;
    228   1.1  christos 	for (c = ciphers; c->name != NULL; c++)
    229   1.1  christos 		if (strcmp(c->name, name) == 0)
    230   1.1  christos 			return c;
    231   1.1  christos 	return NULL;
    232   1.1  christos }
    233   1.1  christos 
    234   1.1  christos #define	CIPHER_SEP	","
    235   1.1  christos int
    236   1.1  christos ciphers_valid(const char *names)
    237   1.1  christos {
    238   1.6  christos 	const struct sshcipher *c;
    239   1.1  christos 	char *cipher_list, *cp;
    240   1.1  christos 	char *p;
    241   1.1  christos 
    242   1.1  christos 	if (names == NULL || strcmp(names, "") == 0)
    243   1.1  christos 		return 0;
    244   1.6  christos 	if ((cipher_list = cp = strdup(names)) == NULL)
    245   1.6  christos 		return 0;
    246   1.1  christos 	for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
    247   1.1  christos 	    (p = strsep(&cp, CIPHER_SEP))) {
    248   1.1  christos 		c = cipher_by_name(p);
    249  1.11  christos 		if (c == NULL || (c->flags & (CFLAG_INTERNAL|CFLAG_NONE)) != 0) {
    250   1.5  christos 			free(cipher_list);
    251   1.1  christos 			return 0;
    252   1.1  christos 		}
    253   1.1  christos 	}
    254   1.5  christos 	free(cipher_list);
    255   1.1  christos 	return 1;
    256   1.1  christos }
    257   1.1  christos 
    258   1.6  christos const char *
    259   1.6  christos cipher_warning_message(const struct sshcipher_ctx *cc)
    260   1.6  christos {
    261   1.6  christos 	if (cc == NULL || cc->cipher == NULL)
    262   1.6  christos 		return NULL;
    263  1.11  christos 	/* XXX repurpose for CBC warning */
    264   1.6  christos 	return NULL;
    265   1.6  christos }
    266   1.6  christos 
    267   1.6  christos int
    268   1.9  christos cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher,
    269   1.1  christos     const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
    270   1.1  christos     int do_encrypt)
    271   1.1  christos {
    272   1.9  christos 	struct sshcipher_ctx *cc = NULL;
    273   1.9  christos 	int ret = SSH_ERR_INTERNAL_ERROR;
    274   1.6  christos #ifdef WITH_OPENSSL
    275   1.1  christos 	const EVP_CIPHER *type;
    276   1.1  christos 	int klen;
    277   1.9  christos #endif
    278   1.9  christos 
    279   1.9  christos 	*ccp = NULL;
    280  1.23  christos 	if ((cc = calloc(1, sizeof(*cc))) == NULL)
    281   1.9  christos 		return SSH_ERR_ALLOC_FAIL;
    282   1.1  christos 
    283  1.11  christos 	cc->plaintext = (cipher->flags & CFLAG_NONE) != 0;
    284   1.4  christos 	cc->encrypt = do_encrypt;
    285   1.1  christos 
    286   1.6  christos 	if (keylen < cipher->key_len ||
    287   1.9  christos 	    (iv != NULL && ivlen < cipher_ivlen(cipher))) {
    288   1.9  christos 		ret = SSH_ERR_INVALID_ARGUMENT;
    289   1.9  christos 		goto out;
    290   1.9  christos 	}
    291   1.6  christos 
    292   1.1  christos 	cc->cipher = cipher;
    293   1.6  christos 	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
    294  1.18  christos 		cc->cp_ctx = chachapoly_new(key, keylen);
    295  1.18  christos 		ret = cc->cp_ctx != NULL ? 0 : SSH_ERR_INVALID_ARGUMENT;
    296   1.9  christos 		goto out;
    297   1.6  christos 	}
    298  1.11  christos 	if ((cc->cipher->flags & CFLAG_NONE) != 0) {
    299  1.11  christos 		ret = 0;
    300  1.11  christos 		goto out;
    301  1.11  christos 	}
    302   1.6  christos #ifndef WITH_OPENSSL
    303   1.6  christos 	if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
    304   1.6  christos 		aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen);
    305   1.6  christos 		aesctr_ivsetup(&cc->ac_ctx, iv);
    306   1.9  christos 		ret = 0;
    307   1.9  christos 		goto out;
    308   1.9  christos 	}
    309   1.9  christos 	ret = SSH_ERR_INVALID_ARGUMENT;
    310   1.9  christos 	goto out;
    311   1.9  christos #else /* WITH_OPENSSL */
    312   1.1  christos 	type = (*cipher->evptype)();
    313   1.9  christos 	if ((cc->evp = EVP_CIPHER_CTX_new()) == NULL) {
    314   1.9  christos 		ret = SSH_ERR_ALLOC_FAIL;
    315   1.9  christos 		goto out;
    316   1.9  christos 	}
    317   1.9  christos 	if (EVP_CipherInit(cc->evp, type, NULL, (const u_char *)iv,
    318   1.6  christos 	    (do_encrypt == CIPHER_ENCRYPT)) == 0) {
    319   1.6  christos 		ret = SSH_ERR_LIBCRYPTO_ERROR;
    320   1.9  christos 		goto out;
    321   1.6  christos 	}
    322   1.4  christos 	if (cipher_authlen(cipher) &&
    323  1.24  christos 	    EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_IV_FIXED,
    324  1.24  christos 	    -1, __UNCONST(iv)) <= 0) {
    325   1.6  christos 		ret = SSH_ERR_LIBCRYPTO_ERROR;
    326   1.9  christos 		goto out;
    327   1.6  christos 	}
    328   1.9  christos 	klen = EVP_CIPHER_CTX_key_length(cc->evp);
    329   1.1  christos 	if (klen > 0 && keylen != (u_int)klen) {
    330   1.9  christos 		if (EVP_CIPHER_CTX_set_key_length(cc->evp, keylen) == 0) {
    331   1.6  christos 			ret = SSH_ERR_LIBCRYPTO_ERROR;
    332   1.9  christos 			goto out;
    333   1.6  christos 		}
    334   1.6  christos 	}
    335  1.12  christos 	/* in OpenSSL 1.1.0, EVP_CipherInit clears all previous setups;
    336  1.12  christos 	   use EVP_CipherInit_ex for augmenting */
    337  1.12  christos 	if (EVP_CipherInit_ex(cc->evp, NULL, NULL, __UNCONST(key), NULL, -1) == 0) {
    338   1.6  christos 		ret = SSH_ERR_LIBCRYPTO_ERROR;
    339   1.9  christos 		goto out;
    340   1.6  christos 	}
    341   1.9  christos 	ret = 0;
    342   1.9  christos #endif /* WITH_OPENSSL */
    343   1.9  christos  out:
    344   1.9  christos 	if (ret == 0) {
    345   1.9  christos 		/* success */
    346   1.9  christos 		*ccp = cc;
    347   1.9  christos 	} else {
    348   1.9  christos 		if (cc != NULL) {
    349   1.9  christos #ifdef WITH_OPENSSL
    350  1.13  christos 			EVP_CIPHER_CTX_free(cc->evp);
    351   1.9  christos #endif /* WITH_OPENSSL */
    352  1.18  christos 			freezero(cc, sizeof(*cc));
    353   1.9  christos 		}
    354   1.9  christos 	}
    355   1.9  christos 	return ret;
    356   1.1  christos }
    357   1.1  christos 
    358   1.4  christos /*
    359   1.4  christos  * cipher_crypt() operates as following:
    360   1.4  christos  * Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'.
    361  1.18  christos  * These bytes are treated as additional authenticated data for
    362   1.4  christos  * authenticated encryption modes.
    363   1.4  christos  * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'.
    364   1.4  christos  * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag.
    365   1.4  christos  * This tag is written on encryption and verified on decryption.
    366   1.4  christos  * Both 'aadlen' and 'authlen' can be set to 0.
    367   1.4  christos  */
    368   1.6  christos int
    369   1.6  christos cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest,
    370   1.6  christos    const u_char *src, u_int len, u_int aadlen, u_int authlen)
    371   1.1  christos {
    372   1.6  christos 	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
    373  1.18  christos 		return chachapoly_crypt(cc->cp_ctx, seqnr, dest, src,
    374   1.6  christos 		    len, aadlen, authlen, cc->encrypt);
    375   1.6  christos 	}
    376  1.11  christos 	if ((cc->cipher->flags & CFLAG_NONE) != 0) {
    377  1.11  christos 		memcpy(dest, src, aadlen + len);
    378  1.11  christos 		return 0;
    379  1.11  christos 	}
    380   1.6  christos #ifndef WITH_OPENSSL
    381   1.6  christos 	if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
    382   1.6  christos 		if (aadlen)
    383   1.6  christos 			memcpy(dest, src, aadlen);
    384   1.6  christos 		aesctr_encrypt_bytes(&cc->ac_ctx, src + aadlen,
    385   1.6  christos 		    dest + aadlen, len);
    386   1.6  christos 		return 0;
    387   1.6  christos 	}
    388   1.6  christos 	return SSH_ERR_INVALID_ARGUMENT;
    389   1.6  christos #else
    390   1.4  christos 	if (authlen) {
    391   1.4  christos 		u_char lastiv[1];
    392   1.4  christos 
    393   1.4  christos 		if (authlen != cipher_authlen(cc->cipher))
    394   1.6  christos 			return SSH_ERR_INVALID_ARGUMENT;
    395   1.4  christos 		/* increment IV */
    396  1.24  christos 		if (EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN,
    397  1.24  christos 		    1, lastiv) <= 0)
    398   1.6  christos 			return SSH_ERR_LIBCRYPTO_ERROR;
    399  1.22  christos 		/* set tag on decryption */
    400   1.4  christos 		if (!cc->encrypt &&
    401  1.24  christos 		    EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_TAG,
    402  1.24  christos 		    authlen, __UNCONST(src + aadlen + len)) <= 0)
    403   1.6  christos 			return SSH_ERR_LIBCRYPTO_ERROR;
    404   1.4  christos 	}
    405   1.4  christos 	if (aadlen) {
    406   1.4  christos 		if (authlen &&
    407   1.9  christos 		    EVP_Cipher(cc->evp, NULL, (const u_char *)src, aadlen) < 0)
    408   1.6  christos 			return SSH_ERR_LIBCRYPTO_ERROR;
    409   1.4  christos 		memcpy(dest, src, aadlen);
    410   1.4  christos 	}
    411   1.1  christos 	if (len % cc->cipher->block_size)
    412   1.6  christos 		return SSH_ERR_INVALID_ARGUMENT;
    413   1.9  christos 	if (EVP_Cipher(cc->evp, dest + aadlen, (const u_char *)src + aadlen,
    414   1.4  christos 	    len) < 0)
    415   1.6  christos 		return SSH_ERR_LIBCRYPTO_ERROR;
    416   1.4  christos 	if (authlen) {
    417   1.4  christos 		/* compute tag (on encrypt) or verify tag (on decrypt) */
    418   1.9  christos 		if (EVP_Cipher(cc->evp, NULL, NULL, 0) < 0)
    419   1.6  christos 			return cc->encrypt ?
    420   1.6  christos 			    SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID;
    421   1.4  christos 		if (cc->encrypt &&
    422  1.24  christos 		    EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_GET_TAG,
    423  1.24  christos 		    authlen, dest + aadlen + len) <= 0)
    424   1.6  christos 			return SSH_ERR_LIBCRYPTO_ERROR;
    425   1.4  christos 	}
    426   1.6  christos 	return 0;
    427   1.6  christos #endif
    428   1.6  christos }
    429   1.6  christos 
    430   1.6  christos /* Extract the packet length, including any decryption necessary beforehand */
    431   1.6  christos int
    432   1.6  christos cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr,
    433   1.6  christos     const u_char *cp, u_int len)
    434   1.6  christos {
    435   1.6  christos 	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
    436  1.18  christos 		return chachapoly_get_length(cc->cp_ctx, plenp, seqnr,
    437   1.6  christos 		    cp, len);
    438   1.6  christos 	if (len < 4)
    439   1.6  christos 		return SSH_ERR_MESSAGE_INCOMPLETE;
    440  1.13  christos 	*plenp = PEEK_U32(cp);
    441   1.6  christos 	return 0;
    442   1.1  christos }
    443   1.1  christos 
    444   1.9  christos void
    445   1.9  christos cipher_free(struct sshcipher_ctx *cc)
    446   1.1  christos {
    447   1.9  christos 	if (cc == NULL)
    448   1.9  christos 		return;
    449  1.18  christos 	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
    450  1.18  christos 		chachapoly_free(cc->cp_ctx);
    451  1.18  christos 		cc->cp_ctx = NULL;
    452  1.18  christos 	} else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
    453   1.6  christos 		explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx));
    454   1.6  christos #ifdef WITH_OPENSSL
    455  1.13  christos 	EVP_CIPHER_CTX_free(cc->evp);
    456  1.13  christos 	cc->evp = NULL;
    457   1.6  christos #endif
    458  1.18  christos 	freezero(cc, sizeof(*cc));
    459   1.1  christos }
    460   1.1  christos 
    461   1.6  christos int
    462  1.15  christos cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, size_t len)
    463   1.1  christos {
    464  1.13  christos #ifdef WITH_OPENSSL
    465   1.6  christos 	const struct sshcipher *c = cc->cipher;
    466  1.13  christos 	int evplen;
    467   1.6  christos #endif
    468   1.6  christos 
    469   1.6  christos 	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
    470   1.6  christos 		if (len != 0)
    471   1.6  christos 			return SSH_ERR_INVALID_ARGUMENT;
    472   1.6  christos 		return 0;
    473   1.6  christos 	}
    474   1.7  christos 	if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
    475   1.7  christos 		if (len != sizeof(cc->ac_ctx.ctr))
    476   1.7  christos 			return SSH_ERR_INVALID_ARGUMENT;
    477   1.7  christos 		memcpy(iv, cc->ac_ctx.ctr, len);
    478   1.7  christos 		return 0;
    479   1.7  christos 	}
    480   1.6  christos 	if ((cc->cipher->flags & CFLAG_NONE) != 0)
    481   1.6  christos 		return 0;
    482   1.1  christos 
    483   1.6  christos #ifdef WITH_OPENSSL
    484  1.11  christos 	evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
    485  1.11  christos 	if (evplen == 0)
    486  1.11  christos 		return 0;
    487  1.11  christos 	else if (evplen < 0)
    488  1.11  christos 		return SSH_ERR_LIBCRYPTO_ERROR;
    489  1.15  christos 	if ((size_t)evplen != len)
    490  1.11  christos 		return SSH_ERR_INVALID_ARGUMENT;
    491  1.11  christos 	if (cipher_authlen(c)) {
    492  1.24  christos 		if (EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN, len,
    493  1.24  christos 		    iv) <= 0)
    494  1.20  christos 			return SSH_ERR_LIBCRYPTO_ERROR;
    495  1.24  christos 	} else if (EVP_CIPHER_CTX_get_iv(cc->evp, iv, len) <= 0)
    496  1.20  christos 		return SSH_ERR_LIBCRYPTO_ERROR;
    497   1.6  christos #endif
    498   1.6  christos 	return 0;
    499   1.1  christos }
    500   1.1  christos 
    501   1.6  christos int
    502  1.15  christos cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv, size_t len)
    503   1.1  christos {
    504  1.13  christos #ifdef WITH_OPENSSL
    505   1.6  christos 	const struct sshcipher *c = cc->cipher;
    506  1.13  christos 	int evplen = 0;
    507   1.6  christos #endif
    508   1.6  christos 
    509   1.6  christos 	if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
    510   1.6  christos 		return 0;
    511   1.6  christos 	if ((cc->cipher->flags & CFLAG_NONE) != 0)
    512   1.6  christos 		return 0;
    513   1.1  christos 
    514   1.6  christos #ifdef WITH_OPENSSL
    515  1.11  christos 	evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
    516  1.11  christos 	if (evplen <= 0)
    517  1.11  christos 		return SSH_ERR_LIBCRYPTO_ERROR;
    518  1.15  christos 	if ((size_t)evplen != len)
    519  1.15  christos 		return SSH_ERR_INVALID_ARGUMENT;
    520  1.11  christos 	if (cipher_authlen(c)) {
    521  1.11  christos 		/* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */
    522  1.24  christos 		if (EVP_CIPHER_CTX_ctrl(cc->evp,
    523  1.24  christos 		    EVP_CTRL_GCM_SET_IV_FIXED, -1, __UNCONST(iv)) <= 0)
    524  1.15  christos 			return SSH_ERR_LIBCRYPTO_ERROR;
    525  1.11  christos 	} else
    526  1.12  christos 		memcpy(EVP_CIPHER_CTX_iv_noconst(cc->evp), iv, evplen);
    527   1.6  christos #endif
    528   1.6  christos 	return 0;
    529   1.1  christos }
    530