Coverage Report

Created: 2023-03-26 08:33

/src/gnutls/lib/algorithms/ciphers.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
3
 *
4
 * Author: Nikos Mavrogiannopoulos
5
 *
6
 * This file is part of GnuTLS.
7
 *
8
 * The GnuTLS is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public License
10
 * as published by the Free Software Foundation; either version 2.1 of
11
 * the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
20
 *
21
 */
22
23
#include "gnutls_int.h"
24
#include <algorithms.h>
25
#include "errors.h"
26
#include <x509/common.h>
27
#include "c-strcase.h"
28
29
/* Note that all algorithms are in CBC or STREAM modes.
30
 * Do not add any algorithms in other modes (avoid modified algorithms).
31
 * View first: "The order of encryption and authentication for
32
 * protecting communications" by Hugo Krawczyk - CRYPTO 2001
33
 *
34
 * On update, make sure to update MAX_CIPHER_BLOCK_SIZE, MAX_CIPHER_IV_SIZE,
35
 * and MAX_CIPHER_KEY_SIZE as well.
36
 * If any ciphers are removed, remove them from the back-end but
37
 * keep them in that list to allow backwards compatibility with applications
38
 * that specify them (they will be a no-op).
39
 */
40
static const cipher_entry_st algorithms[] = {
41
  {.name = "AES-256-CBC",
42
   .id = GNUTLS_CIPHER_AES_256_CBC,
43
   .blocksize = 16,
44
   .keysize = 32,
45
   .type = CIPHER_BLOCK,
46
   .explicit_iv = 16,
47
   .cipher_iv = 16},
48
  {.name = "AES-192-CBC",
49
   .id = GNUTLS_CIPHER_AES_192_CBC,
50
   .blocksize = 16,
51
   .keysize = 24,
52
   .type = CIPHER_BLOCK,
53
   .explicit_iv = 16,
54
   .cipher_iv = 16},
55
  {.name = "AES-128-CBC",
56
   .id = GNUTLS_CIPHER_AES_128_CBC,
57
   .blocksize = 16,
58
   .keysize = 16,
59
   .type = CIPHER_BLOCK,
60
   .explicit_iv = 16,
61
   .cipher_iv = 16},
62
  {.name = "AES-128-GCM",
63
   .id = GNUTLS_CIPHER_AES_128_GCM,
64
   .blocksize = 16,
65
   .keysize = 16,
66
   .type = CIPHER_AEAD,
67
   .implicit_iv = 4,
68
   .explicit_iv = 8,
69
   .cipher_iv = 12,
70
   .tagsize = 16},
71
  {.name = "AES-192-GCM",
72
   .id = GNUTLS_CIPHER_AES_192_GCM,
73
   .blocksize = 16,
74
   .keysize = 24,
75
   .type = CIPHER_AEAD,
76
   .implicit_iv = 4,
77
   .explicit_iv = 8,
78
   .cipher_iv = 12,
79
   .tagsize = 16},
80
  {.name = "AES-256-GCM",
81
   .id = GNUTLS_CIPHER_AES_256_GCM,
82
   .blocksize = 16,
83
   .keysize = 32,
84
   .type = CIPHER_AEAD,
85
   .implicit_iv = 4,
86
   .explicit_iv = 8,
87
   .cipher_iv = 12,
88
   .tagsize = 16},
89
  {.name = "AES-128-CCM",
90
   .id = GNUTLS_CIPHER_AES_128_CCM,
91
   .blocksize = 16,
92
   .keysize = 16,
93
   .type = CIPHER_AEAD,
94
   .implicit_iv = 4,
95
   .explicit_iv = 8,
96
   .cipher_iv = 12,
97
   .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD,
98
   .tagsize = 16},
99
  {.name = "AES-256-CCM",
100
   .id = GNUTLS_CIPHER_AES_256_CCM,
101
   .blocksize = 16,
102
   .keysize = 32,
103
   .type = CIPHER_AEAD,
104
   .implicit_iv = 4,
105
   .explicit_iv = 8,
106
   .cipher_iv = 12,
107
   .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD,
108
   .tagsize = 16},
109
  {.name = "AES-128-CCM-8",
110
   .id = GNUTLS_CIPHER_AES_128_CCM_8,
111
   .blocksize = 16,
112
   .keysize = 16,
113
   .type = CIPHER_AEAD,
114
   .implicit_iv = 4,
115
   .explicit_iv = 8,
116
   .cipher_iv = 12,
117
   .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD,
118
   .tagsize = 8},
119
  {.name = "AES-256-CCM-8",
120
   .id = GNUTLS_CIPHER_AES_256_CCM_8,
121
   .blocksize = 16,
122
   .keysize = 32,
123
   .type = CIPHER_AEAD,
124
   .implicit_iv = 4,
125
   .explicit_iv = 8,
126
   .cipher_iv = 12,
127
   .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD,
128
   .tagsize = 8},
129
  {.name = "ARCFOUR-128",
130
   .id = GNUTLS_CIPHER_ARCFOUR_128,
131
   .blocksize = 1,
132
   .keysize = 16,
133
   .type = CIPHER_STREAM,
134
   0, 0, 0, 0},
135
  {.name = "ESTREAM-SALSA20-256",
136
   .id = GNUTLS_CIPHER_ESTREAM_SALSA20_256,
137
   .blocksize = 64,
138
   .keysize = 32,
139
   .type = CIPHER_STREAM, 0, 0, 8, 0},
140
  {.name = "SALSA20-256",
141
   .id = GNUTLS_CIPHER_SALSA20_256,
142
   .blocksize = 64,
143
   .keysize = 32,
144
   .type = CIPHER_STREAM,
145
   .explicit_iv = 0,
146
   .cipher_iv = 8},
147
  {.name = "CHACHA20-32",
148
   .id = GNUTLS_CIPHER_CHACHA20_32,
149
   .blocksize = 64,
150
   .keysize = 32,
151
   .type = CIPHER_STREAM,
152
   .explicit_iv = 0,
153
   /* IV includes counter */
154
   .cipher_iv = 16},
155
  {.name = "CHACHA20-64",
156
   .id = GNUTLS_CIPHER_CHACHA20_64,
157
   .blocksize = 64,
158
   .keysize = 32,
159
   .type = CIPHER_STREAM,
160
   .explicit_iv = 0,
161
   /* IV includes counter */
162
   .cipher_iv = 16},
163
  {.name = "CAMELLIA-256-CBC",
164
   .id = GNUTLS_CIPHER_CAMELLIA_256_CBC,
165
   .blocksize = 16,
166
   .keysize = 32,
167
   .type = CIPHER_BLOCK,
168
   .explicit_iv = 16,
169
   .cipher_iv = 16},
170
  {.name = "CAMELLIA-192-CBC",
171
   .id = GNUTLS_CIPHER_CAMELLIA_192_CBC,
172
   .blocksize = 16,
173
   .keysize = 24,
174
   .type = CIPHER_BLOCK,
175
   .explicit_iv = 16,
176
   .cipher_iv = 16},
177
  {.name = "CAMELLIA-128-CBC",
178
   .id = GNUTLS_CIPHER_CAMELLIA_128_CBC,
179
   .blocksize = 16,
180
   .keysize = 16,
181
   .type = CIPHER_BLOCK,
182
   .explicit_iv = 16,
183
   .cipher_iv = 16},
184
  {.name = "CHACHA20-POLY1305",
185
   .id = GNUTLS_CIPHER_CHACHA20_POLY1305,
186
   .blocksize = 64,
187
   .keysize = 32,
188
   .type = CIPHER_AEAD,
189
   .implicit_iv = 12,
190
   .explicit_iv = 0,
191
   /* in chacha20 we don't need a rekey after 2^24 messages */
192
   .flags = GNUTLS_CIPHER_FLAG_XOR_NONCE | GNUTLS_CIPHER_FLAG_NO_REKEY,
193
   .cipher_iv = 12,
194
   .tagsize = 16},
195
  {.name = "CAMELLIA-128-GCM",
196
   .id = GNUTLS_CIPHER_CAMELLIA_128_GCM,
197
   .blocksize = 16,
198
   .keysize = 16,
199
   .type = CIPHER_AEAD, 4, 8, 12, 16},
200
  {.name = "CAMELLIA-256-GCM",
201
   .id = GNUTLS_CIPHER_CAMELLIA_256_GCM,
202
   .blocksize = 16,
203
   .keysize = 32,
204
   .type = CIPHER_AEAD,
205
   .implicit_iv = 4,
206
   .explicit_iv = 8,
207
   .cipher_iv = 12,
208
   .tagsize = 16},
209
  {.name = "GOST28147-TC26Z-CFB",
210
   .id = GNUTLS_CIPHER_GOST28147_TC26Z_CFB,
211
   .blocksize = 8,
212
   .keysize = 32,
213
   .type = CIPHER_STREAM,
214
   .implicit_iv = 8,
215
   .cipher_iv = 8},
216
  {.name = "GOST28147-CPA-CFB",
217
   .id = GNUTLS_CIPHER_GOST28147_CPA_CFB,
218
   .blocksize = 8,
219
   .keysize = 32,
220
   .type = CIPHER_STREAM,
221
   .implicit_iv = 8,
222
   .cipher_iv = 8},
223
  {.name = "GOST28147-CPB-CFB",
224
   .id = GNUTLS_CIPHER_GOST28147_CPB_CFB,
225
   .blocksize = 8,
226
   .keysize = 32,
227
   .type = CIPHER_STREAM,
228
   .implicit_iv = 8,
229
   .cipher_iv = 8},
230
  {.name = "GOST28147-CPC-CFB",
231
   .id = GNUTLS_CIPHER_GOST28147_CPC_CFB,
232
   .blocksize = 8,
233
   .keysize = 32,
234
   .type = CIPHER_STREAM,
235
   .implicit_iv = 8,
236
   .cipher_iv = 8},
237
  {.name = "GOST28147-CPD-CFB",
238
   .id = GNUTLS_CIPHER_GOST28147_CPD_CFB,
239
   .blocksize = 8,
240
   .keysize = 32,
241
   .type = CIPHER_STREAM,
242
   .implicit_iv = 8,
243
   .cipher_iv = 8},
244
245
  {.name = "AES-128-CFB8",
246
   .id = GNUTLS_CIPHER_AES_128_CFB8,
247
   .blocksize = 16,
248
   .keysize = 16,
249
   .type = CIPHER_BLOCK,
250
   .explicit_iv = 16,
251
   .cipher_iv = 16},
252
  {.name = "AES-192-CFB8",
253
   .id = GNUTLS_CIPHER_AES_192_CFB8,
254
   .blocksize = 16,
255
   .keysize = 24,
256
   .type = CIPHER_BLOCK,
257
   .explicit_iv = 16,
258
   .cipher_iv = 16},
259
  {.name = "AES-256-CFB8",
260
   .id = GNUTLS_CIPHER_AES_256_CFB8,
261
   .blocksize = 16,
262
   .keysize = 32,
263
   .type = CIPHER_BLOCK,
264
   .explicit_iv = 16,
265
   .cipher_iv = 16},
266
  {.name = "AES-128-XTS",
267
   .id = GNUTLS_CIPHER_AES_128_XTS,
268
   .blocksize = 16,
269
   .keysize = 32,
270
   .type = CIPHER_BLOCK,
271
   .explicit_iv = 16,
272
   .cipher_iv = 16},
273
  {.name = "AES-256-XTS",
274
   .id = GNUTLS_CIPHER_AES_256_XTS,
275
   .blocksize = 16,
276
   .keysize = 64,
277
   .type = CIPHER_BLOCK,
278
   .explicit_iv = 16,
279
   .cipher_iv = 16},
280
  {.name = "AES-128-SIV",
281
   .id = GNUTLS_CIPHER_AES_128_SIV,
282
   .blocksize = 16,
283
   .keysize = 32,
284
   .type = CIPHER_AEAD,
285
   .explicit_iv = 16,
286
   .cipher_iv = 16,
287
   .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD |
288
   GNUTLS_CIPHER_FLAG_TAG_PREFIXED,
289
   .tagsize = 16},
290
  {.name = "AES-256-SIV",
291
   .id = GNUTLS_CIPHER_AES_256_SIV,
292
   .blocksize = 16,
293
   .keysize = 64,
294
   .type = CIPHER_AEAD,
295
   .explicit_iv = 16,
296
   .cipher_iv = 16,
297
   .flags = GNUTLS_CIPHER_FLAG_ONLY_AEAD |
298
   GNUTLS_CIPHER_FLAG_TAG_PREFIXED,
299
   .tagsize = 16},
300
  {.name = "GOST28147-TC26Z-CNT",
301
   .id = GNUTLS_CIPHER_GOST28147_TC26Z_CNT,
302
   .blocksize = 8,
303
   .keysize = 32,
304
   .type = CIPHER_STREAM,
305
   .implicit_iv = 8,
306
   .cipher_iv = 8},
307
  {.name = "MAGMA-CTR-ACPKM",
308
   .id = GNUTLS_CIPHER_MAGMA_CTR_ACPKM,
309
   .blocksize = 8,
310
   .keysize = 32,
311
   .type = CIPHER_STREAM,
312
   .implicit_iv = 4,
313
   .cipher_iv = 8},
314
  {.name = "KUZNYECHIK-CTR-ACPKM",
315
   .id = GNUTLS_CIPHER_KUZNYECHIK_CTR_ACPKM,
316
   .blocksize = 16,
317
   .keysize = 32,
318
   .type = CIPHER_STREAM,
319
   .implicit_iv = 8,
320
   .cipher_iv = 16},
321
  {.name = "3DES-CBC",
322
   .id = GNUTLS_CIPHER_3DES_CBC,
323
   .blocksize = 8,
324
   .keysize = 24,
325
   .type = CIPHER_BLOCK,
326
   .explicit_iv = 8,
327
   .cipher_iv = 8},
328
  {.name = "DES-CBC",
329
   .id = GNUTLS_CIPHER_DES_CBC,
330
   .blocksize = 8,
331
   .keysize = 8,
332
   .type = CIPHER_BLOCK,
333
   .explicit_iv = 8,
334
   .cipher_iv = 8},
335
  {.name = "ARCFOUR-40",
336
   .id = GNUTLS_CIPHER_ARCFOUR_40,
337
   .blocksize = 1,
338
   .keysize = 5,
339
   .type = CIPHER_STREAM},
340
  {.name = "RC2-40",
341
   .id = GNUTLS_CIPHER_RC2_40_CBC,
342
   .blocksize = 8,
343
   .keysize = 5,
344
   .type = CIPHER_BLOCK,
345
   .explicit_iv = 8,
346
   .cipher_iv = 8},
347
  {.name = "NULL",
348
   .id = GNUTLS_CIPHER_NULL,
349
   .blocksize = 1,
350
   .keysize = 0,
351
   .type = CIPHER_STREAM},
352
  {0, 0, 0, 0, 0, 0, 0}
353
};
354
355
#define GNUTLS_CIPHER_LOOP(b) \
356
0
  const cipher_entry_st *p; \
