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