diff options
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/lib/pkcs11/pkcs11_kernel/common/kernelGeneral.c | 31 | ||||
| -rw-r--r-- | usr/src/lib/pkcs11/pkcs11_kernel/common/kernelGlobal.h | 16 | ||||
| -rw-r--r-- | usr/src/lib/pkcs11/pkcs11_kernel/common/kernelUtil.c | 63 | ||||
| -rw-r--r-- | usr/src/uts/common/crypto/core/kcf_mech_tabs.c | 136 | ||||
| -rw-r--r-- | usr/src/uts/common/crypto/io/crypto.c | 7 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/crypto/impl.h | 2 |
6 files changed, 180 insertions, 75 deletions
diff --git a/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelGeneral.c b/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelGeneral.c index 5f13ac2433..f57086c881 100644 --- a/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelGeneral.c +++ b/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelGeneral.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -121,6 +120,7 @@ static pthread_mutex_t globalmutex = PTHREAD_MUTEX_INITIALIZER; ses_to_be_freed_list_t ses_delay_freed; object_to_be_freed_list_t obj_delay_freed; +kmh_elem_t **kernel_mechhash; /* Hash table for kCF mech numbers */ static void finalize_common(); static void cleanup_library(); @@ -129,7 +129,6 @@ static void kernel_fini(); CK_RV C_Initialize(CK_VOID_PTR pInitArgs) { - int initialize_pid; boolean_t supplied_ok; CK_RV rv = CKR_OK; @@ -211,9 +210,18 @@ C_Initialize(CK_VOID_PTR pInitArgs) /* Mark kernel_fd "close on exec" */ (void) fcntl(kernel_fd, F_SETFD, FD_CLOEXEC); + /* Create the hash table */ + kernel_mechhash = calloc(KMECH_HASHTABLE_SIZE, sizeof (void *)); + if (kernel_mechhash == NULL) { + (void) close(kernel_fd); + (void) pthread_mutex_unlock(&globalmutex); + return (CKR_HOST_MEMORY); + } + /* Initialize the slot table */ rv = kernel_slottable_init(); if (rv != CKR_OK) { + free(kernel_mechhash); (void) close(kernel_fd); (void) pthread_mutex_unlock(&globalmutex); return (rv); @@ -286,6 +294,7 @@ static void finalize_common() { int i; + kmh_elem_t *elem, *next; kernel_object_t *delay_free_obj, *tmpo; kernel_session_t *delay_free_ses, *tmps; @@ -307,6 +316,18 @@ finalize_common() { (void) close(kernel_fd); } + /* Walk the hash table and free all entries */ + for (i = 0; i < KMECH_HASHTABLE_SIZE; i++) { + elem = kernel_mechhash[i]; + while (elem != NULL) { + next = elem->knext; + free(elem); + elem = next; + } + } + + free(kernel_mechhash); + kernel_fd = -1; kernel_initialized = B_FALSE; kernel_pid = 0; diff --git a/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelGlobal.h b/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelGlobal.h index 647f62bb8d..257598470b 100644 --- a/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelGlobal.h +++ b/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelGlobal.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,9 +37,18 @@ extern "C" { #include <security/pkcs11t.h> #include "kernelObject.h" +typedef struct kmh_elem { + CK_MECHANISM_TYPE type; + crypto_mech_type_t kmech; /* kCF mech number */ + struct kmh_elem *knext; /* Next in hash chain */ +} kmh_elem_t; + +extern kmh_elem_t **kernel_mechhash; extern boolean_t kernel_initialized; extern int kernel_fd; +#define KMECH_HASHTABLE_SIZE 67 + #define CRYPTO_DEVICE "/dev/crypto" /* CK_INFO: Information about cryptoki */ diff --git a/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelUtil.c b/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelUtil.c index be29dfe176..f243e589e5 100644 --- a/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelUtil.c +++ b/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelUtil.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -152,6 +151,43 @@ crypto2pkcs11_error_number(uint_t n) return (error_number_table[n]); } +#define MECH_HASH(type) (((uintptr_t)type) % KMECH_HASHTABLE_SIZE) +/* + * Serialize writes to the hash table. We don't need a per bucket lock as + * there are only a few writes and we don't need the lock for reads. + */ +static pthread_mutex_t mechhash_mutex = PTHREAD_MUTEX_INITIALIZER; + +static CK_RV +kmech_hash_insert(CK_MECHANISM_TYPE type, crypto_mech_type_t kmech) +{ + uint_t h; + kmh_elem_t *elem, *cur; + + elem = malloc(sizeof (kmh_elem_t)); + if (elem == NULL) + return (CKR_HOST_MEMORY); + + h = MECH_HASH(type); + elem->type = type; + elem->kmech = kmech; + + (void) pthread_mutex_lock(&mechhash_mutex); + for (cur = kernel_mechhash[h]; cur != NULL; cur = cur->knext) { + if (type == cur->type) { + /* Some other thread beat us to it. */ + (void) pthread_mutex_unlock(&mechhash_mutex); + free(elem); + return (CKR_OK); + } + } + elem->knext = kernel_mechhash[h]; + kernel_mechhash[h] = elem; + (void) pthread_mutex_unlock(&mechhash_mutex); + + return (CKR_OK); +} + CK_RV kernel_mech(CK_MECHANISM_TYPE type, crypto_mech_type_t *k_number) { @@ -159,6 +195,20 @@ kernel_mech(CK_MECHANISM_TYPE type, crypto_mech_type_t *k_number) char *string; CK_RV rv; int r; + kmh_elem_t *elem; + uint_t h; + + /* + * Search for an existing entry. No need to lock since we are + * just a reader and we never free the entries in the hash table. + */ + h = MECH_HASH(type); + for (elem = kernel_mechhash[h]; elem != NULL; elem = elem->knext) { + if (type == elem->type) { + *k_number = elem->kmech; + return (CKR_OK); + } + } string = pkcs11_mech2str(type); if (string == NULL) @@ -183,8 +233,11 @@ kernel_mech(CK_MECHANISM_TYPE type, crypto_mech_type_t *k_number) } } - if (rv == CKR_OK) + if (rv == CKR_OK) { *k_number = get_number.pn_internal_number; + /* Add this to the hash table */ + (void) kmech_hash_insert(type, *k_number); + } free(string); return (rv); diff --git a/usr/src/uts/common/crypto/core/kcf_mech_tabs.c b/usr/src/uts/common/crypto/core/kcf_mech_tabs.c index be7273d5f7..67beb2260a 100644 --- a/usr/src/uts/common/crypto/core/kcf_mech_tabs.c +++ b/usr/src/uts/common/crypto/core/kcf_mech_tabs.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -31,6 +30,7 @@ #include <sys/errno.h> #include <sys/disp.h> #include <sys/modctl.h> +#include <sys/modhash.h> #include <sys/crypto/common.h> #include <sys/crypto/api.h> #include <sys/crypto/impl.h> @@ -120,11 +120,29 @@ int kcf_des_threshold = 512; int kcf_des3_threshold = 512; int kcf_aes_threshold = 512; int kcf_bf_threshold = 512; +int kcf_rc4_threshold = 512; kmutex_t kcf_mech_tabs_lock; static uint32_t kcf_gen_swprov = 0; - /* Internal entry points */ +int kcf_mech_hash_size = 256; +mod_hash_t *kcf_mech_hash; /* mech name to id hash */ + +static crypto_mech_type_t +kcf_mech_hash_find(char *mechname) +{ + mod_hash_val_t hv; + crypto_mech_type_t mt; + + mt = CRYPTO_MECH_INVALID; + if (mod_hash_find(kcf_mech_hash, (mod_hash_key_t)mechname, &hv) == 0) { + mt = *(crypto_mech_type_t *)hv; + ASSERT(mt != CRYPTO_MECH_INVALID); + } + + return (mt); +} + /* * kcf_init_mech_tabs() * @@ -141,16 +159,7 @@ kcf_init_mech_tabs() /* Initializes the mutex locks. */ mutex_init(&kcf_mech_tabs_lock, NULL, MUTEX_DEFAULT, NULL); - mutex_enter(&kcf_mech_tabs_lock); - for (class = KCF_FIRST_OPSCLASS; class <= KCF_LAST_OPSCLASS; class++) { - max = kcf_mech_tabs_tab[class].met_size; - me_tab = kcf_mech_tabs_tab[class].met_tab; - for (i = 0; i < max; i++) { - mutex_init(&(me_tab[i].me_mutex), NULL, - MUTEX_DEFAULT, NULL); - } - } /* Then the pre-defined mechanism entries */ /* Two digests */ @@ -195,6 +204,10 @@ kcf_init_mech_tabs() CRYPTO_MAX_MECH_NAME); kcf_cipher_mechs_tab[7].me_threshold = kcf_aes_threshold; + (void) strncpy(kcf_cipher_mechs_tab[8].me_name, SUN_CKM_RC4, + CRYPTO_MAX_MECH_NAME); + kcf_cipher_mechs_tab[8].me_threshold = kcf_rc4_threshold; + /* 4 HMACs */ (void) strncpy(kcf_mac_mechs_tab[0].me_name, SUN_CKM_MD5_HMAC, @@ -218,7 +231,23 @@ kcf_init_mech_tabs() (void) strncpy(kcf_misc_mechs_tab[0].me_name, SUN_RANDOM, CRYPTO_MAX_MECH_NAME); - mutex_exit(&kcf_mech_tabs_lock); + kcf_mech_hash = mod_hash_create_strhash("kcf mech2id hash", + kcf_mech_hash_size, mod_hash_null_valdtor); + + for (class = KCF_FIRST_OPSCLASS; class <= KCF_LAST_OPSCLASS; class++) { + max = kcf_mech_tabs_tab[class].met_size; + me_tab = kcf_mech_tabs_tab[class].met_tab; + for (i = 0; i < max; i++) { + mutex_init(&(me_tab[i].me_mutex), NULL, + MUTEX_DEFAULT, NULL); + if (me_tab[i].me_name[0] != 0) { + me_tab[i].me_mechid = KCF_MECHID(class, i); + (void) mod_hash_insert(kcf_mech_hash, + (mod_hash_key_t)me_tab[i].me_name, + (mod_hash_val_t)&(me_tab[i].me_mechid)); + } + } + } } /* @@ -264,7 +293,7 @@ kcf_create_mech_entry(kcf_ops_class_t class, char *mechname) * The mech_entry could be in another class. */ mutex_enter(&kcf_mech_tabs_lock); - mt = crypto_mech2id_common(mechname, B_FALSE); + mt = kcf_mech_hash_find(mechname); if (mt != CRYPTO_MECH_INVALID) { /* Nothing to do, regardless the suggested class. */ mutex_exit(&kcf_mech_tabs_lock); @@ -281,7 +310,7 @@ kcf_create_mech_entry(kcf_ops_class_t class, char *mechname) (void) strncpy(me_tab[i].me_name, mechname, CRYPTO_MAX_MECH_NAME); me_tab[i].me_name[CRYPTO_MAX_MECH_NAME-1] = '\0'; - + me_tab[i].me_mechid = KCF_MECHID(class, i); /* * No a-priori information about the new mechanism, so * the threshold is set to zero. @@ -289,6 +318,10 @@ kcf_create_mech_entry(kcf_ops_class_t class, char *mechname) me_tab[i].me_threshold = 0; mutex_exit(&(me_tab[i].me_mutex)); + /* Add the new mechanism to the hash table */ + (void) mod_hash_insert(kcf_mech_hash, + (mod_hash_key_t)me_tab[i].me_name, + (mod_hash_val_t)&(me_tab[i].me_mechid)); break; } mutex_exit(&(me_tab[i].me_mutex)); @@ -353,9 +386,7 @@ kcf_add_mech_provider(crypto_mech_info_t *mech_info, * Find the class corresponding to the function group flag of * the mechanism. */ - - - kcf_mech_type = crypto_mech2id_common(mech_info->cm_mech_name, B_FALSE); + kcf_mech_type = kcf_mech_hash_find(mech_info->cm_mech_name); if (kcf_mech_type == CRYPTO_MECH_INVALID) { crypto_func_group_t fg = mech_info->cm_func_group_mask; kcf_ops_class_t class; @@ -392,8 +423,7 @@ kcf_add_mech_provider(crypto_mech_info_t *mech_info, return (error); } /* get the KCF mech type that was assigned to the mechanism */ - kcf_mech_type = crypto_mech2id_common(mech_info->cm_mech_name, - B_FALSE); + kcf_mech_type = kcf_mech_hash_find(mech_info->cm_mech_name); ASSERT(kcf_mech_type != CRYPTO_MECH_INVALID); } @@ -433,7 +463,7 @@ kcf_add_mech_provider(crypto_mech_info_t *mech_info, (dmi->cm_func_group_mask & simple_fg_mask)) continue; - mt = crypto_mech2id_common(dmi->cm_mech_name, B_FALSE); + mt = kcf_mech_hash_find(dmi->cm_mech_name); if (mt == CRYPTO_MECH_INVALID) continue; @@ -581,7 +611,7 @@ kcf_remove_mech_provider(char *mech_name, kcf_provider_desc_t *prov_desc) ASSERT(prov_desc->pd_prov_type != CRYPTO_LOGICAL_PROVIDER); /* get the KCF mech type that was assigned to the mechanism */ - if ((mech_type = crypto_mech2id_common(mech_name, B_FALSE)) == + if ((mech_type = kcf_mech_hash_find(mech_name)) == CRYPTO_MECH_INVALID) { /* * Provider was not allowed for this mech due to policy or @@ -774,54 +804,42 @@ auto_unload_flag_set(kcf_prov_mech_desc_t *pm) } /* - * Walks the mechanisms tables, looking for an entry that matches the - * mechname. Once it find it, it builds the 64-bit mech_type and returns - * it. If there are no hardware or software providers for the mechanism, - * but there is an unloaded software provider, this routine will attempt - * to load it. + * Lookup the hash table for an entry that matches the mechname. + * If there are no hardware or software providers for the mechanism, + * but there is an unloaded software provider, this routine will attempt + * to load it. * - * If the MOD_NOAUTOUNLOAD flag is not set, a software provider is - * in constant danger of being unloaded. For consumers that call - * crypto_mech2id() only once, the provider will not be reloaded - * if it becomes unloaded. If a provider gets loaded elsewhere - * without the MOD_NOAUTOUNLOAD flag being set, we set it now. + * If the MOD_NOAUTOUNLOAD flag is not set, a software provider is + * in constant danger of being unloaded. For consumers that call + * crypto_mech2id() only once, the provider will not be reloaded + * if it becomes unloaded. If a provider gets loaded elsewhere + * without the MOD_NOAUTOUNLOAD flag being set, we set it now. */ crypto_mech_type_t crypto_mech2id_common(char *mechname, boolean_t load_module) { crypto_mech_type_t mt; - kcf_mech_entry_t *me, *me_tab; - int i, max; + kcf_mech_entry_t *me; + int i; kcf_ops_class_t class; boolean_t second_time = B_FALSE; boolean_t try_to_load_software_provider = B_FALSE; try_again: - mt = CRYPTO_MECH_INVALID; - /* Walk the tables */ - for (class = KCF_FIRST_OPSCLASS; class <= KCF_LAST_OPSCLASS && - mt == CRYPTO_MECH_INVALID; class++) { - max = kcf_mech_tabs_tab[class].met_size; - me_tab = kcf_mech_tabs_tab[class].met_tab; - for (i = 0; i < max; i++) { - me = &me_tab[i]; - mutex_enter(&(me->me_mutex)); - if ((me->me_name[0] != 0) && - (strncmp(mechname, me->me_name, - CRYPTO_MAX_MECH_NAME) == 0)) { - mt = KCF_MECHID(class, i); - if (load_module && - !auto_unload_flag_set(me->me_sw_prov)) { - try_to_load_software_provider = B_TRUE; - } - mutex_exit(&(me->me_mutex)); - break; - } - mutex_exit(&(me->me_mutex)); + mt = kcf_mech_hash_find(mechname); + if (!load_module || second_time == B_TRUE || servicing_interrupt()) + return (mt); + + if (mt != CRYPTO_MECH_INVALID) { + class = KCF_MECH2CLASS(mt); + i = KCF_MECH2INDEX(mt); + me = &(kcf_mech_tabs_tab[class].met_tab[i]); + mutex_enter(&(me->me_mutex)); + if (load_module && !auto_unload_flag_set(me->me_sw_prov)) { + try_to_load_software_provider = B_TRUE; } + mutex_exit(&(me->me_mutex)); } - if (second_time == B_TRUE || servicing_interrupt() || !load_module) - return (mt); if (mt == CRYPTO_MECH_INVALID || try_to_load_software_provider) { struct modctl *mcp; diff --git a/usr/src/uts/common/crypto/io/crypto.c b/usr/src/uts/common/crypto/io/crypto.c index 047c5f4b0e..acd37b40be 100644 --- a/usr/src/uts/common/crypto/io/crypto.c +++ b/usr/src/uts/common/crypto/io/crypto.c @@ -823,8 +823,11 @@ get_mechanism_number(dev_t dev, caddr_t arg, int mode, int *rval) return (EFAULT); } - /* get mechanism number from the core module */ - number = crypto_mech2id_common(mechanism_name, B_TRUE); + /* + * Get mechanism number from kcf. We set the load_module + * flag to false since we use only hardware providers. + */ + number = crypto_mech2id_common(mechanism_name, B_FALSE); kmem_free(mechanism_name, len); if (number == CRYPTO_MECH_INVALID) { rv = CRYPTO_ARGUMENTS_BAD; diff --git a/usr/src/uts/common/sys/crypto/impl.h b/usr/src/uts/common/sys/crypto/impl.h index bd237f6200..4fa677ae9a 100644 --- a/usr/src/uts/common/sys/crypto/impl.h +++ b/usr/src/uts/common/sys/crypto/impl.h @@ -300,6 +300,7 @@ typedef struct kcf_prov_mech_desc { #define KCF_CPU_PAD (128 - sizeof (crypto_mech_name_t) - \ + sizeof (crypto_mech_type_t) - \ sizeof (kmutex_t) - 2 * sizeof (kcf_prov_mech_desc_t *) - \ sizeof (int) - sizeof (uint32_t) - sizeof (size_t)) @@ -309,6 +310,7 @@ typedef struct kcf_prov_mech_desc { */ typedef struct kcf_mech_entry { crypto_mech_name_t me_name; /* mechanism name */ + crypto_mech_type_t me_mechid; /* Internal id for mechanism */ kmutex_t me_mutex; /* access protection */ kcf_prov_mech_desc_t *me_hw_prov_chain; /* list of HW providers */ kcf_prov_mech_desc_t *me_sw_prov; /* SW provider */ |
