Coverage Report

Created: 2025-07-23 07:16

/src/gnutls/lib/crypto-backend.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2008-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 "errors.h"
24
#include "gnutls_int.h"
25
#include <gnutls/crypto.h>
26
#include "crypto-backend.h"
27
#include "crypto.h"
28
#include "mpi.h"
29
#include "pk.h"
30
#include "random.h"
31
#include "cipher_int.h"
32
33
#ifdef ENABLE_PKCS11
34
#include "pkcs11/p11_provider.h"
35
#endif
36
37
/* default values for priorities */
38
int crypto_mac_prio = INT_MAX;
39
int crypto_digest_prio = INT_MAX;
40
int crypto_cipher_prio = INT_MAX;
41
42
typedef struct algo_list {
43
  int algorithm;
44
  int priority;
45
  void *alg_data;
46
  int free_alg_data;
47
  struct algo_list *next;
48
} algo_list;
49
50
0
#define cipher_list algo_list
51
#define mac_list algo_list
52
#define digest_list algo_list
53
54
static int _algo_register(algo_list *al, int algorithm, int priority, void *s,
55
        int free_s)
56
560
{
57
560
  algo_list *cl;
58
560
  algo_list *last_cl = al;
59
560
  int ret;
60
61
560
  if (al == NULL) {
62
0
    ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
63
0
    goto cleanup;
64
0
  }
65
66
  /* look if there is any cipher with lowest priority. In that case do not add.
67
   */
68
560
  cl = al;
69
2.58k
  while (cl && cl->alg_data) {
70
2.14k
    if (cl->algorithm == algorithm) {
71
120
      if (cl->priority < priority) {
72
0
        gnutls_assert();
73
0
        ret = GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
74
0
        goto cleanup;
75
120
      } else {
76
        /* the current has higher priority -> overwrite */
77
120
        cl->algorithm = algorithm;
78
120
        cl->priority = priority;
79
120
        cl->alg_data = s;
80
120
        cl->free_alg_data = free_s;
81
120
        return 0;
82
120
      }
83
120
    }
84
2.02k
    cl = cl->next;
85
2.02k
    if (cl)
86
2.02k
      last_cl = cl;
87
2.02k
  }
88
89
440
  cl = gnutls_calloc(1, sizeof(cipher_list));
90
91
440
  if (cl == NULL) {
92
0
    gnutls_assert();
93
0
    ret = GNUTLS_E_MEMORY_ERROR;
94
0
    goto cleanup;
95
0
  }
96
97
440
  last_cl->algorithm = algorithm;
98
440
  last_cl->priority = priority;
99
440
  last_cl->alg_data = s;
100
440
  last_cl->free_alg_data = free_s;
101
440
  last_cl->next = cl;
102
103
440
  return 0;
104
0
cleanup:
105
0
  if (free_s)
106
0
    gnutls_free(s);
107
0
  return ret;
108
440
}
109
110
static const void *_get_algo(algo_list *al, int algo)
111
0
{
112
0
  cipher_list *cl;
113
114
  /* look if there is any cipher with lowest priority. In that case do not add.
115
   */
116
0
  cl = al;
117
0
  while (cl && cl->alg_data) {
118
0
    if (cl->algorithm == algo) {
119
0
      return cl->alg_data;
120
0
    }
121
0
    cl = cl->next;
122
0
  }
123
124
0
  return NULL;
125
0
}
126
127
static cipher_list glob_cl = { GNUTLS_CIPHER_NULL, 0, NULL, 0, NULL };
128
static mac_list glob_ml = { GNUTLS_MAC_NULL, 0, NULL, 0, NULL };
129
static digest_list glob_dl = { GNUTLS_MAC_NULL, 0, NULL, 0, NULL };
130
131
static void _deregister(algo_list *cl)
132
0
{
133
0
  algo_list *next;
134
135
0
  next = cl->next;
136
0
  cl->next = NULL;
137
0
  cl = next;
138
139
0
  while (cl) {
140
0
    next = cl->next;
141
0
    if (cl->free_alg_data)
142
0
      gnutls_free(cl->alg_data);
143
0
    gnutls_free(cl);
144
0
    cl = next;
145
0
  }
146
0
}
147
148
void _gnutls_crypto_deregister(void)
149
0
{
150
0
  _deregister(&glob_cl);
151
0
  _deregister(&glob_ml);
152
0
  _deregister(&glob_dl);
153
0
}
154
155
extern gnutls_crypto_cipher_st _gnutls_cipher_ops;
156
extern gnutls_crypto_pk_st _gnutls_pk_ops;
157
extern gnutls_crypto_mac_st _gnutls_mac_ops;
158
extern gnutls_crypto_digest_st _gnutls_digest_ops;
159
extern gnutls_crypto_kdf_st _gnutls_kdf_ops;
160
161
#ifdef ENABLE_PKCS11
162
extern gnutls_crypto_cipher_st _gnutls_p11_cipher_ops;
163
extern gnutls_crypto_pk_st _gnutls_p11_pk_ops;
164
extern gnutls_crypto_mac_st _gnutls_p11_mac_ops;
165
extern gnutls_crypto_digest_st _gnutls_p11_digest_ops;
166
extern gnutls_crypto_kdf_st _gnutls_p11_kdf_ops;
167
#endif
168
169
const gnutls_crypto_cipher_st *_gnutls_cipher_backend(void)
170
0
{
171
#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
172
  if (_p11_provider_is_initialized())
173
    return &_gnutls_p11_cipher_ops;
174
#endif
175
0
  return &_gnutls_cipher_ops;
176
0
}
177
178
const gnutls_crypto_pk_st *_gnutls_pk_backend(void)
179
0
{
180
#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
181
  if (_p11_provider_is_initialized())
182
    return &_gnutls_p11_pk_ops;
183
#endif
184
0
  return &_gnutls_pk_ops;
185
0
}
186
187
const gnutls_crypto_mac_st *_gnutls_mac_backend(void)
188
0
{
189
#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
190
  if (_p11_provider_is_initialized())
191
    return &_gnutls_p11_mac_ops;
192
#endif
193
0
  return &_gnutls_mac_ops;
194
0
}
195
196
const gnutls_crypto_digest_st *_gnutls_digest_backend(void)
197
0
{
198
#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
199
  if (_p11_provider_is_initialized())
200
    return &_gnutls_p11_digest_ops;
201
#endif
202
0
  return &_gnutls_digest_ops;
203
0
}
204
205
const gnutls_crypto_kdf_st *_gnutls_kdf_backend(void)
206
0
{
207
#if defined(ENABLE_PKCS11) && defined(ENABLE_FIPS140)
208
  if (_p11_provider_is_initialized())
209
    return &_gnutls_p11_kdf_ops;
210
#endif
211
0
  return &_gnutls_kdf_ops;
212
0
}
213
214
/*-
215
 * gnutls_crypto_single_cipher_register:
216
 * @algorithm: is the gnutls algorithm identifier
217
 * @priority: is the priority of the algorithm
218
 * @s: is a structure holding new cipher's data
219
 *
220
 * This function will register a cipher algorithm to be used by
221
 * gnutls.  Any algorithm registered will override the included
222
 * algorithms and by convention kernel implemented algorithms have
223
 * priority of 90 and CPU-assisted of 80.  The algorithm with the lowest priority will be
224
 * used by gnutls.
225
 *
226
 * In the case the registered init or setkey functions return %GNUTLS_E_NEED_FALLBACK,
227
 * GnuTLS will attempt to use the next in priority registered cipher.
228
 *
229
 * This function should be called before gnutls_global_init().
230
 *
231
 * For simplicity you can use the convenience
232
 * gnutls_crypto_single_cipher_register() macro.
233
 *
234
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
235
 *
236
 * Since: 2.6.0
237
 -*/
