Coverage Report

Created: 2026-10-17 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hpn-ssh/cipher.c
Line
Count
Source
1
/* $OpenBSD: cipher.c,v 1.129 2026/06/19 05:26:04 djm Exp $ */
2
/*
3
 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4
 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5
 *                    All rights reserved
6
 *
7
 * As far as I am concerned, the code I have written for this software
8
 * can be used freely for any purpose.  Any derived versions of this
9
 * software must be clearly marked as such, and if the derived work is
10
 * incompatible with the protocol description in the RFC file, it must be
11
 * called by a name other than "ssh" or "Secure Shell".
12
 *
13
 *
14
 * Copyright (c) 1999 Niels Provos.  All rights reserved.
15
 * Copyright (c) 1999, 2000 Markus Friedl.  All rights reserved.
16
 *
17
 * Redistribution and use in source and binary forms, with or without
18
 * modification, are permitted provided that the following conditions
19
 * are met:
20
 * 1. Redistributions of source code must retain the above copyright
21
 *    notice, this list of conditions and the following disclaimer.
22
 * 2. Redistributions in binary form must reproduce the above copyright
23
 *    notice, this list of conditions and the following disclaimer in the
24
 *    documentation and/or other materials provided with the distribution.
25
 *
26
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
 */
37
38
#include "includes.h"
39
40
#include <sys/types.h>
41
42
#include <string.h>
43
#include <stdarg.h>
44
#include <stdio.h>
45
46
#include "cipher.h"
47
#include "misc.h"
48
#include "sshbuf.h"
49
#include "ssherr.h"
50
#include "digest.h"
51
#include "log.h"
52
53
#include "openbsd-compat/openssl-compat.h"
54
55
/* for provider functions */
56
#ifdef WITH_OPENSSL3
57
#include <openssl/err.h>
58
#include <openssl/params.h>
59
#include <openssl/provider.h>
60
#endif
61
62
#ifndef WITH_OPENSSL
63
#define EVP_CIPHER_CTX void
64
#define EVP_CIPHER void
65
#else
66
/* for multi-threaded aes-ctr cipher */
67
extern const EVP_CIPHER *evp_aes_ctr_mt(void);
68
#endif
69
70
struct sshcipher_ctx {
71
  int plaintext;
72
  int encrypt;
73
  EVP_CIPHER_CTX *evp;
74
  const EVP_CIPHER *meth_ptr; /*used to free memory in aes_ctr_mt */
75
  struct chachapoly_ctx *cp_ctx;
76
#ifdef WITH_OPENSSL
77
  struct chachapoly_ctx_mt *cp_ctx_mt;
78
#endif
79
  struct aesctr_ctx ac_ctx; /* XXX union with evp? */
80
  const struct sshcipher *cipher;
81
};
82
83
struct sshcipher {
84
  char  *name;
85
  u_int block_size;
86
  u_int key_len;
87
  u_int iv_len;   /* defaults to block_size */
88
  u_int auth_len;
89
  u_int flags;
90
0
#define CFLAG_CBC   (1<<0)
91
6.67M
#define CFLAG_CHACHAPOLY  (1<<1)
92
132k
#define CFLAG_AESCTR    (1<<2)
93
6.67M
#define CFLAG_NONE    (1<<3)
94
0
#define CFLAG_INTERNAL 0
95
#ifdef WITH_OPENSSL
96
0
#define CFLAG_MT    (1<<4)
97
  const EVP_CIPHER  *(*evptype)(void);
98
#else
99
  void  *ignored;
100
#endif
101
};
102
103
static struct sshcipher ciphers[] = {
104
#ifdef WITH_OPENSSL
105
#ifndef OPENSSL_NO_DES
106
  { "3des-cbc",   8, 24, 0, 0, CFLAG_CBC, EVP_des_ede3_cbc },
107
#endif
108
  { "aes128-cbc",   16, 16, 0, 0, CFLAG_CBC, EVP_aes_128_cbc },
109
  { "aes192-cbc",   16, 24, 0, 0, CFLAG_CBC, EVP_aes_192_cbc },
110
  { "aes256-cbc",   16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc },
111
  { "aes128-ctr",   16, 16, 0, 0, 0, EVP_aes_128_ctr },
112
  { "aes192-ctr",   16, 24, 0, 0, 0, EVP_aes_192_ctr },
113
  { "aes256-ctr",   16, 32, 0, 0, 0, EVP_aes_256_ctr },
114
  { "aes128-gcm@openssh.com",
115
        16, 16, 12, 16, 0, EVP_aes_128_gcm },
116
  { "aes256-gcm@openssh.com",
117
        16, 32, 12, 16, 0, EVP_aes_256_gcm },
118
#else
119
  { "aes128-ctr",   16, 16, 0, 0, CFLAG_AESCTR, NULL },
120
  { "aes192-ctr",   16, 24, 0, 0, CFLAG_AESCTR, NULL },
121
  { "aes256-ctr",   16, 32, 0, 0, CFLAG_AESCTR, NULL },
122
#endif
123
  { "chacha20-poly1305@openssh.com",
124
        8, 64, 0, 16, CFLAG_CHACHAPOLY, NULL },
125
#ifdef WITH_OPENSSL
126
  { "chacha20-poly1305-mt@hpnssh.org",
127
        8, 64, 0, 16, CFLAG_CHACHAPOLY|CFLAG_MT, NULL },
128
#endif
129
  { "none",               8, 0, 0, 0, CFLAG_NONE, NULL },
130
131
  { NULL,                 0, 0, 0, 0, 0, NULL }
132
};
133
134
/*--*/
135
136
/* Returns a comma-separated list of supported ciphers. */
137
char *
138
cipher_alg_list(char sep, int auth_only)
139
0
{
140
0
  char *ret = NULL;
141
0
  const struct sshcipher *c;
142
0
  char sep_str[2] = {sep, '\0'};
143
144
0
  for (c = ciphers; c->name != NULL; c++) {
145
0
    if ((c->flags & CFLAG_INTERNAL) != 0)
146
0
      continue;
147
0
    if (auth_only && c->auth_len == 0)
148
0
      continue;
149
0
    xextendf(&ret, sep_str, "%s", c->name);
150
0
  }
151
0
  return ret;
152
0
}
153
154
const char *
155
compression_alg_list(int compression)
156
0
{
157
0
#ifdef WITH_ZLIB
158
0
  return compression ? "zlib@openssh.com,none" :
159
0
      "none,zlib@openssh.com";
160
#else
161
  return "none";
162
#endif
163
0
}
164
165
/* used to get the cipher name when we are testing to
166
 * see if we can move from a serial to parallel cipher
167
 * only called in cipher-switch.c
168
 */
