/*
* 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
*/
/*
*/
#include <crypt.h>
#include <cryptoutil.h>
#include <pwd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/sysmacros.h>
#include <security/cryptoki.h>
#include "softGlobal.h"
#include "softCrypt.h"
#include "softSession.h"
#include "softObject.h"
#include "softKeys.h"
#include "softKeystore.h"
#include "softKeystoreUtil.h"
#include "softMAC.h"
#include "softOps.h"
/*
* The token session is just a pseudo session (a place holder)
* to hold some information during encryption/decryption and
* token object.
*/
/*
* 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
{
/*
* We need to get the passwd entry of the application, which is required
* by the crypt_gensalt() below.
*/
return (-1);
}
/*
* crypt_gensalt() will allocate memory to store the new salt.
* on return. Pass "$5" here to default to crypt_sha256 since
* SHA256 is a FIPS 140-2 certified algorithm and we shouldn't
* assume the system default is that strong.
*/
return (-1);
}
}
if (new_salt)
return (-1);
}
return (0);
}
/*
* Authenticate user's PIN for C_Login.
*/
{
/*
* Check to see if keystore is initialized.
*/
B_FALSE);
return (rv);
/*
* Authenticate user's PIN for C_Login.
*/
if (pin_initialized) {
if (soft_keystore_get_pin_salt(&salt) < 0) {
goto cleanup;
}
/*
* Generate the hashed value based on the user's supplied pin.
*/
goto cleanup;
}
goto cleanup;
}
/*
* Compare hash value of the user supplied PIN with
* hash value of the keystore PIN.
*/
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) {
} else {
}
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.
*/
}
if (salt)
if (tmp_pin) {
/* Zero out our PIN memory copy. */
}
if (ks_cryptpin)
return (rv);
}
/*
* The second level C_SetPIN function.
*/
{
/*
* Check to see if keystore is initialized.
*/
B_FALSE);
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) {
goto cleanup;
}
if (tmp_old_pin == NULL) {
goto cleanup;
}
&salt) < 0) {
goto cleanup;
}
/*
* Compare hashed value of the user supplied PIN with the
* hashed value of the keystore PIN.
*/
goto cleanup;
}
} else {
/*
* This is the first time to setpin, the oldpin must be
* "changeme".
*/
ulOldPinLen) != 0) {
goto cleanup;
}
}
if (tmp_new_pin == NULL) {
goto cleanup;
}
/*
* Set the new pin after the old pin is authenticated.
*/
goto cleanup;
} else {
(void) pthread_mutex_lock(&soft_giant_mutex);
(void) pthread_mutex_unlock(&soft_giant_mutex);
}
if (salt)
if (ks_cryptpin)
if (tmp_old_pin)
if (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
*
*/
{
int num_attrs = 0;
int i;
/*
* The first part of the packed format contains
* the ks_obj_hdr_t struct.
*/
/*
* The second part of the packed format contains
* the attributes from the extra attribute list.
*/
while (extra_attr) {
num_attrs++;
}
return (CKR_HOST_MEMORY);
}
for (i = 0; i < num_attrs; i++) {
}
/*
* The third part of the packed format contains
* the key itself.
*/
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
*
*/
{
int i;
/*
* Unpack the common area.
*/
/* LINTED: pointer alignment */
/*
* Initialize other stuffs which were not from keystore.
*/
/*
* Unpack extra attribute list.
*/
/* LINTED: pointer alignment */
/* Allocate storage for the value of the attribute. */
if (template.ulValueLen > 0) {
return (CKR_HOST_MEMORY);
}
}
}
return (rv);
}
}
/*
* Unpack the key itself.
*/
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
*
*/
{
/* LINTED: pointer alignment */
return (CKR_HOST_MEMORY);
}
if (cert) {
} else {
}
return (rv);
}
return (CKR_OK);
}
/*
* Calculate the total buffer length required to store the
* object key (the third part) in a keystore format.
*/
{
switch (class) {
case CKO_PUBLIC_KEY:
switch (keytype) {
case CKK_RSA:
/*
* modulus_bits + modulus_len + modulus +
* pubexpo_len + pubexpo
*/
return (ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
3 * sizeof (uint64_t));
case CKK_DSA:
/*
* prime_len + prime + subprime_len + subprime +
* base_len + base + value_len + value
*/
return (ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
4 * sizeof (uint64_t));
case CKK_EC:
/*
* ec_point_len + ec_point
*/
return (ROUNDUP(((biginteger_t *)
sizeof (uint64_t));
case CKK_DH:
/*
* prime_len + prime + base_len + base +
* value_len + value
*/
return (ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
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 *)
ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
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 *)
ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
8 * sizeof (uint64_t));
case CKK_DSA:
/*
* prime_len + prime + subprime_len + subprime +
* base_len + base + value_len + value
*/
return (ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
4 * sizeof (uint64_t));
case CKK_DH:
/*
* value_bits + prime_len + prime + base_len + base +
* value_len + value
*/
return (ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
4 * sizeof (uint64_t));
case CKK_EC:
/*
* value_len + value
*/
return (ROUNDUP(((biginteger_t *)
sizeof (uint64_t));
case CKK_X9_42_DH:
/*
* prime_len + prime + base_len + base +
* subprime_len + subprime + value_len + value
*/
return (ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
ROUNDUP(((biginteger_t *)
4 * sizeof (uint64_t));
} /* keytype */
break;
case CKO_SECRET_KEY:
/*
* value_len + value
*/
sizeof (uint64_t));
case CKO_CERTIFICATE:
switch (certtype) {
case CKC_X_509:
/*
* subject_len + subject + value_len + value
*/
return (ROUNDUP(((cert_attr_t *)
ROUNDUP(((cert_attr_t *)
2 * sizeof (uint64_t));
case CKC_X_509_ATTR_CERT:
/*
* owner_len + owner + value_len + value
*/
return (ROUNDUP(((cert_attr_t *)
ROUNDUP(((cert_attr_t *)
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.
*/
{
switch (class) {
case CKO_PUBLIC_KEY:
switch (keytype) {
case CKK_RSA:
/* modulus_bits */
/* modulus_len + modulus */
((biginteger_t *)
/* pubexpo_len + pubexpo */
((biginteger_t *)
break;
case CKK_DSA:
/* prime_len + prime */
((biginteger_t *)
/* subprime_len + subprime */
((biginteger_t *)
/* base_len + base */
((biginteger_t *)
/* value_len + value */
((biginteger_t *)
break;
case CKK_EC:
/* point_len + point */
((biginteger_t *)
break;
case CKK_DH:
/* prime_len + prime */
((biginteger_t *)
/* base_len + base */
((biginteger_t *)
/* value_len + value */
((biginteger_t *)
break;
case CKK_X9_42_DH:
/* prime_len + prime */
((biginteger_t *)
/* base_len + base */
((biginteger_t *)
/* subprime_len + subprime */
((biginteger_t *)
/* value_len + value */
((biginteger_t *)
break;
} /* keytype */
break;
case CKO_PRIVATE_KEY:
switch (keytype) {
case CKK_RSA:
/* modulus_len + modulus */
((biginteger_t *)
/* pubexpo_len + pubexpo */
((biginteger_t *)
/* priexpo_len + priexpo */
((biginteger_t *)
/* prime1_len + prime1 */
((biginteger_t *)
/* prime2_len + prime2 */
((biginteger_t *)
/* expo1_len + expo1 */
((biginteger_t *)
/* expo2_len + expo2 */
((biginteger_t *)
/* coef_len + coef */
((biginteger_t *)
break;
case CKK_DSA:
/* prime_len + prime */
((biginteger_t *)
/* subprime_len + subprime */
((biginteger_t *)
/* base_len + base */
((biginteger_t *)
/* value_len + value */
((biginteger_t *)
break;
case CKK_EC:
/* value_len + value */
((biginteger_t *)
break;
case CKK_DH:
/* value_bits */
/* prime_len + prime */
((biginteger_t *)
/* base_len + base */
((biginteger_t *)
/* value_len + value */
((biginteger_t *)
break;
case CKK_X9_42_DH:
/* prime_len + prime */
((biginteger_t *)
/* base_len + base */
((biginteger_t *)
/* subprime_len + subprime */
((biginteger_t *)
/* value_len + value */
((biginteger_t *)
break;
} /* keytype */
break;
case CKO_SECRET_KEY:
/* value_len + value */
if (OBJ_SEC_VALUE_LEN(objp) > 0) {
}
break;
case CKO_CERTIFICATE:
switch (certtype) {
case CKC_X_509:
/* subject_len + subject */
((cert_attr_t *)
/* value_len + value */
((cert_attr_t *)
break;
case CKC_X_509_ATTR_CERT:
/* owner_len + owner */
((cert_attr_t *)
/* value_len + value */
((cert_attr_t *)
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.
*/
{
/* prevent bigint_attr_cleanup from freeing invalid attr value */
switch (class) {
case CKO_PUBLIC_KEY:
/* Allocate storage for Public Key Object. */
return (rv);
}
switch (keytype) {
case CKK_RSA: /* modulus_bits */
/* modulus */
goto pub_cleanup;
/* pubexpo */
goto pub_cleanup;
break;
case CKK_DSA:
/* prime */
goto pub_cleanup;
/* subprime */
goto pub_cleanup;
/* base */
goto pub_cleanup;
/* value */
goto pub_cleanup;
break;
case CKK_DH:
/* prime */
goto pub_cleanup;
/* base */
goto pub_cleanup;
/* value */
goto pub_cleanup;
break;
case CKK_EC:
/* ec_point */
goto pri_cleanup;
break;
case CKK_X9_42_DH:
/* prime */
goto pub_cleanup;
/* base */
goto pub_cleanup;
/* subprime */
goto pub_cleanup;
/* value */
goto pub_cleanup;
break;
} /* keytype */
break;
case CKO_PRIVATE_KEY:
/* Allocate storage for Private Key Object. */
return (rv);
}
switch (keytype) {
case CKK_RSA:
/* modulus */
goto pri_cleanup;
/* pubexpo */
goto pri_cleanup;
/* priexpo */
goto pri_cleanup;
/* prime1 */
goto pri_cleanup;
/* prime2 */
goto pri_cleanup;
/* expo1 */
goto pri_cleanup;
/* expo2 */
goto pri_cleanup;
/* coef */
goto pri_cleanup;
break;
case CKK_DSA:
/* prime */
goto pri_cleanup;
/* subprime */
goto pri_cleanup;
/* base */
goto pri_cleanup;
/* value */
goto pri_cleanup;
break;
case CKK_DH:
/* value_bits */
/* prime */
goto pri_cleanup;
/* base */
goto pri_cleanup;
/* value */
goto pri_cleanup;
break;
case CKK_EC:
/* value */
goto pri_cleanup;
break;
case CKK_X9_42_DH:
/* prime */
goto pri_cleanup;
/* base */
goto pri_cleanup;
/* subprime */
goto pri_cleanup;
/* value */
goto pri_cleanup;
break;
} /* keytype */
break;
case CKO_SECRET_KEY:
/* Allocate storage for Secret Key Object. */
return (CKR_HOST_MEMORY);
}
/* value */
if (OBJ_SEC_VALUE_LEN(objp) > 0) {
return (CKR_HOST_MEMORY);
}
}
return (rv);
case CKO_CERTIFICATE:
/* Allocate storage for Certificate Object. */
return (CKR_HOST_MEMORY);
}
switch (certtype) {
case CKC_X_509:
/* subject */
return (rv);
}
/* value */
return (rv);
}
break;
case CKC_X_509_ATTR_CERT:
/* owner */
return (rv);
}
/* value */
return (rv);
}
break;
}
return (rv);
case CKO_DOMAIN_PARAMETERS:
break;
}
/*
* cleanup the storage allocated to the local variables.
*/
return (rv);
/*
* cleanup the storage allocated to the local variables.
*/
return (rv);
}
/*
* Store the token object to a keystore file.
*/
{
return (rv);
return (CKR_FUNCTION_FAILED);
}
} else {
return (CKR_FUNCTION_FAILED);
}
}
return (CKR_OK);
}
/*
* Modify the in-core token object and then write it to
* a keystore file.
*/
{
return (rv);
/* B_TRUE: caller has held a writelock on the keystore */
B_TRUE) < 0) {
return (CKR_FUNCTION_FAILED);
}
return (CKR_OK);
}
/*
* Read the token object from the keystore file.
*/
{
/* Load the token object from keystore based on the object type */
return (rv);
}
while (ks_obj) {
goto cleanup;
}
/* Convert the keystore format to memory format */
else
goto cleanup;
}
/* Free the ks_obj list */
}
return (CKR_OK);
while (ks_obj) {
}
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
*
*/
{
int attrs = 0;
return (CKR_FUNCTION_FAILED);
attrs++;
attrs++;
attrs++;
attrs++;
attrs++;
return (CKR_HOST_MEMORY);
} else {
}
params.ulPrfDataLen = 0;
return (rv);
}
/* Obtain the secret object pointer. */
return (CKR_HOST_MEMORY);
}
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
*
*/
{
int attrs = 0;
return (CKR_FUNCTION_FAILED);
attrs++;
attrs++;
attrs++;
attrs++;
attrs++;
return (CKR_HOST_MEMORY);
} else {
}
params.ulPrfDataLen = 0;
return (rv);
}
/* Obtain the secret object pointer. */
return (CKR_HOST_MEMORY);
}
else
*key = secret_key;
return (rv);
}
soft_init_token_session(void)
{
token_session.ses_refcnt = 0;
/* Initialize the lock for the token session */
return (CKR_CANT_LOCK);
}
return (CKR_OK);
}
void
{
token_session.ses_refcnt = 0;
}
/*
* This function only applies to the private token object.
*/
{
/*
* The caller will pass NULL for "out" (output buffer) to find out
* the output buffer size that it need to allocate for the encryption
* or decryption.
*/
return (rv);
if (encrypt)
else
/* Copy Initialization Vector (IV) into the context. */
/* Allocate a context for AES cipher-block chaining. */
soft_aes_ctx->ivec);
if (encrypt) {
} else {
}
(void) pthread_mutex_unlock(&token_session.
return (CKR_HOST_MEMORY);
}
/*
* Since out == NULL, the soft_aes_xxcrypt_common() will
* simply return the output buffer length to the caller.
*/
if (encrypt) {
} else {
}
} else {
/*
* The caller has allocated the output buffer, so that we
* are doing the real encryption/decryption this time.
*/
if (encrypt) {
}
} else {
}
}
}
return (rv);
}
/*
* when dealing with the keystore.
* This function only applies to the private token object.
*/
{
mech.ulParameterLen = 0;
return (rv);
if (sign) {
} else {
}
return (rv);
}