238
int gnutls_crypto_single_cipher_register(gnutls_cipher_algorithm_t algorithm,
239
           int priority,
240
           const gnutls_crypto_cipher_st *s,
241
           int free_s)
242
360
{
243
  /* we override const in case free_s is set */
244
360
  return _algo_register(&glob_cl, algorithm, priority, (void *)s, free_s);
245
360
}
246
247
const gnutls_crypto_cipher_st *
248
_gnutls_get_crypto_cipher(gnutls_cipher_algorithm_t algo)
249
0
{
250
0
  return _get_algo(&glob_cl, algo);
251
0
}
252
253
/**
254
 * gnutls_crypto_register_cipher:
255
 * @algorithm: is the gnutls algorithm identifier
256
 * @priority: is the priority of the algorithm
257
 * @init: A function which initializes the cipher
258
 * @setkey: A function which sets the key of the cipher
259
 * @setiv: A function which sets the nonce/IV of the cipher (non-AEAD)
260
 * @encrypt: A function which performs encryption (non-AEAD)
261
 * @decrypt: A function which performs decryption (non-AEAD)
262
 * @deinit: A function which deinitializes the cipher
263
 *
264
 * This function will register a cipher algorithm to be used by
265
 * gnutls.  Any algorithm registered will override the included
266
 * algorithms and by convention kernel implemented algorithms have
267
 * priority of 90 and CPU-assisted of 80.  The algorithm with the lowest priority will be
268
 * used by gnutls.
269
 *
270
 * In the case the registered init or setkey functions return %GNUTLS_E_NEED_FALLBACK,
271
 * GnuTLS will attempt to use the next in priority registered cipher.
272
 *
273
 * The functions which are marked as non-AEAD they are not required when
274
 * registering a cipher to be used with the new AEAD API introduced in
275
 * GnuTLS 3.4.0. Internally GnuTLS uses the new AEAD API.
276
 *
277
 * Deprecated: since 3.7.0 it is no longer possible to override cipher implementation
278
 *
279
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
280
 *
281
 * Since: 3.4.0
282
 **/
