#include <crypt.h>
#include <cryptoutil.h>
#include <pwd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.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"
soft_session_t token_session;
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;
uid = geteuid();
if (getpwuid_r(uid, &pwd, pwdbuf, PWD_BUFFER_SIZE, &pw) != 0) {
return (-1);
}
if (*salt == NULL) {
new_salt = B_TRUE;
if ((*salt = crypt_gensalt("$5", pw)) == NULL) {
return (-1);
}
}
if ((*result = crypt((char *)pPin, *salt)) == NULL) {
if (new_salt) {
size_t saltlen = strlen(*salt) + 1;
freezero(*salt, saltlen);
}
return (-1);
}
return (0);
}
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;
size_t len = 0;
rv = soft_keystore_pin_initialized(&pin_initialized, &ks_cryptpin,
B_FALSE);
if (rv != CKR_OK)
return (rv);
if (pin_initialized) {
if (soft_keystore_get_pin_salt(&salt) < 0) {
rv = CKR_FUNCTION_FAILED;
goto cleanup;
}
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;
}
if (strcmp(user_cryptpin, ks_cryptpin) != 0) {
rv = CKR_PIN_INCORRECT;
goto cleanup;
}
if (soft_keystore_authpin(tmp_pin) != 0) {
rv = CKR_FUNCTION_FAILED;
} else {
rv = CKR_OK;
}
goto cleanup;
} else {
soft_slot.userpin_change_needed = 1;
rv = CKR_OK;
}
cleanup:
if (salt) {
len = strlen(salt) + 1;
freezero(salt, len);
}
if (tmp_pin) {
len = strlen((char *)tmp_pin) + 1;
freezero(tmp_pin, len);
}
if (ks_cryptpin) {
len = strlen(ks_cryptpin) + 1;
freezero(ks_cryptpin, len);
}
return (rv);
}
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;
size_t len = 0;
rv = soft_keystore_pin_initialized(&pin_initialized, &ks_cryptpin,
B_FALSE);
if (rv != CKR_OK)
return (rv);
if (pin_initialized) {
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;
}
if (strcmp(user_cryptpin, ks_cryptpin) != 0) {
rv = CKR_PIN_INCORRECT;
goto cleanup;
}
} else {
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';
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) {
len = strlen(salt) + 1;
freezero(salt, len);
}
if (ks_cryptpin) {
len = strlen(ks_cryptpin) + 1;
freezero(ks_cryptpin, len);
}
if (tmp_old_pin) {
len = strlen((char *)tmp_old_pin) + 1;
freezero(tmp_old_pin, len);
}
if (tmp_new_pin) {
len = strlen((char *)tmp_new_pin) + 1;
freezero(tmp_new_pin, len);
}
return (rv);
}
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));
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;
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;
}
rv = soft_pack_object(obj, buf1);
*len = ks_len;
*ks_buf = buf;
return (rv);
}
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;
(void) strcpy((char *)obj->ks_handle.name,
(char *)ks_obj->ks_handle.name);
obj->ks_handle.public = ks_obj->ks_handle.public;
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;
(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);
for (i = 0; i < SWAP32(hdr->num_attrs); i++) {
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);
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);
freezero(template.pValue, template.ulValueLen);
if (rv != CKR_OK) {
return (rv);
}
buf = buf + ROUNDUP(template.ulValueLen, 8);
}
rv = soft_unpack_object(obj, buf);
return (rv);
}
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;
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);
}
freezero(template.pValue, template.ulValueLen);
if (rv != CKR_OK) {
return (rv);
}
*offset = sizeof (uint64_t) + template.ulValueLen;
return (CKR_OK);
}
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:
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:
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_EC:
return (ROUNDUP(((biginteger_t *)
OBJ_PUB_EC_POINT(objp))->big_value_len, 8) +
sizeof (uint64_t));
case CKK_DH:
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:
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));
}
break;
case CKO_PRIVATE_KEY:
switch (keytype) {
case CKK_RSA:
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:
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:
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_EC:
return (ROUNDUP(((biginteger_t *)
OBJ_PRI_EC_VALUE(objp))->big_value_len, 8) +
sizeof (uint64_t));
case CKK_X9_42_DH:
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));
}
break;
case CKO_SECRET_KEY:
return (ROUNDUP(OBJ_SEC_VALUE_LEN(objp), 8) +
sizeof (uint64_t));
case CKO_CERTIFICATE:
switch (certtype) {
case CKC_X_509:
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:
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);
}
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:
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);
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);
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:
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);
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);
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);
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_EC:
tmp_val = SWAP64((uint64_t)((biginteger_t *)
OBJ_PUB_EC_POINT(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_EC_POINT(objp))->big_value,
((biginteger_t *)
OBJ_PUB_EC_POINT(objp))->big_value_len);
break;
case CKK_DH:
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);
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);
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:
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);
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);
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);
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;
}
break;
case CKO_PRIVATE_KEY:
switch (keytype) {
case CKK_RSA:
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);
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);
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);
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);
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);
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);
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);
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:
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);
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);
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);
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_EC:
tmp_val = SWAP64((uint64_t)((biginteger_t *)
OBJ_PRI_EC_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_EC_VALUE(objp))->big_value,
((biginteger_t *)
OBJ_PRI_EC_VALUE(objp))->big_value_len);
break;
case CKK_DH:
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);
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);
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);
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:
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);
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);
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);
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;
}
break;
case CKO_SECRET_KEY:
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:
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);
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:
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);
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);
}
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;
(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:
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:
(void) memcpy(&tmp_val, buf, sizeof (uint64_t));
KEY_PUB_RSA_MOD_BITS(pbk) = (CK_ULONG)(SWAP64(tmp_val));
buf = buf + sizeof (uint64_t);
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);
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:
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);
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);
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);
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:
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);
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);
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_EC:
if ((rv = soft_unpack_obj_attribute(buf, &value,
NULL, &offset, B_FALSE)) != CKR_OK)
goto pri_cleanup;
copy_bigint_attr(&value, KEY_PUB_EC_POINT(pbk));
break;
case CKK_X9_42_DH:
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);
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);
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);
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;
}
break;
case CKO_PRIVATE_KEY:
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:
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);
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);
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);
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);
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);
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);
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);
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:
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);
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);
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);
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:
(void) memcpy(&tmp_val, buf, sizeof (uint64_t));
KEY_PRI_DH_VAL_BITS(pvk) = (CK_ULONG)(SWAP64(tmp_val));
buf = buf + sizeof (uint64_t);
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);
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);
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_EC:
if ((rv = soft_unpack_obj_attribute(buf, &value,
NULL, &offset, B_FALSE)) != CKR_OK)
goto pri_cleanup;
copy_bigint_attr(&value, KEY_PRI_EC_VALUE(pvk));
break;
case CKK_X9_42_DH:
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);
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);
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);
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;
}
break;
case CKO_SECRET_KEY:
sck = calloc(1, sizeof (secret_key_obj_t));
if (sck == NULL) {
return (CKR_HOST_MEMORY);
}
objp->object_class_u.secret_key = sck;
(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:
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:
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);
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:
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);
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:
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:
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);
}
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);
(void) pthread_mutex_lock(&soft_slot.slot_mutex);
if (soft_keystore_put_new_obj(buf, len,
!!(objp->object_type == TOKEN_PUBLIC), B_FALSE,
&objp->ks_handle) == -1) {
rv = CKR_FUNCTION_FAILED;
}
(void) pthread_mutex_unlock(&soft_slot.slot_mutex);
freezero(buf, len);
return (rv);
}
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);
if (soft_keystore_modify_obj(&objp->ks_handle, buf, len,
B_TRUE) < 0) {
rv = CKR_FUNCTION_FAILED;
}
freezero(buf, len);
return (rv);
}
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;
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;
}
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);
ks_obj_next = ks_obj->next;
freezero(ks_obj->buf, ks_obj->size);
free(ks_obj);
ks_obj = ks_obj_next;
}
return (CKR_OK);
cleanup:
while (ks_obj) {
ks_obj_next = ks_obj->next;
freezero(ks_obj->buf, ks_obj->size);
free(ks_obj);
ks_obj = ks_obj_next;
}
return (rv);
}
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_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) pkcs11_get_nzero_urandom(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, &secret_key, &token_session,
CKO_SECRET_KEY, CKK_AES, 0, SOFT_GEN_KEY, B_TRUE);
if (rv != CKR_OK) {
return (rv);
}
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, 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, B_FALSE);
else
*key = secret_key;
return (rv);
}
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_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) pkcs11_get_nzero_urandom(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, &secret_key, &token_session,
CKO_SECRET_KEY, CKK_GENERIC_SECRET, 0, SOFT_GEN_KEY, B_TRUE);
if (rv != CKR_OK) {
return (rv);
}
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, 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, B_FALSE);
else
*key = secret_key;
return (rv);
}
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;
token_session.next = NULL;
token_session.prev = NULL;
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);
}
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;
CK_RV rv;
CK_ULONG tmplen, tmplen1;
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);
if (encrypt) {
rv = soft_aes_encrypt(&token_session, in, in_len,
out, out_len);
} else {
rv = soft_aes_decrypt(&token_session, in, in_len,
out, out_len);
}
} else {
tmplen = *out_len;
if (encrypt) {
rv = soft_aes_encrypt_update(&token_session, in,
in_len, out, &tmplen);
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_update(&token_session, in,
in_len, out, &tmplen);
if (rv == CKR_OK) {
tmplen1 = *out_len - tmplen;
rv = soft_decrypt_final(&token_session,
out+tmplen, &tmplen1);
*out_len = tmplen + tmplen1;
}
}
}
return (rv);
}
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);
}