/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * 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. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include #include #include #include #include #include #include #include #include #include "softGlobal.h" #include "softCrypt.h" #include "softSession.h" #include "softObject.h" #include "softKeys.h" #include "softKeystore.h" #include "softKeystoreUtil.h" #include "softRandom.h" #include "softMAC.h" #include "softOps.h" soft_session_t token_session; /* * Generate a 16-byte Initialization Vector (IV). */ CK_RV soft_gen_iv(CK_BYTE *iv) { return (soft_nzero_random_generator(iv, 16)); } /* * soft_gen_hashed_pin() * * Arguments: * * pPin: pointer to caller provided Pin * result: output argument which contains the address of the * pointer to the hashed pin * salt: input argument (if non-NULL), or * output argument (if NULL): * address of pointer to the "salt" of the hashed pin * * Description: * * Generate a hashed pin using system provided crypt(3C) function. * * Returns: * * 0: no error * -1: some error occurred while generating the hashed pin * */ int soft_gen_hashed_pin(CK_UTF8CHAR_PTR pPin, char **result, char **salt) { uid_t uid; struct passwd pwd, *pw; char pwdbuf[PWD_BUFFER_SIZE]; boolean_t new_salt = B_FALSE; /* * We need to get the passwd entry of the application, which is required * by the crypt_gensalt() below. */ uid = geteuid(); if (getpwuid_r(uid, &pwd, pwdbuf, PWD_BUFFER_SIZE, &pw) != 0) { return (-1); } if (*salt == NULL) { new_salt = B_TRUE; /* * crypt_gensalt() will allocate memory to store the new salt. * on return. */ if ((*salt = crypt_gensalt(NULL, pw)) == NULL) { return (-1); } } if ((*result = crypt((char *)pPin, *salt)) == NULL) { if (new_salt) free(*salt); return (-1); } return (0); } /* * Authenticate user's PIN for C_Login. */ CK_RV soft_verify_pin(CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) { char *user_cryptpin = NULL; char *ks_cryptpin = NULL; char *salt = NULL; uchar_t *tmp_pin = NULL; boolean_t pin_initialized = B_FALSE; CK_RV rv = CKR_OK; /* * Check to see if keystore is initialized. */ rv = soft_keystore_pin_initialized(&pin_initialized, &ks_cryptpin, B_FALSE); if (rv != CKR_OK) return (rv); /* * Authenticate user's PIN for C_Login. */ if (pin_initialized) { if (soft_keystore_get_pin_salt(&salt) < 0) { rv = CKR_FUNCTION_FAILED; goto cleanup; } /* * Generate the hashed value based on the user's supplied pin. */ tmp_pin = malloc(ulPinLen + 1); if (tmp_pin == NULL) { rv = CKR_HOST_MEMORY; goto cleanup; } (void) memcpy(tmp_pin, pPin, ulPinLen); tmp_pin[ulPinLen] = '\0'; if (soft_gen_hashed_pin(tmp_pin, &user_cryptpin, &salt) < 0) { rv = CKR_FUNCTION_FAILED; goto cleanup; } /* * Compare hash value of the user supplied PIN with * hash value of the keystore PIN. */ if (strcmp(user_cryptpin, ks_cryptpin) != 0) { rv = CKR_PIN_INCORRECT; goto cleanup; } /* * Provide the user's PIN to low-level keystore so that * it can use it to generate encryption key as needed for * encryption/decryption of the private objects in * keystore. */ if (soft_keystore_authpin(tmp_pin) != 0) { rv = CKR_FUNCTION_FAILED; } else { rv = CKR_OK; } goto cleanup; } else { /* * The PIN is not initialized in the keystore * We will let it pass the authentication anyway but set the * "userpin_change_needed" flag so that the application * will get CKR_PIN_EXPIRED by other C_functions such as * C_CreateObject, C_FindObjectInit, C_GenerateKey etc. */ soft_slot.userpin_change_needed = 1; rv = CKR_OK; } cleanup: if (salt) free(salt); if (tmp_pin) free(tmp_pin); if (ks_cryptpin) free(ks_cryptpin); return (rv); } /* * The second level C_SetPIN function. */ CK_RV soft_setpin(CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldPinLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewPinLen) { char *user_cryptpin = NULL; char *ks_cryptpin = NULL; char *salt = NULL; boolean_t pin_initialized = B_FALSE; uchar_t *tmp_old_pin = NULL, *tmp_new_pin = NULL; CK_RV rv = CKR_OK; /* * Check to see if keystore is initialized. */ rv = soft_keystore_pin_initialized(&pin_initialized, &ks_cryptpin, B_FALSE); if (rv != CKR_OK) return (rv); /* * Authenticate user's PIN for C_SetPIN. */ if (pin_initialized) { /* * Generate the hashed value based on the user supplied PIN. */ if (soft_keystore_get_pin_salt(&salt) < 0) { rv = CKR_FUNCTION_FAILED; goto cleanup; } tmp_old_pin = malloc(ulOldPinLen + 1); if (tmp_old_pin == NULL) { rv = CKR_HOST_MEMORY; goto cleanup; } (void) memcpy(tmp_old_pin, pOldPin, ulOldPinLen); tmp_old_pin[ulOldPinLen] = '\0'; if (soft_gen_hashed_pin(tmp_old_pin, &user_cryptpin, &salt) < 0) { rv = CKR_FUNCTION_FAILED; goto cleanup; } /* * Compare hashed value of the user supplied PIN with the * hashed value of the keystore PIN. */ if (strcmp(user_cryptpin, ks_cryptpin) != 0) { rv = CKR_PIN_INCORRECT; goto cleanup; } } else { /* * This is the first time to setpin, the oldpin must be * "changeme". */ if (strncmp("changeme", (const char *)pOldPin, ulOldPinLen) != 0) { rv = CKR_PIN_INCORRECT; goto cleanup; } } tmp_new_pin = malloc(ulNewPinLen + 1); if (tmp_new_pin == NULL) { rv = CKR_HOST_MEMORY; goto cleanup; } (void) memcpy(tmp_new_pin, pNewPin, ulNewPinLen); tmp_new_pin[ulNewPinLen] = '\0'; /* * Set the new pin after the old pin is authenticated. */ if (soft_keystore_setpin(tmp_old_pin, tmp_new_pin, B_FALSE)) { rv = CKR_FUNCTION_FAILED; goto cleanup; } else { (void) pthread_mutex_lock(&soft_giant_mutex); soft_slot.userpin_change_needed = 0; (void) pthread_mutex_unlock(&soft_giant_mutex); rv = CKR_OK; } cleanup: if (salt) free(salt); if (ks_cryptpin) free(ks_cryptpin); if (tmp_old_pin) free(tmp_old_pin); if (tmp_new_pin) free(tmp_new_pin); return (rv); } /* * soft_keystore_pack_obj() * * Arguments: * * obj: pointer to the soft_object_t of the token object to * be packed * ks_buf: output argument which contains the address of the * pointer to the buf of the packed token object * soft_keystore_pack_obj() will allocate memory for the buf, * it is caller's responsibility to free it. * len: output argument which contains the address of the * buffer length of the packed token object * * Description: * * Pack the in-core token object into the keystore format. * * Returns: * * CKR_OK: no error * Other: some error occurred while packing the object * */ CK_RV soft_keystore_pack_obj(soft_object_t *obj, uchar_t **ks_buf, size_t *len) { ks_obj_hdr_t hdr; ks_attr_hdr_t attr_hdr; CK_ATTRIBUTE_INFO_PTR extra_attr; int num_attrs = 0; ulong_t len_attrs = 0; size_t ks_len; uchar_t *buf, *buf1; CK_RV rv; int i; (void) memset(&hdr, 0, sizeof (ks_obj_hdr_t)); /* * The first part of the packed format contains * the ks_obj_hdr_t struct. */ hdr.class = SWAP64((uint64_t)obj->class); hdr.key_type = SWAP64((uint64_t)obj->key_type); hdr.cert_type = SWAP64((uint64_t)obj->cert_type); hdr.bool_attr_mask = SWAP64(obj->bool_attr_mask); hdr.mechanism = SWAP64((uint64_t)obj->mechanism); hdr.object_type = obj->object_type; /* * The second part of the packed format contains * the attributes from the extra atrribute list. */ extra_attr = obj->extra_attrlistp; while (extra_attr) { num_attrs++; len_attrs += ROUNDUP(extra_attr->attr.ulValueLen, 8); extra_attr = extra_attr->next; } hdr.num_attrs = SWAP32(num_attrs); ks_len = soft_pack_object_size(obj); ks_len += sizeof (ks_obj_hdr_t) + len_attrs + 2 * num_attrs * sizeof (uint64_t); buf = calloc(1, ks_len); if (buf == NULL) { return (CKR_HOST_MEMORY); } (void) memcpy(buf, &hdr, sizeof (ks_obj_hdr_t)); buf1 = buf + sizeof (ks_obj_hdr_t); extra_attr = obj->extra_attrlistp; for (i = 0; i < num_attrs; i++) { attr_hdr.type = SWAP64((uint64_t)extra_attr->attr.type); attr_hdr.ulValueLen = SWAP64((uint64_t)extra_attr->attr.ulValueLen); (void) memcpy(buf1, &attr_hdr, sizeof (ks_attr_hdr_t)); buf1 = buf1 + sizeof (ks_attr_hdr_t); (void) memcpy(buf1, extra_attr->attr.pValue, extra_attr->attr.ulValueLen); buf1 = buf1 + ROUNDUP(extra_attr->attr.ulValueLen, 8); extra_attr = extra_attr->next; } /* * The third part of the packed format contains * the key itself. */ rv = soft_pack_object(obj, buf1); *len = ks_len; *ks_buf = buf; return (rv); } /* * soft_keystore_unpack_obj() * * Arguments: * * obj: pointer to the soft_object_t to store the unpacked * token object * ks_obj: input argument which contains the pointer to the * ks_obj_t struct of packed token object to be unpacked * * Description: * * Unpack the token object in keystore format to in-core soft_object_t. * * Returns: * * CKR_OK: no error * Other: some error occurred while unpacking the object * */ CK_RV soft_keystore_unpack_obj(soft_object_t *obj, ks_obj_t *ks_obj) { CK_RV rv; ks_obj_hdr_t *hdr; ks_attr_hdr_t *attr_hdr; CK_ATTRIBUTE template; int i; uchar_t *buf; /* * Unpack the common area. */ (void) strcpy((char *)obj->ks_handle.name, (char *)ks_obj->ks_handle.name); obj->ks_handle.public = ks_obj->ks_handle.public; /* LINTED: pointer alignment */ hdr = (ks_obj_hdr_t *)ks_obj->buf; obj->version = ks_obj->obj_version; obj->class = (CK_OBJECT_CLASS)(SWAP64(hdr->class)); obj->key_type = (CK_KEY_TYPE)(SWAP64(hdr->key_type)); obj->cert_type = (CK_CERTIFICATE_TYPE)(SWAP64(hdr->cert_type)); obj->bool_attr_mask = SWAP64(hdr->bool_attr_mask); obj->mechanism = (CK_MECHANISM_TYPE)(SWAP64(hdr->mechanism)); obj->object_type = hdr->object_type; /* * Initialize other stuffs which were not from keystore. */ (void) pthread_mutex_init(&obj->object_mutex, NULL); obj->magic_marker = SOFTTOKEN_OBJECT_MAGIC; obj->session_handle = (CK_SESSION_HANDLE)NULL; buf = ks_obj->buf + sizeof (ks_obj_hdr_t); /* * Unpack extra attribute list. */ for (i = 0; i < SWAP32(hdr->num_attrs); i++) { /* LINTED: pointer alignment */ attr_hdr = (ks_attr_hdr_t *)buf; (void) memset(&template, 0, sizeof (CK_ATTRIBUTE)); template.type = (CK_ATTRIBUTE_TYPE)(SWAP64(attr_hdr->type)); template.ulValueLen = (CK_ULONG)(SWAP64(attr_hdr->ulValueLen)); buf = buf + sizeof (ks_attr_hdr_t); /* Allocate storage for the value of the attribute. */ if (template.ulValueLen > 0) { template.pValue = malloc(template.ulValueLen); if (template.pValue == NULL) { return (CKR_HOST_MEMORY); } (void) memcpy(template.pValue, buf, template.ulValueLen); } rv = soft_add_extra_attr(&template, obj); if (template.pValue) { free(template.pValue); } if (rv != CKR_OK) { return (rv); } buf = buf + ROUNDUP(template.ulValueLen, 8); } /* * Unpack the key itself. */ rv = soft_unpack_object(obj, buf); return (rv); } /* * soft_unpack_obj_attribute() * * Arguments: * * buf: contains the packed data (attributes) from keystore * key_dest: the key attribute will be unpacked and save in key_dest * cert_dest: the certificate attribute will be unpacked an * in cert_dest * offset: length of the current attribute occupies. * The caller should use this returned "offset" to * advance the buffer pointer to next attribute. * cert: TRUE for certificate (use cert_dest) * FALSE for key (use key_dest) * * Description: * * Unpack the attribute from keystore format to the big integer format. * * Returns: * * CKR_OK: no error * Other: some error occurred while unpacking the object attribute * */ CK_RV soft_unpack_obj_attribute(uchar_t *buf, biginteger_t *key_dest, cert_attr_t **cert_dest, ulong_t *offset, boolean_t cert) { CK_RV rv; CK_ATTRIBUTE template; /* LINTED: pointer alignment */ template.ulValueLen = SWAP64(*(uint64_t *)buf); buf = buf + sizeof (uint64_t); template.pValue = malloc(template.ulValueLen); if (template.pValue == NULL) { return (CKR_HOST_MEMORY); } (void) memcpy(template.pValue, buf, template.ulValueLen); if (cert) { rv = get_cert_attr_from_template(cert_dest, &template); } else { rv = get_bigint_attr_from_template(key_dest, &template); } free(template.pValue); if (rv != CKR_OK) { return (rv); } *offset = sizeof (uint64_t) + template.ulValueLen; return (CKR_OK); } /* * Calculate the total buffer length required to store the * object key (the third part) in a keystore format. */ ulong_t soft_pack_object_size(soft_object_t *objp) { CK_OBJECT_CLASS class = objp->class; CK_KEY_TYPE keytype = objp->key_type; CK_CERTIFICATE_TYPE certtype = objp->cert_type; switch (class) { case CKO_PUBLIC_KEY: switch (keytype) { case CKK_RSA: /* * modulus_bits + modulus_len + modulus + * pubexpo_len + pubexpo */ return (ROUNDUP(((biginteger_t *) OBJ_PUB_RSA_MOD(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PUB_RSA_PUBEXPO(objp))->big_value_len, 8) + 3 * sizeof (uint64_t)); case CKK_DSA: /* * prime_len + prime + subprime_len + subprime + * base_len + base + value_len + value */ return (ROUNDUP(((biginteger_t *) OBJ_PUB_DSA_PRIME(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PUB_DSA_SUBPRIME(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PUB_DSA_BASE(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PUB_DSA_VALUE(objp))->big_value_len, 8) + 4 * sizeof (uint64_t)); case CKK_DH: /* * prime_len + prime + base_len + base + * value_len + value */ return (ROUNDUP(((biginteger_t *) OBJ_PUB_DH_PRIME(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PUB_DH_BASE(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PUB_DH_VALUE(objp))->big_value_len, 8) + 3 * sizeof (uint64_t)); case CKK_X9_42_DH: /* * prime_len + prime + base_len + base + * subprime_len + subprime + value_len + value */ return (ROUNDUP(((biginteger_t *) OBJ_PUB_DH942_PRIME(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PUB_DH942_BASE(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PUB_DH942_SUBPRIME(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PUB_DH942_VALUE(objp))->big_value_len, 8) + 4 * sizeof (uint64_t)); } /* keytype */ break; case CKO_PRIVATE_KEY: switch (keytype) { case CKK_RSA: /* * modulus_len + modulus + pubexpo_len + pubexpo + * priexpo_len + priexpo + prime1_len + prime1 + * prime2_len + prime2 + expo1_len + expo1 + * expo2_len + expo2 + coef_len + coef */ return (ROUNDUP(((biginteger_t *) OBJ_PRI_RSA_MOD(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PRI_RSA_PUBEXPO(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PRI_RSA_PRIEXPO(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PRI_RSA_PRIME1(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PRI_RSA_PRIME2(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PRI_RSA_EXPO1(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PRI_RSA_EXPO2(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PRI_RSA_COEF(objp))->big_value_len, 8) + 8 * sizeof (uint64_t)); case CKK_DSA: /* * prime_len + prime + subprime_len + subprime + * base_len + base + value_len + value */ return (ROUNDUP(((biginteger_t *) OBJ_PRI_DSA_PRIME(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PRI_DSA_SUBPRIME(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PRI_DSA_BASE(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PRI_DSA_VALUE(objp))->big_value_len, 8) + 4 * sizeof (uint64_t)); case CKK_DH: /* * value_bits + prime_len + prime + base_len + base + * value_len + value */ return (ROUNDUP(((biginteger_t *) OBJ_PRI_DH_PRIME(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PRI_DH_BASE(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PRI_DH_VALUE(objp))->big_value_len, 8) + 4 * sizeof (uint64_t)); case CKK_X9_42_DH: /* * prime_len + prime + base_len + base + * subprime_len + subprime + value_len + value */ return (ROUNDUP(((biginteger_t *) OBJ_PRI_DH942_PRIME(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PRI_DH942_BASE(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PRI_DH942_SUBPRIME(objp))->big_value_len, 8) + ROUNDUP(((biginteger_t *) OBJ_PRI_DH942_VALUE(objp))->big_value_len, 8) + 4 * sizeof (uint64_t)); } /* keytype */ break; case CKO_SECRET_KEY: /* * value_len + value */ return (ROUNDUP(OBJ_SEC_VALUE_LEN(objp), 8) + sizeof (uint64_t)); case CKO_CERTIFICATE: switch (certtype) { case CKC_X_509: /* * subject_len + subject + value_len + value */ return (ROUNDUP(((cert_attr_t *) X509_CERT_SUBJECT(objp))->length, 8) + ROUNDUP(((cert_attr_t *) X509_CERT_VALUE(objp))->length, 8) + 2 * sizeof (uint64_t)); case CKC_X_509_ATTR_CERT: /* * owner_len + owner + value_len + value */ return (ROUNDUP(((cert_attr_t *) X509_ATTR_CERT_OWNER(objp))->length, 8) + ROUNDUP(((cert_attr_t *) X509_ATTR_CERT_VALUE(objp))->length, 8) + 2 * sizeof (uint64_t)); } return (0); case CKO_DOMAIN_PARAMETERS: return (0); } return (0); } /* * Pack the object key (the third part) from the soft_object_t * into the keystore format. */ CK_RV soft_pack_object(soft_object_t *objp, uchar_t *buf) { CK_OBJECT_CLASS class = objp->class; CK_KEY_TYPE keytype = objp->key_type; CK_CERTIFICATE_TYPE certtype = objp->cert_type; uint64_t tmp_val; switch (class) { case CKO_PUBLIC_KEY: switch (keytype) { case CKK_RSA: /* modulus_bits */ tmp_val = SWAP64((uint64_t)OBJ_PUB_RSA_MOD_BITS(objp)); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); /* modulus_len + modulus */ tmp_val = SWAP64((uint64_t)(((biginteger_t *) OBJ_PUB_RSA_MOD(objp))->big_value_len)); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)(((biginteger_t *) OBJ_PUB_RSA_MOD(objp))->big_value), ((biginteger_t *) OBJ_PUB_RSA_MOD(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PUB_RSA_MOD(objp))->big_value_len, 8); /* pubexpo_len + pubexpo */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PUB_RSA_PUBEXPO(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)(((biginteger_t *) OBJ_PUB_RSA_PUBEXPO(objp))->big_value), ((biginteger_t *) OBJ_PUB_RSA_PUBEXPO(objp))->big_value_len); break; case CKK_DSA: /* prime_len + prime */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PUB_DSA_PRIME(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PUB_DSA_PRIME(objp))->big_value, ((biginteger_t *) OBJ_PUB_DSA_PRIME(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PUB_DSA_PRIME(objp))->big_value_len, 8); /* subprime_len + subprime */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PUB_DSA_SUBPRIME(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PUB_DSA_SUBPRIME(objp))->big_value, ((biginteger_t *) OBJ_PUB_DSA_SUBPRIME(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PUB_DSA_SUBPRIME(objp))->big_value_len, 8); /* base_len + base */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PUB_DSA_BASE(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PUB_DSA_BASE(objp))->big_value, ((biginteger_t *) OBJ_PUB_DSA_BASE(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PUB_DSA_BASE(objp))->big_value_len, 8); /* value_len + value */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PUB_DSA_VALUE(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PUB_DSA_VALUE(objp))->big_value, ((biginteger_t *) OBJ_PUB_DSA_VALUE(objp))->big_value_len); break; case CKK_DH: /* prime_len + prime */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PUB_DH_PRIME(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PUB_DH_PRIME(objp))->big_value, ((biginteger_t *) OBJ_PUB_DH_PRIME(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PUB_DH_PRIME(objp))->big_value_len, 8); /* base_len + base */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PUB_DH_BASE(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PUB_DH_BASE(objp))->big_value, ((biginteger_t *) OBJ_PUB_DH_BASE(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PUB_DH_BASE(objp))->big_value_len, 8); /* value_len + value */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PUB_DH_VALUE(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PUB_DH_VALUE(objp))->big_value, ((biginteger_t *) OBJ_PUB_DH_VALUE(objp))->big_value_len); break; case CKK_X9_42_DH: /* prime_len + prime */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PUB_DH942_PRIME(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PUB_DH942_PRIME(objp))->big_value, ((biginteger_t *) OBJ_PUB_DH942_PRIME(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PUB_DH942_PRIME(objp))->big_value_len, 8); /* base_len + base */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PUB_DH942_BASE(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PUB_DH942_BASE(objp))->big_value, ((biginteger_t *) OBJ_PUB_DH942_BASE(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PUB_DH942_BASE(objp))->big_value_len, 8); /* subprime_len + subprime */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PUB_DH942_SUBPRIME(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PUB_DH942_SUBPRIME(objp))->big_value, ((biginteger_t *) OBJ_PUB_DH942_SUBPRIME(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PUB_DH942_SUBPRIME(objp))->big_value_len, 8); /* value_len + value */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PUB_DH942_VALUE(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PUB_DH942_VALUE(objp))->big_value, ((biginteger_t *) OBJ_PUB_DH942_VALUE(objp))->big_value_len); break; } /* keytype */ break; case CKO_PRIVATE_KEY: switch (keytype) { case CKK_RSA: /* modulus_len + modulus */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_RSA_MOD(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_RSA_MOD(objp))->big_value, ((biginteger_t *) OBJ_PRI_RSA_MOD(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PRI_RSA_MOD(objp))->big_value_len, 8); /* pubexpo_len + pubexpo */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_RSA_PUBEXPO(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_RSA_PUBEXPO(objp))->big_value, ((biginteger_t *) OBJ_PRI_RSA_PUBEXPO(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PRI_RSA_PUBEXPO(objp))->big_value_len, 8); /* priexpo_len + priexpo */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_RSA_PRIEXPO(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_RSA_PRIEXPO(objp))->big_value, ((biginteger_t *) OBJ_PRI_RSA_PRIEXPO(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PRI_RSA_PRIEXPO(objp))->big_value_len, 8); /* prime1_len + prime1 */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_RSA_PRIME1(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_RSA_PRIME1(objp))->big_value, ((biginteger_t *) OBJ_PRI_RSA_PRIME1(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PRI_RSA_PRIME1(objp))->big_value_len, 8); /* prime2_len + prime2 */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_RSA_PRIME2(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_RSA_PRIME2(objp))->big_value, ((biginteger_t *) OBJ_PRI_RSA_PRIME2(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PRI_RSA_PRIME2(objp))->big_value_len, 8); /* expo1_len + expo1 */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_RSA_EXPO1(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_RSA_EXPO1(objp))->big_value, ((biginteger_t *) OBJ_PRI_RSA_EXPO1(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PRI_RSA_EXPO1(objp))->big_value_len, 8); /* expo2_len + expo2 */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_RSA_EXPO2(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_RSA_EXPO2(objp))->big_value, ((biginteger_t *) OBJ_PRI_RSA_EXPO2(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PRI_RSA_EXPO2(objp))->big_value_len, 8); /* coef_len + coef */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_RSA_COEF(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_RSA_COEF(objp))->big_value, ((biginteger_t *) OBJ_PRI_RSA_COEF(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PRI_RSA_COEF(objp))->big_value_len, 8); break; case CKK_DSA: /* prime_len + prime */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_DSA_PRIME(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_DSA_PRIME(objp))->big_value, ((biginteger_t *) OBJ_PRI_DSA_PRIME(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PRI_DSA_PRIME(objp))->big_value_len, 8); /* subprime_len + subprime */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_DSA_SUBPRIME(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_DSA_SUBPRIME(objp))->big_value, ((biginteger_t *) OBJ_PRI_DSA_SUBPRIME(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PRI_DSA_SUBPRIME(objp))->big_value_len, 8); /* base_len + base */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_DSA_BASE(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_DSA_BASE(objp))->big_value, ((biginteger_t *) OBJ_PRI_DSA_BASE(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PRI_DSA_BASE(objp))->big_value_len, 8); /* value_len + value */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_DSA_VALUE(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_DSA_VALUE(objp))->big_value, ((biginteger_t *) OBJ_PRI_DSA_VALUE(objp))->big_value_len); break; case CKK_DH: /* value_bits */ tmp_val = SWAP64((uint64_t)OBJ_PRI_DH_VAL_BITS(objp)); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); /* prime_len + prime */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_DH_PRIME(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_DH_PRIME(objp))->big_value, ((biginteger_t *) OBJ_PRI_DH_PRIME(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PRI_DH_PRIME(objp))->big_value_len, 8); /* base_len + base */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_DH_BASE(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_DH_BASE(objp))->big_value, ((biginteger_t *) OBJ_PRI_DH_BASE(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PRI_DH_BASE(objp))->big_value_len, 8); /* value_len + value */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_DH_VALUE(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_DH_VALUE(objp))->big_value, ((biginteger_t *) OBJ_PRI_DH_VALUE(objp))->big_value_len); break; case CKK_X9_42_DH: /* prime_len + prime */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_DH942_PRIME(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_DH942_PRIME(objp))->big_value, ((biginteger_t *) OBJ_PRI_DH942_PRIME(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PRI_DH942_PRIME(objp))->big_value_len, 8); /* base_len + base */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_DH942_BASE(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_DH942_BASE(objp))->big_value, ((biginteger_t *) OBJ_PRI_DH942_BASE(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PRI_DH942_BASE(objp))->big_value_len, 8); /* subprime_len + subprime */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_DH942_SUBPRIME(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_DH942_SUBPRIME(objp))->big_value, ((biginteger_t *) OBJ_PRI_DH942_SUBPRIME(objp))->big_value_len); buf = buf + ROUNDUP(((biginteger_t *) OBJ_PRI_DH942_SUBPRIME(objp))->big_value_len, 8); /* value_len + value */ tmp_val = SWAP64((uint64_t)((biginteger_t *) OBJ_PRI_DH942_VALUE(objp))->big_value_len); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((biginteger_t *) OBJ_PRI_DH942_VALUE(objp))->big_value, ((biginteger_t *) OBJ_PRI_DH942_VALUE(objp))->big_value_len); break; } /* keytype */ break; case CKO_SECRET_KEY: /* value_len + value */ tmp_val = SWAP64((uint64_t)OBJ_SEC_VALUE_LEN(objp)); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); if (OBJ_SEC_VALUE_LEN(objp) > 0) { (void) memcpy(buf, (char *)OBJ_SEC_VALUE(objp), OBJ_SEC_VALUE_LEN(objp)); buf = buf + ROUNDUP(OBJ_SEC_VALUE_LEN(objp), 8); } break; case CKO_CERTIFICATE: switch (certtype) { case CKC_X_509: /* subject_len + subject */ tmp_val = SWAP64((uint64_t)(((cert_attr_t *) X509_CERT_SUBJECT(objp))->length)); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((cert_attr_t *) X509_CERT_SUBJECT(objp))->value, ((cert_attr_t *) X509_CERT_SUBJECT(objp))->length); buf = buf + ROUNDUP(((cert_attr_t *) X509_CERT_SUBJECT(objp))->length, 8); /* value_len + value */ tmp_val = SWAP64((uint64_t)(((cert_attr_t *) X509_CERT_VALUE(objp))->length)); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((cert_attr_t *) X509_CERT_VALUE(objp))->value, ((cert_attr_t *) X509_CERT_VALUE(objp))->length); break; case CKC_X_509_ATTR_CERT: /* owner_len + owner */ tmp_val = SWAP64((uint64_t)(((cert_attr_t *) X509_ATTR_CERT_OWNER(objp))->length)); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((cert_attr_t *) X509_ATTR_CERT_OWNER(objp))->value, ((cert_attr_t *) X509_ATTR_CERT_OWNER(objp))->length); buf = buf + ROUNDUP(((cert_attr_t *) X509_ATTR_CERT_OWNER(objp))->length, 8); /* value_len + value */ tmp_val = SWAP64((uint64_t)(((cert_attr_t *) X509_ATTR_CERT_VALUE(objp))->length)); (void) memcpy(buf, (char *)&tmp_val, sizeof (uint64_t)); buf = buf + sizeof (uint64_t); (void) memcpy(buf, (char *)((cert_attr_t *) X509_ATTR_CERT_VALUE(objp))->value, ((cert_attr_t *) X509_ATTR_CERT_VALUE(objp))->length); break; } break; case CKO_DOMAIN_PARAMETERS: return (0); } return (CKR_OK); } /* * Unpack the object key in keystore format (the third part) * into soft_object_t. */ CK_RV soft_unpack_object(soft_object_t *objp, uchar_t *buf) { public_key_obj_t *pbk; private_key_obj_t *pvk; secret_key_obj_t *sck; certificate_obj_t *cert; CK_OBJECT_CLASS class = objp->class; CK_KEY_TYPE keytype = objp->key_type; CK_CERTIFICATE_TYPE certtype = objp->cert_type; biginteger_t modulus; biginteger_t pubexpo; biginteger_t prime; biginteger_t subprime; biginteger_t base; biginteger_t value; biginteger_t priexpo; biginteger_t prime1; biginteger_t prime2; biginteger_t expo1; biginteger_t expo2; biginteger_t coef; CK_RV rv = CKR_OK; ulong_t offset = 0; uint64_t tmp_val; /* prevent bigint_attr_cleanup from freeing invalid attr value */ (void) memset(&modulus, 0x0, sizeof (biginteger_t)); (void) memset(&pubexpo, 0x0, sizeof (biginteger_t)); (void) memset(&prime, 0x0, sizeof (biginteger_t)); (void) memset(&subprime, 0x0, sizeof (biginteger_t)); (void) memset(&base, 0x0, sizeof (biginteger_t)); (void) memset(&value, 0x0, sizeof (biginteger_t)); (void) memset(&priexpo, 0x0, sizeof (biginteger_t)); (void) memset(&prime1, 0x0, sizeof (biginteger_t)); (void) memset(&prime2, 0x0, sizeof (biginteger_t)); (void) memset(&expo1, 0x0, sizeof (biginteger_t)); (void) memset(&expo2, 0x0, sizeof (biginteger_t)); (void) memset(&coef, 0x0, sizeof (biginteger_t)); switch (class) { case CKO_PUBLIC_KEY: /* Allocate storage for Public Key Object. */ pbk = calloc(1, sizeof (public_key_obj_t)); if (pbk == NULL) { rv = CKR_HOST_MEMORY; return (rv); } objp->object_class_u.public_key = pbk; switch (keytype) { case CKK_RSA: /* modulus_bits */ (void) memcpy(&tmp_val, buf, sizeof (uint64_t)); KEY_PUB_RSA_MOD_BITS(pbk) = (CK_ULONG)(SWAP64(tmp_val)); buf = buf + sizeof (uint64_t); /* modulus */ if ((rv = soft_unpack_obj_attribute(buf, &modulus, NULL, &offset, B_FALSE)) != CKR_OK) goto pub_cleanup; copy_bigint_attr(&modulus, KEY_PUB_RSA_MOD(pbk)); buf += ROUNDUP(offset, 8); /* pubexpo */ if ((rv = soft_unpack_obj_attribute(buf, &pubexpo, NULL, &offset, B_FALSE)) != CKR_OK) goto pub_cleanup; copy_bigint_attr(&pubexpo, KEY_PUB_RSA_PUBEXPO(pbk)); break; case CKK_DSA: /* prime */ if ((rv = soft_unpack_obj_attribute(buf, &prime, NULL, &offset, B_FALSE)) != CKR_OK) goto pub_cleanup; copy_bigint_attr(&prime, KEY_PUB_DSA_PRIME(pbk)); buf += ROUNDUP(offset, 8); /* subprime */ if ((rv = soft_unpack_obj_attribute(buf, &subprime, NULL, &offset, B_FALSE)) != CKR_OK) goto pub_cleanup; copy_bigint_attr(&subprime, KEY_PUB_DSA_SUBPRIME(pbk)); buf += ROUNDUP(offset, 8); /* base */ if ((rv = soft_unpack_obj_attribute(buf, &base, NULL, &offset, B_FALSE)) != CKR_OK) goto pub_cleanup; copy_bigint_attr(&base, KEY_PUB_DSA_BASE(pbk)); buf += ROUNDUP(offset, 8); /* value */ if ((rv = soft_unpack_obj_attribute(buf, &value, NULL, &offset, B_FALSE)) != CKR_OK) goto pub_cleanup; copy_bigint_attr(&value, KEY_PUB_DSA_VALUE(pbk)); break; case CKK_DH: /* prime */ if ((rv = soft_unpack_obj_attribute(buf, &prime, NULL, &offset, B_FALSE)) != CKR_OK) goto pub_cleanup; copy_bigint_attr(&prime, KEY_PUB_DH_PRIME(pbk)); buf += ROUNDUP(offset, 8); /* base */ if ((rv = soft_unpack_obj_attribute(buf, &base, NULL, &offset, B_FALSE)) != CKR_OK) goto pub_cleanup; copy_bigint_attr(&base, KEY_PUB_DH_BASE(pbk)); buf += ROUNDUP(offset, 8); /* value */ if ((rv = soft_unpack_obj_attribute(buf, &value, NULL, &offset, B_FALSE)) != CKR_OK) goto pub_cleanup; copy_bigint_attr(&value, KEY_PUB_DH_VALUE(pbk)); break; case CKK_X9_42_DH: /* prime */ if ((rv = soft_unpack_obj_attribute(buf, &prime, NULL, &offset, B_FALSE)) != CKR_OK) goto pub_cleanup; copy_bigint_attr(&prime, KEY_PUB_DH942_PRIME(pbk)); buf += ROUNDUP(offset, 8); /* base */ if ((rv = soft_unpack_obj_attribute(buf, &base, NULL, &offset, B_FALSE)) != CKR_OK) goto pub_cleanup; copy_bigint_attr(&base, KEY_PUB_DH942_BASE(pbk)); buf += ROUNDUP(offset, 8); /* subprime */ if ((rv = soft_unpack_obj_attribute(buf, &subprime, NULL, &offset, B_FALSE)) != CKR_OK) goto pub_cleanup; copy_bigint_attr(&subprime, KEY_PUB_DH942_SUBPRIME(pbk)); buf += ROUNDUP(offset, 8); /* value */ if ((rv = soft_unpack_obj_attribute(buf, &value, NULL, &offset, B_FALSE)) != CKR_OK) goto pub_cleanup; copy_bigint_attr(&value, KEY_PUB_DH942_VALUE(pbk)); break; } /* keytype */ break; case CKO_PRIVATE_KEY: /* Allocate storage for Private Key Object. */ pvk = calloc(1, sizeof (private_key_obj_t)); if (pvk == NULL) { rv = CKR_HOST_MEMORY; return (rv); } objp->object_class_u.private_key = pvk; switch (keytype) { case CKK_RSA: /* modulus */ if ((rv = soft_unpack_obj_attribute(buf, &modulus, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&modulus, KEY_PRI_RSA_MOD(pvk)); buf += ROUNDUP(offset, 8); /* pubexpo */ if ((rv = soft_unpack_obj_attribute(buf, &pubexpo, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&pubexpo, KEY_PRI_RSA_PUBEXPO(pvk)); buf += ROUNDUP(offset, 8); /* priexpo */ if ((rv = soft_unpack_obj_attribute(buf, &priexpo, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&priexpo, KEY_PRI_RSA_PRIEXPO(pvk)); buf += ROUNDUP(offset, 8); /* prime1 */ if ((rv = soft_unpack_obj_attribute(buf, &prime1, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&prime1, KEY_PRI_RSA_PRIME1(pvk)); buf += ROUNDUP(offset, 8); /* prime2 */ if ((rv = soft_unpack_obj_attribute(buf, &prime2, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&prime2, KEY_PRI_RSA_PRIME2(pvk)); buf += ROUNDUP(offset, 8); /* expo1 */ if ((rv = soft_unpack_obj_attribute(buf, &expo1, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&expo1, KEY_PRI_RSA_EXPO1(pvk)); buf += ROUNDUP(offset, 8); /* expo2 */ if ((rv = soft_unpack_obj_attribute(buf, &expo2, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&expo2, KEY_PRI_RSA_EXPO2(pvk)); buf += ROUNDUP(offset, 8); /* coef */ if ((rv = soft_unpack_obj_attribute(buf, &coef, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&coef, KEY_PRI_RSA_COEF(pvk)); break; case CKK_DSA: /* prime */ if ((rv = soft_unpack_obj_attribute(buf, &prime, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&prime, KEY_PRI_DSA_PRIME(pvk)); buf += ROUNDUP(offset, 8); /* subprime */ if ((rv = soft_unpack_obj_attribute(buf, &subprime, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&subprime, KEY_PRI_DSA_SUBPRIME(pvk)); buf += ROUNDUP(offset, 8); /* base */ if ((rv = soft_unpack_obj_attribute(buf, &base, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&base, KEY_PRI_DSA_BASE(pvk)); buf += ROUNDUP(offset, 8); /* value */ if ((rv = soft_unpack_obj_attribute(buf, &value, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&value, KEY_PRI_DSA_VALUE(pvk)); break; case CKK_DH: /* value_bits */ (void) memcpy(&tmp_val, buf, sizeof (uint64_t)); KEY_PRI_DH_VAL_BITS(pvk) = (CK_ULONG)(SWAP64(tmp_val)); buf = buf + sizeof (uint64_t); /* prime */ if ((rv = soft_unpack_obj_attribute(buf, &prime, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&prime, KEY_PRI_DH_PRIME(pvk)); buf += ROUNDUP(offset, 8); /* base */ if ((rv = soft_unpack_obj_attribute(buf, &base, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&base, KEY_PRI_DH_BASE(pvk)); buf += ROUNDUP(offset, 8); /* value */ if ((rv = soft_unpack_obj_attribute(buf, &value, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&value, KEY_PRI_DH_VALUE(pvk)); break; case CKK_X9_42_DH: /* prime */ if ((rv = soft_unpack_obj_attribute(buf, &prime, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&prime, KEY_PRI_DH942_PRIME(pvk)); buf += ROUNDUP(offset, 8); /* base */ if ((rv = soft_unpack_obj_attribute(buf, &base, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&base, KEY_PRI_DH942_BASE(pvk)); buf += ROUNDUP(offset, 8); /* subprime */ if ((rv = soft_unpack_obj_attribute(buf, &subprime, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&subprime, KEY_PRI_DH942_BASE(pvk)); buf += ROUNDUP(offset, 8); /* value */ if ((rv = soft_unpack_obj_attribute(buf, &value, NULL, &offset, B_FALSE)) != CKR_OK) goto pri_cleanup; copy_bigint_attr(&value, KEY_PRI_DH942_VALUE(pvk)); break; } /* keytype */ break; case CKO_SECRET_KEY: /* Allocate storage for Secret Key Object. */ sck = calloc(1, sizeof (secret_key_obj_t)); if (sck == NULL) { return (CKR_HOST_MEMORY); } objp->object_class_u.secret_key = sck; /* value */ (void) memcpy((void *)&tmp_val, buf, sizeof (uint64_t)); OBJ_SEC_VALUE_LEN(objp) = (CK_ULONG)(SWAP64(tmp_val)); buf = buf + sizeof (uint64_t); if (OBJ_SEC_VALUE_LEN(objp) > 0) { OBJ_SEC_VALUE(objp) = malloc(OBJ_SEC_VALUE_LEN(objp)); if (OBJ_SEC_VALUE(objp) == NULL) { free(sck); return (CKR_HOST_MEMORY); } (void) memcpy(OBJ_SEC_VALUE(objp), buf, OBJ_SEC_VALUE_LEN(objp)); buf = buf + ROUNDUP(OBJ_SEC_VALUE_LEN(objp), 8); } return (rv); case CKO_CERTIFICATE: /* Allocate storage for Certificate Object. */ cert = calloc(1, sizeof (certificate_obj_t)); if (cert == NULL) { return (CKR_HOST_MEMORY); } (void) memset((void *)cert, 0, sizeof (certificate_obj_t)); cert->certificate_type = certtype; objp->object_class_u.certificate = cert; switch (certtype) { case CKC_X_509: /* subject */ if ((rv = soft_unpack_obj_attribute(buf, NULL, &cert->cert_type_u.x509.subject, &offset, B_TRUE)) != CKR_OK) { free(cert); return (rv); } buf += ROUNDUP(offset, 8); /* value */ if ((rv = soft_unpack_obj_attribute(buf, NULL, &cert->cert_type_u.x509.value, &offset, B_TRUE)) != CKR_OK) { free(cert); return (rv); } break; case CKC_X_509_ATTR_CERT: /* owner */ if ((rv = soft_unpack_obj_attribute(buf, NULL, &cert->cert_type_u.x509_attr.owner, &offset, B_TRUE)) != CKR_OK) { free(cert); return (rv); } buf += ROUNDUP(offset, 8); /* value */ if ((rv = soft_unpack_obj_attribute(buf, NULL, &cert->cert_type_u.x509_attr.value, &offset, B_TRUE)) != CKR_OK) { free(cert); return (rv); } break; } return (rv); case CKO_DOMAIN_PARAMETERS: break; } pub_cleanup: /* * cleanup the storage allocated to the local variables. */ if (rv != CKR_OK) free(pbk); bigint_attr_cleanup(&modulus); bigint_attr_cleanup(&pubexpo); bigint_attr_cleanup(&prime); bigint_attr_cleanup(&subprime); bigint_attr_cleanup(&base); bigint_attr_cleanup(&value); return (rv); pri_cleanup: /* * cleanup the storage allocated to the local variables. */ if (rv != CKR_OK) free(pvk); bigint_attr_cleanup(&modulus); bigint_attr_cleanup(&priexpo); bigint_attr_cleanup(&prime); bigint_attr_cleanup(&subprime); bigint_attr_cleanup(&base); bigint_attr_cleanup(&value); bigint_attr_cleanup(&pubexpo); bigint_attr_cleanup(&prime1); bigint_attr_cleanup(&prime2); bigint_attr_cleanup(&expo1); bigint_attr_cleanup(&expo2); bigint_attr_cleanup(&coef); return (rv); } /* * Store the token object to a keystore file. */ CK_RV soft_put_object_to_keystore(soft_object_t *objp) { uchar_t *buf; size_t len; CK_RV rv; rv = soft_keystore_pack_obj(objp, &buf, &len); if (rv != CKR_OK) return (rv); if (objp->object_type == TOKEN_PUBLIC) { if ((soft_keystore_put_new_obj(buf, len, B_TRUE, B_FALSE, &objp->ks_handle)) == -1) { free(buf); return (CKR_FUNCTION_FAILED); } } else { if ((soft_keystore_put_new_obj(buf, len, B_FALSE, B_FALSE, &objp->ks_handle)) == -1) { free(buf); return (CKR_FUNCTION_FAILED); } } free(buf); return (CKR_OK); } /* * Modify the in-core token object and then write it to * a keystore file. */ CK_RV soft_modify_object_to_keystore(soft_object_t *objp) { uchar_t *buf; size_t len; CK_RV rv; rv = soft_keystore_pack_obj(objp, &buf, &len); if (rv != CKR_OK) return (rv); /* B_TRUE: caller has held a writelock on the keystore */ if (soft_keystore_modify_obj(&objp->ks_handle, buf, len, B_TRUE) < 0) { return (CKR_FUNCTION_FAILED); } free(buf); return (CKR_OK); } /* * Read the token object from the keystore file. */ CK_RV soft_get_token_objects_from_keystore(ks_search_type_t type) { CK_RV rv; ks_obj_t *ks_obj = NULL, *ks_obj_next; soft_object_t *new_objp = NULL; /* Load the token object from keystore based on the object type */ rv = soft_keystore_get_objs(type, &ks_obj, B_FALSE); if (rv != CKR_OK) { return (rv); } while (ks_obj) { new_objp = calloc(1, sizeof (soft_object_t)); if (new_objp == NULL) { rv = CKR_HOST_MEMORY; goto cleanup; } /* Convert the keystore format to memory format */ rv = soft_keystore_unpack_obj(new_objp, ks_obj); if (rv != CKR_OK) { if (new_objp->class == CKO_CERTIFICATE) soft_cleanup_cert_object(new_objp); else soft_cleanup_object(new_objp); goto cleanup; } soft_add_token_object_to_slot(new_objp); /* Free the ks_obj list */ ks_obj_next = ks_obj->next; if (ks_obj->buf) free(ks_obj->buf); free(ks_obj); ks_obj = ks_obj_next; } return (CKR_OK); cleanup: while (ks_obj) { ks_obj_next = ks_obj->next; free(ks_obj->buf); free(ks_obj); ks_obj = ks_obj_next; } return (rv); } /* * soft_gen_crypt_key() * * Arguments: * * pPIN: pointer to caller provided Pin * key: output argument which contains the address of the * pointer to encryption key in the soft_object_t. * It is caller's responsibility to call soft_delete_object() * if this key is no longer in use. * saltdata: input argument (if non-NULL), or * output argument (if NULL): * address of pointer to the "salt" of the encryption key * * Description: * * Generate an encryption key of the input PIN. * * Returns: * * CKR_OK: no error * Other: some error occurred while generating the encryption key * */ CK_RV soft_gen_crypt_key(uchar_t *pPIN, soft_object_t **key, CK_BYTE **saltdata) { CK_OBJECT_CLASS class = CKO_SECRET_KEY; CK_ATTRIBUTE tmpl[5]; int attrs = 0; CK_RV rv; CK_MECHANISM Mechanism; CK_PKCS5_PBKD2_PARAMS params; CK_BYTE salt[PBKD2_SALT_SIZE]; CK_ULONG keylen = AES_MIN_KEY_BYTES; 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) return (CKR_FUNCTION_FAILED); tmpl[attrs].type = CKA_CLASS; tmpl[attrs].pValue = &class; tmpl[attrs].ulValueLen = sizeof (class); attrs++; tmpl[attrs].type = CKA_KEY_TYPE; tmpl[attrs].pValue = &keytype; tmpl[attrs].ulValueLen = sizeof (keytype); attrs++; tmpl[attrs].type = CKA_ENCRYPT; tmpl[attrs].pValue = &truevalue; tmpl[attrs].ulValueLen = sizeof (CK_BBOOL); attrs++; tmpl[attrs].type = CKA_DECRYPT; tmpl[attrs].pValue = &truevalue; tmpl[attrs].ulValueLen = sizeof (CK_BBOOL); attrs++; tmpl[attrs].type = CKA_VALUE_LEN; tmpl[attrs].pValue = &keylen; tmpl[attrs].ulValueLen = sizeof (keylen); attrs++; if (*saltdata == NULL) { bzero(salt, sizeof (salt)); (void) soft_nzero_random_generator(salt, sizeof (salt)); *saltdata = malloc(PBKD2_SALT_SIZE); if (*saltdata == NULL) return (CKR_HOST_MEMORY); (void) memcpy(*saltdata, salt, PBKD2_SALT_SIZE); } else { bzero(salt, sizeof (salt)); (void) memcpy(salt, *saltdata, PBKD2_SALT_SIZE); } Mechanism.mechanism = CKM_PKCS5_PBKD2; Mechanism.pParameter = ¶ms; Mechanism.ulParameterLen = sizeof (params); passwd_size = (CK_ULONG)strlen((const char *)pPIN); params.saltSource = CKZ_SALT_SPECIFIED; params.pSaltSourceData = (void *)salt; params.ulSaltSourceDataLen = sizeof (salt); params.iterations = PBKD2_ITERATIONS; params.prf = CKP_PKCS5_PBKD2_HMAC_SHA1; params.pPrfData = NULL; params.ulPrfDataLen = 0; params.pPassword = (CK_UTF8CHAR_PTR)pPIN; params.ulPasswordLen = &passwd_size; rv = soft_gen_keyobject(tmpl, attrs, &hKey, &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, B_FALSE); return (CKR_HOST_MEMORY); } rv = soft_generate_pkcs5_pbkdf2_key(&token_session, &Mechanism, secret_key); if (rv != CKR_OK) soft_delete_object(&token_session, secret_key, B_FALSE); else *key = secret_key; return (rv); } /* * soft_gen_hmac_key() * * Arguments: * * pPIN: pointer to caller provided Pin * key: output argument which contains the address of the * pointer to hmac key in the soft_object_t. * It is caller's responsibility to call soft_delete_object() * if this key is no longer in use. * saltdata: input argument (if non-NULL), or * output argument (if NULL): * address of pointer to the "salt" of the hmac key * * Description: * * Generate a hmac key of the input PIN. * * Returns: * * CKR_OK: no error * Other: some error occurred while generating the hmac key * */ CK_RV soft_gen_hmac_key(uchar_t *pPIN, soft_object_t **key, CK_BYTE **saltdata) { CK_OBJECT_CLASS class = CKO_SECRET_KEY; CK_ATTRIBUTE tmpl[5]; int attrs = 0; CK_RV rv; CK_MECHANISM Mechanism; CK_PKCS5_PBKD2_PARAMS params; CK_BYTE salt[PBKD2_SALT_SIZE]; CK_ULONG keylen = 16; 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) return (CKR_FUNCTION_FAILED); tmpl[attrs].type = CKA_CLASS; tmpl[attrs].pValue = &class; tmpl[attrs].ulValueLen = sizeof (class); attrs++; tmpl[attrs].type = CKA_KEY_TYPE; tmpl[attrs].pValue = &keytype; tmpl[attrs].ulValueLen = sizeof (keytype); attrs++; tmpl[attrs].type = CKA_SIGN; tmpl[attrs].pValue = &truevalue; tmpl[attrs].ulValueLen = sizeof (CK_BBOOL); attrs++; tmpl[attrs].type = CKA_VERIFY; tmpl[attrs].pValue = &truevalue; tmpl[attrs].ulValueLen = sizeof (CK_BBOOL); attrs++; tmpl[attrs].type = CKA_VALUE_LEN; tmpl[attrs].pValue = &keylen; tmpl[attrs].ulValueLen = sizeof (keylen); attrs++; if (*saltdata == NULL) { bzero(salt, sizeof (salt)); (void) soft_nzero_random_generator(salt, sizeof (salt)); *saltdata = malloc(PBKD2_SALT_SIZE); if (*saltdata == NULL) return (CKR_HOST_MEMORY); (void) memcpy(*saltdata, salt, PBKD2_SALT_SIZE); } else { bzero(salt, sizeof (salt)); (void) memcpy(salt, *saltdata, PBKD2_SALT_SIZE); } Mechanism.mechanism = CKM_PKCS5_PBKD2; Mechanism.pParameter = ¶ms; Mechanism.ulParameterLen = sizeof (params); passwd_size = (CK_ULONG)strlen((const char *)pPIN); params.saltSource = CKZ_SALT_SPECIFIED; params.pSaltSourceData = (void *)salt; params.ulSaltSourceDataLen = sizeof (salt); params.iterations = PBKD2_ITERATIONS; params.prf = CKP_PKCS5_PBKD2_HMAC_SHA1; params.pPrfData = NULL; params.ulPrfDataLen = 0; params.pPassword = (CK_UTF8CHAR_PTR)pPIN; params.ulPasswordLen = &passwd_size; rv = soft_gen_keyobject(tmpl, attrs, &hKey, &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, B_FALSE); return (CKR_HOST_MEMORY); } rv = soft_generate_pkcs5_pbkdf2_key(&token_session, &Mechanism, secret_key); if (rv != CKR_OK) soft_delete_object(&token_session, secret_key, B_FALSE); else *key = secret_key; return (rv); } /* * The token session is just a psuedo session (a place holder) * to hold some information during encryption/decryption and * sign/verify operations when writing/reading the keystore * token object. */ CK_RV soft_init_token_session(void) { token_session.magic_marker = SOFTTOKEN_SESSION_MAGIC; token_session.pApplication = NULL_PTR; token_session.Notify = NULL; token_session.flags = CKF_SERIAL_SESSION; token_session.state = CKS_RO_PUBLIC_SESSION; token_session.object_list = NULL; token_session.ses_refcnt = 0; token_session.ses_close_sync = 0; /* Initialize the lock for the token session */ if (pthread_mutex_init(&token_session.session_mutex, NULL) != 0) { return (CKR_CANT_LOCK); } (void) pthread_cond_init(&token_session.ses_free_cond, NULL); return (CKR_OK); } void soft_destroy_token_session(void) { (void) pthread_cond_destroy(&token_session.ses_free_cond); (void) pthread_mutex_destroy(&token_session.session_mutex); } /* * Encrypt/Decrypt the private token object when dealing with the keystore. * This function only applies to the private token object. */ CK_RV soft_keystore_crypt(soft_object_t *key_p, uchar_t *ivec, boolean_t encrypt, CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len) { CK_MECHANISM mech; soft_aes_ctx_t *soft_aes_ctx; CK_RV rv; CK_ULONG tmplen, tmplen1; /* * The caller will pass NULL for "out" (output buffer) to find out * the output buffer size that it need to allocate for the encrption * or decryption. */ if (out == NULL) { mech.mechanism = CKM_AES_CBC_PAD; mech.pParameter = (void *)ivec; mech.ulParameterLen = AES_BLOCK_LEN; if (encrypt) rv = soft_aes_crypt_init_common(&token_session, &mech, key_p, B_TRUE); else rv = soft_aes_crypt_init_common(&token_session, &mech, key_p, B_FALSE); if (rv != CKR_OK) return (rv); (void) pthread_mutex_lock(&token_session.session_mutex); if (encrypt) soft_aes_ctx = (soft_aes_ctx_t *)token_session.encrypt.context; else soft_aes_ctx = (soft_aes_ctx_t *)token_session.decrypt.context; /* Copy Initialization Vector (IV) into the context. */ (void) memcpy(soft_aes_ctx->ivec, ivec, AES_BLOCK_LEN); /* Allocate a context for AES cipher-block chaining. */ soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init( soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len, soft_aes_ctx->ivec); if (soft_aes_ctx->aes_cbc == NULL) { bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len); free(soft_aes_ctx->key_sched); if (encrypt) { free(token_session.encrypt.context); token_session.encrypt.context = NULL; } else { free(token_session.encrypt.context); token_session.encrypt.context = NULL; } (void) pthread_mutex_unlock(&token_session. session_mutex); return (CKR_HOST_MEMORY); } (void) pthread_mutex_unlock(&token_session.session_mutex); /* * Since out == NULL, the soft_aes_xxcrypt_common() will * simply return the output buffer length to the caller. */ if (encrypt) { rv = soft_aes_encrypt_common(&token_session, in, in_len, out, out_len, B_FALSE); } else { rv = soft_aes_decrypt_common(&token_session, in, in_len, out, out_len, B_FALSE); } } else { /* * The caller has allocated the output buffer, so that we * are doing the real encryption/decryption this time. */ tmplen = *out_len; if (encrypt) { rv = soft_aes_encrypt_common(&token_session, in, in_len, out, &tmplen, B_TRUE); if (rv == CKR_OK) { tmplen1 = *out_len - tmplen; rv = soft_encrypt_final(&token_session, out+tmplen, &tmplen1); *out_len = tmplen + tmplen1; } } else { rv = soft_aes_decrypt_common(&token_session, in, in_len, out, &tmplen, B_TRUE); if (rv == CKR_OK) { tmplen1 = *out_len - tmplen; rv = soft_decrypt_final(&token_session, out+tmplen, &tmplen1); *out_len = tmplen + tmplen1; } } } return (rv); } /* * Sign/Verify the private token object for checking its data integrity * when dealing with the keystore. * This function only applies to the private token object. */ CK_RV soft_keystore_hmac(soft_object_t *key_p, boolean_t sign, CK_BYTE_PTR in, CK_ULONG in_len, CK_BYTE_PTR out, CK_ULONG_PTR out_len) { CK_MECHANISM mech; CK_RV rv; mech.mechanism = CKM_MD5_HMAC; mech.pParameter = NULL_PTR; mech.ulParameterLen = 0; rv = soft_hmac_sign_verify_init_common(&token_session, &mech, key_p, sign); if (rv != CKR_OK) return (rv); if (sign) { rv = soft_sign(&token_session, in, in_len, out, out_len); } else { rv = soft_verify(&token_session, in, in_len, out, *out_len); } return (rv); }