283
int gnutls_crypto_register_cipher(gnutls_cipher_algorithm_t algorithm,
284
          int priority, gnutls_cipher_init_func init,
285
          gnutls_cipher_setkey_func setkey,
286
          gnutls_cipher_setiv_func setiv,
287
          gnutls_cipher_encrypt_func encrypt,
288
          gnutls_cipher_decrypt_func decrypt,
289
          gnutls_cipher_deinit_func deinit)
290
0
{
291
0
  _gnutls_debug_log(
292
0
    "called the deprecated gnutls_crypto_register_cipher()\n");
293
0
  return 0;
294
0
}
295
296
int _gnutls_crypto_register_cipher(gnutls_cipher_algorithm_t algorithm,
297
           int priority, gnutls_cipher_init_func init,
298
           gnutls_cipher_setkey_func setkey,
299
           gnutls_cipher_setiv_func setiv,
300
           gnutls_cipher_encrypt_func encrypt,
301
           gnutls_cipher_decrypt_func decrypt,
302
           gnutls_cipher_deinit_func deinit)
303
0
{
304
0
  gnutls_crypto_cipher_st *s =
305
0
    gnutls_calloc(1, sizeof(gnutls_crypto_cipher_st));
306
0
  if (s == NULL)
307
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
308
309
0
  s->init = init;
310
0
  s->setkey = setkey;
311
0
  s->setiv = setiv;
312
0
  s->encrypt = encrypt;
313
0
  s->decrypt = decrypt;
314
0
  s->deinit = deinit;
315
316
0
  return gnutls_crypto_single_cipher_register(algorithm, priority, s, 1);
317
0
}
318
319
/**
320
 * gnutls_crypto_register_aead_cipher:
321
 * @algorithm: is the gnutls AEAD cipher identifier
322
 * @priority: is the priority of the algorithm
323
 * @init: A function which initializes the cipher
324
 * @setkey: A function which sets the key of the cipher
325
 * @aead_encrypt: Perform the AEAD encryption
326
 * @aead_decrypt: Perform the AEAD decryption
327
 * @deinit: A function which deinitializes the cipher
328
 *
329
 * This function will register a cipher algorithm to be used by
330
 * gnutls.  Any algorithm registered will override the included
331
 * algorithms and by convention kernel implemented algorithms have
332
 * priority of 90 and CPU-assisted of 80.  The algorithm with the lowest priority will be
333
 * used by gnutls.
334
 *
335
 * In the case the registered init or setkey functions return %GNUTLS_E_NEED_FALLBACK,
336
 * GnuTLS will attempt to use the next in priority registered cipher.
337
 *
338
 * The functions registered will be used with the new AEAD API introduced in
339
 * GnuTLS 3.4.0. Internally GnuTLS uses the new AEAD API.
340
 *
341
 * Deprecated: since 3.7.0 it is no longer possible to override cipher implementation
342
 *
343
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
344
 *
345
 * Since: 3.4.0
346
 **/
