Coverage Report

Created: 2025-07-01 06:04

/src/hpn-ssh/cipher.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD: cipher.c,v 1.124 2025/03/14 09:49:49 tb 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
3.43M
#define CFLAG_CHACHAPOLY  (1<<1)
92
118k
#define CFLAG_AESCTR    (1<<2)
93
3.43M
#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 *tmp, *ret = NULL;
141
0
  size_t nlen, rlen = 0;
142
0
  const struct sshcipher *c;
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
    if (ret != NULL)
150
0
      ret[rlen++] = sep;
151
0
    nlen = strlen(c->name);
152
0
    if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
153
0
      free(ret);
154
0
      return NULL;
155
0
    }
156
0
    ret = tmp;
157
0
    memcpy(ret + rlen, c->name, nlen + 1);
158
0
    rlen += nlen;
159
0
  }
160
0
  return ret;
161
0
}
162
163
const char *
164
compression_alg_list(int compression)
165
0
{
166
0
#ifdef WITH_ZLIB
167
0
  return compression ? "zlib@openssh.com,none" :
168
0
      "none,zlib@openssh.com";
169
#else
170
  return "none";
171
#endif
172
0
}
173
174
/* used to get the cipher name when we are testing to
175
 * see if we can move from a serial to parallel cipher
176
 * only called in cipher-switch.c
177
 */
178
const char *
179
cipher_ctx_name(const struct sshcipher_ctx *cc)
180
0
{
181
0
        return cc->cipher->name;
182
0
}
183
184
u_int
185
cipher_blocksize(const struct sshcipher *c)
186
88
{
187
88
  return (c->block_size);
188
88
}
189
190
uint64_t
191
cipher_rekey_blocks(const struct sshcipher *c)
192
0
{
193
  /*
194
   * Chacha20-Poly1305 does not benefit from data-based rekeying,
195
   * per "The Security of ChaCha20-Poly1305 in the Multi-user Setting",
196
   * Degabriele, J. P., Govinden, J, Gunther, F. and Paterson K.
197
   * ACM CCS 2021; https://eprint.iacr.org/2023/085.pdf
198
   *
199
   * Cryptanalysis aside, we do still want do need to prevent the SSH
200
   * sequence number wrapping and also to rekey to provide some
201
   * protection for long lived sessions against key disclosure at the
202
   * endpoints, so arrange for rekeying every 2**32 blocks as the
203
   * 128-bit block ciphers do (i.e. every 32GB data).
204
   */
205
0
  if ((c->flags & CFLAG_CHACHAPOLY) != 0)
206
0
    return (uint64_t)1 << 32;
207
208
  /* there is no actual need to rekey the NULL cipher but
209
   * rekeying is a necessary step. In part, as mentioned above,
210
   * to keep the seqnr from wrapping. So we set it to the
211
   * maximum possible -cjr 4/10/23 */
212
0
  if ((c->flags & CFLAG_NONE) != 0)
213
0
    return (uint64_t)1 << 32;
214
215
  /*
216
   * The 2^(blocksize*2) limit is too expensive for 3DES,
217
   * so enforce a 1GB data limit for small blocksizes.
218
   * See discussion in RFC4344 section 3.2.
219
   */
220
0
  if (c->block_size < 16)
221
0
    return ((uint64_t)1 << 30) / c->block_size;
222
  /*
223
   * Otherwise, use the RFC4344 s3.2 recommendation of 2**(L/4) blocks
224
   * before rekeying where L is the blocksize in bits.
225
   * Most other ciphers have a 128 bit blocksize, so this equates to
226
   * 2**32 blocks / 64GB data.
227
   */
228
0
  return (uint64_t)1 << (c->block_size * 2);
229
0
}
230
231
u_int
232
cipher_keylen(const struct sshcipher *c)
233
88
{
234
88
  return (c->key_len);
235
88
}
236
237
u_int
238
cipher_seclen(const struct sshcipher *c)
239
0
{
240
0
  if (strcmp("3des-cbc", c->name) == 0)
241
0
    return 14;
242
0
  return cipher_keylen(c);
243
0
}
244
245
u_int
246
cipher_authlen(const struct sshcipher *c)
247
88
{
248
88
  return (c->auth_len);
249
88
}
250
251
u_int
252
cipher_ivlen(const struct sshcipher *c)
253
91
{
254
  /*
255
   * Default is cipher block size, except for chacha20+poly1305 that
256
   * needs no IV. XXX make iv_len == -1 default?
257
   */
258
91
  return (c->iv_len != 0 || (c->flags & CFLAG_CHACHAPOLY) != 0) ?
259
91
      c->iv_len : c->block_size;
260
91
}
261
262
u_int
263
cipher_is_cbc(const struct sshcipher *c)
264
0
{
265
0
  return (c->flags & CFLAG_CBC) != 0;
266
0
}
267
268
u_int
269
cipher_ctx_is_plaintext(struct sshcipher_ctx *cc)
270
0
{
271
0
  return cc->plaintext;
272
0
}
273
274
struct sshcipher *
275
cipher_by_name(const char *name)
276
59.4k
{
277
59.4k
  struct sshcipher *c;
278
713k
  for (c = ciphers; c->name != NULL; c++)
279
713k
    if (strcmp(c->name, name) == 0)
280
59.4k
      return c;
281
0
  return NULL;
282
59.4k
}
283
284
0
#define CIPHER_SEP  ","
285
int
286
ciphers_valid(const char *names)
287
0
{
288
0
  const struct sshcipher *c;
289
0
  char *cipher_list, *cp;
290
0
  char *p;
291
292
0
  if (names == NULL || strcmp(names, "") == 0)
293
0
    return 0;
294
0
  if ((cipher_list = cp = strdup(names)) == NULL)
295
0
    return 0;
296
0
  for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
297
0
      (p = strsep(&cp, CIPHER_SEP))) {
298
0
    c = cipher_by_name(p);
299
0
      if (c == NULL || ((c->flags & CFLAG_INTERNAL) != 0 &&
300
0
            (c->flags & CFLAG_NONE) != 0)) {
301
0
      free(cipher_list);
302
0
      return 0;
303
0
    }
304
0
  }