357
0
    for(p = algorithms; p->name != NULL; p++) { b ; }
358
359
#define GNUTLS_ALG_LOOP(a) \
360
0
      GNUTLS_CIPHER_LOOP( if(p->id == algorithm) { a; break; } )
361
362
/* CIPHER functions */
363
364
const cipher_entry_st *_gnutls_cipher_to_entry(gnutls_cipher_algorithm_t c)
365
0
{
366
0
  GNUTLS_CIPHER_LOOP(if (c == p->id) return p) ;
367
368
0
  return NULL;
369
0
}
370
371
/* Returns cipher entry even for ciphers that are not supported,
372
 * but are listed (e.g., deprecated ciphers).
373
 */
374
const cipher_entry_st *cipher_name_to_entry(const char *name)
375
0
{
376
0
  GNUTLS_CIPHER_LOOP(if (c_strcasecmp(p->name, name) == 0) {
377
0
         return p;}
378
0
  ) ;
379
380
0
  return NULL;
381
0
}
382
383
/**
384
 * gnutls_cipher_get_block_size:
385
 * @algorithm: is an encryption algorithm
386
 *
387
 * Returns: the block size of the encryption algorithm.
388
 *
389
 * Since: 2.10.0
390
 **/
391
unsigned gnutls_cipher_get_block_size(gnutls_cipher_algorithm_t algorithm)
392
0
{
393
0
  size_t ret = 0;
394
0
  GNUTLS_ALG_LOOP(ret = p->blocksize);
395
0
  return ret;
396
397
0
}
398
399
/**
400
 * gnutls_cipher_get_tag_size:
401
 * @algorithm: is an encryption algorithm
402
 *
403
 * This function returns the tag size of an authenticated encryption
404
 * algorithm. For non-AEAD algorithms, it returns zero.
405
 *
406
 * Returns: the tag size of the authenticated encryption algorithm.
407
 *
408
 * Since: 3.2.2
409
 **/