347
int gnutls_crypto_register_aead_cipher(
348
  gnutls_cipher_algorithm_t algorithm, int priority,
349
  gnutls_cipher_init_func init, gnutls_cipher_setkey_func setkey,
350
  gnutls_cipher_aead_encrypt_func aead_encrypt,
351
  gnutls_cipher_aead_decrypt_func aead_decrypt,
352
  gnutls_cipher_deinit_func deinit)
353
0
{
354
0
  _gnutls_debug_log(
355
0
    "called the deprecated gnutls_crypto_register_aead_cipher()\n");
356
0
  return 0;
357
0
}
358
359
/*-
360
 * gnutls_crypto_rnd_register:
361
 * @priority: is the priority of the generator
362
 * @s: is a structure holding new generator's data
363
 *
364
 * This function will register a random generator to be used by
365
 * gnutls.  Any generator registered will override the included
366
 * generator and by convention kernel implemented generators have
367
 * priority of 90 and CPU-assisted of 80. The generator with the lowest priority will be
368
 * used by gnutls.
369
 *
370
 * This function should be called before gnutls_global_init().
371
 *
372
 * For simplicity you can use the convenience
373
 * gnutls_crypto_rnd_register() macro.
374
 *
375
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
376
 *
377
 * Since: 2.6.0
378
 -*/
379
int gnutls_crypto_rnd_register(int priority, const gnutls_crypto_rnd_st *s)
380
0
{
381
0
  if (crypto_rnd_prio >= priority) {
382
0
    memcpy(&_gnutls_rnd_ops, s, sizeof(*s));
383
0
    crypto_rnd_prio = priority;
384
0
    return 0;
385
0
  }
386
387
0
  return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
388
0
}
389
390
/*-
391
 * gnutls_crypto_single_mac_register:
392
 * @algorithm: is the gnutls algorithm identifier
393
 * @priority: is the priority of the algorithm
394
 * @s: is a structure holding new algorithms's data
395
 *
396
 * This function will register a MAC algorithm to be used by gnutls.
397
 * Any algorithm registered will override the included algorithms and
398
 * by convention kernel implemented algorithms have priority of 90
399
 *  and CPU-assisted of 80.
400
 * The algorithm with the lowest priority will be used by gnutls.
401
 *
402
 * This function should be called before gnutls_global_init().
403
 *
404
 * For simplicity you can use the convenience
405
 * gnutls_crypto_single_mac_register() macro.
406
 *
407
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
408
 *
409
 * Since: 2.6.0
410
 -*/
411
int gnutls_crypto_single_mac_register(gnutls_mac_algorithm_t algorithm,
412
              int priority,
413
              const gnutls_crypto_mac_st *s, int free_s)
414
100
{
415
100
  return _algo_register(&glob_ml, algorithm, priority, (void *)s, free_s);
416
100
}
417
418
const gnutls_crypto_mac_st *_gnutls_get_crypto_mac(gnutls_mac_algorithm_t algo)
419
0
{
420
0
  return _get_algo(&glob_ml, algo);
421
0
}
422
423
/*-
424
 * gnutls_crypto_single_digest_register:
425
 * @algorithm: is the gnutls algorithm identifier
426
 * @priority: is the priority of the algorithm
427
 * @s: is a structure holding new algorithms's data
428
 *
429
 * This function will register a digest (hash) algorithm to be used by
430
 * gnutls.  Any algorithm registered will override the included
431
 * algorithms and by convention kernel implemented algorithms have
432
 * priority of 90  and CPU-assisted of 80.  The algorithm with the lowest priority will be
433
 * used by gnutls.
434
 *
435
 * This function should be called before gnutls_global_init().
436
 *
437
 * For simplicity you can use the convenience
438
 * gnutls_crypto_single_digest_register() macro.
439
 *
440
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
441
 *
442
 * Since: 2.6.0
443
 -*/