169
const char *
170
cipher_ctx_name(const struct sshcipher_ctx *cc)
171
0
{
172
0
        return cc->cipher->name;
173
0
}
174
175
u_int
176
cipher_blocksize(const struct sshcipher *c)
177
83
{
178
83
  return (c->block_size);
179
83
}
180
181
uint64_t
182
cipher_rekey_blocks(const struct sshcipher *c)
183
0
{
184
  /*
185
   * Chacha20-Poly1305 does not benefit from data-based rekeying,
186
   * per "The Security of ChaCha20-Poly1305 in the Multi-user Setting",
187
   * Degabriele, J. P., Govinden, J, Gunther, F. and Paterson K.
188
   * ACM CCS 2021; https://eprint.iacr.org/2023/085.pdf
189
   *
190
   * Cryptanalysis aside, we do still want do need to prevent the SSH
191
   * sequence number wrapping and also to rekey to provide some
192
   * protection for long lived sessions against key disclosure at the
193
   * endpoints, so arrange for rekeying every 2**32 blocks as the
194
   * 128-bit block ciphers do (i.e. every 32GB data).
195
   */
196
0
  if ((c->flags & CFLAG_CHACHAPOLY) != 0)
197
0
    return (uint64_t)1 << 32;
198
199
  /* there is no actual need to rekey the NULL cipher but
200
   * rekeying is a necessary step. In part, as mentioned above,
201
   * to keep the seqnr from wrapping. So we set it to the
202
   * maximum possible -cjr 4/10/23 */
203
0
  if ((c->flags & CFLAG_NONE) != 0)
204
0
    return (uint64_t)1 << 32;
205
206
  /*
207
   * The 2^(blocksize*2) limit is too expensive for 3DES,
208
   * so enforce a 1GB data limit for small blocksizes.
209
   * See discussion in RFC4344 section 3.2.
210
   */
211
0
  if (c->block_size < 16)
212
0
    return ((uint64_t)1 << 30) / c->block_size;
213
  /*
214
   * Otherwise, use the RFC4344 s3.2 recommendation of 2**(L/4) blocks
215
   * before rekeying where L is the blocksize in bits.
216
   * Most other ciphers have a 128 bit blocksize, so this equates to
217
   * 2**32 blocks / 64GB data.
218
   */
219
0
  return (uint64_t)1 << (c->block_size * 2);
220
0
}
221
222
u_int
223
cipher_keylen(const struct sshcipher *c)
224
83
{
225
83
  return (c->key_len);
226
83
}
227
228
u_int
229
cipher_seclen(const struct sshcipher *c)
230
0
{
231
0
  if (strcmp("3des-cbc", c->name) == 0)
232
0
    return 14;
233
0
  return cipher_keylen(c);
234
0
}
235
236
u_int
237
cipher_authlen(const struct sshcipher *c)
238
83
{
239
83
  return (c->auth_len);
240
83
}
241
242
u_int
243
cipher_ivlen(const struct sshcipher *c)
244
86
{
245
  /*
246
   * Default is cipher block size, except for chacha20+poly1305 that
247
   * needs no IV. XXX make iv_len == -1 default?
248
   */
249
86
  return (c->iv_len != 0 || (c->flags & CFLAG_CHACHAPOLY) != 0) ?
250
86
      c->iv_len : c->block_size;
251
86
}
252
253
u_int
254
cipher_is_cbc(const struct sshcipher *c)
255
0
{
256
0
  return (c->flags & CFLAG_CBC) != 0;
257
0
}
258
259
u_int
260
cipher_is_internal(const struct sshcipher *c)
261
0
{
262
0
  return (c->flags & CFLAG_INTERNAL) != 0;
263
0
}
264
265
u_int
266
cipher_ctx_is_plaintext(struct sshcipher_ctx *cc)
267
0
{
268
0
  return cc->plaintext;
269
0
}
270
271
struct sshcipher *
272
cipher_by_name(const char *name)
273
66.3k
{
274
66.3k
  struct sshcipher *c;
275
796k
  for (c = ciphers; c->name != NULL; c++)
276
796k
    if (strcmp(c->name, name) == 0)
277
66.3k
      return c;
278
0
  return NULL;
279
66.3k
}
280
281
0
#define CIPHER_SEP  ","
282
int
283
ciphers_valid(const char *names)
284
0
{
285
0
  const struct sshcipher *c;
286
0
  char *cipher_list, *cp;
287
0
  char *p;
288
0
  int found = 0;
289
290
0
  if (names == NULL || strcmp(names, "") == 0)
291
0
    return 0;
292
0
  if ((cipher_list = cp = strdup(names)) == NULL)
293
0
    return 0;
294
0
  for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
295
0
      (p = strsep(&cp, CIPHER_SEP))) {
296
0
    c = cipher_by_name(p);
297
0
      if (c == NULL || ((c->flags & CFLAG_INTERNAL) != 0 &&
298
0
            (c->flags & CFLAG_NONE) != 0)) {
299
0
      free(cipher_list);
300
0
      return 0;
301
0
    } else
302
0
      found = 1;
303
0
  }
