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