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