410
unsigned gnutls_cipher_get_tag_size(gnutls_cipher_algorithm_t algorithm)
411
0
{
412
0
  return _gnutls_cipher_get_tag_size(cipher_to_entry(algorithm));
413
0
}
414
415
/**
416
 * gnutls_cipher_get_iv_size:
417
 * @algorithm: is an encryption algorithm
418
 *
419
 * This function returns the size of the initialization vector (IV) for the
420
 * provided algorithm. For algorithms with variable size IV (e.g., AES-CCM),
421
 * the returned size will be the one used by TLS.
422
 *
423
 * Returns: block size for encryption algorithm.
424
 *
425
 * Since: 3.2.0
426
 **/
427
unsigned gnutls_cipher_get_iv_size(gnutls_cipher_algorithm_t algorithm)
428
0
{
429
0
  size_t ret = 0;
430
0
  GNUTLS_ALG_LOOP(ret = p->cipher_iv);
431
0
  return ret;
432
0
}
433
434
/**
435
 * gnutls_cipher_get_key_size:
436
 * @algorithm: is an encryption algorithm
437
 *
438
 * This function returns the key size of the provided algorithm.
439
 *
440
 * Returns: length (in bytes) of the given cipher's key size, or 0 if
441
 *   the given cipher is invalid.
442
 **/
