Coverage Report

Created: 2023-03-26 07:33

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