304
0
  free(cipher_list);
305
0
  return found;
306
0
}
307
308
const char *
309
cipher_warning_message(const struct sshcipher_ctx *cc)
310
0
{
311
0
  if (cc == NULL || cc->cipher == NULL)
312
0
    return NULL;
313
  /* XXX repurpose for CBC warning */
314
0
  return NULL;
315
0
}
316
317
int
318
cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher,
319
    const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
320
    u_int seqnr, int do_encrypt, int enable_threads)
321
132k
{
322
132k
  struct sshcipher_ctx *cc = NULL;
323
132k
  int ret = SSH_ERR_INTERNAL_ERROR;
324
132k
#ifdef WITH_OPENSSL
325
132k
  const EVP_CIPHER *type;
326
132k
  int klen;
327
132k
#endif
328
329
132k
  *ccp = NULL;
330
132k
  if ((cc = calloc(1, sizeof(*cc))) == NULL)
331
0
    return SSH_ERR_ALLOC_FAIL;
332
333
132k
  cc->plaintext = (cipher->flags & CFLAG_NONE) != 0;
334
132k
  cc->encrypt = do_encrypt;
335
132k
  cc->meth_ptr = NULL;
336
337
132k
  if (keylen < cipher->key_len ||
338
132k
      (iv != NULL && ivlen < cipher_ivlen(cipher))) {
339
0
    ret = SSH_ERR_INVALID_ARGUMENT;
340
0
    goto out;
341
0
  }
342
343
132k
  cc->cipher = cipher;
344
132k
  if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
345
0
#ifdef WITH_OPENSSL
346
0
    if ((cc->cipher->flags & CFLAG_MT) != 0) {
347
0
      cc->cp_ctx_mt = chachapoly_new_mt(seqnr, key, keylen);
348
0
      ret = cc->cp_ctx_mt != NULL ? 0 :
349
0
          SSH_ERR_INVALID_ARGUMENT;
350
0
    } else {
351
0
      cc->cp_ctx = chachapoly_new(key, keylen);
352
0
      ret = cc->cp_ctx != NULL ? 0 : SSH_ERR_INVALID_ARGUMENT;
353
0
    }
354
#else
355
    cc->cp_ctx = chachapoly_new(key, keylen);
356
    ret = cc->cp_ctx != NULL ? 0 : SSH_ERR_INVALID_ARGUMENT;
357
#endif
358
0
    goto out;
359
0
  }