443
size_t gnutls_cipher_get_key_size(gnutls_cipher_algorithm_t algorithm)
444
0
{       /* In bytes */
445
0
  size_t ret = 0;
446
0
  GNUTLS_ALG_LOOP(ret = p->keysize);
447
0
  return ret;
448
449
0
}
450
451
/**
452
 * gnutls_cipher_get_name:
453
 * @algorithm: is an encryption algorithm
454
 *
455
 * Convert a #gnutls_cipher_algorithm_t type to a string.
456
 *
457
 * Returns: a pointer to a string that contains the name of the
458
 *   specified cipher, or %NULL.
459
 **/
460
const char *gnutls_cipher_get_name(gnutls_cipher_algorithm_t algorithm)
461
0
{
462
0
  const char *ret = NULL;
463
464
  /* avoid prefix */
465
0
  GNUTLS_ALG_LOOP(ret = p->name);
466
467
0
  return ret;
468
0
}
469
470
/**
471
 * gnutls_cipher_get_id:
472
 * @name: is a cipher algorithm name
473
 *
474
 * The names are compared in a case insensitive way.
475
 *
476
 * Returns: return a #gnutls_cipher_algorithm_t value corresponding to
477
 *   the specified cipher, or %GNUTLS_CIPHER_UNKNOWN on error.
478
 **/
