/*
* 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
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <security/cryptoki.h>
#include <aes_impl.h>
#include <blowfish_impl.h>
#include <des_impl.h>
#include <arcfour.h>
#include <cryptoutil.h>
#include "softGlobal.h"
#include "softSession.h"
#include "softObject.h"
#include "softDSA.h"
#include "softRSA.h"
#include "softDH.h"
#include "softEC.h"
#include "softMAC.h"
#include "softOps.h"
#include "softKeys.h"
#include "softKeystore.h"
#include "softSSL.h"
#include "softASN1.h"
#define local_min(a, b) ((a) < (b) ? (a) : (b))
static CK_RV
/*
* Create a temporary key object struct by filling up its template attributes.
*/
{
return (CKR_HOST_MEMORY);
}
/*
* Validate attribute template and fill in the attributes
* in the soft_object_t.
*/
goto fail_cleanup1;
}
/*
* If generating a key is an internal request (i.e. not a C_XXX
* API request), then skip the following checks.
*/
if (!internal) {
goto fail_cleanup2;
}
goto fail_cleanup2;
}
}
/* Initialize the rest of stuffs in soft_object_t. */
/* Write the new token object to the keystore */
if (IS_TOKEN_OBJECT(new_objp)) {
/*
* Type casting the address of an object struct to
* an object handle.
*/
return (CKR_OK);
}
/* Add the new object to the session's object list. */
/* Type casting the address of an object struct to an object handle. */
return (CKR_OK);
/*
* When any error occurs after soft_build_key(), we will need to
* clean up the memory allocated by the soft_build_key().
*/
if (new_objp) {
/*
* The storage allocated inside of this object should have
* been cleaned up by the soft_build_key() if it failed.
* Therefore, we can safely free the object.
*/
}
return (rv);
}
{
CK_ULONG i;
int des_strength = 0;
int retry = 0;
int keyfound = 0;
switch (pMechanism->mechanism) {
case CKM_DES_KEY_GEN:
break;
case CKM_DES2_KEY_GEN:
break;
case CKM_DES3_KEY_GEN:
break;
case CKM_AES_KEY_GEN:
break;
case CKM_BLOWFISH_KEY_GEN:
break;
case CKM_RC4_KEY_GEN:
break;
return (CKR_TEMPLATE_INCOMPLETE);
keylen = 48;
break;
case CKM_PKCS5_PBKD2:
keyfound = 0;
keyfound = 1;
}
}
if (!keyfound)
return (CKR_TEMPLATE_INCOMPLETE);
/*
* Make sure that parameters were given for this
* mechanism.
*/
sizeof (CK_PKCS5_PBKD2_PARAMS))
return (CKR_TEMPLATE_INCOMPLETE);
break;
case CKM_PBE_SHA1_RC4_128:
keyfound = 0;
for (i = 0; i < ulCount; i++) {
keyfound = 1;
}
}
}
/* If a keytype was specified, it had better be CKK_RC4 */
return (CKR_TEMPLATE_INCONSISTENT);
else if (!keyfound)
/* If key length was specified, it better be 16 bytes */
return (CKR_TEMPLATE_INCONSISTENT);
/*
* Make sure that parameters were given for this
* mechanism.
*/
sizeof (CK_PBE_PARAMS))
return (CKR_TEMPLATE_INCOMPLETE);
break;
default:
return (CKR_MECHANISM_INVALID);
}
/* Create a new object for secret key. */
return (rv);
}
/* Obtain the secret object pointer. */
switch (pMechanism->mechanism) {
case CKM_DES_KEY_GEN:
/*
* Set up key value len since it is not a required
* attribute for C_GenerateKey.
*/
des_strength = DES;
break;
case CKM_DES2_KEY_GEN:
/*
* Set up key value len since it is not a required
* attribute for C_GenerateKey.
*/
des_strength = DES2;
break;
case CKM_DES3_KEY_GEN:
/*
* Set up key value len since it is not a required
* attribute for C_GenerateKey.
*/
des_strength = DES3;
break;
/* FALLTHRU */
case CKM_AES_KEY_GEN:
case CKM_BLOWFISH_KEY_GEN:
case CKM_PBE_SHA1_RC4_128:
case CKM_RC4_KEY_GEN:
break;
case CKM_PKCS5_PBKD2:
/*
* PKCS#11 does not allow one to specify key
* sizes for DES and 3DES, so we must set it here
* when using PBKD2 algorithms.
*/
des_strength = DES;
des_strength = DES3;
}
break;
}
if (IS_TOKEN_OBJECT(secret_key))
else
return (CKR_HOST_MEMORY);
}
switch (pMechanism->mechanism) {
case CKM_PBE_SHA1_RC4_128:
/*
* Use the PBE algorithm described in PKCS#11 section
* 12.33 to derive the key.
*/
break;
case CKM_PKCS5_PBKD2:
/* Generate keys using PKCS#5 PBKD2 algorithm */
/* Perform weak key checking for DES and DES3. */
B_FALSE) {
/* We got a weak secret key. */
}
}
break;
default:
do {
/* If this fails, bail out */
if (pkcs11_get_urandom(
break;
}
/* Perform weak key checking for DES and DES3. */
if (des_strength > 0) {
B_FALSE) {
/* We got a weak key, retry! */
retry++;
}
}
/*
* Copy over the SSL client version For SSL mechs
* The first two bytes of the key is the version
*/
if (is_ssl_mech)
sizeof (CK_VERSION));
if (retry == KEYGEN_RETRY)
break;
}
if (IS_TOKEN_OBJECT(secret_key))
else
if (IS_TOKEN_OBJECT(secret_key)) {
/*
* All the info has been filled, so we can write to
* keystore now.
*/
}
return (rv);
}
{
switch (pMechanism->mechanism) {
break;
case CKM_DSA_KEY_PAIR_GEN:
break;
case CKM_DH_PKCS_KEY_PAIR_GEN:
break;
case CKM_EC_KEY_PAIR_GEN:
break;
default:
return (CKR_MECHANISM_INVALID);
}
/* Create a new object for public key. */
return (rv);
}
/* Obtain the public object pointer. */
/* Create a new object for private key. */
/*
* Both public key and private key must be successful.
*/
if (IS_TOKEN_OBJECT(public_key))
else
return (rv);
}
/* Obtain the private object pointer. */
/*
* At this point, both public key and private key objects
* are settled with the application specified attributes.
* We are ready to generate the rest of key attributes based
* on the existing attributes.
*/
switch (key_type) {
case CKK_RSA:
break;
case CKK_DSA:
break;
case CKK_DH:
break;
case CKK_EC:
break;
}
if (IS_TOKEN_OBJECT(public_key)) {
} else {
}
return (rv);
}
if (IS_TOKEN_OBJECT(public_key)) {
/*
* All the info has been filled, so we can write to
* keystore now.
*/
return (rv);
}
}
if (IS_TOKEN_OBJECT(private_key)) {
/*
* We also need to delete the public token object
* from keystore.
*/
}
}
return (rv);
}
{
switch (secret_key->key_type) {
case CKK_GENERIC_SECRET:
if (OBJ_SEC_VALUE_LEN(secret_key) == 0) {
return (CKR_OK);
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
break;
case CKK_RC4:
case CKK_AES:
case CKK_BLOWFISH:
if ((OBJ_SEC_VALUE_LEN(secret_key) == 0) ||
/* RC4 and AES has variable key length */
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
break;
case CKK_DES:
if (OBJ_SEC_VALUE_LEN(secret_key) == 0) {
/* DES has a well-defined length */
return (CKR_OK);
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
break;
case CKK_DES2:
if (OBJ_SEC_VALUE_LEN(secret_key) == 0) {
/* DES2 has a well-defined length */
return (CKR_OK);
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
break;
default:
return (CKR_MECHANISM_INVALID);
}
return (CKR_OK);
}
/*
* PKCS#11 (12.33) says that v = 512 bits (64 bytes) for SHA1
* PBE methods.
*/
/*
* PKCS#12 defines 3 different ID bytes to be used for
* deriving keys for different operations.
*/
#define PBE_CEIL(a, b) (((a)/(b)) + (((a)%(b)) > 0))
static CK_RV
{
CK_ULONG c, i, j, k;
/*
* Terse variable names are used to make following
* the PKCS#12 spec easier.
*/
/* U = hash function output bits */
} else {
/* we only support 1 PBE mech for now */
return (CKR_MECHANISM_INVALID);
}
if (D == NULL) {
goto cleanup;
}
if (B == NULL) {
goto cleanup;
}
/*
* Initialize some values and create some buffers
* that we need later.
*
* Slen = buffSize * CEIL(SaltLength/buffSize)
*/
/*
* Plen = buffSize * CEIL(PasswordLength/buffSize)
*/
/*
* From step 4: I = S + P, so: Ilen = Slen + Plen
*/
if (I == NULL) {
goto cleanup;
}
S = I;
P = I + Slen;
/*
* Step 1.
* for now, so construct the "D"iversifier accordingly.
*/
/*
* Step 2.
* Concatenate copies of the salt together to make S.
*/
}
/*
* Step 3.
* Concatenate copies of the password together to make
* a string P.
*/
}
/*
* Step 4.
* I = S+P - this is now done because S and P are
* pointers into I.
*
* Step 5.
* c= CEIL[n/u]
* where n = pseudorandom bits of output desired.
*/
/*
* Step 6.
*/
if (A == NULL) {
goto cleanup;
}
goto cleanup;
}
/*
* Step 6a.
* Ai = Hr(D+I)
*/
for (i = 0; i < c; i++) {
goto cleanup;
}
for (j = 0; j < params->ulIteration; j++) {
goto digest_done;
if (j == 0) {
goto digest_done;
} else {
}
goto digest_done;
goto digest_done;
}
goto cleanup;
/*
* Step 6b.
* Concatenate Ai to make B
*/
}
/*
* Step 6c.
*/
for (j = 0; j < k; j++) {
q += cbit;
cbit = (q > 0xff);
}
}
/*
* Step 7.
* A += Ai
*/
}
/*
* Step 8.
* The final output of this process is the A buffer
*/
if (A) {
free(A);
}
if (Ai) {
}
if (B) {
free(B);
}
if (D) {
free(D);
}
if (I) {
free(I);
}
return (rv);
}
{
switch (pMechanism->mechanism) {
case CKM_DH_PKCS_DERIVE:
/*
* Create a new object for secret key. The key type should
* be provided in the template.
*/
return (rv);
}
/* Obtain the secret object pointer. */
if (IS_TOKEN_OBJECT(secret_key))
B_FALSE);
else
return (rv);
}
break;
case CKM_ECDH1_DERIVE:
/*
* Create a new object for secret key. The key type should
* be provided in the template.
*/
return (rv);
}
/* Obtain the secret object pointer. */
if (IS_TOKEN_OBJECT(secret_key))
B_FALSE);
else
return (rv);
}
break;
case CKM_SHA1_KEY_DERIVATION:
goto common;
case CKM_MD5_KEY_DERIVATION:
goto common;
goto common;
goto common;
goto common;
/*
* Create a new object for secret key. The key type is optional
* to be provided in the template. If it is not specified in
* the template, the default is CKK_GENERIC_SECRET.
*/
return (rv);
}
/* Obtain the secret object pointer. */
/* Validate the key type and key length */
if (IS_TOKEN_OBJECT(secret_key))
B_FALSE);
else
return (rv);
}
/*
* Derive the secret key by digesting the value of another
* secret key (base key) with SHA-1 or MD5.
*/
if (IS_TOKEN_OBJECT(secret_key))
B_FALSE);
else
return (rv);
}
/* soft_digest_common() has freed the digest context */
if (IS_TOKEN_OBJECT(secret_key))
B_FALSE);
else
return (rv);
}
NULL) {
if (IS_TOKEN_OBJECT(secret_key))
B_FALSE);
else
return (CKR_HOST_MEMORY);
}
/*
* The key produced by this mechanism will be of the
* specified type and length.
* The truncation removes extra bytes from the leading
* of the digested key value.
*/
break;
/*
* The key sensitivity and extractability rules for the generated
* keys will be enforced inside soft_ssl_master_key_derive() and
* soft_ssl_key_and_mac_derive()
*/
return (CKR_ARGUMENTS_BAD);
case CKM_TLS_PRF:
return (CKR_ARGUMENTS_BAD);
return (CKR_TEMPLATE_INCONSISTENT);
return (derive_tls_prf(
default:
return (CKR_MECHANISM_INVALID);
}
if (IS_TOKEN_OBJECT(secret_key)) {
/*
* All the info has been filled, so we can write to
* keystore now.
*/
}
return (rv);
}
/*
* Perform key derivation rules on key's sensitivity and extractability.
*/
void
{
/*
* The sensitive and extractable bits have been set when
* the newkey was built.
*/
}
}
/* Derive the CKA_ALWAYS_SENSITIVE flag */
/*
* If the base key has its CKA_ALWAYS_SENSITIVE set to
* FALSE, then the derived key will as well.
*/
} else {
/*
* If the base key has its CKA_ALWAYS_SENSITIVE set to TRUE,
* then the derived key has the CKA_ALWAYS_SENSITIVE set to
* the same value as its CKA_SENSITIVE;
*/
if (new_sensitive) {
} else {
}
}
/* Derive the CKA_NEVER_EXTRACTABLE flag */
/*
* If the base key has its CKA_NEVER_EXTRACTABLE set to
* FALSE, then the derived key will as well.
*/
} else {
/*
* If the base key has its CKA_NEVER_EXTRACTABLE set to TRUE,
* then the derived key has the CKA_NEVER_EXTRACTABLE set to
* the opposite value from its CKA_EXTRACTABLE;
*/
if (new_extractable) {
} else {
}
}
/* Set the CKA_LOCAL flag to false */
}
/*
* do_prf
*
* This routine implements Step 3. of the PBKDF2 function
* defined in PKCS#5 for generating derived keys from a
* password.
*
* Currently, PRF is always SHA_1_HMAC.
*/
static CK_RV
{
CK_ULONG i, j;
return (CKR_OPERATION_ACTIVE);
}
for (i = 0; i < params->iterations; i++) {
/*
* The key doesn't change, its always the
* password iniitally given.
*/
goto cleanup;
}
/* Call PRF function (SHA1_HMAC for now). */
goto cleanup;
}
/*
* The first time, initialize the output buffer
* with the HMAC signature.
*/
if (i == 0) {
} else {
/*
* XOR the existing data with output from PRF.
*
* Only XOR up to the length of the blockdata,
* it may be less than a full hmac buffer when
* the final block is being computed.
*/
for (j = 0; j < hmac_outlen && j < blocklen; j++)
}
/* Output from previous PRF is input for next round */
inlen = hmac_outlen;
/*
* Switch buffers to avoid overuse of memcpy.
* Initially we used buffer[1], so after the end of
* the first iteration (i==0), we switch to buffer[0]
* and continue swapping with each iteration.
*/
}
return (rv);
}
static CK_RV
{
/*
* We must initialize each template member individually
* because at the time of initial coding for ON10, the
* compiler was using the "-xc99=%none" option
* which prevents us from being able to declare the whole
* template in place as usual.
*/
/*
* Create a generic key object to be used for HMAC operations.
* The "value" for this key is the password from the
* mechanism parameter structure.
*/
return (rv);
}
{
return (CKR_MECHANISM_PARAM_INVALID);
return (CKR_DATA_INVALID);
params->iterations == 0)
return (CKR_MECHANISM_PARAM_INVALID);
/*
* Create a key object to use for HMAC operations.
*/
return (rv);
/* Step 1. */
B_FALSE);
return (CKR_KEY_SIZE_RANGE);
}
/* Step 2. */
/* crude "Ceiling" function to adjust the number of blocks to use */
blocks++;
/* Step 3 */
B_FALSE);
return (CKR_HOST_MEMORY);
}
/*
* Nothing in PKCS#5 says you cannot pass an empty
* salt, so we will allow for this and not return error
* if the salt is not specified.
*/
/*
* Get pointer to the data section of the key,
* this will be used below as output from the
* PRF iteration/concatenations so that when the
* blocks are all iterated, the secret_key will
* have the resulting derived key value.
*/
/* Step 4. */
CK_BYTE *s;
/*
* Append the block index to the salt as input
* to the PRF. Block index should start at 1
* not 0.
*/
*s++ = ((i+1) >> 24) & 0xff;
*s++ = ((i+1) >> 16) & 0xff;
*s++ = ((i+1) >> 8) & 0xff;
*s = ((i+1)) & 0xff;
/*
* Adjust the key pointer so we always append the
* PRF output to the current key.
*/
}
return (rv);
}
{
/* Check if the mechanism is supported. */
switch (pMechanism->mechanism) {
case CKM_DES_CBC_PAD:
case CKM_DES3_CBC_PAD:
case CKM_AES_CBC_PAD:
/*
* Secret key mechs with padding can be used to wrap secret
* keys and private keys only. See PKCS#11, * sec 11.14,
* C_WrapKey and secs 12.* for each mechanism's wrapping/
* unwrapping constraints.
*/
return (CKR_MECHANISM_INVALID);
break;
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:
/*
* Unpadded secret key mechs and private key mechs are only
* defined for wrapping secret keys. See PKCS#11 refs above.
*/
return (CKR_MECHANISM_INVALID);
break;
default:
return (CKR_MECHANISM_INVALID);
}
} else {
/*
* BER-encode the object to be wrapped: call first with
* plain_data = NULL to get the size needed, allocate that
* much space, call again to fill space with actual data.
*/
return (rv);
return (CKR_HOST_MEMORY);
goto cleanup_wrap;
}
/*
* For unpadded ECB and CBC mechanisms, the object needs to be
* padded to the wrapping key's blocksize prior to the encryption.
*/
switch (pMechanism->mechanism) {
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:
/* Find the block size of the wrapping key. */
switch (wrappingKey_p->key_type) {
case CKK_DES:
case CKK_DES2:
case CKK_DES3:
break;
case CKK_AES:
break;
case CKK_BLOWFISH:
break;
default:
break;
}
} else {
goto cleanup_wrap;
}
/* Extend the plain text data to block size boundary. */
if ((padded_len % wkey_blksz) != 0) {
goto cleanup_wrap;
}
}
break;
default:
break;
}
goto cleanup_wrap;
/* Clear buffer before returning to memory pool. */
}
/* Clear buffer before returning to memory pool. */
}
return (rv);
}
/*
* Quick check for whether unwrapped key length is appropriate for key type
* and whether it needs to be truncated (in case the wrapping function had
* to pad the key prior to wrapping).
*/
static CK_RV
{
CK_ULONG i;
/*
* Based on the key type and the mech used to unwrap, need to
* determine if CKA_VALUE_LEN should or should not be specified.
* PKCS#11 v2.11 restricts CKA_VALUE_LEN from being specified
* for C_UnwrapKey for all mechs and key types, but v2.20 loosens
* that restriction, perhaps because it makes it impossible to
* determine the original length of unwrapped variable-length secret
* keys, such as RC4, AES, and GENERIC_SECRET. These variable-length
* secret keys would have been padded with trailing null-bytes so
* that they could be successfully wrapped with *_ECB and *_CBC
* mechanisms. Hence for unwrapping with these mechs, CKA_VALUE_LEN
* must be specified. For unwrapping with other mechs, such as
* *_CBC_PAD, the CKA_VALUE_LEN is not needed.
*/
/* Find out if template has CKA_VALUE_LEN. */
for (i = 0; i < ulAttributeCount; i++) {
isValueLen = B_TRUE;
break;
}
}
/* Does its presence conflict with the mech type and key type? */
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:
/*
* CKA_VALUE_LEN must be specified
* if keytype is CKK_RC4, CKK_AES and CKK_GENERIC_SECRET
* and must not be specified otherwise
*/
switch (keytype) {
case CKK_DES:
case CKK_DES2:
case CKK_DES3:
if (isValueLen)
return (CKR_TEMPLATE_INCONSISTENT);
break;
case CKK_GENERIC_SECRET:
case CKK_RC4:
case CKK_AES:
case CKK_BLOWFISH:
if (!isValueLen)
return (CKR_TEMPLATE_INCOMPLETE);
break;
default:
return (CKR_FUNCTION_NOT_SUPPORTED);
}
break;
default:
/* CKA_VALUE_LEN must not be specified */
if (isValueLen)
return (CKR_TEMPLATE_INCONSISTENT);
break;
}
return (CKR_OK);
}
{
int i = 0;
/* Scan the attribute template for the object class. */
for (i = 0; i < ulAttributeCount; i++) {
break;
}
}
if (new_obj_class == ~0UL)
return (CKR_TEMPLATE_INCOMPLETE);
}
/*
* Check if the mechanism is supported, and now that the new
* object's class is known, the mechanism selected should be
* capable of doing the unwrap.
*/
switch (pMechanism->mechanism) {
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:
if (new_obj_class != CKO_SECRET_KEY)
return (CKR_MECHANISM_INVALID);
break;
case CKM_DES_CBC_PAD:
case CKM_DES3_CBC_PAD:
case CKM_AES_CBC_PAD:
return (CKR_MECHANISM_INVALID);
break;
default:
return (CKR_MECHANISM_INVALID);
}
/* Create a new object based on the attribute template. */
return (rv);
/*
* New key will have CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE
* both set to FALSE. CKA_EXTRACTABLE will be set _by_default_ to
* true -- leaving the possibility that it may be set FALSE by the
* supplied attribute template. If the precise template cannot be
* supported, unwrap fails. PKCS#11 spec, Sec. 11.14, C_UnwrapKey.
*
* Therefore, check the new object's NEVER_EXTRACTABLE_BOOL_ON and
* ALWAYS_SENSITVE_BOOL_ON; if they are TRUE, the template must
* have supplied them and therefore we cannot honor the unwrap.
*/
goto cleanup_unwrap;
}
goto cleanup_unwrap;
/* First get the length of the plain data */
&plain_len);
goto cleanup_unwrap;
/* Allocate space for the unwrapped data */
goto cleanup_unwrap;
}
/* Perform actual decryption into the allocated space. */
&plain_len);
goto cleanup_unwrap;
/*
* Since no ASN.1 encoding is done for secret keys, check for
* appropriateness and copy decrypted buffer to the key object.
*/
/* Check keytype and mechtype don't conflict with valuelen */
goto cleanup_unwrap;
/*
* Allocate the secret key structure if not already there;
* it will exist for variable length keys since CKA_VALUE_LEN
* is specified and saved, but not for fixed length keys.
*/
NULL) {
goto cleanup_unwrap;
}
}
/* Fixed length secret keys don't have CKA_VALUE_LEN */
case CKK_DES:
break;
case CKK_DES2:
break;
case CKK_DES3:
break;
/*
* Variable length secret keys. CKA_VALUE_LEN must be
* provided by the template when mech is *_ECB or *_CBC, and
* should already have been set during soft_gen_keyobject().
* Otherwise we don't need CKA_VALUE_LEN.
*/
case CKK_GENERIC_SECRET:
case CKK_RC4:
case CKK_AES:
case CKK_BLOWFISH:
break;
default:
goto cleanup_unwrap;
};
if (OBJ_SEC_VALUE_LEN(new_objp) == 0) {
/* No CKA_VALUE_LEN set so set it now and save data */
/* No need to truncate, just save the data */
/* Length can't be bigger than what was decrypted */
goto cleanup_unwrap;
} else { /* betw 0 and plain_len, hence padded */
/* Truncate the data before saving. */
goto cleanup_unwrap;
}
}
} else {
/* BER-decode the object to be unwrapped. */
goto cleanup_unwrap;
}
/* If it needs to be persistent, write it to the keystore */
if (IS_TOKEN_OBJECT(new_objp)) {
persistent = B_TRUE;
goto cleanup_unwrap;
}
/* Clear buffer before returning to memory pool. */
}
return (CKR_OK);
/* The decrypted private key buffer must be freed explicitly. */
/* Clear buffer before returning to memory pool. */
}
/* sck and new_objp are indirectly free()d inside these functions */
if (IS_TOKEN_OBJECT(new_objp))
else
return (rv);
}