444
int gnutls_crypto_single_digest_register(gnutls_digest_algorithm_t algorithm,
445
           int priority,
446
           const gnutls_crypto_digest_st *s,
447
           int free_s)
448
100
{
449
100
  return _algo_register(&glob_dl, algorithm, priority, (void *)s, free_s);
450
100
}
451
452
const gnutls_crypto_digest_st *
453
_gnutls_get_crypto_digest(gnutls_digest_algorithm_t algo)
454
0
{
455
0
  return _get_algo(&glob_dl, algo);
456
0
}
457
458
/**
459
 * gnutls_crypto_register_mac:
460
 * @algorithm: is the gnutls MAC identifier
461
 * @priority: is the priority of the algorithm
462
 * @init: A function which initializes the MAC
463
 * @setkey: A function which sets the key of the MAC
464
 * @setnonce: A function which sets the nonce for the mac (may be %NULL for common MAC algorithms)
465
 * @hash: Perform the hash operation
466
 * @output: Provide the output of the MAC
467
 * @deinit: A function which deinitializes the MAC
468
 * @hash_fast: Perform the MAC operation in one go
469
 *
470
 * This function will register a MAC algorithm to be used by gnutls.
471
 * Any algorithm registered will override the included algorithms and
472
 * by convention kernel implemented algorithms have priority of 90
473
 *  and CPU-assisted of 80.
474
 * The algorithm with the lowest priority will be used by gnutls.
475
 *
476
 * Deprecated: since 3.7.0 it is no longer possible to override cipher implementation
477
 *
478
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
479
 *
480
 * Since: 3.4.0
481
 **/
482
int gnutls_crypto_register_mac(gnutls_mac_algorithm_t algorithm, int priority,
483
             gnutls_mac_init_func init,
484
             gnutls_mac_setkey_func setkey,
485
             gnutls_mac_setnonce_func setnonce,
486
             gnutls_mac_hash_func hash,
487
             gnutls_mac_output_func output,
488
             gnutls_mac_deinit_func deinit,
489
             gnutls_mac_fast_func hash_fast)
490
0
{
491
0
  _gnutls_debug_log(
492
0
    "called the deprecated gnutls_crypto_register_mac()\n");
493
0
  return 0;
494
0
}
495
496
/**
497
 * gnutls_crypto_register_digest:
498
 * @algorithm: is the gnutls digest identifier
499
 * @priority: is the priority of the algorithm
500
 * @init: A function which initializes the digest
501
 * @hash: Perform the hash operation
502
 * @output: Provide the output of the digest
503
 * @deinit: A function which deinitializes the digest
504
 * @hash_fast: Perform the digest operation in one go
505
 *
506
 * This function will register a digest algorithm to be used by gnutls.
507
 * Any algorithm registered will override the included algorithms and
508
 * by convention kernel implemented algorithms have priority of 90
509
 *  and CPU-assisted of 80.
510
 * The algorithm with the lowest priority will be used by gnutls.
511
 *
512
 * Deprecated: since 3.7.0 it is no longer possible to override cipher implementation
513
 *
514
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
515
 *
516
 * Since: 3.4.0
517
 **/
518
int gnutls_crypto_register_digest(gnutls_digest_algorithm_t algorithm,
519
          int priority, gnutls_digest_init_func init,
520
          gnutls_digest_hash_func hash,
521
          gnutls_digest_output_func output,
522
          gnutls_digest_deinit_func deinit,
523
          gnutls_digest_fast_func hash_fast)
524
0
{
525
0
  _gnutls_debug_log(
526
0
    "called the deprecated gnutls_crypto_register_digest()\n");
527
0
  return 0;
528
0
}