360
132k
  if ((cc->cipher->flags & CFLAG_NONE) != 0) {
361
132k
    ret = 0;
362
132k
    goto out;
363
132k
  }
364
#ifndef WITH_OPENSSL
365
  if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
366
    aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen);
367
    aesctr_ivsetup(&cc->ac_ctx, iv);
368
    ret = 0;
369
    goto out;
370
  }
371
  ret = SSH_ERR_INVALID_ARGUMENT;
372
  goto out;
373
#else /* WITH_OPENSSL */
374
0
  type = (*cipher->evptype)();
375
0
  if ((cc->evp = EVP_CIPHER_CTX_new()) == NULL) {
376
0
    ret = SSH_ERR_ALLOC_FAIL;
377
0
    goto out;
378
0
  }
379
  /* the following block is for AES-CTR-MT cipher switching
380
   * if we are using the ctr cipher and we are post-auth then
381
   * start the threaded cipher. If OSSL supports providers (OSSL 3.0+) then
382
   * we load our hpnssh provider. If it doesn't (OSSL < 1.1) then we use the
383
   * _meth_new process found in cipher-ctr-mt.c */
384
0
  if (strstr(cc->cipher->name, "ctr") && enable_threads) {
385
#ifdef WITH_OPENSSL3
386
    /* this version of openssl uses providers */
387
    OSSL_LIB_CTX *aes_lib = NULL; /* probably not needed */
388
    OSSL_PROVIDER *aes_mt_provider = NULL;
389
    type = NULL;
390
391
    if (OSSL_PROVIDER_add_builtin(aes_lib, "hpnssh",
392
                OSSL_provider_init) != 1) {
393
      fatal("Failed to add HPNSSH provider for AES-CTR");
394
    }
395
    aes_mt_provider = OSSL_PROVIDER_load(aes_lib, "hpnssh");
396
397
    if (aes_mt_provider != NULL) {
398
      /* use the previous key length to determine which cipher to load */
399
      if (cipher->key_len == 32)
400
        type = EVP_CIPHER_fetch(aes_lib, "aes_ctr_mt_256", NULL);
401
      if (cipher->key_len == 24)
402
        type = EVP_CIPHER_fetch(aes_lib, "aes_ctr_mt_192", NULL);
403
      if (cipher->key_len == 16)
404
        type = EVP_CIPHER_fetch(aes_lib, "aes_ctr_mt_128", NULL);
405
      if (type == NULL) {
406
        ERR_print_errors_fp(stderr);
407
        fatal("FAILED TO LOAD aes_ctr_mt");
408
      } else {
409
        debug("LOADED aes_ctr_mt");
410
      }
411
    }
412
    else {
413
      ERR_print_errors_fp(stderr);
414
      fatal("Failed to load HPN-SSH AES-CTR-MT provider.");
415
    }
416
#else
417
0
    type = (*evp_aes_ctr_mt)(); /* see cipher-ctr-mt.c */
418
    /* we need to free this later if using aes_ctr_mt
419
     * under OSSL 1.1. Honestly, we could avoid this by making
420
     * it a global in cipher-ctr_mt.c and exporting it here
421
     * then we'd only have to call EVP_CIPHER_meth once but this
422
     * works for now. TODO: This. cjr 02.22.2023 */
423
0
    cc->meth_ptr = type;
424
0
#endif /* WITH_OPENSSL3 */
425
0
  } /* if (strstr()) */
