diff options
Diffstat (limited to 'grub-core/lib/libgcrypt/src/module.c')
-rw-r--r-- | grub-core/lib/libgcrypt/src/module.c | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/grub-core/lib/libgcrypt/src/module.c b/grub-core/lib/libgcrypt/src/module.c new file mode 100644 index 0000000..32f668d --- /dev/null +++ b/grub-core/lib/libgcrypt/src/module.c @@ -0,0 +1,212 @@ +/* module.c - Module management for libgcrypt. + * Copyright (C) 2003, 2008 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <errno.h> +#include "g10lib.h" + +/* Please match these numbers with the allocated algorithm + numbers. */ +#define MODULE_ID_MIN 600 +#define MODULE_ID_LAST 65500 +#define MODULE_ID_USER GCRY_MODULE_ID_USER +#define MODULE_ID_USER_LAST GCRY_MODULE_ID_USER_LAST + +#if MODULE_ID_MIN >= MODULE_ID_USER +#error Need to implement a different search strategy +#endif + +/* Internal function. Generate a new, unique module ID for a module + that should be inserted into the module chain starting at + MODULES. */ +static gcry_err_code_t +_gcry_module_id_new (gcry_module_t modules, unsigned int *id_new) +{ + unsigned int mod_id; + gcry_err_code_t err = GPG_ERR_NO_ERROR; + gcry_module_t module; + + /* Search for unused ID. */ + for (mod_id = MODULE_ID_MIN; mod_id < MODULE_ID_LAST; mod_id++) + { + if (mod_id == MODULE_ID_USER) + { + mod_id = MODULE_ID_USER_LAST; + continue; + } + + /* Search for a module with the current ID. */ + for (module = modules; module; module = module->next) + if (mod_id == module->mod_id) + break; + + if (! module) + /* None found -> the ID is available for use. */ + break; + } + + if (mod_id < MODULE_ID_LAST) + /* Done. */ + *id_new = mod_id; + else + /* No free ID found. */ + err = GPG_ERR_INTERNAL; + + return err; +} + +/* Add a module specification to the list ENTRIES. The new module has + it's use-counter set to one. */ +gcry_err_code_t +_gcry_module_add (gcry_module_t *entries, unsigned int mod_id, + void *spec, void *extraspec, gcry_module_t *module) +{ + gcry_err_code_t err = 0; + gcry_module_t entry; + + if (! mod_id) + err = _gcry_module_id_new (*entries, &mod_id); + + if (! err) + { + entry = gcry_malloc (sizeof (struct gcry_module)); + if (! entry) + err = gpg_err_code_from_errno (errno); + } + + if (! err) + { + /* Fill new module entry. */ + entry->flags = 0; + entry->counter = 1; + entry->spec = spec; + entry->extraspec = extraspec; + entry->mod_id = mod_id; + + /* Link it into the list. */ + entry->next = *entries; + entry->prevp = entries; + if (*entries) + (*entries)->prevp = &entry->next; + *entries = entry; + + /* And give it to the caller. */ + if (module) + *module = entry; + } + return err; +} + +/* Internal function. Unlink CIPHER_ENTRY from the list of registered + ciphers and destroy it. */ +static void +_gcry_module_drop (gcry_module_t entry) +{ + *entry->prevp = entry->next; + if (entry->next) + entry->next->prevp = entry->prevp; + + gcry_free (entry); +} + +/* Lookup a module specification by it's ID. After a successful + lookup, the module has it's resource counter incremented. */ +gcry_module_t +_gcry_module_lookup_id (gcry_module_t entries, unsigned int mod_id) +{ + gcry_module_t entry; + + for (entry = entries; entry; entry = entry->next) + if (entry->mod_id == mod_id) + { + entry->counter++; + break; + } + + return entry; +} + +/* Lookup a module specification. After a successful lookup, the + module has it's resource counter incremented. FUNC is a function + provided by the caller, which is responsible for identifying the + wanted module. */ +gcry_module_t +_gcry_module_lookup (gcry_module_t entries, void *data, + gcry_module_lookup_t func) +{ + gcry_module_t entry; + + for (entry = entries; entry; entry = entry->next) + if ((*func) (entry->spec, data)) + { + entry->counter++; + break; + } + + return entry; +} + +/* Release a module. In case the use-counter reaches zero, destroy + the module. Passing MODULE as NULL is a dummy operation (similar + to free()). */ +void +_gcry_module_release (gcry_module_t module) +{ + if (module && ! --module->counter) + _gcry_module_drop (module); +} + +/* Add a reference to a module. */ +void +_gcry_module_use (gcry_module_t module) +{ + ++module->counter; +} + +/* If LIST is zero, write the number of modules identified by MODULES + to LIST_LENGTH and return. If LIST is non-zero, the first + *LIST_LENGTH algorithm IDs are stored in LIST, which must be of + according size. In case there are less cipher modules than + *LIST_LENGTH, *LIST_LENGTH is updated to the correct number. */ +gcry_err_code_t +_gcry_module_list (gcry_module_t modules, + int *list, int *list_length) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + gcry_module_t module; + int length, i; + + for (module = modules, length = 0; module; module = module->next, length++); + + if (list) + { + if (length > *list_length) + length = *list_length; + + for (module = modules, i = 0; i < length; module = module->next, i++) + list[i] = module->mod_id; + + if (length < *list_length) + *list_length = length; + } + else + *list_length = length; + + return err; +} |