Corrected bugs in record parsing.
[gnutls.git] / lib / crypto-backend.c
blob93fb799d45555a803655ce6747ad43e8a6384f5d
1 /*
2 * Copyright (C) 2008-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
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 3 of
11 * the License, or (at your option) any later version.
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.
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/>
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>
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;
38 typedef struct algo_list
40 int algorithm;
41 int priority;
42 const void *alg_data;
43 struct algo_list *next;
44 } algo_list;
46 #define cipher_list algo_list
47 #define mac_list algo_list
48 #define digest_list algo_list
50 static int
51 _algo_register (algo_list * al, int algorithm, int priority, const void *s)
53 algo_list *cl;
54 algo_list *last_cl = al;
56 if (al == NULL)
57 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
59 /* look if there is any cipher with lowest priority. In that case do not add.
61 cl = al;
62 while (cl && cl->alg_data)
64 if (cl->algorithm == algorithm)
66 if (cl->priority < priority)
68 gnutls_assert ();
69 return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
71 else
73 /* the current has higher priority -> overwrite */
74 cl->algorithm = algorithm;
75 cl->priority = priority;
76 cl->alg_data = s;
77 return 0;
80 cl = cl->next;
81 if (cl)
82 last_cl = cl;
85 cl = gnutls_calloc (1, sizeof (cipher_list));
87 if (cl == NULL)
89 gnutls_assert ();
90 return GNUTLS_E_MEMORY_ERROR;
93 last_cl->algorithm = algorithm;
94 last_cl->priority = priority;
95 last_cl->alg_data = s;
96 last_cl->next = cl;
98 return 0;
102 static const void *
103 _get_algo (algo_list * al, int algo)
105 cipher_list *cl;
107 /* look if there is any cipher with lowest priority. In that case do not add.
109 cl = al;
110 while (cl && cl->alg_data)
112 if (cl->algorithm == algo)
114 return cl->alg_data;
116 cl = cl->next;
119 return NULL;
122 static cipher_list glob_cl = { GNUTLS_CIPHER_NULL, 0, NULL, NULL };
123 static mac_list glob_ml = { GNUTLS_MAC_NULL, 0, NULL, NULL };
124 static digest_list glob_dl = { GNUTLS_MAC_NULL, 0, NULL, NULL };
126 static void
127 _deregister (algo_list * cl)
129 algo_list *next;
131 next = cl->next;
132 cl->next = NULL;
133 cl = next;
135 while (cl)
137 next = cl->next;
138 gnutls_free (cl);
139 cl = next;
143 void
144 _gnutls_crypto_deregister (void)
146 _deregister (&glob_cl);
147 _deregister (&glob_ml);
148 _deregister (&glob_dl);
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
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.
163 * This function should be called before gnutls_global_init().
165 * For simplicity you can use the convenience
166 * gnutls_crypto_single_cipher_register() macro.
168 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
170 * Since: 2.6.0
173 gnutls_crypto_single_cipher_register (gnutls_cipher_algorithm_t algorithm,
174 int priority,
175 const gnutls_crypto_cipher_st * s)
177 return _algo_register (&glob_cl, algorithm, priority, s);
180 const gnutls_crypto_cipher_st *
181 _gnutls_get_crypto_cipher (gnutls_cipher_algorithm_t algo)
183 return _get_algo (&glob_cl, algo);
187 * gnutls_crypto_rnd_register:
188 * @priority: is the priority of the generator
189 * @s: is a structure holding new generator's data
191 * This function will register a random generator to be used by
192 * gnutls. Any generator registered will override the included
193 * generator and by convention kernel implemented generators have
194 * priority of 90 and CPU-assisted of 80. The generator with the lowest priority will be
195 * used by gnutls.
197 * This function should be called before gnutls_global_init().
199 * For simplicity you can use the convenience
200 * gnutls_crypto_rnd_register() macro.
202 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
204 * Since: 2.6.0
207 gnutls_crypto_rnd_register (int priority,
208 const gnutls_crypto_rnd_st * s)
210 if (crypto_rnd_prio > priority)
212 memcpy (&_gnutls_rnd_ops, s, sizeof (*s));
213 crypto_rnd_prio = priority;
214 return 0;
217 return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
221 * gnutls_crypto_single_mac_register:
222 * @algorithm: is the gnutls algorithm identifier
223 * @priority: is the priority of the algorithm
224 * @s: is a structure holding new algorithms's data
226 * This function will register a MAC algorithm to be used by gnutls.
227 * Any algorithm registered will override the included algorithms and
228 * by convention kernel implemented algorithms have priority of 90
229 * and CPU-assisted of 80.
230 * The algorithm with the lowest priority will be used by gnutls.
232 * This function should be called before gnutls_global_init().
234 * For simplicity you can use the convenience
235 * gnutls_crypto_single_mac_register() macro.
237 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
239 * Since: 2.6.0
242 gnutls_crypto_single_mac_register (gnutls_mac_algorithm_t algorithm,
243 int priority,
244 const gnutls_crypto_mac_st * s)
246 return _algo_register (&glob_ml, algorithm, priority, s);
249 const gnutls_crypto_mac_st *
250 _gnutls_get_crypto_mac (gnutls_mac_algorithm_t algo)
252 return _get_algo (&glob_ml, algo);
256 * gnutls_crypto_single_digest_register:
257 * @algorithm: is the gnutls algorithm identifier
258 * @priority: is the priority of the algorithm
259 * @s: is a structure holding new algorithms's data
261 * This function will register a digest (hash) algorithm to be used by
262 * gnutls. Any algorithm registered will override the included
263 * algorithms and by convention kernel implemented algorithms have
264 * priority of 90 and CPU-assisted of 80. The algorithm with the lowest priority will be
265 * used by gnutls.
267 * This function should be called before gnutls_global_init().
269 * For simplicity you can use the convenience
270 * gnutls_crypto_single_digest_register() macro.
272 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
274 * Since: 2.6.0
277 gnutls_crypto_single_digest_register (gnutls_digest_algorithm_t algorithm,
278 int priority,
279 const gnutls_crypto_digest_st * s)
281 return _algo_register (&glob_dl, algorithm, priority, s);
284 const gnutls_crypto_digest_st *
285 _gnutls_get_crypto_digest (gnutls_digest_algorithm_t algo)
287 return _get_algo (&glob_dl, algo);
291 * gnutls_crypto_bigint_register:
292 * @priority: is the priority of the interface
293 * @s: is a structure holding new interface's data
295 * This function will register an interface for gnutls to operate
296 * on big integers. Any interface registered will override
297 * the included interface. The interface with the lowest
298 * priority will be used by gnutls.
300 * Note that the bigint interface must interoperate with the public
301 * key interface. Thus if this interface is updated the
302 * gnutls_crypto_pk_register() should also be used.
304 * This function should be called before gnutls_global_init().
306 * For simplicity you can use the convenience gnutls_crypto_bigint_register()
307 * macro.
309 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
311 * Since: 2.6.0
314 gnutls_crypto_bigint_register (int priority,
315 const gnutls_crypto_bigint_st * s)
317 if (crypto_bigint_prio > priority)
319 memcpy (&_gnutls_mpi_ops, s, sizeof (*s));
320 crypto_bigint_prio = priority;
321 return 0;
324 return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
328 * gnutls_crypto_pk_register:
329 * @priority: is the priority of the interface
330 * @s: is a structure holding new interface's data
332 * This function will register an interface for gnutls to operate
333 * on public key operations. Any interface registered will override
334 * the included interface. The interface with the lowest
335 * priority will be used by gnutls.
337 * Note that the bigint interface must interoperate with the bigint
338 * interface. Thus if this interface is updated the
339 * gnutls_crypto_bigint_register() should also be used.
341 * This function should be called before gnutls_global_init().
343 * For simplicity you can use the convenience gnutls_crypto_pk_register()
344 * macro.
346 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
348 * Since: 2.6.0
351 gnutls_crypto_pk_register (int priority,
352 const gnutls_crypto_pk_st * s)
354 if (crypto_pk_prio > priority)
356 memcpy (&_gnutls_pk_ops, s, sizeof (*s));
357 crypto_pk_prio = priority;
358 return 0;
361 return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
365 * gnutls_crypto_cipher_register:
366 * @priority: is the priority of the cipher interface
367 * @s: is a structure holding new interface's data
369 * This function will register a cipher interface to be used by
370 * gnutls. Any interface registered will override the included engine
371 * and by convention kernel implemented interfaces should have
372 * priority of 90 and CPU-assisted of 80. The interface with the lowest priority will be used
373 * by gnutls.
375 * This function should be called before gnutls_global_init().
377 * For simplicity you can use the convenience
378 * gnutls_crypto_cipher_register() macro.
380 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
382 * Since: 2.6.0
385 gnutls_crypto_cipher_register (int priority,
386 const gnutls_crypto_cipher_st * s)
388 if (crypto_cipher_prio > priority)
390 memcpy (&_gnutls_cipher_ops, s, sizeof (*s));
391 crypto_cipher_prio = priority;
392 return 0;
395 return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
399 * gnutls_crypto_mac_register:
400 * @priority: is the priority of the mac interface
401 * @s: is a structure holding new interface's data
403 * This function will register a mac interface to be used by
404 * gnutls. Any interface registered will override the included engine
405 * and by convention kernel implemented interfaces should have
406 * priority of 90 and CPU-assisted of 80. The interface with the lowest priority will be used
407 * by gnutls.
409 * This function should be called before gnutls_global_init().
411 * For simplicity you can use the convenience
412 * gnutls_crypto_digest_register() macro.
414 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
416 * Since: 2.6.0
419 gnutls_crypto_mac_register (int priority,
420 const gnutls_crypto_mac_st * s)
422 if (crypto_mac_prio > priority)
424 memcpy (&_gnutls_mac_ops, s, sizeof (*s));
425 crypto_mac_prio = priority;
426 return 0;
429 return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
433 * gnutls_crypto_digest_register:
434 * @priority: is the priority of the digest interface
435 * @s: is a structure holding new interface's data
437 * This function will register a digest interface to be used by
438 * gnutls. Any interface registered will override the included engine
439 * and by convention kernel implemented interfaces should have
440 * priority of 90 and CPU-assisted of 80. The interface with the lowest priority will be used
441 * by gnutls.
443 * This function should be called before gnutls_global_init().
445 * For simplicity you can use the convenience
446 * gnutls_crypto_digest_register() macro.
448 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
450 * Since: 2.6.0
453 gnutls_crypto_digest_register (int priority,
454 const gnutls_crypto_digest_st * s)
456 if (crypto_digest_prio > priority)
458 memcpy (&_gnutls_digest_ops, s, sizeof (*s));
459 crypto_digest_prio = priority;
460 return 0;
463 return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;