426
0
  if (EVP_CipherInit(cc->evp, type, NULL, (u_char *)iv,
427
0
      (do_encrypt == CIPHER_ENCRYPT)) == 0) {
428
0
    ret = SSH_ERR_LIBCRYPTO_ERROR;
429
0
    goto out;
430
0
  }
431
0
  if (cipher_authlen(cipher) &&
432
0
      EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_IV_FIXED,
433
0
      -1, (u_char *)iv) <= 0) {
434
0
    ret = SSH_ERR_LIBCRYPTO_ERROR;
435
0
    goto out;
436
0
  }
437
0
  klen = EVP_CIPHER_CTX_key_length(cc->evp);
438
0
  if (klen > 0 && keylen != (u_int)klen) {
439
0
    if (EVP_CIPHER_CTX_set_key_length(cc->evp, keylen) == 0) {
440
0
      ret = SSH_ERR_LIBCRYPTO_ERROR;
441
0
      goto out;
442
0
    }
443
0
  }
444
0
  if (EVP_CipherInit(cc->evp, NULL, (u_char *)key, NULL, -1) == 0) {
445
0
    ret = SSH_ERR_LIBCRYPTO_ERROR;
446
0
    goto out;
447
0
  }
448
0
  ret = 0;
449
0
#endif /* WITH_OPENSSL */
450
132k
 out:
451
132k
  if (ret == 0) {
452
    /* success */
453
132k
    *ccp = cc;
454
132k
  } else {
455
0
    if (cc != NULL) {
456
0
#ifdef WITH_OPENSSL
457
0
      EVP_CIPHER_CTX_free(cc->evp);
458
0
#endif /* WITH_OPENSSL */
459
0
      freezero(cc, sizeof(*cc));
460
0
    }
461
0
  }
