softKeysUtil.c revision 6ea3c0609e50782557505b88bb391b786bca32c9
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * CDDL HEADER START
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The contents of this file are subject to the terms of the
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Common Development and Distribution License (the "License").
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * You may not use this file except in compliance with the License.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * or http://www.opensolaris.org/os/licensing.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * See the License for the specific language governing permissions
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * and limitations under the License.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * When distributing Covered Code, include this CDDL HEADER in each
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * If applicable, add the following below this CDDL HEADER, with the
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * fields enclosed by brackets "[]" replaced with your own identifying
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * information: Portions Copyright [yyyy] [name of copyright owner]
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * CDDL HEADER END
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Use is subject to license terms.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra#define local_min(a, b) ((a) < (b) ? (a) : (b))
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrasoft_pkcs12_pbe(soft_session_t *, CK_MECHANISM_PTR, soft_object_t *);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Create a temporary key object struct by filling up its template attributes.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrasoft_gen_keyobject(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra CK_ULONG *objecthandle_p, soft_session_t *sp,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra CK_OBJECT_CLASS class, CK_KEY_TYPE key_type, CK_ULONG keylen, CK_ULONG mode,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra new_objp = calloc(1, sizeof (soft_object_t));
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Validate attribute template and fill in the attributes
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * in the soft_object_t.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rv = soft_build_key(pTemplate, ulCount, new_objp, class, key_type,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * If generating a key is an internal request (i.e. not a C_XXX
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * API request), then skip the following checks.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rv = soft_object_write_access_check(sp, new_objp);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Initialize the rest of stuffs in soft_object_t. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra (void) pthread_mutex_init(&new_objp->object_mutex, NULL);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra new_objp->magic_marker = SOFTTOKEN_OBJECT_MAGIC;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Write the new token object to the keystore */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra new_objp->session_handle = (CK_SESSION_HANDLE)NULL;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Type casting the address of an object struct to
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * an object handle.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra new_objp->session_handle = (CK_SESSION_HANDLE)sp;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Add the new object to the session's object list. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Type casting the address of an object struct to an object handle. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * When any error occurs after soft_build_key(), we will need to
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * clean up the memory allocated by the soft_build_key().
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The storage allocated inside of this object should have
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * been cleaned up by the soft_build_key() if it failed.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Therefore, we can safely free the object.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrasoft_genkey(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra pMechanism->ulParameterLen != sizeof (CK_VERSION))
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra key_type = *((CK_KEY_TYPE*)pTemplate[i].pValue);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Make sure that parameters were given for this
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra for (i = 0; i < ulCount; i++) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra key_type = *((CK_KEY_TYPE*)pTemplate[i].pValue);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* If a keytype was specified, it had better be CKK_RC4 */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* If key length was specified, it better be 16 bytes */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Make sure that parameters were given for this
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Create a new object for secret key. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rv = soft_gen_keyobject(pTemplate, ulCount, phKey, session_p,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra CKO_SECRET_KEY, key_type, keylen, SOFT_GEN_KEY, B_FALSE);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Obtain the secret object pointer. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Set up key value len since it is not a required
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * attribute for C_GenerateKey.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra keylen = OBJ_SEC_VALUE_LEN(secret_key) = DES_KEYSIZE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Set up key value len since it is not a required
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * attribute for C_GenerateKey.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra keylen = OBJ_SEC_VALUE_LEN(secret_key) = DES2_KEYSIZE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Set up key value len since it is not a required
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * attribute for C_GenerateKey.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra keylen = OBJ_SEC_VALUE_LEN(secret_key) = DES3_KEYSIZE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra secret_key->bool_attr_mask |= DERIVE_BOOL_ON;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* FALLTHRU */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * PKCS#11 does not allow one to specify key
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * sizes for DES and 3DES, so we must set it here
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * when using PBKD2 algorithms.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra OBJ_SEC_VALUE_LEN(secret_key) = DES3_KEYSIZE;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if ((OBJ_SEC_VALUE(secret_key) = malloc(keylen)) == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra soft_delete_token_object(secret_key, B_FALSE, B_FALSE);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Use the PBE algorithm described in PKCS#11 section
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * 12.33 to derive the key.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rv = soft_pkcs12_pbe(session_p, pMechanism, secret_key);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Generate keys using PKCS#5 PBKD2 algorithm */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rv = soft_generate_pkcs5_pbkdf2_key(session_p, pMechanism,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Perform weak key checking for DES and DES3. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* We got a weak secret key. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* If this fails, bail out */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* Perform weak key checking for DES and DES3. */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /* We got a weak key, retry! */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Copy over the SSL client version For SSL mechs
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * The first two bytes of the key is the version
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra } while (rv != CKR_OK && retry < KEYGEN_RETRY);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra soft_delete_token_object(secret_key, B_FALSE, B_FALSE);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * All the info has been filled, so we can write to
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * keystore now.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra rv = soft_put_object_to_keystore(secret_key);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra soft_delete_token_object(secret_key, B_FALSE, B_FALSE);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misrasoft_genkey_pair(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicAttrCount,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateAttrCount,
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey)
case CKM_DSA_KEY_PAIR_GEN:
case CKM_DH_PKCS_KEY_PAIR_GEN:
case CKM_EC_KEY_PAIR_GEN:
return (CKR_MECHANISM_INVALID);
return (rv);
return (rv);
switch (key_type) {
case CKK_RSA:
case CKK_DSA:
case CKK_DH:
case CKK_EC:
return (rv);
return (rv);
return (rv);
case CKK_GENERIC_SECRET:
return (CKR_OK);
return (CKR_ATTRIBUTE_VALUE_INVALID);
case CKK_RC4:
case CKK_AES:
case CKK_BLOWFISH:
return (CKR_ATTRIBUTE_VALUE_INVALID);
case CKK_DES:
return (CKR_OK);
return (CKR_ATTRIBUTE_VALUE_INVALID);
case CKK_DES2:
return (CKR_OK);
return (CKR_ATTRIBUTE_VALUE_INVALID);
return (CKR_MECHANISM_INVALID);
return (CKR_OK);
#define PBE_CEIL(a, b) (((a)/(b)) + (((a)%(b)) > 0))
static CK_RV
CK_ULONG c, i, j, k;
return (CKR_MECHANISM_INVALID);
if (D == NULL) {
goto cleanup;
if (B == NULL) {
goto cleanup;
* Slen = buffSize * CEIL(SaltLength/buffSize)
* Plen = buffSize * CEIL(PasswordLength/buffSize)
if (I == NULL) {
goto cleanup;
P = I + Slen;
if (A == NULL) {
goto cleanup;
goto cleanup;
goto cleanup;
goto digest_done;
goto digest_done;
goto digest_done;
goto digest_done;
goto cleanup;
q += cbit;
free(A);
if (Ai) {
free(B);
free(D);
free(I);
return (rv);
case CKM_DH_PKCS_DERIVE:
return (rv);
B_FALSE);
return (rv);
case CKM_ECDH1_DERIVE:
return (rv);
B_FALSE);
return (rv);
case CKM_SHA1_KEY_DERIVATION:
goto common;
case CKM_MD5_KEY_DERIVATION:
goto common;
goto common;
goto common;
goto common;
return (rv);
B_FALSE);
return (rv);
B_FALSE);
return (rv);
B_FALSE);
return (rv);
NULL) {
B_FALSE);
return (CKR_HOST_MEMORY);
return (CKR_ARGUMENTS_BAD);
case CKM_TLS_PRF:
return (CKR_ARGUMENTS_BAD);
return (CKR_TEMPLATE_INCONSISTENT);
return (derive_tls_prf(
return (CKR_MECHANISM_INVALID);
return (rv);
if (new_sensitive) {
if (new_extractable) {
static CK_RV
CK_ULONG i, j;
return (CKR_OPERATION_ACTIVE);
goto cleanup;
goto cleanup;
return (rv);
static CK_RV
return (rv);
return (CKR_MECHANISM_PARAM_INVALID);
return (CKR_DATA_INVALID);
return (CKR_MECHANISM_PARAM_INVALID);
return (rv);
B_FALSE);
return (CKR_KEY_SIZE_RANGE);
blocks++;
B_FALSE);
return (CKR_HOST_MEMORY);
* PRF iteration/concatenations so that when the
CK_BYTE *s;
return (rv);
case CKM_DES_CBC_PAD:
case CKM_DES3_CBC_PAD:
case CKM_AES_CBC_PAD:
return (CKR_MECHANISM_INVALID);
case CKM_RSA_PKCS:
case CKM_RSA_X_509:
case CKM_DES_ECB:
case CKM_DES3_ECB:
case CKM_AES_ECB:
case CKM_DES_CBC:
case CKM_DES3_CBC:
case CKM_AES_CBC:
case CKM_AES_CTR:
case CKM_BLOWFISH_CBC:
return (CKR_MECHANISM_INVALID);
return (CKR_MECHANISM_INVALID);
return (rv);
return (CKR_HOST_MEMORY);
goto cleanup_wrap;
case CKM_DES_ECB:
case CKM_DES3_ECB:
case CKM_AES_ECB:
case CKM_DES_CBC:
case CKM_DES3_CBC:
case CKM_AES_CBC:
case CKM_BLOWFISH_CBC:
case CKK_DES:
case CKK_DES2:
case CKK_DES3:
case CKK_AES:
case CKK_BLOWFISH:
goto cleanup_wrap;
goto cleanup_wrap;
goto cleanup_wrap;
return (rv);
static CK_RV
CK_ULONG i;
for (i = 0; i < ulAttributeCount; i++) {
switch (mechtype) {
case CKM_DES_ECB:
case CKM_DES3_ECB:
case CKM_AES_ECB:
case CKM_DES_CBC:
case CKM_DES3_CBC:
case CKM_AES_CBC:
case CKM_BLOWFISH_CBC:
switch (keytype) {
case CKK_DES:
case CKK_DES2:
case CKK_DES3:
if (isValueLen)
return (CKR_TEMPLATE_INCONSISTENT);
case CKK_GENERIC_SECRET:
case CKK_RC4:
case CKK_AES:
case CKK_BLOWFISH:
if (!isValueLen)
return (CKR_TEMPLATE_INCOMPLETE);
return (CKR_FUNCTION_NOT_SUPPORTED);
if (isValueLen)
return (CKR_TEMPLATE_INCONSISTENT);
return (CKR_OK);
for (i = 0; i < ulAttributeCount; i++) {
return (CKR_TEMPLATE_INCOMPLETE);
case CKM_RSA_PKCS:
case CKM_RSA_X_509:
case CKM_DES_ECB:
case CKM_DES3_ECB:
case CKM_AES_ECB:
case CKM_DES_CBC:
case CKM_DES3_CBC:
case CKM_AES_CBC:
case CKM_BLOWFISH_CBC:
return (CKR_MECHANISM_INVALID);
case CKM_DES_CBC_PAD:
case CKM_DES3_CBC_PAD:
case CKM_AES_CBC_PAD:
return (CKR_MECHANISM_INVALID);
return (CKR_MECHANISM_INVALID);
return (rv);
goto cleanup_unwrap;
goto cleanup_unwrap;
&plain_len);
goto cleanup_unwrap;
goto cleanup_unwrap;
&plain_len);
goto cleanup_unwrap;
goto cleanup_unwrap;
NULL) {
goto cleanup_unwrap;
case CKK_DES:
case CKK_DES2:
case CKK_DES3:
case CKK_GENERIC_SECRET:
case CKK_RC4:
case CKK_AES:
case CKK_BLOWFISH:
goto cleanup_unwrap;
goto cleanup_unwrap;
goto cleanup_unwrap;
goto cleanup_unwrap;
goto cleanup_unwrap;
return (CKR_OK);
return (rv);