305
0
  free(cipher_list);
306
0
  return 1;
307
0
}
308
309
const char *
310
cipher_warning_message(const struct sshcipher_ctx *cc)
311
0
{
312
0
  if (cc == NULL || cc->cipher == NULL)
313
0
    return NULL;
314
  /* XXX repurpose for CBC warning */
315
0
  return NULL;
316
0
}
317
318
int
319
cipher_init(struct sshcipher_ctx **ccp, const struct sshcipher *cipher,
320
    const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
321
    u_int seqnr, int do_encrypt, int enable_threads)
322
118k
{
323
118k
  struct sshcipher_ctx *cc = NULL;
324
118k
  int ret = SSH_ERR_INTERNAL_ERROR;
325
118k
#ifdef WITH_OPENSSL
326
118k
  const EVP_CIPHER *type;
327
118k
  int klen;
328
118k
#endif
329
330
118k
  *ccp = NULL;
331
118k
  if ((cc = calloc(1, sizeof(*cc))) == NULL)
332
0
    return SSH_ERR_ALLOC_FAIL;
333
334
118k
  cc->plaintext = (cipher->flags & CFLAG_NONE) != 0;
335
118k
  cc->encrypt = do_encrypt;
336
118k
  cc->meth_ptr = NULL;
337
338
118k
  if (keylen < cipher->key_len ||
339
118k
      (iv != NULL && ivlen < cipher_ivlen(cipher))) {
340
0
    ret = SSH_ERR_INVALID_ARGUMENT;
341
0
    goto out;
342
0
  }
343
344
118k
  cc->cipher = cipher;
345
118k
  if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
346
0
#ifdef WITH_OPENSSL
347
0
    if ((cc->cipher->flags & CFLAG_MT) != 0) {
348
0
      cc->cp_ctx_mt = chachapoly_new_mt(seqnr, key, keylen);
349
0
      ret = cc->cp_ctx_mt != NULL ? 0 :
350
0
          SSH_ERR_INVALID_ARGUMENT;
351
0
    } else {
352
0
      cc->cp_ctx = chachapoly_new(key, keylen);
353
0
      ret = cc->cp_ctx != NULL ? 0 : SSH_ERR_INVALID_ARGUMENT;
354
0
    }
355
#else
356
    cc->cp_ctx = chachapoly_new(key, keylen);
357
    ret = cc->cp_ctx != NULL ? 0 : SSH_ERR_INVALID_ARGUMENT;
358
#endif
359
0
    goto out;
360
0
  }
361
118k
  if ((cc->cipher->flags & CFLAG_NONE) != 0) {
362
118k
    ret = 0;
363
118k
    goto out;
364
118k
  }
365
#ifndef WITH_OPENSSL
366
  if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
367
    aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen);
368
    aesctr_ivsetup(&cc->ac_ctx, iv);
369
    ret = 0;