462
132k
  return ret;
463
0
}
464
465
/*
466
 * cipher_crypt() operates as following:
467
 * Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'.
468
 * These bytes are treated as additional authenticated data for
469
 * authenticated encryption modes.
470
 * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'.
471
 * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag.
472
 * This tag is written on encryption and verified on decryption.
473
 * Both 'aadlen' and 'authlen' can be set to 0.
474
 */
475
int
476
cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest,
477
   const u_char *src, u_int len, u_int aadlen, u_int authlen)
478
6.41M
{
479
6.41M
  if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
480
0
#ifdef WITH_OPENSSL
481
0
    if ((cc->cipher->flags & CFLAG_MT) != 0) {
482
0
      return chachapoly_crypt_mt(cc->cp_ctx_mt, seqnr, dest,
483
0
          src, len, aadlen, authlen, cc->encrypt);
484
0
    }
485
0
#endif
486
0
    return chachapoly_crypt(cc->cp_ctx, seqnr, dest, src,
487
0
        len, aadlen, authlen, cc->encrypt);
488
0
  }
489
6.41M
  if ((cc->cipher->flags & CFLAG_NONE) != 0) {
490
6.41M
    memcpy(dest, src, aadlen + len);
491
6.41M
    return 0;
492
6.41M
  }
493
#ifndef WITH_OPENSSL
494
  if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
495
    if (aadlen)
496
      memcpy(dest, src, aadlen);
497
    aesctr_encrypt_bytes(&cc->ac_ctx, src + aadlen, dest + aadlen,
498
        len);
499
    return 0;
500
  }
501
  return SSH_ERR_INVALID_ARGUMENT;
502
#else
503
0
  if (authlen) {
504
0
    u_char lastiv[1];
505
506
0
    if (authlen != cipher_authlen(cc->cipher))
507
0
      return SSH_ERR_INVALID_ARGUMENT;
508
    /* increment IV */
509
0
    if (EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN,
510
0
        1, lastiv) <= 0)
511
0
      return SSH_ERR_LIBCRYPTO_ERROR;
512
    /* set tag on decryption */
513
0
    if (!cc->encrypt &&
514
0
        EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_TAG,
515
0
        authlen, (u_char *)src + aadlen + len) <= 0)
516
0
      return SSH_ERR_LIBCRYPTO_ERROR;
517
0
  }
518
0
  if (aadlen) {
519
0
    if (authlen &&
520
0
        EVP_Cipher(cc->evp, NULL, (u_char *)src, aadlen) < 0)
521
0
      return SSH_ERR_LIBCRYPTO_ERROR;
522
0
    memcpy(dest, src, aadlen);
523
0
  }
524
0
  if (len % cc->cipher->block_size)
525
0
    return SSH_ERR_INVALID_ARGUMENT;
526
0
  if (EVP_Cipher(cc->evp, dest + aadlen, (u_char *)src + aadlen,
527
0
      len) < 0)
528
0
    return SSH_ERR_LIBCRYPTO_ERROR;
529
0
  if (authlen) {
530
    /* compute tag (on encrypt) or verify tag (on decrypt) */
531
0
    if (EVP_Cipher(cc->evp, NULL, NULL, 0) < 0)
532
0
      return cc->encrypt ?
533
0
          SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID;
534
0
    if (cc->encrypt &&
535
0
        EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_GET_TAG,
536
0
        authlen, dest + aadlen + len) <= 0)
537
0
      return SSH_ERR_LIBCRYPTO_ERROR;
538
0
  }
539
0
  return 0;
540
0
#endif
541
0
}
542
543
/* Extract the packet length, including any decryption necessary beforehand */
544
int
545
cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr,
546
    const u_char *cp, u_int len)