479
gnutls_cipher_algorithm_t gnutls_cipher_get_id(const char *name)
480
0
{
481
0
  gnutls_cipher_algorithm_t ret = GNUTLS_CIPHER_UNKNOWN;
482
483
0
  GNUTLS_CIPHER_LOOP(if (c_strcasecmp(p->name, name) == 0) {
484
0
         if (p->id == GNUTLS_CIPHER_NULL
485
0
             || _gnutls_cipher_exists(p->id))
486
0
         ret = p->id; break;}
487
0
  ) ;
488
489
0
  return ret;
490
0
}
491
492
/**
493
 * gnutls_cipher_list:
494
 *
495
 * Get a list of supported cipher algorithms.  Note that not
496
 * necessarily all ciphers are supported as TLS cipher suites.  For
497
 * example, DES is not supported as a cipher suite, but is supported
498
 * for other purposes (e.g., PKCS#8 or similar).
499
 *
500
 * This function is not thread safe.
501
 *
502
 * Returns: a (0)-terminated list of #gnutls_cipher_algorithm_t
503
 *   integers indicating the available ciphers.
504
 *
505
 **/
506
const gnutls_cipher_algorithm_t *gnutls_cipher_list(void)
507
0
{
508
0
  static gnutls_cipher_algorithm_t supported_ciphers[MAX_ALGOS] = { 0 };
509
510
0
  if (supported_ciphers[0] == 0) {
511
0
    int i = 0;
512
513
0
    GNUTLS_CIPHER_LOOP(if
514
0
           (p->id == GNUTLS_CIPHER_NULL
515
0
            || _gnutls_cipher_exists(p->id))
516
0
           supported_ciphers[i++] = p->id;) ;
517
0
    supported_ciphers[i++] = 0;
518
0
  }
519
520
0
  return supported_ciphers;
521
0
}