diff options
Diffstat (limited to 'usr/src')
11 files changed, 273 insertions, 156 deletions
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/Makefile.com b/usr/src/lib/pkcs11/pkcs11_softtoken/Makefile.com index a3d76fd04e..39fc82a46a 100644 --- a/usr/src/lib/pkcs11/pkcs11_softtoken/Makefile.com +++ b/usr/src/lib/pkcs11/pkcs11_softtoken/Makefile.com @@ -22,9 +22,8 @@ # Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. # # Copyright 2010 Nexenta Systems, Inc. All rights reserved. -# Copyright 2018, Joyent, Inc. +# Copyright 2020 Joyent, Inc. # -# Copyright (c) 2018, Joyent, Inc. LIBRARY = pkcs11_softtoken.a VERS= .1 @@ -121,7 +120,7 @@ SRCS = \ # libelfsign needs a static pkcs11_softtoken LIBS = $(DYNLIB) -LDLIBS += -lc -lmd -lcryptoutil -lsoftcrypto -lgen +LDLIBS += -lc -lmd -lcryptoutil -lsoftcrypto -lgen -lavl CSTD = $(CSTD_GNU99) diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softGeneral.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softGeneral.c index c44cbcb2a2..f52cc26ba0 100644 --- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softGeneral.c +++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softGeneral.c @@ -23,6 +23,8 @@ * Use is subject to license terms. * * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved. + * + * Copyright 2020 Joyent, Inc. */ #include <strings.h> @@ -30,7 +32,9 @@ #include <cryptoutil.h> #include <unistd.h> /* for pid_t */ #include <pthread.h> +#include <stddef.h> #include <security/cryptoki.h> +#include <sys/debug.h> #include "softGlobal.h" #include "softSession.h" #include "softObject.h" @@ -118,9 +122,31 @@ boolean_t softtoken_initialized = B_FALSE; static pid_t softtoken_pid = 0; -/* This mutex protects soft_session_list, all_sessions_closing */ +/* + * Lock ordering in pkcs11_softtoken is as follows: + * soft_giant_mutex + * soft_sessionlist_mutex + * soft_slot.slot_mutex + * soft_slot.keystore_mutex + * token session mutexes + * soft_session_t->session_mutex + * soft_object_mutex + * soft_object_t->object_mutex + * obj_delay_freed.obj_to_be_free_mutex + * ses_delay_freed.ses_to_br_free_mutex + */ + +/* + * This mutex protects soft_session_list, all_sessions_closing, + * and soft_session_tree + */ pthread_mutex_t soft_sessionlist_mutex; soft_session_t *soft_session_list = NULL; +avl_tree_t soft_session_tree; + +/* This protects soft_object_tree */ +pthread_mutex_t soft_object_mutex; +avl_tree_t soft_object_tree; int all_sessions_closing = 0; @@ -132,15 +158,17 @@ ses_to_be_freed_list_t ses_delay_freed; pthread_mutex_t soft_giant_mutex = PTHREAD_MUTEX_INITIALIZER; static CK_RV finalize_common(boolean_t force, CK_VOID_PTR pReserved); -static void softtoken_init(); -static void softtoken_fini(); -static void softtoken_fork_prepare(); -static void softtoken_fork_after(); +static void softtoken_init(void); +static void softtoken_fini(void); +static void softtoken_fork_prepare(void); +static void softtoken_fork_after(void); +static int session_compare(const void *a, const void *b); +static int object_compare(const void *a, const void *b); CK_RV C_Initialize(CK_VOID_PTR pInitArgs) { - + pthread_mutexattr_t attr = { 0 }; int initialize_pid; boolean_t supplied_ok; CK_RV rv; @@ -211,12 +239,28 @@ C_Initialize(CK_VOID_PTR pInitArgs) } } + if (pthread_mutexattr_init(&attr) != 0) { + (void) pthread_mutex_unlock(&soft_giant_mutex); + return (CKR_HOST_MEMORY); + } + + VERIFY0(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK)); + /* Initialize the session list lock */ - if (pthread_mutex_init(&soft_sessionlist_mutex, NULL) != 0) { + if (pthread_mutex_init(&soft_sessionlist_mutex, &attr) != 0) { + (void) pthread_mutexattr_destroy(&attr); (void) pthread_mutex_unlock(&soft_giant_mutex); return (CKR_CANT_LOCK); } + if (pthread_mutex_init(&soft_object_mutex, &attr) != 0) { + (void) pthread_mutexattr_destroy(&attr); + (void) pthread_mutex_unlock(&soft_giant_mutex); + return (CKR_CANT_LOCK); + } + + VERIFY0(pthread_mutexattr_destroy(&attr)); + /* * token object related initialization */ @@ -322,8 +366,8 @@ C_Finalize(CK_VOID_PTR pReserved) * must be held before calling this function. */ static CK_RV -finalize_common(boolean_t force, CK_VOID_PTR pReserved) { - +finalize_common(boolean_t force, CK_VOID_PTR pReserved) +{ CK_RV rv = CKR_OK; struct object *delay_free_obj, *tmpo; struct session *delay_free_ses, *tmps; @@ -363,6 +407,8 @@ finalize_common(boolean_t force, CK_VOID_PTR pReserved) { * two also prevent deadlocks and other artificial dependencies. */ + (void) pthread_mutex_destroy(&soft_object_mutex); + /* Destroy the session list lock here */ (void) pthread_mutex_destroy(&soft_sessionlist_mutex); @@ -404,6 +450,12 @@ finalize_common(boolean_t force, CK_VOID_PTR pReserved) { static void softtoken_init() { + avl_create(&soft_session_tree, session_compare, sizeof (soft_session_t), + offsetof(soft_session_t, node)); + + avl_create(&soft_object_tree, object_compare, sizeof (soft_object_t), + offsetof(soft_object_t, node)); + /* Children inherit parent's atfork handlers */ (void) pthread_atfork(softtoken_fork_prepare, softtoken_fork_after, softtoken_fork_after); @@ -426,6 +478,9 @@ softtoken_fini() (void) finalize_common(B_TRUE, NULL_PTR); + avl_destroy(&soft_object_tree); + avl_destroy(&soft_session_tree); + (void) pthread_mutex_unlock(&soft_giant_mutex); } @@ -510,6 +565,7 @@ softtoken_fork_prepare() (void) pthread_mutex_lock(&soft_slot.keystore_mutex); soft_acquire_all_session_mutexes(&token_session); soft_acquire_all_session_mutexes(soft_session_list); + VERIFY0(pthread_mutex_lock(&soft_object_mutex)); (void) pthread_mutex_lock( &obj_delay_freed.obj_to_be_free_mutex); (void) pthread_mutex_lock( @@ -529,6 +585,7 @@ softtoken_fork_after() &ses_delay_freed.ses_to_be_free_mutex); (void) pthread_mutex_unlock( &obj_delay_freed.obj_to_be_free_mutex); + VERIFY0(pthread_mutex_unlock(&soft_object_mutex)); soft_release_all_session_mutexes(soft_session_list); soft_release_all_session_mutexes(&token_session); (void) pthread_mutex_unlock(&soft_slot.keystore_mutex); @@ -537,3 +594,29 @@ softtoken_fork_after() } (void) pthread_mutex_unlock(&soft_giant_mutex); } + +static int +session_compare(const void *a, const void *b) +{ + const soft_session_t *l = a; + const soft_session_t *r = b; + + if (l->handle < r->handle) + return (-1); + if (l->handle > r->handle) + return (1); + return (0); +} + +static int +object_compare(const void *a, const void *b) +{ + const soft_object_t *l = a; + const soft_object_t *r = b; + + if (l->handle < r->handle) + return (-1); + if (l->handle > r->handle) + return (1); + return (0); +} diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeys.h b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeys.h index 82af35991f..7bb9fa2c88 100644 --- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeys.h +++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeys.h @@ -22,13 +22,13 @@ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2020 Joyent, Inc. */ #ifndef _SOFTKEYS_H #define _SOFTKEYS_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -55,7 +55,7 @@ CK_RV soft_derivekey(soft_session_t *, CK_MECHANISM_PTR, soft_object_t *, void soft_derive_enforce_flags(soft_object_t *, soft_object_t *); CK_RV soft_gen_keyobject(CK_ATTRIBUTE_PTR, CK_ULONG, - CK_ULONG *, soft_session_t *, CK_OBJECT_CLASS, CK_KEY_TYPE, + soft_object_t **, soft_session_t *, CK_OBJECT_CLASS, CK_KEY_TYPE, CK_ULONG, CK_ULONG, boolean_t); CK_RV soft_generate_pkcs5_pbkdf2_key(soft_session_t *, CK_MECHANISM_PTR, diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeysUtil.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeysUtil.c index b3c48663aa..67bb1f7a24 100644 --- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeysUtil.c +++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeysUtil.c @@ -21,7 +21,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright (c) 2018, Joyent, Inc. + * + * Copyright 2020 Joyent, Inc. */ #include <pthread.h> @@ -61,11 +62,10 @@ soft_pkcs12_pbe(soft_session_t *, CK_MECHANISM_PTR, soft_object_t *); */ CK_RV soft_gen_keyobject(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, - CK_ULONG *objecthandle_p, soft_session_t *sp, + soft_object_t **objp, soft_session_t *sp, CK_OBJECT_CLASS class, CK_KEY_TYPE key_type, CK_ULONG keylen, CK_ULONG mode, boolean_t internal) { - CK_RV rv; soft_object_t *new_objp = NULL; @@ -109,24 +109,22 @@ soft_gen_keyobject(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, /* Write the new token object to the keystore */ if (IS_TOKEN_OBJECT(new_objp)) { new_objp->version = 1; - new_objp->session_handle = (CK_SESSION_HANDLE)NULL; + new_objp->session_handle = CK_INVALID_HANDLE; soft_add_token_object_to_slot(new_objp); - /* - * Type casting the address of an object struct to - * an object handle. - */ - *objecthandle_p = (CK_ULONG)new_objp; + + set_objecthandle(new_objp); + *objp = new_objp; return (CKR_OK); } - new_objp->session_handle = (CK_SESSION_HANDLE)sp; + new_objp->session_handle = sp->handle; /* Add the new object to the session's object list. */ soft_add_object_to_session(new_objp, sp); - /* Type casting the address of an object struct to an object handle. */ - *objecthandle_p = (CK_ULONG)new_objp; + set_objecthandle(new_objp); + *objp = new_objp; return (CKR_OK); @@ -258,16 +256,13 @@ soft_genkey(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism, } /* Create a new object for secret key. */ - rv = soft_gen_keyobject(pTemplate, ulCount, phKey, session_p, + rv = soft_gen_keyobject(pTemplate, ulCount, &secret_key, session_p, CKO_SECRET_KEY, key_type, keylen, SOFT_GEN_KEY, B_FALSE); if (rv != CKR_OK) { return (rv); } - /* Obtain the secret object pointer. */ - secret_key = (soft_object_t *)*phKey; - switch (pMechanism->mechanism) { case CKM_DES_KEY_GEN: /* @@ -410,6 +405,7 @@ soft_genkey(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism, soft_delete_token_object(secret_key, B_FALSE, B_FALSE); } + *phKey = secret_key->handle; return (rv); } @@ -448,19 +444,16 @@ soft_genkey_pair(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism, /* Create a new object for public key. */ rv = soft_gen_keyobject(pPublicKeyTemplate, ulPublicAttrCount, - phPublicKey, session_p, CKO_PUBLIC_KEY, key_type, 0, + &public_key, session_p, CKO_PUBLIC_KEY, key_type, 0, SOFT_GEN_KEY, B_FALSE); if (rv != CKR_OK) { return (rv); } - /* Obtain the public object pointer. */ - public_key = (soft_object_t *)*phPublicKey; - /* Create a new object for private key. */ rv = soft_gen_keyobject(pPrivateKeyTemplate, ulPrivateAttrCount, - phPrivateKey, session_p, CKO_PRIVATE_KEY, key_type, 0, + &private_key, session_p, CKO_PRIVATE_KEY, key_type, 0, SOFT_GEN_KEY, B_FALSE); if (rv != CKR_OK) { @@ -475,9 +468,6 @@ soft_genkey_pair(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism, return (rv); } - /* Obtain the private object pointer. */ - private_key = (soft_object_t *)*phPrivateKey; - /* * At this point, both public key and private key objects * are settled with the application specified attributes. @@ -542,6 +532,9 @@ soft_genkey_pair(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism, } } + *phPublicKey = public_key->handle; + *phPrivateKey = private_key->handle; + return (rv); } @@ -851,16 +844,13 @@ soft_derivekey(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism, * be provided in the template. */ rv = soft_gen_keyobject(pTemplate, ulAttributeCount, - phKey, session_p, CKO_SECRET_KEY, (CK_KEY_TYPE)~0UL, 0, - SOFT_DERIVE_KEY_DH, B_FALSE); + &secret_key, session_p, CKO_SECRET_KEY, (CK_KEY_TYPE)~0UL, + 0, SOFT_DERIVE_KEY_DH, B_FALSE); if (rv != CKR_OK) { return (rv); } - /* Obtain the secret object pointer. */ - secret_key = (soft_object_t *)*phKey; - rv = soft_dh_key_derive(basekey_p, secret_key, (CK_BYTE *)pMechanism->pParameter, pMechanism->ulParameterLen); @@ -883,16 +873,13 @@ soft_derivekey(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism, * be provided in the template. */ rv = soft_gen_keyobject(pTemplate, ulAttributeCount, - phKey, session_p, CKO_SECRET_KEY, (CK_KEY_TYPE)~0UL, 0, - SOFT_DERIVE_KEY_DH, B_FALSE); + &secret_key, session_p, CKO_SECRET_KEY, (CK_KEY_TYPE)~0UL, + 0, SOFT_DERIVE_KEY_DH, B_FALSE); if (rv != CKR_OK) { return (rv); } - /* Obtain the secret object pointer. */ - secret_key = (soft_object_t *)*phKey; - rv = soft_ec_key_derive(basekey_p, secret_key, (CK_BYTE *)pMechanism->pParameter, pMechanism->ulParameterLen); @@ -951,7 +938,7 @@ common: * the template, the default is CKK_GENERIC_SECRET. */ rv = soft_gen_keyobject(pTemplate, ulAttributeCount, - phKey, session_p, CKO_SECRET_KEY, + &secret_key, session_p, CKO_SECRET_KEY, (CK_KEY_TYPE)CKK_GENERIC_SECRET, 0, SOFT_DERIVE_KEY_OTHER, B_FALSE); @@ -959,8 +946,7 @@ common: return (rv); } - /* Obtain the secret object pointer. */ - secret_key = (soft_object_t *)*phKey; + *phKey = secret_key->handle; /* Validate the key type and key length */ rv = soft_key_derive_check_length(secret_key, hash_size); @@ -1249,6 +1235,8 @@ soft_create_hmac_key(soft_session_t *session_p, CK_BYTE *passwd, CK_KEY_TYPE keytype = CKK_GENERIC_SECRET; CK_BBOOL True = TRUE; CK_ATTRIBUTE keytemplate[4]; + soft_object_t *keyobj; + /* * We must initialize each template member individually * because at the time of initial coding for ON10, the @@ -1277,10 +1265,13 @@ soft_create_hmac_key(soft_session_t *session_p, CK_BYTE *passwd, * mechanism parameter structure. */ rv = soft_gen_keyobject(keytemplate, - sizeof (keytemplate)/sizeof (CK_ATTRIBUTE), phKey, session_p, + sizeof (keytemplate)/sizeof (CK_ATTRIBUTE), &keyobj, session_p, CKO_SECRET_KEY, (CK_KEY_TYPE)CKK_GENERIC_SECRET, 0, SOFT_CREATE_OBJ, B_TRUE); + if (keyobj != NULL) + *phKey = keyobj->handle; + return (rv); } @@ -1675,7 +1666,7 @@ soft_unwrapkey(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism, /* Create a new object based on the attribute template. */ rv = soft_gen_keyobject(pTemplate, ulAttributeCount, - (CK_ULONG *)&new_objp, session_p, (CK_OBJECT_CLASS)~0UL, + &new_objp, session_p, (CK_OBJECT_CLASS)~0UL, (CK_KEY_TYPE)~0UL, 0, SOFT_UNWRAP_KEY, B_FALSE); if (rv != CKR_OK) return (rv); diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeystore.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeystore.c index 72e16bfe29..2524678a01 100644 --- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeystore.c +++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softKeystore.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2018, Joyent, Inc. + * Copyright 2020 Joyent, Inc. */ #include <crypt.h> @@ -2004,7 +2004,6 @@ soft_gen_crypt_key(uchar_t *pPIN, soft_object_t **key, CK_BYTE **saltdata) CK_KEY_TYPE keytype = CKK_AES; static CK_BBOOL truevalue = TRUE; soft_object_t *secret_key; - CK_OBJECT_HANDLE hKey; CK_ULONG passwd_size; if (pPIN == NULL) @@ -2062,15 +2061,13 @@ soft_gen_crypt_key(uchar_t *pPIN, soft_object_t **key, CK_BYTE **saltdata) params.pPassword = (CK_UTF8CHAR_PTR)pPIN; params.ulPasswordLen = &passwd_size; - rv = soft_gen_keyobject(tmpl, attrs, &hKey, &token_session, + rv = soft_gen_keyobject(tmpl, attrs, &secret_key, &token_session, CKO_SECRET_KEY, CKK_AES, 0, SOFT_GEN_KEY, B_TRUE); if (rv != CKR_OK) { return (rv); } - /* Obtain the secret object pointer. */ - secret_key = (soft_object_t *)hKey; keylen = OBJ_SEC_VALUE_LEN(secret_key); if ((OBJ_SEC_VALUE(secret_key) = malloc(keylen)) == NULL) { soft_delete_object(&token_session, secret_key, @@ -2129,7 +2126,6 @@ soft_gen_hmac_key(uchar_t *pPIN, soft_object_t **key, CK_BYTE **saltdata) CK_KEY_TYPE keytype = CKK_GENERIC_SECRET; static CK_BBOOL truevalue = TRUE; soft_object_t *secret_key; - CK_OBJECT_HANDLE hKey; CK_ULONG passwd_size; if (pPIN == NULL) @@ -2187,15 +2183,13 @@ soft_gen_hmac_key(uchar_t *pPIN, soft_object_t **key, CK_BYTE **saltdata) params.pPassword = (CK_UTF8CHAR_PTR)pPIN; params.ulPasswordLen = &passwd_size; - rv = soft_gen_keyobject(tmpl, attrs, &hKey, &token_session, + rv = soft_gen_keyobject(tmpl, attrs, &secret_key, &token_session, CKO_SECRET_KEY, CKK_GENERIC_SECRET, 0, SOFT_GEN_KEY, B_TRUE); if (rv != CKR_OK) { return (rv); } - /* Obtain the secret object pointer. */ - secret_key = (soft_object_t *)hKey; keylen = OBJ_SEC_VALUE_LEN(secret_key); if ((OBJ_SEC_VALUE(secret_key) = malloc(keylen)) == NULL) { soft_delete_object(&token_session, secret_key, diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softObject.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softObject.c index d5aae80910..27a3d95a08 100644 --- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softObject.c +++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softObject.c @@ -21,8 +21,9 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2020 Joyent, Inc. */ - #include <pthread.h> #include <stdlib.h> #include <security/cryptoki.h> @@ -165,7 +166,7 @@ C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, goto fail; } - new_object->session_handle = (CK_SESSION_HANDLE)NULL; + new_object->session_handle = CK_INVALID_HANDLE; /* * Add the newly created token object to the global * token object list in the slot struct. @@ -173,11 +174,13 @@ C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, soft_add_token_object_to_slot(new_object); OBJ_REFRELE(old_object); SES_REFRELE(session_p, lock_held); - *phNewObject = (CK_ULONG)new_object; + *phNewObject = set_objecthandle(new_object); return (CKR_OK); } + *phNewObject = set_objecthandle(new_object); + /* Insert new object into this session's object list */ soft_add_object_to_session(new_object, session_p); @@ -188,9 +191,6 @@ C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, OBJ_REFRELE(old_object); SES_REFRELE(session_p, lock_held); - /* set handle of the new object */ - *phNewObject = (CK_ULONG)new_object; - return (rv); fail: @@ -210,7 +210,7 @@ C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) CK_RV rv; soft_object_t *object_p; - soft_session_t *session_p = (soft_session_t *)(hSession); + soft_session_t *session_p; boolean_t lock_held = B_FALSE; CK_SESSION_HANDLE creating_session; @@ -218,21 +218,14 @@ C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) if (!softtoken_initialized) return (CKR_CRYPTOKI_NOT_INITIALIZED); - /* - * The reason that we don't call handle2session is because - * the argument hSession may not be the creating_session of - * the object to be destroyed, and we want to avoid the lock - * contention. The handle2session will be called later for - * the creating_session. - */ - if ((session_p == NULL) || - (session_p->magic_marker != SOFTTOKEN_SESSION_MAGIC)) { - return (CKR_SESSION_HANDLE_INVALID); - } + rv = handle2session(hSession, &session_p); + if (rv != CKR_OK) + return (rv); /* Obtain the object pointer. */ HANDLE2OBJECT_DESTROY(hObject, object_p, rv); if (rv != CKR_OK) { + SES_REFRELE(session_p, lock_held); return (rv); } @@ -247,12 +240,7 @@ C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) */ rv = soft_pin_expired_check(object_p); if (rv != CKR_OK) { - return (rv); - } - - /* Obtain the session pointer just for validity check. */ - rv = handle2session(hSession, &session_p); - if (rv != CKR_OK) { + SES_REFRELE(session_p, lock_held); return (rv); } @@ -287,15 +275,6 @@ C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) } /* - * Obtain the session pointer. Also, increment the session - * reference count. - */ - rv = handle2session(creating_session, &session_p); - if (rv != CKR_OK) { - return (rv); - } - - /* * Set OBJECT_IS_DELETING flag so any access to this * object will be rejected. */ diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softObject.h b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softObject.h index ea73e1a58d..8179497b29 100644 --- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softObject.h +++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softObject.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2020 Joyent, Inc. */ #ifndef _SOFTOBJECT_H @@ -32,6 +33,7 @@ extern "C" { #include <pthread.h> #include <security/pkcs11t.h> +#include <sys/avl.h> #include "softKeystoreUtil.h" #include "softSession.h" @@ -272,8 +274,8 @@ typedef struct x509_attr_cert { typedef struct certificate_obj { CK_CERTIFICATE_TYPE certificate_type; union { - x509_cert_t x509; - x509_attr_cert_t x509_attr; + x509_cert_t x509; + x509_attr_cert_t x509_attr; } cert_type_u; } certificate_obj_t; @@ -293,9 +295,11 @@ typedef attribute_info_t *CK_ATTRIBUTE_INFO_PTR; * This is the main structure of the Objects. */ typedef struct object { + avl_node_t node; + CK_OBJECT_HANDLE handle; /* Generic common fields. Always present */ uint_t version; /* for token objects only */ - CK_OBJECT_CLASS class; + CK_OBJECT_CLASS class; CK_KEY_TYPE key_type; CK_CERTIFICATE_TYPE cert_type; ulong_t magic_marker; @@ -745,38 +749,11 @@ typedef enum { #define OBJECT_REFCNT_WAITING 2 /* Waiting for object reference */ /* count to become zero */ -/* - * This macro is used to type cast an object handle to a pointer to - * the object struct. Also, it checks to see if the object struct - * is tagged with an object magic number. This is to detect when an - * application passes a bogus object pointer. - * Also, it checks to see if the object is in the deleting state that - * another thread is performing. If not, increment the object reference - * count by one. This is to prevent this object from being deleted by - * other thread. - */ -#define HANDLE2OBJECT_COMMON(hObject, object_p, rv, REFCNT_CODE) { \ - object_p = (soft_object_t *)(hObject); \ - if ((object_p == NULL) || \ - (object_p->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {\ - rv = CKR_OBJECT_HANDLE_INVALID; \ - } else { \ - (void) pthread_mutex_lock(&object_p->object_mutex); \ - if (!(object_p->obj_delete_sync & OBJECT_IS_DELETING)) { \ - REFCNT_CODE; \ - rv = CKR_OK; \ - } else { \ - rv = CKR_OBJECT_HANDLE_INVALID; \ - } \ - (void) pthread_mutex_unlock(&object_p->object_mutex); \ - } \ -} - #define HANDLE2OBJECT(hObject, object_p, rv) \ - HANDLE2OBJECT_COMMON(hObject, object_p, rv, object_p->obj_refcnt++) + rv = handle2object(hObject, &(object_p), B_TRUE); #define HANDLE2OBJECT_DESTROY(hObject, object_p, rv) \ - HANDLE2OBJECT_COMMON(hObject, object_p, rv, /* no refcnt increment */) + rv = handle2object(hObject, &(object_p), B_FALSE); #define OBJ_REFRELE(object_p) { \ @@ -788,13 +765,22 @@ typedef enum { (void) pthread_mutex_unlock(&object_p->object_mutex); \ } +extern pthread_mutex_t soft_object_mutex; +extern avl_tree_t soft_object_tree; + /* * Function Prototypes. */ + +CK_RV handle2object(CK_OBJECT_HANDLE hObject, soft_object_t **object_p, + boolean_t refhold); + +CK_ULONG set_objecthandle(soft_object_t *obj); + void soft_cleanup_object(soft_object_t *objp); CK_RV soft_add_object(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, - CK_ULONG *objecthandle_p, soft_session_t *sp); + CK_OBJECT_HANDLE_PTR objecthandle_p, soft_session_t *sp); void soft_delete_object(soft_session_t *sp, soft_object_t *objp, boolean_t force, boolean_t lock_held); diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softObjectUtil.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softObjectUtil.c index 9794565299..021ae200ed 100644 --- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softObjectUtil.c +++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softObjectUtil.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2020 Joyent, Inc. */ #include <pthread.h> @@ -28,6 +29,7 @@ #include <stdlib.h> #include <string.h> #include <security/cryptoki.h> +#include <sys/debug.h> #include "softGlobal.h" #include "softObject.h" #include "softSession.h" @@ -159,7 +161,7 @@ soft_copy_object(soft_object_t *old_object, soft_object_t **new_object, * Save the session handle of the C_CopyObject function * in the new copy of the session object. */ - new_objp->session_handle = (CK_SESSION_HANDLE)sp; + new_objp->session_handle = sp->handle; break; } @@ -220,13 +222,72 @@ soft_merge_object(soft_object_t *old_object, soft_object_t *new_object) old_object->extra_attrlistp = new_object->extra_attrlistp; } +/* + * Sets *object_p to the soft_object_t corresponding to hObject. If + * hObject is valid, and not in the deleting state, CKR_OK is returned, + * otherwise an error is returned. If hObject is valid and refhold is B_TRUE, + * the object is also held. + */ +CK_RV +handle2object(CK_OBJECT_HANDLE hObject, soft_object_t **object_p, + boolean_t refhold) +{ + soft_object_t *obj; + soft_object_t node; + + (void) memset(&node, 0, sizeof (node)); + node.handle = hObject; + + VERIFY0(pthread_mutex_lock(&soft_object_mutex)); + if ((obj = avl_find(&soft_object_tree, &node, NULL)) == NULL || + obj->magic_marker != SOFTTOKEN_OBJECT_MAGIC) { + VERIFY0(pthread_mutex_unlock(&soft_object_mutex)); + return (CKR_OBJECT_HANDLE_INVALID); + } + + (void) pthread_mutex_lock(&obj->object_mutex); + VERIFY0(pthread_mutex_unlock(&soft_object_mutex)); + + if (obj->obj_delete_sync & OBJECT_IS_DELETING) { + (void) pthread_mutex_unlock(&obj->object_mutex); + return (CKR_OBJECT_HANDLE_INVALID); + } + + if (refhold) + obj->obj_refcnt++; + + (void) pthread_mutex_unlock(&obj->object_mutex); + + *object_p = obj; + return (CKR_OK); +} + +CK_ULONG +set_objecthandle(soft_object_t *obj) +{ + avl_index_t where; + + (void) pthread_mutex_lock(&soft_object_mutex); + + do { + arc4random_buf(&obj->handle, sizeof (obj->handle)); + if (obj->handle == CK_INVALID_HANDLE) + continue; + } while (avl_find(&soft_object_tree, obj, &where) != NULL); + + avl_insert(&soft_object_tree, obj, where); + + (void) pthread_mutex_unlock(&soft_object_mutex); + + return (obj->handle); +} /* * Create a new object struct, and add it to the session's object list. */ CK_RV soft_add_object(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, - CK_ULONG *objecthandle_p, soft_session_t *sp) + CK_OBJECT_HANDLE_PTR objecthandle_p, soft_session_t *sp) { CK_RV rv = CKR_OK; @@ -278,24 +339,20 @@ soft_add_object(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, (void) pthread_mutex_destroy(&new_objp->object_mutex); goto fail_cleanup2; } - new_objp->session_handle = (CK_SESSION_HANDLE)NULL; + new_objp->session_handle = CK_INVALID_HANDLE; soft_add_token_object_to_slot(new_objp); - /* - * Type casting the address of an object struct to - * an object handle. - */ - *objecthandle_p = (CK_ULONG)new_objp; + + *objecthandle_p = set_objecthandle(new_objp); return (CKR_OK); } - new_objp->session_handle = (CK_SESSION_HANDLE)sp; + new_objp->session_handle = sp->handle; /* Add the new object to the session's object list. */ soft_add_object_to_session(new_objp, sp); - /* Type casting the address of an object struct to an object handle. */ - *objecthandle_p = (CK_ULONG)new_objp; + *objecthandle_p = set_objecthandle(new_objp); return (CKR_OK); @@ -470,6 +527,10 @@ soft_delete_object_cleanup(soft_object_t *objp, boolean_t force) */ soft_cleanup_object(objp); + (void) pthread_mutex_lock(&soft_object_mutex); + avl_remove(&soft_object_tree, objp); + (void) pthread_mutex_unlock(&soft_object_mutex); + /* Reset OBJECT_IS_DELETING flag. */ objp->obj_delete_sync &= ~OBJECT_IS_DELETING; @@ -506,7 +567,7 @@ soft_delete_object_cleanup(soft_object_t *objp, boolean_t force) */ void soft_delete_object(soft_session_t *sp, soft_object_t *objp, - boolean_t force, boolean_t lock_held) + boolean_t force, boolean_t lock_held) { /* @@ -801,8 +862,7 @@ soft_find_objects(soft_session_t *sp, CK_OBJECT_HANDLE *obj_found, (void) pthread_mutex_lock(&obj->object_mutex); /* a sanity check to make sure the obj is still valid */ if (obj->magic_marker == SOFTTOKEN_OBJECT_MAGIC) { - obj_found[num_obj_found] = - (CK_OBJECT_HANDLE)obj; + obj_found[num_obj_found] = obj->handle; num_obj_found++; } (void) pthread_mutex_unlock(&obj->object_mutex); diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSSL.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSSL.c index f836ddc009..6e22ad745b 100644 --- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSSL.c +++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSSL.c @@ -21,7 +21,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright 2018, Joyent, Inc. + * + * Copyright 2020 Joyent, Inc. */ #include <fcntl.h> @@ -999,23 +1000,23 @@ soft_add_derived_key(CK_ATTRIBUTE_PTR tmpl, CK_ULONG attrcount, /* ... and, if it needs to persist, write on the token */ if (IS_TOKEN_OBJECT(secret_key)) { - secret_key->session_handle = (CK_SESSION_HANDLE)NULL; + secret_key->session_handle = CK_INVALID_HANDLE; soft_add_token_object_to_slot(secret_key); rv = soft_put_object_to_keystore(secret_key); if (rv != CKR_OK) { soft_delete_token_object(secret_key, B_FALSE, B_FALSE); return (rv); } - *phKey = (CK_OBJECT_HANDLE)secret_key; + *phKey = set_objecthandle(secret_key); return (CKR_OK); } /* Add the new object to the session's object list. */ soft_add_object_to_session(secret_key, sp); - secret_key->session_handle = (CK_SESSION_HANDLE)sp; + secret_key->session_handle = sp->handle; - *phKey = (CK_OBJECT_HANDLE)secret_key; + *phKey = set_objecthandle(secret_key); return (rv); } diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSession.h b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSession.h index cede49858f..c8f22781f8 100644 --- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSession.h +++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSession.h @@ -21,6 +21,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2020 Joyent, Inc. */ #ifndef _SOFTSESSION_H @@ -32,7 +34,7 @@ extern "C" { #include <pthread.h> #include <security/pkcs11t.h> - +#include <sys/avl.h> #define SOFTTOKEN_SESSION_MAGIC 0xECF00002 @@ -71,6 +73,8 @@ typedef struct crypto_active_op { #define CRYPTO_KEY_DIGESTED 3 /* A C_DigestKey() was called */ typedef struct session { + avl_node_t node; + CK_SESSION_HANDLE handle; ulong_t magic_marker; /* magic # be validated for integrity */ pthread_mutex_t session_mutex; /* session's mutex lock */ pthread_cond_t ses_free_cond; /* cond variable for signal and wait */ @@ -168,6 +172,7 @@ typedef struct ses_to_be_freed_list { extern pthread_mutex_t soft_sessionlist_mutex; extern soft_session_t *soft_session_list; +extern avl_tree_t soft_session_tree; extern int all_sessions_closing; extern CK_ULONG soft_session_cnt; /* the number of opened sessions */ extern CK_ULONG soft_session_rw_cnt; /* the number of opened R/W sessions */ diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSessionUtil.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSessionUtil.c index a1302a1649..254f6438e6 100644 --- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSessionUtil.c +++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softSessionUtil.c @@ -21,6 +21,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2020 Joyent, Inc. */ #include <md5.h> @@ -95,7 +97,6 @@ soft_delete_all_sessions(boolean_t force) } - /* * Create a new session struct, and add it to the session linked list. * @@ -104,9 +105,8 @@ soft_delete_all_sessions(boolean_t force) */ CK_RV soft_add_session(CK_FLAGS flags, CK_VOID_PTR pApplication, - CK_NOTIFY notify, CK_ULONG *sessionhandle_p) + CK_NOTIFY notify, CK_ULONG *sessionhandle_p) { - soft_session_t *new_sp = NULL; /* Allocate a new session struct */ @@ -152,6 +152,16 @@ soft_add_session(CK_FLAGS flags, CK_VOID_PTR pApplication, /* Acquire the global session list lock */ (void) pthread_mutex_lock(&soft_sessionlist_mutex); + /* Generate a unique session handle. */ + do { + arc4random_buf(&new_sp->handle, sizeof (new_sp->handle)); + if (new_sp->handle == CK_INVALID_HANDLE) + continue; + } while (avl_find(&soft_session_tree, new_sp, NULL) != NULL); + + avl_add(&soft_session_tree, new_sp); + *sessionhandle_p = new_sp->handle; + /* Insert the new session in front of session list */ if (soft_session_list == NULL) { soft_session_list = new_sp; @@ -164,8 +174,6 @@ soft_add_session(CK_FLAGS flags, CK_VOID_PTR pApplication, soft_session_list = new_sp; } - /* Type casting the address of a session struct to a session handle */ - *sessionhandle_p = (CK_ULONG)new_sp; ++soft_session_cnt; if (flags & CKF_RW_SESSION) ++soft_session_rw_cnt; @@ -276,6 +284,8 @@ soft_delete_session(soft_session_t *session_p, } } + avl_remove(&soft_session_tree, session_p); + --soft_session_cnt; if (session_p->flags & CKF_RW_SESSION) --soft_session_rw_cnt; @@ -379,7 +389,7 @@ soft_delete_session(soft_session_t *session_p, free(fcontext); } - /* Reset SESSION_IS_CLOSIN flag. */ + /* Reset SESSION_IS_CLOSING flag. */ session_p->ses_close_sync &= ~SESSION_IS_CLOSING; (void) pthread_mutex_unlock(&session_p->session_mutex); @@ -410,7 +420,8 @@ CK_RV handle2session(CK_SESSION_HANDLE hSession, soft_session_t **session_p) { - soft_session_t *sp = (soft_session_t *)(hSession); + soft_session_t *sp; + soft_session_t node; /* * No need to hold soft_sessionlist_mutex as we are @@ -420,11 +431,19 @@ handle2session(CK_SESSION_HANDLE hSession, soft_session_t **session_p) return (CKR_SESSION_CLOSED); } + (void) memset(&node, 0, sizeof (node)); + node.handle = hSession; + + (void) pthread_mutex_lock(&soft_sessionlist_mutex); + + sp = avl_find(&soft_session_tree, &node, NULL); if ((sp == NULL) || (sp->magic_marker != SOFTTOKEN_SESSION_MAGIC)) { + (void) pthread_mutex_unlock(&soft_sessionlist_mutex); return (CKR_SESSION_HANDLE_INVALID); } (void) pthread_mutex_lock(&sp->session_mutex); + (void) pthread_mutex_unlock(&soft_sessionlist_mutex); if (sp->ses_close_sync & SESSION_IS_CLOSING) { (void) pthread_mutex_unlock(&sp->session_mutex); |