370
    goto out;
371
  }
372
  ret = SSH_ERR_INVALID_ARGUMENT;
373
  goto out;
374
#else /* WITH_OPENSSL */
375
0
  type = (*cipher->evptype)();
376
0
  if ((cc->evp = EVP_CIPHER_CTX_new()) == NULL) {
377
0
    ret = SSH_ERR_ALLOC_FAIL;
378
0
    goto out;
379
0
  }
380
  /* the following block is for AES-CTR-MT cipher switching
381
   * if we are using the ctr cipher and we are post-auth then
382
   * start the threaded cipher. If OSSL supports providers (OSSL 3.0+) then
383
   * we load our hpnssh provider. If it doesn't (OSSL < 1.1) then we use the
384
   * _meth_new process found in cipher-ctr-mt.c */
385
0
  if (strstr(cc->cipher->name, "ctr") && enable_threads) {
386
#ifdef WITH_OPENSSL3
387
    /* this version of openssl uses providers */
388
    OSSL_LIB_CTX *aes_lib = NULL; /* probably not needed */
389
    OSSL_PROVIDER *aes_mt_provider = NULL;
390
    type = NULL;
391
392
    if (OSSL_PROVIDER_add_builtin(aes_lib, "hpnssh",
393
                OSSL_provider_init) != 1) {
394
      fatal("Failed to add HPNSSH provider for AES-CTR");
395
    }
396
    aes_mt_provider = OSSL_PROVIDER_load(aes_lib, "hpnssh");
397
398
    if (aes_mt_provider != NULL) {
399
      /* use the previous key length to determine which cipher to load */
400
      if (cipher->key_len == 32)
401
        type = EVP_CIPHER_fetch(aes_lib, "aes_ctr_mt_256", NULL);
402
      if (cipher->key_len == 24)
403
        type = EVP_CIPHER_fetch(aes_lib, "aes_ctr_mt_192", NULL);
404
      if (cipher->key_len == 16)
405
        type = EVP_CIPHER_fetch(aes_lib, "aes_ctr_mt_128", NULL);
406
      if (type == NULL) {
407
        ERR_print_errors_fp(stderr);
408
        fatal("FAILED TO LOAD aes_ctr_mt");
409
      } else {
410
        debug("LOADED aes_ctr_mt");
411
      }
412
    }
413
    else {
414
      ERR_print_errors_fp(stderr);
415
      fatal("Failed to load HPN-SSH AES-CTR-MT provider.");
416
    }
417
#else
418
0
    type = (*evp_aes_ctr_mt)(); /* see cipher-ctr-mt.c */
419
    /* we need to free this later if using aes_ctr_mt
420
     * under OSSL 1.1. Honestly, we could avoid this by making
421
     * it a global in cipher-ctr_mt.c and exporting it here
422
     * then we'd only have to call EVP_CIPHER_meth once but this
423
     * works for now. TODO: This. cjr 02.22.2023 */
424
0
    cc->meth_ptr = type;
425
0
#endif /* WITH_OPENSSL3 */
426
0
  } /* if (strstr()) */
427
0
  if (EVP_CipherInit(cc->evp, type, NULL, (u_char *)iv,
428
0
      (do_encrypt == CIPHER_ENCRYPT)) == 0) {
429
0
    ret = SSH_ERR_LIBCRYPTO_ERROR;
430
0
    goto out;
431
0
  }
432
0
  if (cipher_authlen(cipher) &&
433
0
      EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_IV_FIXED,
434
0
      -1, (u_char *)iv) <= 0) {
435
0
    ret = SSH_ERR_LIBCRYPTO_ERROR;
436
0
    goto out;
437
0
  }
438
0
  klen = EVP_CIPHER_CTX_key_length(cc->evp);
439
0
  if (klen > 0 && keylen != (u_int)klen) {
440
0
    if (EVP_CIPHER_CTX_set_key_length(cc->evp, keylen) == 0) {
441
0
      ret = SSH_ERR_LIBCRYPTO_ERROR;
442
0
      goto out;
443
0
    }
444
0
  }
445
0
  if (EVP_CipherInit(cc->evp, NULL, (u_char *)key, NULL, -1) == 0) {
446
0
    ret = SSH_ERR_LIBCRYPTO_ERROR;
447
0
    goto out;
448
0
  }
449
0
  ret = 0;
450
0
#endif /* WITH_OPENSSL */
451
118k
 out:
452
118k
  if (ret == 0) {
453
    /* success */
454
118k
    *ccp = cc;
455
118k
  } else {
456
0
    if (cc != NULL) {
457
0
#ifdef WITH_OPENSSL
458
0
      EVP_CIPHER_CTX_free(cc->evp);
459
0
#endif /* WITH_OPENSSL */
460
0
      freezero(cc, sizeof(*cc));
461
0
    }
462
0
  }
463
118k
  return ret;
464
0
}
465
466
/*
467
 * cipher_crypt() operates as following:
468
 * Copy 'aadlen' bytes (without en/decryption) from 'src' to 'dest'.
469
 * These bytes are treated as additional authenticated data for
470
 * authenticated encryption modes.
471
 * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'.
472
 * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag.
473
 * This tag is written on encryption and verified on decryption.
474
 * Both 'aadlen' and 'authlen' can be set to 0.
475
 */
476
int
477
cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest,
478
   const u_char *src, u_int len, u_int aadlen, u_int authlen)
479
3.20M
{
480
3.20M
  if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
481
0
#ifdef WITH_OPENSSL
482
0
    if ((cc->cipher->flags & CFLAG_MT) != 0) {
483
0
      return chachapoly_crypt_mt(cc->cp_ctx_mt, seqnr, dest,
484
0
          src, len, aadlen, authlen, cc->encrypt);
485
0
    }
486
0
#endif
487
0
    return chachapoly_crypt(cc->cp_ctx, seqnr, dest, src,
488
0
        len, aadlen, authlen, cc->encrypt);
489
0
  }
490
3.20M
  if ((cc->cipher->flags & CFLAG_NONE) != 0) {
491
3.20M
    memcpy(dest, src, aadlen + len);
492
3.20M
    return 0;
493
3.20M
  }
494
#ifndef WITH_OPENSSL
495
  if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
496
    if (aadlen)
497
      memcpy(dest, src, aadlen);
498
    aesctr_encrypt_bytes(&cc->ac_ctx, src + aadlen, dest + aadlen,
499
        len);
500
    return 0;
501
  }
502
  return SSH_ERR_INVALID_ARGUMENT;
503
#else
504
0
  if (authlen) {
505
0
    u_char lastiv[1];
506
507
0
    if (authlen != cipher_authlen(cc->cipher))
508
0
      return SSH_ERR_INVALID_ARGUMENT;
509
    /* increment IV */
510
0
    if (EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN,
511
0
        1, lastiv) <= 0)
512
0
      return SSH_ERR_LIBCRYPTO_ERROR;
513
    /* set tag on decryption */
514
0
    if (!cc->encrypt &&
515
0
        EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_SET_TAG,
516
0
        authlen, (u_char *)src + aadlen + len) <= 0)
517
0
      return SSH_ERR_LIBCRYPTO_ERROR;
518
0
  }
519
0
  if (aadlen) {
520
0
    if (authlen &&
521
0
        EVP_Cipher(cc->evp, NULL, (u_char *)src, aadlen) < 0)
522
0
      return SSH_ERR_LIBCRYPTO_ERROR;
523
0
    memcpy(dest, src, aadlen);
524
0
  }
525
0
  if (len % cc->cipher->block_size)
526
0
    return SSH_ERR_INVALID_ARGUMENT;
527
0
  if (EVP_Cipher(cc->evp, dest + aadlen, (u_char *)src + aadlen,
528
0
      len) < 0)
529
0
    return SSH_ERR_LIBCRYPTO_ERROR;
530
0
  if (authlen) {
531
    /* compute tag (on encrypt) or verify tag (on decrypt) */
532
0
    if (EVP_Cipher(cc->evp, NULL, NULL, 0) < 0)
533
0
      return cc->encrypt ?
534
0
          SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID;
535
0
    if (cc->encrypt &&
536
0
        EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_GET_TAG,
537
0
        authlen, dest + aadlen + len) <= 0)
538
0
      return SSH_ERR_LIBCRYPTO_ERROR;
539
0
  }
540
0
  return 0;
541
0
#endif
542
0
}
543
544
/* Extract the packet length, including any decryption necessary beforehand */
545
int
546
cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr,
547
    const u_char *cp, u_int len)
548
0
{
549
0
  if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
550
0
#ifdef WITH_OPENSSL
551
0
    if ((cc->cipher->flags & CFLAG_MT) != 0) {
552
0
      return chachapoly_get_length_mt(cc->cp_ctx_mt, plenp,
553
0
          seqnr, cp, len);
554
0
    }
555
0
#endif
556
0
    return chachapoly_get_length(cc->cp_ctx, plenp, seqnr,
557
0
        cp, len);
558
0
  }
