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 2.1 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>
28 #include <gnutls_mpi.h>
29 #include <gnutls_pk.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 {
42 struct algo_list *next;
45 #define cipher_list algo_list
46 #define mac_list algo_list
47 #define digest_list algo_list
50 _algo_register(algo_list * al, int algorithm, int priority, const void *s)
53 algo_list *last_cl = al;
56 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
58 /* look if there is any cipher with lowest priority. In that case do not add.
61 while (cl && cl->alg_data) {
62 if (cl->algorithm == algorithm) {
63 if (cl->priority < priority) {
65 return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
67 /* the current has higher priority -> overwrite */
68 cl->algorithm = algorithm;
69 cl->priority = priority;
79 cl = gnutls_calloc(1, sizeof(cipher_list));
83 return GNUTLS_E_MEMORY_ERROR;
86 last_cl->algorithm = algorithm;
87 last_cl->priority = priority;
88 last_cl->alg_data = s;
95 static const void *_get_algo(algo_list * al, int algo)
99 /* look if there is any cipher with lowest priority. In that case do not add.
102 while (cl && cl->alg_data) {
103 if (cl->algorithm == algo) {
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 };
116 static void _deregister(algo_list * cl)
131 void _gnutls_crypto_deregister(void)
133 _deregister(&glob_cl);
134 _deregister(&glob_ml);
135 _deregister(&glob_dl);
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
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
150 * This function should be called before gnutls_global_init().
152 * For simplicity you can use the convenience
153 * gnutls_crypto_single_cipher_register() macro.
155 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
160 gnutls_crypto_single_cipher_register(gnutls_cipher_algorithm_t algorithm,
162 const gnutls_crypto_cipher_st * s)
164 return _algo_register(&glob_cl, algorithm, priority, s);
167 const gnutls_crypto_cipher_st
168 *_gnutls_get_crypto_cipher(gnutls_cipher_algorithm_t algo)
170 return _get_algo(&glob_cl, algo);
174 * gnutls_crypto_rnd_register:
175 * @priority: is the priority of the generator
176 * @s: is a structure holding new generator's data
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
184 * This function should be called before gnutls_global_init().
186 * For simplicity you can use the convenience
187 * gnutls_crypto_rnd_register() macro.
189 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
194 gnutls_crypto_rnd_register(int priority, const gnutls_crypto_rnd_st * s)
196 if (crypto_rnd_prio >= priority) {
197 memcpy(&_gnutls_rnd_ops, s, sizeof(*s));
198 crypto_rnd_prio = priority;
202 return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
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
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.
217 * This function should be called before gnutls_global_init().
219 * For simplicity you can use the convenience
220 * gnutls_crypto_single_mac_register() macro.
222 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
227 gnutls_crypto_single_mac_register(gnutls_mac_algorithm_t algorithm,
229 const gnutls_crypto_mac_st * s)
231 return _algo_register(&glob_ml, algorithm, priority, s);
234 const gnutls_crypto_mac_st *_gnutls_get_crypto_mac(gnutls_mac_algorithm_t
237 return _get_algo(&glob_ml, algo);
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
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
252 * This function should be called before gnutls_global_init().
254 * For simplicity you can use the convenience
255 * gnutls_crypto_single_digest_register() macro.
257 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
262 gnutls_crypto_single_digest_register(gnutls_digest_algorithm_t algorithm,
264 const gnutls_crypto_digest_st * s)
266 return _algo_register(&glob_dl, algorithm, priority, s);
269 const gnutls_crypto_digest_st
270 *_gnutls_get_crypto_digest(gnutls_digest_algorithm_t algo)
272 return _get_algo(&glob_dl, algo);
276 * gnutls_crypto_bigint_register:
277 * @priority: is the priority of the interface
278 * @s: is a structure holding new interface's data
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.
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.
289 * This function should be called before gnutls_global_init().
291 * For simplicity you can use the convenience gnutls_crypto_bigint_register()
294 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
299 gnutls_crypto_bigint_register(int priority,
300 const gnutls_crypto_bigint_st * s)
302 if (crypto_bigint_prio > priority) {
303 memcpy(&_gnutls_mpi_ops, s, sizeof(*s));
304 crypto_bigint_prio = priority;
308 return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
312 * gnutls_crypto_pk_register:
313 * @priority: is the priority of the interface
314 * @s: is a structure holding new interface's data
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.
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.
325 * This function should be called before gnutls_global_init().
327 * For simplicity you can use the convenience gnutls_crypto_pk_register()
330 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
334 int gnutls_crypto_pk_register(int priority, const gnutls_crypto_pk_st * s)
336 if (crypto_pk_prio > priority) {
337 memcpy(&_gnutls_pk_ops, s, sizeof(*s));
338 crypto_pk_prio = priority;
342 return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
346 * gnutls_crypto_cipher_register:
347 * @priority: is the priority of the cipher interface
348 * @s: is a structure holding new interface's data
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
356 * This function should be called before gnutls_global_init().
358 * For simplicity you can use the convenience
359 * gnutls_crypto_cipher_register() macro.
361 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
366 gnutls_crypto_cipher_register(int priority,
367 const gnutls_crypto_cipher_st * s)
369 if (crypto_cipher_prio > priority) {
370 memcpy(&_gnutls_cipher_ops, s, sizeof(*s));
371 crypto_cipher_prio = priority;
375 return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
379 * gnutls_crypto_mac_register:
380 * @priority: is the priority of the mac interface
381 * @s: is a structure holding new interface's data
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
389 * This function should be called before gnutls_global_init().
391 * For simplicity you can use the convenience
392 * gnutls_crypto_digest_register() macro.
394 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
399 gnutls_crypto_mac_register(int priority, const gnutls_crypto_mac_st * s)
401 if (crypto_mac_prio > priority) {
402 memcpy(&_gnutls_mac_ops, s, sizeof(*s));
403 crypto_mac_prio = priority;
407 return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
411 * gnutls_crypto_digest_register:
412 * @priority: is the priority of the digest interface
413 * @s: is a structure holding new interface's data
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
421 * This function should be called before gnutls_global_init().
423 * For simplicity you can use the convenience
424 * gnutls_crypto_digest_register() macro.
426 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
431 gnutls_crypto_digest_register(int priority,
432 const gnutls_crypto_digest_st * s)
434 if (crypto_digest_prio > priority) {
435 memcpy(&_gnutls_digest_ops, s, sizeof(*s));
436 crypto_digest_prio = priority;
440 return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;