547
0
{
548
0
  if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
549
0
#ifdef WITH_OPENSSL
550
0
    if ((cc->cipher->flags & CFLAG_MT) != 0) {
551
0
      return chachapoly_get_length_mt(cc->cp_ctx_mt, plenp,
552
0
          seqnr, cp, len);
553
0
    }
554
0
#endif
555
0
    return chachapoly_get_length(cc->cp_ctx, plenp, seqnr,
556
0
        cp, len);
557
0
  }
558
0
  if (len < 4)
559
0
    return SSH_ERR_MESSAGE_INCOMPLETE;
560
0
  *plenp = PEEK_U32(cp);
561
0
  return 0;
562
0
}
563
564
void
565
cipher_free(struct sshcipher_ctx *cc)
566
132k
{
567
132k
  if (cc == NULL)
568
0
    return;
569
132k
  if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
570
0
#ifdef WITH_OPENSSL
571
0
    if ((cc->cipher->flags & CFLAG_MT) != 0) {
572
0
      chachapoly_free_mt(cc->cp_ctx_mt);
573
0
      cc->cp_ctx_mt = NULL;
574
0
    } else {
575
0
      chachapoly_free(cc->cp_ctx);
576
0
      cc->cp_ctx = NULL;
577
0
    }
578
#else
579
    chachapoly_free(cc->cp_ctx);
580
    cc->cp_ctx = NULL;
581
#endif
582
132k
  } else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
583
0
    explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx));
584
132k
#ifdef WITH_OPENSSL
585
132k
  EVP_CIPHER_CTX_free(cc->evp);
586
132k
  cc->evp = NULL;
587
  /* if meth_ptr isn't null then we are using the aes_ctr_mt
588
   * evp_cipher_meth_new() in cipher-ctr-mt.c under OSSL 1.1
589
   * if we don't explicitly free it then, even though we free
590
   * the ctx it is a part of it doesn't get freed. So...
591
   * cjr 2/7/2023
592
   */
593
132k
#if !defined(WITH_OPENSSL3)
594
132k
  if (cc->meth_ptr != NULL) {
595
0
    EVP_CIPHER_meth_free((void *)(EVP_CIPHER *)cc->meth_ptr);
596
0
    cc->meth_ptr = NULL;
597
0
  }
598
132k
#endif
599
132k
#endif
600
132k
  freezero(cc, sizeof(*cc));
601
132k
}
602
603
int
604
cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, size_t len)
605
0
{
606
0
#ifdef WITH_OPENSSL
607
0
  const struct sshcipher *c = cc->cipher;
608
0
  int evplen;
609
0
#endif
610
611
0
  if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
612
0
    if (len != 0)
613
0
      return SSH_ERR_INVALID_ARGUMENT;
614
0
    return 0;
615
0
  }
616
0
  if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
617
0
    if (len != sizeof(cc->ac_ctx.ctr))
618
0
      return SSH_ERR_INVALID_ARGUMENT;
619
0
    memcpy(iv, cc->ac_ctx.ctr, len);
620
0
    return 0;
621
0
  }
622
0
  if ((cc->cipher->flags & CFLAG_NONE) != 0)
623
0
    return 0;
624
625
0
#ifdef WITH_OPENSSL
626
0
  evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
627
0
  if (evplen == 0)
628
0
    return 0;
629
0
  else if (evplen < 0)
630
0
    return SSH_ERR_LIBCRYPTO_ERROR;
631
0
  if ((size_t)evplen != len)
632
0
    return SSH_ERR_INVALID_ARGUMENT;
633
0
  if (cipher_authlen(c)) {
634
0
    if (EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN, len,
635
0
        iv) <= 0)
636
0
      return SSH_ERR_LIBCRYPTO_ERROR;
637
0
  } else if (EVP_CIPHER_CTX_get_iv(cc->evp, iv, len) <= 0)
638
0
    return SSH_ERR_LIBCRYPTO_ERROR;
639
0
#endif
640
0
  return 0;
641
0
}