Fix CVE-2017-6891 in minitasn1 code
[platform/upstream/gnutls.git] / lib / crypto-backend.c
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 <http://www.gnu.org/licenses/>
20  *
21  */
22
23 #include <gnutls_errors.h>
24 #include <gnutls_int.h>
25 #include <gnutls/crypto.h>
26 #include <crypto-backend.h>
27 #include <crypto.h>
28 #include <gnutls_mpi.h>
29 #include <gnutls_pk.h>
30 #include <random.h>
31 #include <gnutls_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         const void *alg_data;
42         struct algo_list *next;
43 } algo_list;
44
45 #define cipher_list algo_list
46 #define mac_list algo_list
47 #define digest_list algo_list
48
49 static int
50 _algo_register(algo_list * al, int algorithm, int priority, const void *s)
51 {
52         algo_list *cl;
53         algo_list *last_cl = al;
54
55         if (al == NULL)
56                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
57
58         /* look if there is any cipher with lowest priority. In that case do not add.
59          */
60         cl = al;
61         while (cl && cl->alg_data) {
62                 if (cl->algorithm == algorithm) {
63                         if (cl->priority < priority) {
64                                 gnutls_assert();
65                                 return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
66                         } else {
67                                 /* the current has higher priority -> overwrite */
68                                 cl->algorithm = algorithm;
69                                 cl->priority = priority;
70                                 cl->alg_data = s;
71                                 return 0;
72                         }
73                 }
74                 cl = cl->next;
75                 if (cl)
76                         last_cl = cl;
77         }
78
79         cl = gnutls_calloc(1, sizeof(cipher_list));
80
81         if (cl == NULL) {
82                 gnutls_assert();
83                 return GNUTLS_E_MEMORY_ERROR;
84         }
85
86         last_cl->algorithm = algorithm;
87         last_cl->priority = priority;
88         last_cl->alg_data = s;
89         last_cl->next = cl;
90
91         return 0;
92
93 }
94
95 static const void *_get_algo(algo_list * al, int algo)
96 {
97         cipher_list *cl;
98
99         /* look if there is any cipher with lowest priority. In that case do not add.
100          */
101         cl = al;
102         while (cl && cl->alg_data) {
103                 if (cl->algorithm == algo) {
104                         return cl->alg_data;
105                 }
106                 cl = cl->next;
107         }
108
109         return NULL;
110 }
111
112 static cipher_list glob_cl = { GNUTLS_CIPHER_NULL, 0, NULL, NULL };
113 static mac_list glob_ml = { GNUTLS_MAC_NULL, 0, NULL, NULL };
114 static digest_list glob_dl = { GNUTLS_MAC_NULL, 0, NULL, NULL };
115
116 static void _deregister(algo_list * cl)
117 {
118         algo_list *next;
119
120         next = cl->next;
121         cl->next = NULL;
122         cl = next;
123
124         while (cl) {
125                 next = cl->next;
126                 gnutls_free(cl);
127                 cl = next;
128         }
129 }
130
131 void _gnutls_crypto_deregister(void)
132 {
133         _deregister(&glob_cl);
134         _deregister(&glob_ml);
135         _deregister(&glob_dl);
136 }
137
138 /*-
139  * gnutls_crypto_single_cipher_register:
140  * @algorithm: is the gnutls algorithm identifier
141  * @priority: is the priority of the algorithm
142  * @s: is a structure holding new cipher's data
143  *
144  * This function will register a cipher algorithm to be used by
145  * gnutls.  Any algorithm registered will override the included
146  * algorithms and by convention kernel implemented algorithms have
147  * priority of 90 and CPU-assisted of 80.  The algorithm with the lowest priority will be
148  * used by gnutls.
149  *
150  * This function should be called before gnutls_global_init().
151  *
152  * For simplicity you can use the convenience
153  * gnutls_crypto_single_cipher_register() macro.
154  *
155  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
156  *
157  * Since: 2.6.0
158  -*/
159 int
160 gnutls_crypto_single_cipher_register(gnutls_cipher_algorithm_t algorithm,
161                                      int priority,
162                                      const gnutls_crypto_cipher_st * s)
163 {
164         return _algo_register(&glob_cl, algorithm, priority, s);
165 }
166
167 const gnutls_crypto_cipher_st
168     *_gnutls_get_crypto_cipher(gnutls_cipher_algorithm_t algo)
169 {
170         return _get_algo(&glob_cl, algo);
171 }
172
173 /*-
174  * gnutls_crypto_rnd_register:
175  * @priority: is the priority of the generator
176  * @s: is a structure holding new generator's data
177  *
178  * This function will register a random generator to be used by
179  * gnutls.  Any generator registered will override the included
180  * generator and by convention kernel implemented generators have
181  * priority of 90 and CPU-assisted of 80. The generator with the lowest priority will be
182  * used by gnutls.
183  *
184  * This function should be called before gnutls_global_init().
185  *
186  * For simplicity you can use the convenience
187  * gnutls_crypto_rnd_register() macro.
188  *
189  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
190  *
191  * Since: 2.6.0
192  -*/
193 int
194 gnutls_crypto_rnd_register(int priority, const gnutls_crypto_rnd_st * s)
195 {
196         if (crypto_rnd_prio >= priority) {
197                 memcpy(&_gnutls_rnd_ops, s, sizeof(*s));
198                 crypto_rnd_prio = priority;
199                 return 0;
200         }
201
202         return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
203 }
204
205 /*-
206  * gnutls_crypto_single_mac_register:
207  * @algorithm: is the gnutls algorithm identifier
208  * @priority: is the priority of the algorithm
209  * @s: is a structure holding new algorithms's data
210  *
211  * This function will register a MAC algorithm to be used by gnutls.
212  * Any algorithm registered will override the included algorithms and
213  * by convention kernel implemented algorithms have priority of 90
214  *  and CPU-assisted of 80.
215  * The algorithm with the lowest priority will be used by gnutls.
216  *
217  * This function should be called before gnutls_global_init().
218  *
219  * For simplicity you can use the convenience
220  * gnutls_crypto_single_mac_register() macro.
221  *
222  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
223  *
224  * Since: 2.6.0
225  -*/
226 int
227 gnutls_crypto_single_mac_register(gnutls_mac_algorithm_t algorithm,
228                                   int priority,
229                                   const gnutls_crypto_mac_st * s)
230 {
231         return _algo_register(&glob_ml, algorithm, priority, s);
232 }
233
234 const gnutls_crypto_mac_st *_gnutls_get_crypto_mac(gnutls_mac_algorithm_t
235                                                    algo)
236 {
237         return _get_algo(&glob_ml, algo);
238 }
239
240 /*-
241  * gnutls_crypto_single_digest_register:
242  * @algorithm: is the gnutls algorithm identifier
243  * @priority: is the priority of the algorithm
244  * @s: is a structure holding new algorithms's data
245  *
246  * This function will register a digest (hash) algorithm to be used by
247  * gnutls.  Any algorithm registered will override the included
248  * algorithms and by convention kernel implemented algorithms have
249  * priority of 90  and CPU-assisted of 80.  The algorithm with the lowest priority will be
250  * used by gnutls.
251  *
252  * This function should be called before gnutls_global_init().
253  *
254  * For simplicity you can use the convenience
255  * gnutls_crypto_single_digest_register() macro.
256  *
257  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
258  *
259  * Since: 2.6.0
260  -*/
261 int
262 gnutls_crypto_single_digest_register(gnutls_digest_algorithm_t algorithm,
263                                      int priority,
264                                      const gnutls_crypto_digest_st * s)
265 {
266         return _algo_register(&glob_dl, algorithm, priority, s);
267 }
268
269 const gnutls_crypto_digest_st
270     *_gnutls_get_crypto_digest(gnutls_digest_algorithm_t algo)
271 {
272         return _get_algo(&glob_dl, algo);
273 }
274
275 /*-
276  * gnutls_crypto_bigint_register:
277  * @priority: is the priority of the interface
278  * @s: is a structure holding new interface's data
279  *
280  * This function will register an interface for gnutls to operate
281  * on big integers. Any interface registered will override
282  * the included interface. The interface with the lowest
283  * priority will be used by gnutls.
284  *
285  * Note that the bigint interface must interoperate with the public
286  * key interface. Thus if this interface is updated the
287  * gnutls_crypto_pk_register() should also be used.
288  *
289  * This function should be called before gnutls_global_init().
290  *
291  * For simplicity you can use the convenience gnutls_crypto_bigint_register()
292  * macro.
293  *
294  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
295  *
296  * Since: 2.6.0
297  -*/
298 int
299 gnutls_crypto_bigint_register(int priority,
300                               const gnutls_crypto_bigint_st * s)
301 {
302         if (crypto_bigint_prio > priority) {
303                 memcpy(&_gnutls_mpi_ops, s, sizeof(*s));
304                 crypto_bigint_prio = priority;
305                 return 0;
306         }
307
308         return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
309 }
310
311 /*-
312  * gnutls_crypto_pk_register:
313  * @priority: is the priority of the interface
314  * @s: is a structure holding new interface's data
315  *
316  * This function will register an interface for gnutls to operate
317  * on public key operations. Any interface registered will override
318  * the included interface. The interface with the lowest
319  * priority will be used by gnutls.
320  *
321  * Note that the bigint interface must interoperate with the bigint
322  * interface. Thus if this interface is updated the
323  * gnutls_crypto_bigint_register() should also be used.
324  *
325  * This function should be called before gnutls_global_init().
326  *
327  * For simplicity you can use the convenience gnutls_crypto_pk_register()
328  * macro.
329  *
330  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
331  *
332  * Since: 2.6.0
333  -*/
334 int gnutls_crypto_pk_register(int priority, const gnutls_crypto_pk_st * s)
335 {
336         if (crypto_pk_prio > priority) {
337                 memcpy(&_gnutls_pk_ops, s, sizeof(*s));
338                 crypto_pk_prio = priority;
339                 return 0;
340         }
341
342         return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
343 }
344
345 /*-
346  * gnutls_crypto_cipher_register:
347  * @priority: is the priority of the cipher interface
348  * @s: is a structure holding new interface's data
349  *
350  * This function will register a cipher interface to be used by
351  * gnutls. Any interface registered will override the included engine
352  * and by convention kernel implemented interfaces should have
353  * priority of 90  and CPU-assisted of 80. The interface with the lowest priority will be used
354  * by gnutls.
355  *
356  * This function should be called before gnutls_global_init().
357  *
358  * For simplicity you can use the convenience
359  * gnutls_crypto_cipher_register() macro.
360  *
361  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
362  *
363  * Since: 2.6.0
364  -*/
365 int
366 gnutls_crypto_cipher_register(int priority,
367                               const gnutls_crypto_cipher_st * s)
368 {
369         if (crypto_cipher_prio > priority) {
370                 memcpy(&_gnutls_cipher_ops, s, sizeof(*s));
371                 crypto_cipher_prio = priority;
372                 return 0;
373         }
374
375         return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
376 }
377
378 /*-
379  * gnutls_crypto_mac_register:
380  * @priority: is the priority of the mac interface
381  * @s: is a structure holding new interface's data
382  *
383  * This function will register a mac interface to be used by
384  * gnutls. Any interface registered will override the included engine
385  * and by convention kernel implemented interfaces should have
386  * priority of 90  and CPU-assisted of 80. The interface with the lowest priority will be used
387  * by gnutls.
388  *
389  * This function should be called before gnutls_global_init().
390  *
391  * For simplicity you can use the convenience
392  * gnutls_crypto_digest_register() macro.
393  *
394  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
395  *
396  * Since: 2.6.0
397  -*/
398 int
399 gnutls_crypto_mac_register(int priority, const gnutls_crypto_mac_st * s)
400 {
401         if (crypto_mac_prio > priority) {
402                 memcpy(&_gnutls_mac_ops, s, sizeof(*s));
403                 crypto_mac_prio = priority;
404                 return 0;
405         }
406
407         return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
408 }
409
410 /*-
411  * gnutls_crypto_digest_register:
412  * @priority: is the priority of the digest interface
413  * @s: is a structure holding new interface's data
414  *
415  * This function will register a digest interface to be used by
416  * gnutls. Any interface registered will override the included engine
417  * and by convention kernel implemented interfaces should have
418  * priority of 90  and CPU-assisted of 80. The interface with the lowest priority will be used
419  * by gnutls.
420  *
421  * This function should be called before gnutls_global_init().
422  *
423  * For simplicity you can use the convenience
424  * gnutls_crypto_digest_register() macro.
425  *
426  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
427  *
428  * Since: 2.6.0
429  -*/
430 int
431 gnutls_crypto_digest_register(int priority,
432                               const gnutls_crypto_digest_st * s)
433 {
434         if (crypto_digest_prio > priority) {
435                 memcpy(&_gnutls_digest_ops, s, sizeof(*s));
436                 crypto_digest_prio = priority;
437                 return 0;
438         }
439
440         return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
441 }