559
0
  if (len < 4)
560
0
    return SSH_ERR_MESSAGE_INCOMPLETE;
561
0
  *plenp = PEEK_U32(cp);
562
0
  return 0;
563
0
}
564
565
void
566
cipher_free(struct sshcipher_ctx *cc)
567
118k
{
568
118k
  if (cc == NULL)
569
0
    return;
570
118k
  if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
571
0
#ifdef WITH_OPENSSL
572
0
    if ((cc->cipher->flags & CFLAG_MT) != 0) {
573
0
      chachapoly_free_mt(cc->cp_ctx_mt);
574
0
      cc->cp_ctx_mt = NULL;
575
0
    } else {
576
0
      chachapoly_free(cc->cp_ctx);
577
0
      cc->cp_ctx = NULL;
578
0
    }
579
#else
580
    chachapoly_free(cc->cp_ctx);
581
    cc->cp_ctx = NULL;
582
#endif
583
118k
  } else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
584
0
    explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx));
585
118k
#ifdef WITH_OPENSSL
586
118k
  EVP_CIPHER_CTX_free(cc->evp);
587
118k
  cc->evp = NULL;
588
  /* if meth_ptr isn't null then we are using the aes_ctr_mt
589
   * evp_cipher_meth_new() in cipher-ctr-mt.c under OSSL 1.1
590
   * if we don't explicitly free it then, even though we free
591
   * the ctx it is a part of it doesn't get freed. So...
592
   * cjr 2/7/2023
593
   */
594
118k
  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
118k
#endif
599
118k
  freezero(cc, sizeof(*cc));
600
118k
}
601
602
int
603
cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, size_t len)
604
0
{
605
0
#ifdef WITH_OPENSSL
606
0
  const struct sshcipher *c = cc->cipher;
607
0
  int evplen;
608
0
#endif
609
610
0
  if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
611
0
    if (len != 0)
612
0
      return SSH_ERR_INVALID_ARGUMENT;
613
0
    return 0;
614
0
  }
615
0
  if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
616
0
    if (len != sizeof(cc->ac_ctx.ctr))
617
0
      return SSH_ERR_INVALID_ARGUMENT;
618
0
    memcpy(iv, cc->ac_ctx.ctr, len);
619
0
    return 0;
620
0
  }
621
0
  if ((cc->cipher->flags & CFLAG_NONE) != 0)
622
0
    return 0;
623
624
0
#ifdef WITH_OPENSSL
625
0
  evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
626
0
  if (evplen == 0)
627
0
    return 0;
628
0
  else if (evplen < 0)
629
0
    return SSH_ERR_LIBCRYPTO_ERROR;
630
0
  if ((size_t)evplen != len)
631
0
    return SSH_ERR_INVALID_ARGUMENT;
632
0
  if (cipher_authlen(c)) {
633
0
    if (EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN, len,
634
0
        iv) <= 0)
635
0
      return SSH_ERR_LIBCRYPTO_ERROR;
636
0
  } else if (EVP_CIPHER_CTX_get_iv(cc->evp, iv, len) <= 0)
637
0
    return SSH_ERR_LIBCRYPTO_ERROR;
638
0
#endif
639
0
  return 0;
640
0
}
641
642
int
643
cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv, size_t len)
644
0
{
645
0
#ifdef WITH_OPENSSL
646
0
  const struct sshcipher *c = cc->cipher;
647
0
  int evplen = 0;
648
0
#endif
649
650
0
  if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
651
0
    return 0;
652
0
  if ((cc->cipher->flags & CFLAG_NONE) != 0)
653
0
    return 0;
654
655
0
#ifdef WITH_OPENSSL
656
0
  evplen = EVP_CIPHER_CTX_iv_length(cc->evp);
657
0
  if (evplen <= 0)
658
0
    return SSH_ERR_LIBCRYPTO_ERROR;
659
0
  if ((size_t)evplen != len)
660
0
    return SSH_ERR_INVALID_ARGUMENT;
661
0
  if (cipher_authlen(c)) {
662
    /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */
663
0
    if (EVP_CIPHER_CTX_ctrl(cc->evp,
664
0
        EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv) <= 0)
665
0
      return SSH_ERR_LIBCRYPTO_ERROR;
666
0
  } else if (!EVP_CIPHER_CTX_set_iv(cc->evp, iv, evplen))
667
0
    return SSH_ERR_LIBCRYPTO_ERROR;
668
0
#endif
669
0
  return 0;
670
0
}