/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 | } |