/*
* COPYRIGHT (c) International Business Machines Corp. 2001-2017
*
* This program is provided under the terms of the Common Public License,
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
* found in the file LICENSE file or at
* https://opensource.org/licenses/cpl1.0.php
*/
// File: key.c
//
// Functions contained within:
//
// key_object_check_required_attributes
// key_object_set_default_attributes
// key_object_validate_attribute
//
// publ_key_check_required_attributes
// publ_key_set_default_attributes
// publ_key_validate_attribute
//
// priv_key_check_required_attributes
// priv_key_set_default_attributes
// priv_key_validate_attribute
//
// secret_key_check_required_attributes
// secret_key_set_default_attributes
// secret_key_validate_attribute
//
// rsa_publ_check_required_attributes
// rsa_publ_validate_attribute
// rsa_priv_check_required_attributes
// rsa_priv_validate_attribute
// rsa_priv_check_exportability
//
// dsa_publ_check_required_attributes
// dsa_publ_validate_attribute
// dsa_priv_check_required_attributes
// dsa_priv_validate_attribute
// dsa_priv_check_exportability
//
// ecdsa_publ_check_required_attributes
// ecdsa_publ_validate_attribute
// ecdsa_priv_checK_required_attributes
// ecdsa_priv_validate_attribute
// ecdsa_priv_check_exportability
//
// dh_publ_check_required_attributes
// dh_publ_validate_attribute
// dh_priv_check_required_attributes
// dh_priv_validate_attribute
// dh_priv_check_exportability
//
// kea_publ_check_required_attributes
// kea_publ_validate_attribute
// kea_priv_check_required_attributes
// kea_priv_validate_attribute
// kea_priv_check_exportability
//
// generic_secret_check_required_attributes
// generic_secret_validate_attribute
// generic_secret_set_default_attributes
//
// rc2_check_required_attributes
// rc2_validate_attribute
// rc2_priv_check_exportability
//
// rc4_check_required_attributes
// rc4_validate_attribute
// rc4_priv_check_exportability
//
// rc5_check_required_attributes
// rc5_validate_attribute
// rc5_priv_check_exportability
//
// des_check_required_attributes
// des_validate_attribute
// des_priv_check_exportability
//
// des2_check_required_attributes
// des2_validate_attribute
// des2_priv_check_exportability
//
// des3_check_required_attributes
// des3_validate_attribute
// des3_priv_check_exportability
//
// cast_check_required_attributes
// cast_validate_attribute
// cast_priv_check_exportability
//
// cast3_check_required_attributes
// cast3_validate_attribute
// cast3_priv_check_exportability
//
// cast5_check_required_attributes
// cast5_validate_attribute
// cast5_priv_check_exportability
//
// idea_check_required_attributes
// idea_validate_attribute
// idea_priv_check_exportability
//
// cdmf_check_required_attributes
// cdmf_validate_attribute
// cdmf_priv_check_exportability
//
// skipjack_check_required_attributes
// skipjack_validate_attribute
// skipjack_priv_check_exportability
//
// baton_check_required_attributes
// baton_validate_attribute
// baton_priv_check_exportability
//
// juniper_check_required_attributes
// juniper_validate_attribute
// juniper_priv_check_exportability
//
#include <pthread.h>
#include <stdlib.h>
#include <string.h> // for memcmp() et al
#include "pkcs11types.h"
#include "p11util.h"
#include "defs.h"
#include "host_defs.h"
#include "h_extern.h"
#include "trace.h"
#include "tok_spec_struct.h"
// key_object_check_required_attributes()
//
// Check required common attributes for key objects
//
CK_RV key_object_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_KEY_TYPE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return template_check_required_base_attributes(tmpl, mode);
}
// key_object_set_default_attributes()
//
CK_RV key_object_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *id_attr = NULL;
CK_ATTRIBUTE *sdate_attr = NULL;
CK_ATTRIBUTE *edate_attr = NULL;
CK_ATTRIBUTE *derive_attr = NULL;
CK_ATTRIBUTE *local_attr = NULL;
CK_ATTRIBUTE *keygenmech_attr = NULL;
// satisfy the compiler
//
if (mode)
id_attr = NULL;
id_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
sdate_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
edate_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
derive_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
local_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
keygenmech_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE)
+ sizeof(CK_MECHANISM_TYPE));
if (!id_attr || !sdate_attr || !edate_attr || !derive_attr || !local_attr
|| !keygenmech_attr) {
if (id_attr)
free(id_attr);
if (sdate_attr)
free(sdate_attr);
if (edate_attr)
free(edate_attr);
if (derive_attr)
free(derive_attr);
if (local_attr)
free(local_attr);
if (keygenmech_attr)
free(keygenmech_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
id_attr->type = CKA_ID;
id_attr->ulValueLen = 0;
id_attr->pValue = NULL;
sdate_attr->type = CKA_START_DATE;
sdate_attr->ulValueLen = 0;
sdate_attr->pValue = NULL;
edate_attr->type = CKA_END_DATE;
edate_attr->ulValueLen = 0;
edate_attr->pValue = NULL;
derive_attr->type = CKA_DERIVE;
derive_attr->ulValueLen = sizeof(CK_BBOOL);
derive_attr->pValue = (CK_BYTE *) derive_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) derive_attr->pValue = FALSE;
local_attr->type = CKA_LOCAL;
local_attr->ulValueLen = sizeof(CK_BBOOL);
local_attr->pValue = (CK_BYTE *) local_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) local_attr->pValue = FALSE;
keygenmech_attr->type = CKA_KEY_GEN_MECHANISM;
keygenmech_attr->ulValueLen = sizeof(CK_MECHANISM_TYPE);
keygenmech_attr->pValue = (CK_BYTE *) keygenmech_attr + sizeof(CK_ATTRIBUTE);
*(CK_MECHANISM_TYPE *) keygenmech_attr->pValue = CK_UNAVAILABLE_INFORMATION;
template_update_attribute(tmpl, id_attr);
template_update_attribute(tmpl, sdate_attr);
template_update_attribute(tmpl, edate_attr);
template_update_attribute(tmpl, derive_attr);
template_update_attribute(tmpl, local_attr);
template_update_attribute(tmpl, keygenmech_attr);
return CKR_OK;
}
// key_object_validate_attribute()
//
CK_RV key_object_validate_attribute(TEMPLATE *tmpl, CK_ATTRIBUTE *attr,
CK_ULONG mode)
{
switch (attr->type) {
case CKA_KEY_TYPE:
if (mode == MODE_CREATE || mode == MODE_DERIVE ||
mode == MODE_KEYGEN || mode == MODE_UNWRAP)
return CKR_OK;
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
case CKA_ID:
case CKA_START_DATE:
case CKA_END_DATE:
case CKA_DERIVE:
return CKR_OK;
case CKA_LOCAL:
// CKA_LOCAL is only set by the key-generate routine
//
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
default:
return template_validate_base_attribute(tmpl, attr, mode);
}
TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID), attr->type);
return CKR_ATTRIBUTE_TYPE_INVALID;
}
// publ_key_check_required_attributes()
//
CK_RV publ_key_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
// CKO_PUBLIC_KEY has no required attributes
//
return key_object_check_required_attributes(tmpl, mode);
}
// publ_key_set_default_attributes()
//
// some of the common public key attributes have defaults but none of the
// specific public keytypes have default attributes
//
CK_RV publ_key_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *class_attr = NULL;
CK_ATTRIBUTE *subject_attr = NULL;
CK_ATTRIBUTE *encrypt_attr = NULL;
CK_ATTRIBUTE *verify_attr = NULL;
CK_ATTRIBUTE *verify_recover_attr = NULL;
CK_ATTRIBUTE *wrap_attr = NULL;
CK_OBJECT_CLASS class = CKO_PUBLIC_KEY;
CK_RV rc;
rc = key_object_set_default_attributes(tmpl, mode);
if (rc != CKR_OK) {
TRACE_DEVEL("key_object_set_default_attributes failed\n");
return rc;
}
// add the default CKO_PUBLIC_KEY attributes
//
class_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS));
subject_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
encrypt_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
verify_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
verify_recover_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
wrap_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
if (!class || !subject_attr || !encrypt_attr ||
!verify_attr || !verify_recover_attr || !wrap_attr) {
if (class_attr)
free(class_attr);
if (subject_attr)
free(subject_attr);
if (encrypt_attr)
free(encrypt_attr);
if (verify_attr)
free(verify_attr);
if (verify_recover_attr)
free(verify_recover_attr);
if (wrap_attr)
free(wrap_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
class_attr->type = CKA_CLASS;
class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS);
class_attr->pValue = (CK_BYTE *) class_attr + sizeof(CK_ATTRIBUTE);
*(CK_OBJECT_CLASS *) class_attr->pValue = CKO_PUBLIC_KEY;
subject_attr->type = CKA_SUBJECT;
subject_attr->ulValueLen = 0; // empty string
subject_attr->pValue = NULL;
encrypt_attr->type = CKA_ENCRYPT;
encrypt_attr->ulValueLen = sizeof(CK_BBOOL);
encrypt_attr->pValue = (CK_BYTE *) encrypt_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) encrypt_attr->pValue = TRUE;
verify_attr->type = CKA_VERIFY;
verify_attr->ulValueLen = sizeof(CK_BBOOL);
verify_attr->pValue = (CK_BYTE *) verify_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) verify_attr->pValue = TRUE;
verify_recover_attr->type = CKA_VERIFY_RECOVER;
verify_recover_attr->ulValueLen = sizeof(CK_BBOOL);
verify_recover_attr->pValue =
(CK_BYTE *) verify_recover_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) verify_recover_attr->pValue = TRUE;
wrap_attr->type = CKA_WRAP;
wrap_attr->ulValueLen = sizeof(CK_BBOOL);
wrap_attr->pValue = (CK_BYTE *) wrap_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) wrap_attr->pValue = TRUE;
template_update_attribute(tmpl, class_attr);
template_update_attribute(tmpl, subject_attr);
template_update_attribute(tmpl, encrypt_attr);
template_update_attribute(tmpl, verify_attr);
template_update_attribute(tmpl, verify_recover_attr);
template_update_attribute(tmpl, wrap_attr);
return CKR_OK;
}
// publ_key_validate_attribute
//
CK_RV publ_key_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_SUBJECT:
return CKR_OK;
case CKA_ENCRYPT:
case CKA_VERIFY:
case CKA_VERIFY_RECOVER:
case CKA_WRAP:
if (mode == MODE_MODIFY) {
if (tokdata->nv_token_data->tweak_vector.allow_key_mods == TRUE)
return CKR_OK;
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
return CKR_OK;
default:
return key_object_validate_attribute(tmpl, attr, mode);
}
TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID), attr->type);
return CKR_ATTRIBUTE_TYPE_INVALID;
}
// priv_key_check_required_attributes()
//
CK_RV priv_key_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
// CKO_PRIVATE_KEY has no required attributes
//
return key_object_check_required_attributes(tmpl, mode);
}
// priv_key_set_default_attributes()
//
// some of the common private key attributes have defaults but none of the
// specific private keytypes have default attributes
//
CK_RV priv_key_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *class_attr = NULL;
CK_ATTRIBUTE *subject_attr = NULL;
CK_ATTRIBUTE *sensitive_attr = NULL;
CK_ATTRIBUTE *decrypt_attr = NULL;
CK_ATTRIBUTE *sign_attr = NULL;
CK_ATTRIBUTE *sign_recover_attr = NULL;
CK_ATTRIBUTE *unwrap_attr = NULL;
CK_ATTRIBUTE *extractable_attr = NULL;
CK_ATTRIBUTE *never_extr_attr = NULL;
CK_ATTRIBUTE *always_sens_attr = NULL;
CK_ATTRIBUTE *always_auth_attr = NULL;
CK_RV rc;
rc = key_object_set_default_attributes(tmpl, mode);
if (rc != CKR_OK) {
TRACE_DEVEL("key_object_set_default_attributes failed\n");
return rc;
}
// add the default CKO_PUBLIC_KEY attributes
//
class_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS));
subject_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
sensitive_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
decrypt_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
sign_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
sign_recover_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
unwrap_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
extractable_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
never_extr_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
always_sens_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
always_auth_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
if (!class_attr || !subject_attr || !sensitive_attr || !decrypt_attr ||
!sign_attr || !sign_recover_attr || !unwrap_attr || !extractable_attr ||
!never_extr_attr || !always_sens_attr || !always_auth_attr) {
if (class_attr)
free(class_attr);
if (subject_attr)
free(subject_attr);
if (sensitive_attr)
free(sensitive_attr);
if (decrypt_attr)
free(decrypt_attr);
if (sign_attr)
free(sign_attr);
if (sign_recover_attr)
free(sign_recover_attr);
if (unwrap_attr)
free(unwrap_attr);
if (extractable_attr)
free(extractable_attr);
if (always_sens_attr)
free(always_sens_attr);
if (never_extr_attr)
free(never_extr_attr);
if (always_auth_attr)
free(always_auth_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
class_attr->type = CKA_CLASS;
class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS);
class_attr->pValue = (CK_BYTE *) class_attr + sizeof(CK_ATTRIBUTE);
*(CK_OBJECT_CLASS *) class_attr->pValue = CKO_PRIVATE_KEY;
subject_attr->type = CKA_SUBJECT;
subject_attr->ulValueLen = 0; // empty string
subject_attr->pValue = NULL;
sensitive_attr->type = CKA_SENSITIVE;
sensitive_attr->ulValueLen = sizeof(CK_BBOOL);
sensitive_attr->pValue = (CK_BYTE *) sensitive_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) sensitive_attr->pValue = FALSE;
decrypt_attr->type = CKA_DECRYPT;
decrypt_attr->ulValueLen = sizeof(CK_BBOOL);
decrypt_attr->pValue = (CK_BYTE *) decrypt_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) decrypt_attr->pValue = TRUE;
sign_attr->type = CKA_SIGN;
sign_attr->ulValueLen = sizeof(CK_BBOOL);
sign_attr->pValue = (CK_BYTE *) sign_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) sign_attr->pValue = TRUE;
sign_recover_attr->type = CKA_SIGN_RECOVER;
sign_recover_attr->ulValueLen = sizeof(CK_BBOOL);
sign_recover_attr->pValue =
(CK_BYTE *) sign_recover_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) sign_recover_attr->pValue = TRUE;
unwrap_attr->type = CKA_UNWRAP;
unwrap_attr->ulValueLen = sizeof(CK_BBOOL);
unwrap_attr->pValue = (CK_BYTE *) unwrap_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) unwrap_attr->pValue = TRUE;
extractable_attr->type = CKA_EXTRACTABLE;
extractable_attr->ulValueLen = sizeof(CK_BBOOL);
extractable_attr->pValue =
(CK_BYTE *) extractable_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) extractable_attr->pValue = TRUE;
// by default, we'll set NEVER_EXTRACTABLE == FALSE and
// ALWAYS_SENSITIVE == FALSE
// If the key is being created with KEYGEN, it will adjust as necessary.
//
never_extr_attr->type = CKA_NEVER_EXTRACTABLE;
never_extr_attr->ulValueLen = sizeof(CK_BBOOL);
never_extr_attr->pValue =
(CK_BYTE *) never_extr_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) never_extr_attr->pValue = FALSE;
always_sens_attr->type = CKA_ALWAYS_SENSITIVE;
always_sens_attr->ulValueLen = sizeof(CK_BBOOL);
always_sens_attr->pValue =
(CK_BYTE *) always_sens_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) always_sens_attr->pValue = FALSE;
always_auth_attr->type = CKA_ALWAYS_AUTHENTICATE;
always_auth_attr->ulValueLen = sizeof(CK_BBOOL);
always_auth_attr->pValue =
(CK_BYTE *) always_auth_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) always_auth_attr->pValue = FALSE;
template_update_attribute(tmpl, class_attr);
template_update_attribute(tmpl, subject_attr);
template_update_attribute(tmpl, sensitive_attr);
template_update_attribute(tmpl, decrypt_attr);
template_update_attribute(tmpl, sign_attr);
template_update_attribute(tmpl, sign_recover_attr);
template_update_attribute(tmpl, unwrap_attr);
template_update_attribute(tmpl, extractable_attr);
template_update_attribute(tmpl, never_extr_attr);
template_update_attribute(tmpl, always_sens_attr);
template_update_attribute(tmpl, always_auth_attr);
return CKR_OK;
}
//
//
CK_RV priv_key_unwrap(TEMPLATE *tmpl,
CK_ULONG keytype,
CK_BYTE *data, CK_ULONG data_len)
{
CK_ATTRIBUTE *extractable = NULL;
CK_ATTRIBUTE *always_sens = NULL;
CK_ATTRIBUTE *never_extract = NULL;
CK_ATTRIBUTE *sensitive = NULL;
CK_ATTRIBUTE *local = NULL;
CK_BBOOL true = TRUE;
CK_BBOOL false = FALSE;
CK_RV rc;
switch (keytype) {
case CKK_RSA:
rc = rsa_priv_unwrap(tmpl, data, data_len);
break;
case CKK_DSA:
rc = dsa_priv_unwrap(tmpl, data, data_len);
break;
case CKK_DH:
rc = dh_priv_unwrap(tmpl, data, data_len);
break;
case CKK_EC:
rc = ec_priv_unwrap(tmpl, data, data_len);
break;
case CKK_IBM_PQC_DILITHIUM:
rc = ibm_dilithium_priv_unwrap(tmpl, data, data_len);
break;
default:
TRACE_ERROR("%s\n", ock_err(ERR_WRAPPED_KEY_INVALID));
return CKR_WRAPPED_KEY_INVALID;
}
if (rc != CKR_OK) {
TRACE_DEVEL("priv unwrap failed\n");
return rc;
}
// make sure
// CKA_LOCAL == FALSE
// CKA_ALWAYS_SENSITIVE == FALSE
// CKA_EXTRACTABLE == TRUE
// CKA_NEVER_EXTRACTABLE == FALSE
//
rc = build_attribute(CKA_LOCAL, &false, 1, &local);
if (rc != CKR_OK) {
TRACE_DEVEL("build_attribute failed\n");
goto cleanup;
}
rc = build_attribute(CKA_ALWAYS_SENSITIVE, &false, 1, &always_sens);
if (rc != CKR_OK) {
TRACE_DEVEL("build_attribute failed\n");
goto cleanup;
}
rc = build_attribute(CKA_SENSITIVE, &false, 1, &sensitive);
if (rc != CKR_OK) {
TRACE_DEVEL("build_attribute failed\n");
goto cleanup;
}
rc = build_attribute(CKA_EXTRACTABLE, &true, 1, &extractable);
if (rc != CKR_OK) {
TRACE_DEVEL("build_attribute failed\n");
goto cleanup;
}
rc = build_attribute(CKA_NEVER_EXTRACTABLE, &false, 1, &never_extract);
if (rc != CKR_OK) {
TRACE_DEVEL("build_attribute failed\n");
goto cleanup;
}
template_update_attribute(tmpl, local);
template_update_attribute(tmpl, always_sens);
template_update_attribute(tmpl, sensitive);
template_update_attribute(tmpl, extractable);
template_update_attribute(tmpl, never_extract);
return CKR_OK;
cleanup:
if (local)
free(local);
if (always_sens)
free(always_sens);
if (extractable)
free(extractable);
if (never_extract)
free(never_extract);
return rc;
}
// priv_key_validate_attribute()
//
CK_RV priv_key_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_SUBJECT:
return CKR_OK;
case CKA_DECRYPT:
case CKA_SIGN:
case CKA_SIGN_RECOVER:
case CKA_UNWRAP:
// we might want to do this for MODE_COPY too
//
if (mode == MODE_MODIFY) {
if (tokdata->nv_token_data->tweak_vector.allow_key_mods == TRUE)
return CKR_OK;
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
return CKR_OK;
// after key creation, CKA_SENSITIVE may only be set to TRUE
//
case CKA_SENSITIVE:
{
CK_BBOOL value;
if (mode == MODE_CREATE || mode == MODE_KEYGEN)
return CKR_OK;
value = *(CK_BBOOL *) attr->pValue;
if (value != TRUE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
return CKR_OK;
}
// after key creation, CKA_EXTRACTABLE may only be set to FALSE
//
case CKA_EXTRACTABLE:
{
CK_BBOOL value;
value = *(CK_BBOOL *) attr->pValue;
if ((mode != MODE_CREATE && mode != MODE_KEYGEN) &&
value != FALSE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
if (value == FALSE) {
CK_ATTRIBUTE *attr;
attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) +
sizeof(CK_BBOOL));
if (!attr) {
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
attr->type = CKA_NEVER_EXTRACTABLE;
attr->ulValueLen = sizeof(CK_BBOOL);
attr->pValue = (CK_BYTE *) attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) attr->pValue = FALSE;
template_update_attribute(tmpl, attr);
}
return CKR_OK;
}
case CKA_ALWAYS_SENSITIVE:
case CKA_NEVER_EXTRACTABLE:
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
default:
return key_object_validate_attribute(tmpl, attr, mode);
}
TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID), attr->type);
return CKR_ATTRIBUTE_TYPE_INVALID;
}
// secret_key_check_required_attributes()
//
CK_RV secret_key_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
return key_object_check_required_attributes(tmpl, mode);
}
// secret_key_set_default_attributes()
//
// some of the common secret key attributes have defaults but none of the
// specific secret keytypes have default attributes
//
CK_RV secret_key_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *class_attr = NULL;
CK_ATTRIBUTE *sensitive_attr = NULL;
CK_ATTRIBUTE *encrypt_attr = NULL;
CK_ATTRIBUTE *decrypt_attr = NULL;
CK_ATTRIBUTE *sign_attr = NULL;
CK_ATTRIBUTE *verify_attr = NULL;
CK_ATTRIBUTE *wrap_attr = NULL;
CK_ATTRIBUTE *unwrap_attr = NULL;
CK_ATTRIBUTE *extractable_attr = NULL;
CK_ATTRIBUTE *never_extr_attr = NULL;
CK_ATTRIBUTE *always_sens_attr = NULL;
CK_RV rc;
rc = key_object_set_default_attributes(tmpl, mode);
if (rc != CKR_OK)
return rc;
// add the default CKO_DATA attributes
//
class_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS));
sensitive_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
encrypt_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
decrypt_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
sign_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
verify_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
wrap_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
unwrap_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
extractable_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
never_extr_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
always_sens_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
if (!class_attr || !sensitive_attr || !encrypt_attr || !decrypt_attr ||
!sign_attr || !verify_attr || !wrap_attr ||
!unwrap_attr || !extractable_attr || !never_extr_attr
|| !always_sens_attr) {
if (class_attr)
free(class_attr);
if (sensitive_attr)
free(sensitive_attr);
if (encrypt_attr)
free(encrypt_attr);
if (decrypt_attr)
free(decrypt_attr);
if (sign_attr)
free(sign_attr);
if (verify_attr)
free(verify_attr);
if (wrap_attr)
free(wrap_attr);
if (unwrap_attr)
free(unwrap_attr);
if (extractable_attr)
free(extractable_attr);
if (never_extr_attr)
free(never_extr_attr);
if (always_sens_attr)
free(always_sens_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
class_attr->type = CKA_CLASS;
class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS);
class_attr->pValue = (CK_BYTE *) class_attr + sizeof(CK_ATTRIBUTE);
*(CK_OBJECT_CLASS *) class_attr->pValue = CKO_SECRET_KEY;
sensitive_attr->type = CKA_SENSITIVE;
sensitive_attr->ulValueLen = sizeof(CK_BBOOL);
sensitive_attr->pValue = (CK_BYTE *) sensitive_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) sensitive_attr->pValue = FALSE;
encrypt_attr->type = CKA_ENCRYPT;
encrypt_attr->ulValueLen = sizeof(CK_BBOOL);
encrypt_attr->pValue = (CK_BYTE *) encrypt_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) encrypt_attr->pValue = TRUE;
decrypt_attr->type = CKA_DECRYPT;
decrypt_attr->ulValueLen = sizeof(CK_BBOOL);
decrypt_attr->pValue = (CK_BYTE *) decrypt_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) decrypt_attr->pValue = TRUE;
sign_attr->type = CKA_SIGN;
sign_attr->ulValueLen = sizeof(CK_BBOOL);
sign_attr->pValue = (CK_BYTE *) sign_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) sign_attr->pValue = TRUE;
verify_attr->type = CKA_VERIFY;
verify_attr->ulValueLen = sizeof(CK_BBOOL);
verify_attr->pValue = (CK_BYTE *) verify_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) verify_attr->pValue = TRUE;
wrap_attr->type = CKA_WRAP;
wrap_attr->ulValueLen = sizeof(CK_BBOOL);
wrap_attr->pValue = (CK_BYTE *) wrap_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) wrap_attr->pValue = TRUE;
unwrap_attr->type = CKA_UNWRAP;
unwrap_attr->ulValueLen = sizeof(CK_BBOOL);
unwrap_attr->pValue = (CK_BYTE *) unwrap_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) unwrap_attr->pValue = TRUE;
extractable_attr->type = CKA_EXTRACTABLE;
extractable_attr->ulValueLen = sizeof(CK_BBOOL);
extractable_attr->pValue =
(CK_BYTE *) extractable_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) extractable_attr->pValue = TRUE;
// by default, we'll set NEVER_EXTRACTABLE == FALSE and
// ALWAYS_SENSITIVE == FALSE
// If the key is being created with KEYGEN, it will adjust as necessary.
//
always_sens_attr->type = CKA_ALWAYS_SENSITIVE;
always_sens_attr->ulValueLen = sizeof(CK_BBOOL);
always_sens_attr->pValue =
(CK_BYTE *) always_sens_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) always_sens_attr->pValue = FALSE;
never_extr_attr->type = CKA_NEVER_EXTRACTABLE;
never_extr_attr->ulValueLen = sizeof(CK_BBOOL);
never_extr_attr->pValue =
(CK_BYTE *) never_extr_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) never_extr_attr->pValue = FALSE;
template_update_attribute(tmpl, class_attr);
template_update_attribute(tmpl, sensitive_attr);
template_update_attribute(tmpl, encrypt_attr);
template_update_attribute(tmpl, decrypt_attr);
template_update_attribute(tmpl, sign_attr);
template_update_attribute(tmpl, verify_attr);
template_update_attribute(tmpl, wrap_attr);
template_update_attribute(tmpl, unwrap_attr);
template_update_attribute(tmpl, extractable_attr);
template_update_attribute(tmpl, never_extr_attr);
template_update_attribute(tmpl, always_sens_attr);
return CKR_OK;
}
//
//
CK_RV secret_key_unwrap(STDLL_TokData_t *tokdata,
TEMPLATE *tmpl,
CK_ULONG keytype,
CK_BYTE *data,
CK_ULONG data_len, CK_BBOOL fromend)
{
CK_ATTRIBUTE *local = NULL;
CK_ATTRIBUTE *always_sens = NULL;
CK_ATTRIBUTE *sensitive = NULL;
CK_ATTRIBUTE *extractable = NULL;
CK_ATTRIBUTE *never_extract = NULL;
CK_BBOOL true = TRUE;
CK_BBOOL false = FALSE;
CK_RV rc;
switch (keytype) {
case CKK_CDMF:
case CKK_DES:
rc = des_unwrap(tokdata, tmpl, data, data_len, fromend);
break;
case CKK_DES3:
rc = des3_unwrap(tokdata, tmpl, data, data_len, fromend);
break;
case CKK_AES:
rc = aes_unwrap(tokdata, tmpl, data, data_len, fromend);
break;
case CKK_GENERIC_SECRET:
case CKK_RC2:
case CKK_RC4:
case CKK_RC5:
case CKK_CAST:
case CKK_CAST3:
case CKK_CAST5:
rc = generic_secret_unwrap(tmpl, data, data_len, fromend);
break;
default:
TRACE_ERROR("%s\n", ock_err(ERR_WRAPPED_KEY_INVALID));
return CKR_WRAPPED_KEY_INVALID;
}
if (rc != CKR_OK)
return rc;
// make sure
// CKA_LOCAL == FALSE
// CKA_ALWAYS_SENSITIVE == FALSE
// CKA_EXTRACTABLE == TRUE
// CKA_NEVER_EXTRACTABLE == FALSE
//
rc = build_attribute(CKA_LOCAL, &false, 1, &local);
if (rc != CKR_OK) {
TRACE_DEVEL("build attribute failed\n");
goto cleanup;
}
rc = build_attribute(CKA_ALWAYS_SENSITIVE, &false, 1, &always_sens);
if (rc != CKR_OK) {
TRACE_DEVEL("build attribute failed\n");
goto cleanup;
}
rc = build_attribute(CKA_SENSITIVE, &false, 1, &sensitive);
if (rc != CKR_OK) {
TRACE_DEVEL("build_attribute failed\n");
goto cleanup;
}
rc = build_attribute(CKA_EXTRACTABLE, &true, 1, &extractable);
if (rc != CKR_OK) {
TRACE_DEVEL("build_attribute failed\n");
goto cleanup;
}
rc = build_attribute(CKA_NEVER_EXTRACTABLE, &false, 1, &never_extract);
if (rc != CKR_OK) {
TRACE_DEVEL("build_attribute failed\n");
goto cleanup;
}
template_update_attribute(tmpl, local);
template_update_attribute(tmpl, always_sens);
template_update_attribute(tmpl, sensitive);
template_update_attribute(tmpl, extractable);
template_update_attribute(tmpl, never_extract);
return CKR_OK;
cleanup:
if (local)
free(local);
if (extractable)
free(extractable);
if (always_sens)
free(always_sens);
if (never_extract)
free(never_extract);
return rc;
}
// secret_key_validate_attribute()
//
CK_RV secret_key_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_ENCRYPT:
case CKA_DECRYPT:
case CKA_SIGN:
case CKA_VERIFY:
case CKA_WRAP:
case CKA_UNWRAP:
if (mode == MODE_MODIFY) {
if (tokdata->nv_token_data->tweak_vector.allow_key_mods == TRUE)
return CKR_OK;
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
return CKR_OK;
// after key creation, CKA_SENSITIVE may only be set to TRUE
//
case CKA_SENSITIVE:
{
CK_BBOOL value;
value = *(CK_BBOOL *) attr->pValue;
if ((mode != MODE_CREATE && mode != MODE_DERIVE &&
mode != MODE_KEYGEN) && (value != TRUE)) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
return CKR_OK;
}
// after key creation, CKA_EXTRACTABLE may only be set to FALSE
//
case CKA_EXTRACTABLE:
{
CK_BBOOL value;
// the unwrap routine will automatically set extractable to TRUE
//
value = *(CK_BBOOL *) attr->pValue;
if ((mode != MODE_CREATE && mode != MODE_DERIVE &&
mode != MODE_KEYGEN) && (value != FALSE)) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
if (value == FALSE) {
CK_ATTRIBUTE *attr;
attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) +
sizeof(CK_BBOOL));
if (!attr) {
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
attr->type = CKA_NEVER_EXTRACTABLE;
attr->ulValueLen = sizeof(CK_BBOOL);
attr->pValue = (CK_BYTE *) attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) attr->pValue = FALSE;
template_update_attribute(tmpl, attr);
}
return CKR_OK;
}
case CKA_ALWAYS_SENSITIVE:
case CKA_NEVER_EXTRACTABLE:
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
default:
return key_object_validate_attribute(tmpl, attr, mode);
}
TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_TYPE_INVALID), attr->type);
return CKR_ATTRIBUTE_TYPE_INVALID;
}
// secret_key_check_exportability()
//
CK_BBOOL secret_key_check_exportability(CK_ATTRIBUTE_TYPE type)
{
switch (type) {
case CKA_VALUE:
TRACE_ERROR("%s\n", ock_err(ERR_KEY_UNEXTRACTABLE));
return FALSE;
}
return TRUE;
}
// rsa_publ_check_required_attributes()
//
CK_RV rsa_publ_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_MODULUS, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_MODULUS_BITS, &attr);
if (!found) {
if (mode == MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_PUBLIC_EXPONENT, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return publ_key_check_required_attributes(tmpl, mode);
}
// rsa_publ_set_default_attributes()
//
CK_RV rsa_publ_set_default_attributes(TEMPLATE *tmpl, TEMPLATE *basetmpl,
CK_ULONG mode)
{
CK_ATTRIBUTE *type_attr = NULL;
CK_ATTRIBUTE *modulus_attr = NULL;
CK_ATTRIBUTE *modulus_bits_attr = NULL;
CK_ATTRIBUTE *public_exp_attr = NULL;
CK_ATTRIBUTE *tmpattr = NULL;
CK_ULONG bits = 0L;
CK_BYTE pubExp[3] = { 0x01, 0x00, 0x01 };
publ_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
modulus_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
modulus_bits_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG));
public_exp_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(pubExp));
if (!type_attr || !modulus_attr || !modulus_bits_attr || !public_exp_attr) {
if (type_attr)
free(type_attr);
if (modulus_attr)
free(modulus_attr);
if (modulus_bits_attr)
free(modulus_bits_attr);
if (public_exp_attr)
free(public_exp_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_RSA;
modulus_attr->type = CKA_MODULUS;
modulus_attr->ulValueLen = 0;
modulus_attr->pValue = NULL;
modulus_bits_attr->type = CKA_MODULUS_BITS;
modulus_bits_attr->ulValueLen = sizeof(CK_ULONG);
modulus_bits_attr->pValue =
(CK_BYTE *) modulus_bits_attr + sizeof(CK_ATTRIBUTE);
if (template_attribute_find(basetmpl, CKA_MODULUS, &tmpattr)) {
*(CK_ULONG *) modulus_bits_attr->pValue = 8 * tmpattr->ulValueLen;
} else {
*(CK_ULONG *) modulus_bits_attr->pValue = bits;
}
public_exp_attr->type = CKA_PUBLIC_EXPONENT;
public_exp_attr->ulValueLen = sizeof(pubExp);
public_exp_attr->pValue =
(CK_BYTE *) public_exp_attr + sizeof(CK_ATTRIBUTE);
memcpy(public_exp_attr->pValue, pubExp, sizeof(pubExp));
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, modulus_attr);
template_update_attribute(tmpl, modulus_bits_attr);
template_update_attribute(tmpl, public_exp_attr);
return CKR_OK;
}
// rsa_publ_validate_attributes()
//
CK_RV rsa_publ_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_MODULUS_BITS:
if (mode == MODE_KEYGEN) {
if (attr->ulValueLen != sizeof(CK_ULONG)) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
} else {
CK_ULONG mod_bits = *(CK_ULONG *) attr->pValue;
if (mod_bits < 512 || mod_bits > 4096) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
if (mod_bits % 8 != 0) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
}
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
case CKA_MODULUS:
if (mode == MODE_CREATE) {
p11_attribute_trim(attr);
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
case CKA_PUBLIC_EXPONENT:
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
p11_attribute_trim(attr);
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
default:
return publ_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// rsa_priv_check_required_attributes()
//
CK_RV rsa_priv_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_MODULUS, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
//
// PKCS #11 is flexible with respect to which attributes must be present
// in an RSA key. Keys can be specified in Chinese-Remainder format or
// they can be specified in modular-exponent format. Right now, I only
// support keys created in Chinese-Remainder format. That is, we return
// CKR_TEMPLATE_INCOMPLETE if a modular-exponent key is specified. This
// is allowed by PKCS #11.
//
// In the future, we should allow for creation of keys in modular-exponent
// format too. This raises some issues. It's easy enough to recognize
// when a key has been specified in modular-exponent format. And it's
// easy enough to recognize when all attributes have been specified
// (which is what we require right now). What's trickier to handle is
// the "middle" cases in which more than the minimum yet less than the
// full number of attributes have been specified. Do we revert back to
// modular-exponent representation? Do we compute the missing attributes
// ourselves? Do we simply return CKR_TEMPLATE_INCOMPLETE?
//
found = template_attribute_find(tmpl, CKA_PUBLIC_EXPONENT, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_PRIVATE_EXPONENT, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_PRIME_1, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_PRIME_2, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_EXPONENT_1, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_EXPONENT_2, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_COEFFICIENT, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
// we should probably verify that the (e != p) and (e != q).
// ie. gcd(e,n) == 1
//
return priv_key_check_required_attributes(tmpl, mode);
}
// rsa_priv_set_default_attributes()
//
CK_RV rsa_priv_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *modulus_attr = NULL;
CK_ATTRIBUTE *public_exp_attr = NULL;
CK_ATTRIBUTE *private_exp_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
// satisfy the compiler
//
if (mode)
modulus_attr = NULL;
priv_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
modulus_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
public_exp_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
private_exp_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
if (!type_attr || !modulus_attr || !public_exp_attr || !private_exp_attr) {
if (type_attr)
free(type_attr);
if (modulus_attr)
free(modulus_attr);
if (public_exp_attr)
free(public_exp_attr);
if (private_exp_attr)
free(private_exp_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
modulus_attr->type = CKA_MODULUS;
modulus_attr->ulValueLen = 0;
modulus_attr->pValue = NULL;
public_exp_attr->type = CKA_PUBLIC_EXPONENT;
public_exp_attr->ulValueLen = 0;
public_exp_attr->pValue = NULL;
private_exp_attr->type = CKA_PRIVATE_EXPONENT;
private_exp_attr->ulValueLen = 0;
private_exp_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_RSA;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, modulus_attr);
template_update_attribute(tmpl, public_exp_attr);
template_update_attribute(tmpl, private_exp_attr);
return CKR_OK;
}
// rsa_priv_validate_attributes()
//
CK_RV rsa_priv_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_MODULUS:
case CKA_PRIVATE_EXPONENT:
if (mode == MODE_CREATE) {
p11_attribute_trim(attr);
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
case CKA_PUBLIC_EXPONENT:
case CKA_PRIME_1:
case CKA_PRIME_2:
case CKA_EXPONENT_1:
case CKA_EXPONENT_2:
case CKA_COEFFICIENT:
if (mode == MODE_CREATE) {
p11_attribute_trim(attr);
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
default:
return priv_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// rsa_priv_check_exportability()
//
CK_BBOOL rsa_priv_check_exportability(CK_ATTRIBUTE_TYPE type)
{
switch (type) {
case CKA_PRIVATE_EXPONENT:
case CKA_PRIME_1:
case CKA_PRIME_2:
case CKA_EXPONENT_1:
case CKA_EXPONENT_2:
case CKA_COEFFICIENT:
TRACE_ERROR("%s\n", ock_err(ERR_KEY_UNEXTRACTABLE));
return FALSE;
}
return TRUE;
}
// create the ASN.1 encoding for the private key for wrapping as defined
// in PKCS #8
//
// ASN.1 type PrivateKeyInfo ::= SEQUENCE {
// version Version
// privateKeyAlgorithm PrivateKeyAlgorithmIdentifier
// privateKey PrivateKey
// attributes OPTIONAL
// }
//
// Where PrivateKey is defined as follows for RSA:
//
// ASN.1 type RSAPrivateKey
//
// RSAPrivateKey ::= SEQUENCE {
// version Version
// modulus INTEGER
// publicExponent INTEGER
// privateExponent INTEGER
// prime1 INTEGER
// prime2 INTEGER
// exponent1 INTEGER
// exponent2 INTEGER
// coefficient INTEGER
// }
//
CK_RV rsa_priv_wrap_get_data(TEMPLATE *tmpl,
CK_BBOOL length_only,
CK_BYTE **data, CK_ULONG *data_len)
{
CK_ATTRIBUTE *modulus = NULL;
CK_ATTRIBUTE *publ_exp = NULL, *priv_exp = NULL;
CK_ATTRIBUTE *prime1 = NULL, *prime2 = NULL;
CK_ATTRIBUTE *exponent1 = NULL, *exponent2 = NULL;
CK_ATTRIBUTE *coeff = NULL;
CK_RV rc;
// compute the total length of the BER-encoded data
//
if (template_attribute_find(tmpl, CKA_MODULUS, &modulus) == FALSE) {
TRACE_ERROR("Could not find CKA_MODULUS for the key.\n");
return CKR_FUNCTION_FAILED;
}
if (template_attribute_find(tmpl, CKA_PUBLIC_EXPONENT, &publ_exp) == FALSE) {
TRACE_ERROR("Could not find CKA_PUBLIC_EXPONENT for the key.\n");
return CKR_FUNCTION_FAILED;
}
if (template_attribute_find(tmpl, CKA_PRIVATE_EXPONENT, &priv_exp) ==
FALSE) {
TRACE_ERROR("Could not find private exponent for the key.\n");
return CKR_FUNCTION_FAILED;
}
if (template_attribute_find(tmpl, CKA_PRIME_1, &prime1) == FALSE) {
TRACE_ERROR("Could not find CKA_PRIME_1 for the key.\n");
return CKR_FUNCTION_FAILED;
}
if (template_attribute_find(tmpl, CKA_PRIME_2, &prime2) == FALSE) {
TRACE_ERROR("Could not find CKA_PRIME_2 for the key.\n");
return CKR_FUNCTION_FAILED;
}
if (template_attribute_find(tmpl, CKA_EXPONENT_1, &exponent1) == FALSE) {
TRACE_ERROR("Could not find CKA_EXPONENT_1 for the key.\n");
return CKR_FUNCTION_FAILED;
}
if (template_attribute_find(tmpl, CKA_EXPONENT_2, &exponent2) == FALSE) {
TRACE_ERROR("Could not find CKA_EXPONENT_2 for the key.\n");
return CKR_FUNCTION_FAILED;
}
if (template_attribute_find(tmpl, CKA_COEFFICIENT, &coeff) == FALSE) {
TRACE_ERROR("Could not find CKA_COEFFICIENT for the key.\n");
return CKR_FUNCTION_FAILED;
}
rc = ber_encode_RSAPrivateKey(length_only, data, data_len, modulus,
publ_exp, priv_exp, prime1, prime2,
exponent1, exponent2, coeff);
if (rc != CKR_OK) {
TRACE_DEVEL("ber_encode_RSAPrivateKey failed\n");
}
return rc;
}
//
//
CK_RV rsa_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG total_length)
{
CK_ATTRIBUTE *modulus = NULL;
CK_ATTRIBUTE *publ_exp = NULL;
CK_ATTRIBUTE *priv_exp = NULL;
CK_ATTRIBUTE *prime1 = NULL;
CK_ATTRIBUTE *prime2 = NULL;
CK_ATTRIBUTE *exponent1 = NULL;
CK_ATTRIBUTE *exponent2 = NULL;
CK_ATTRIBUTE *coeff = NULL;
CK_RV rc;
rc = ber_decode_RSAPrivateKey(data,
total_length,
&modulus,
&publ_exp,
&priv_exp,
&prime1,
&prime2,
&exponent1,
&exponent2, &coeff);
if (rc != CKR_OK) {
TRACE_DEVEL("ber_decode_RSAPrivateKey failed\n");
return rc;
}
p11_attribute_trim(modulus);
p11_attribute_trim(publ_exp);
p11_attribute_trim(priv_exp);
p11_attribute_trim(prime1);
p11_attribute_trim(prime2);
p11_attribute_trim(exponent1);
p11_attribute_trim(exponent2);
p11_attribute_trim(coeff);
template_update_attribute(tmpl, modulus);
template_update_attribute(tmpl, publ_exp);
template_update_attribute(tmpl, priv_exp);
template_update_attribute(tmpl, prime1);
template_update_attribute(tmpl, prime2);
template_update_attribute(tmpl, exponent1);
template_update_attribute(tmpl, exponent2);
template_update_attribute(tmpl, coeff);
return CKR_OK;
}
CK_RV rsa_priv_unwrap_get_data(TEMPLATE *tmpl,
CK_BYTE *data, CK_ULONG total_length)
{
CK_ATTRIBUTE *modulus = NULL;
CK_ATTRIBUTE *publ_exp = NULL;
CK_RV rc;
rc = ber_decode_RSAPublicKey(data, total_length, &modulus, &publ_exp);
if (rc != CKR_OK) {
TRACE_DEVEL("ber_decode_RSAPublicKey failed\n");
return rc;
}
p11_attribute_trim(modulus);
p11_attribute_trim(publ_exp);
rc = template_update_attribute(tmpl, modulus);
if (rc != CKR_OK)
TRACE_DEVEL("template_update_attribute(CKA_MODULUS) failed\n");
rc = template_update_attribute(tmpl, publ_exp);
if (rc != CKR_OK)
TRACE_DEVEL("template_update_attribute(CKA_PUBLIC_EXPONENT) failed\n");
return CKR_OK;
}
CK_RV ibm_dilithium_priv_wrap_get_data(TEMPLATE *tmpl,
CK_BBOOL length_only,
CK_BYTE **data, CK_ULONG *data_len)
{
CK_ATTRIBUTE *keyform, *rho = NULL, *seed = NULL;
CK_ATTRIBUTE *tr = NULL, *s1 = NULL, *s2 = NULL;
CK_ATTRIBUTE *t0 = NULL, *t1 = NULL;
CK_RV rc;
/* A private Dilithium key must have a keyform value */
if (!template_attribute_find(tmpl, CKA_IBM_DILITHIUM_KEYFORM, &keyform)) {
TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_KEYFORM for the key.\n");
return CKR_TEMPLATE_INCOMPLETE;
}
/* Check if it's an expected keyform */
if (*(CK_ULONG *) keyform->pValue != IBM_DILITHIUM_KEYFORM_ROUND2) {
TRACE_ERROR("This key has an unexpected CKA_IBM_DILITHIUM_KEYFORM: %ld \n",
*(CK_ULONG *) keyform->pValue);
return CKR_TEMPLATE_INCONSISTENT;
}
if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_RHO, &rho) == FALSE) {
TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_RHO for the key.\n");
return CKR_TEMPLATE_INCONSISTENT;
}
if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_SEED, &seed) == FALSE) {
TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_SEED for the key.\n");
return CKR_TEMPLATE_INCONSISTENT;
}
if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_TR, &tr) == FALSE) {
TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_TR for the key.\n");
return CKR_TEMPLATE_INCONSISTENT;
}
if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_S1, &s1) == FALSE) {
TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_S1 for the key.\n");
return CKR_TEMPLATE_INCONSISTENT;
}
if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_S2, &s2) == FALSE) {
TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_S2 for the key.\n");
return CKR_TEMPLATE_INCONSISTENT;
}
if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_T0, &t0) == FALSE) {
TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_T0 for the key.\n");
return CKR_TEMPLATE_INCONSISTENT;
}
if (template_attribute_find(tmpl, CKA_IBM_DILITHIUM_T1, &t1) == FALSE) {
TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_T1 for the key.\n");
return CKR_TEMPLATE_INCONSISTENT;
}
rc = ber_encode_IBM_DilithiumPrivateKey(length_only, data, data_len,
rho, seed, tr, s1, s2, t0, t1);
if (rc != CKR_OK) {
TRACE_DEVEL("ber_encode_IBM_DilithiumPrivateKey failed\n");
}
return rc;
}
CK_RV ibm_dilithium_priv_unwrap_get_data(TEMPLATE *tmpl, CK_BYTE *data,
CK_ULONG total_length)
{
CK_ATTRIBUTE *rho = NULL;
CK_ATTRIBUTE *t1 = NULL;
CK_RV rc;
rc = ber_decode_IBM_DilithiumPublicKey(data, total_length, &rho, &t1);
if (rc != CKR_OK) {
TRACE_ERROR("ber_decode_DilithiumPublicKey failed\n");
return rc;
}
rc = template_update_attribute(tmpl, rho);
if (rc != CKR_OK) {
TRACE_ERROR("template_update_attribute(CKA_IBM_DILITHIUM_RHO) failed\n");
return rc;
}
rc = template_update_attribute(tmpl, t1);
if (rc != CKR_OK) {
TRACE_ERROR("template_update_attribute(CKA_IBM_DILITHIUM_T1) failed\n");
return rc;
}
return CKR_OK;
}
//
//
CK_RV ibm_dilithium_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data,
CK_ULONG total_length)
{
CK_ATTRIBUTE *rho = NULL, *seed = NULL, *tr = NULL;
CK_ATTRIBUTE *s1 = NULL, *s2 = NULL, *t0 = NULL, *t1 = NULL;
CK_RV rc;
rc = ber_decode_IBM_DilithiumPrivateKey(data, total_length,
&rho, &seed, &tr, &s1, &s2, &t0, &t1);
if (rc != CKR_OK) {
TRACE_ERROR("der_decode_IBM_DilithiumPrivateKey failed\n");
return rc;
}
rc = template_update_attribute(tmpl, rho);
rc |= template_update_attribute(tmpl, seed);
rc |= template_update_attribute(tmpl, tr);
rc |= template_update_attribute(tmpl, s1);
rc |= template_update_attribute(tmpl, s2);
rc |= template_update_attribute(tmpl, t0);
rc |= template_update_attribute(tmpl, t1);
if (rc != CKR_OK) {
TRACE_ERROR("template_update_attribute failed\n");
return rc;
}
return CKR_OK;
}
// dsa_publ_check_required_attributes()
//
CK_RV dsa_publ_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_PRIME, &attr);
if (!found) {
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_SUBPRIME, &attr);
if (!found) {
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_BASE, &attr);
if (!found) {
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return publ_key_check_required_attributes(tmpl, mode);
}
// dsa_publ_set_default_attributes()
//
CK_RV dsa_publ_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *prime_attr = NULL;
CK_ATTRIBUTE *subprime_attr = NULL;
CK_ATTRIBUTE *base_attr = NULL;
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
if (mode)
prime_attr = NULL;
publ_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
prime_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
subprime_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
base_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
if (!type_attr || !prime_attr || !subprime_attr || !base_attr
|| !value_attr) {
if (type_attr)
free(type_attr);
if (prime_attr)
free(prime_attr);
if (subprime_attr)
free(subprime_attr);
if (base_attr)
free(base_attr);
if (value_attr)
free(value_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
prime_attr->type = CKA_PRIME;
prime_attr->ulValueLen = 0;
prime_attr->pValue = NULL;
subprime_attr->type = CKA_SUBPRIME;
subprime_attr->ulValueLen = 0;
subprime_attr->pValue = NULL;
base_attr->type = CKA_BASE;
base_attr->ulValueLen = 0;
base_attr->pValue = NULL;
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_DSA;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, prime_attr);
template_update_attribute(tmpl, subprime_attr);
template_update_attribute(tmpl, base_attr);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
// dsa_publ_validate_attributes()
//
CK_RV dsa_publ_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_PRIME:
{
CK_ULONG size;
if (mode != MODE_CREATE && mode != MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
// must be between [512, 1024] bits, and a multiple of 64 bits
//
size = attr->ulValueLen;
if (size < 64 || size > 128 || (size % 8 != 0)) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
p11_attribute_trim(attr);
return CKR_OK;
}
case CKA_SUBPRIME:
if (mode != MODE_CREATE && mode != MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
// subprime must be 160 bits
//
if (attr->ulValueLen != 20) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
p11_attribute_trim(attr);
return CKR_OK;
case CKA_BASE:
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
p11_attribute_trim(attr);
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
case CKA_VALUE:
if (mode == MODE_CREATE) {
p11_attribute_trim(attr);
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
default:
return publ_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// dsa_priv_check_required_attributes()
//
CK_RV dsa_priv_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_PRIME, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_SUBPRIME, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_BASE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return priv_key_check_required_attributes(tmpl, mode);
}
// dsa_priv_set_default_attributes()
//
CK_RV dsa_priv_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *prime_attr = NULL;
CK_ATTRIBUTE *subprime_attr = NULL;
CK_ATTRIBUTE *base_attr = NULL;
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
if (mode)
prime_attr = NULL;
priv_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
prime_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
subprime_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
base_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
if (!type_attr || !prime_attr || !subprime_attr || !base_attr
|| !value_attr) {
if (type_attr)
free(type_attr);
if (prime_attr)
free(prime_attr);
if (subprime_attr)
free(subprime_attr);
if (base_attr)
free(base_attr);
if (value_attr)
free(value_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
prime_attr->type = CKA_PRIME;
prime_attr->ulValueLen = 0;
prime_attr->pValue = NULL;
subprime_attr->type = CKA_SUBPRIME;
subprime_attr->ulValueLen = 0;
subprime_attr->pValue = NULL;
base_attr->type = CKA_BASE;
base_attr->ulValueLen = 0;
base_attr->pValue = NULL;
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_DSA;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, prime_attr);
template_update_attribute(tmpl, subprime_attr);
template_update_attribute(tmpl, base_attr);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
// dsa_priv_validate_attributes()
//
CK_RV dsa_priv_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_PRIME:
{
CK_ULONG size;
if (mode != MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
// must be between [512, 1024] bits, and a multiple of 64 bits
//
size = attr->ulValueLen;
if (size < 64 || size > 128 || (size % 8 != 0)) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
p11_attribute_trim(attr);
return CKR_OK;
}
case CKA_SUBPRIME:
if (mode != MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
// subprime must be 160 bits
//
if (attr->ulValueLen != 20) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
p11_attribute_trim(attr);
return CKR_OK;
case CKA_BASE:
case CKA_VALUE:
if (mode == MODE_CREATE) {
p11_attribute_trim(attr);
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
default:
return priv_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// dsa_priv_check_exportability()
//
CK_BBOOL dsa_priv_check_exportability(CK_ATTRIBUTE_TYPE type)
{
switch (type) {
case CKA_VALUE:
return FALSE;
}
return TRUE;
}
// create the ASN.1 encoding for the private key for wrapping as defined
// in PKCS #8
//
// ASN.1 type PrivateKeyInfo ::= SEQUENCE {
// version Version
// privateKeyAlgorithm PrivateKeyAlgorithmIdentifier
// privateKey PrivateKey
// attributes OPTIONAL
// }
//
// PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
//
// AlgorithmIdentifier ::= SEQUENCE {
// algorithm OBJECT IDENTIFIER
// parameters ANY DEFINED BY algorithm OPTIONAL
// }
//
// paramters ::= SEQUENCE {
// p INTEGER
// q INTEGER
// g INTEGER
// }
//
// privateKey ::= INTEGER
//
//
CK_RV dsa_priv_wrap_get_data(TEMPLATE *tmpl,
CK_BBOOL length_only,
CK_BYTE **data, CK_ULONG *data_len)
{
CK_ATTRIBUTE *prime = NULL;
CK_ATTRIBUTE *subprime = NULL;
CK_ATTRIBUTE *base = NULL;
CK_ATTRIBUTE *value = NULL;
CK_RV rc;
// compute the total length of the BER-encoded data
//
if (template_attribute_find(tmpl, CKA_PRIME, &prime) == FALSE) {
TRACE_ERROR("Could not find CKA_PRIME for the key.\n");
return CKR_FUNCTION_FAILED;
}
if (template_attribute_find(tmpl, CKA_SUBPRIME, &subprime) == FALSE) {
TRACE_ERROR("Could not find CKA_SUBPRIME for the key.\n");
return CKR_FUNCTION_FAILED;
}
if (template_attribute_find(tmpl, CKA_BASE, &base) == FALSE) {
TRACE_ERROR("Could not find CKA_BASE for the key.\n");
return CKR_FUNCTION_FAILED;
}
if (template_attribute_find(tmpl, CKA_VALUE, &value) == FALSE) {
TRACE_ERROR("Could not find CKA_VALUE for the key.\n");
return CKR_FUNCTION_FAILED;
}
rc = ber_encode_DSAPrivateKey(length_only, data, data_len,
prime, subprime, base, value);
if (rc != CKR_OK)
TRACE_DEVEL("ber_encode_DSAPrivateKey failed\n");
return rc;
}
//
//
CK_RV dsa_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG total_length)
{
CK_ATTRIBUTE *prime = NULL;
CK_ATTRIBUTE *subprime = NULL;
CK_ATTRIBUTE *base = NULL;
CK_ATTRIBUTE *value = NULL;
CK_RV rc;
rc = ber_decode_DSAPrivateKey(data, total_length,
&prime, &subprime, &base, &value);
if (rc != CKR_OK) {
TRACE_DEVEL("ber_decode_DSAPrivateKey failed\n");
return rc;
}
p11_attribute_trim(prime);
p11_attribute_trim(subprime);
p11_attribute_trim(base);
p11_attribute_trim(value);
template_update_attribute(tmpl, prime);
template_update_attribute(tmpl, subprime);
template_update_attribute(tmpl, base);
template_update_attribute(tmpl, value);
return CKR_OK;
}
CK_RV dsa_priv_unwrap_get_data(TEMPLATE *tmpl,
CK_BYTE *data, CK_ULONG total_length)
{
CK_ATTRIBUTE *prime = NULL;
CK_ATTRIBUTE *subprime = NULL;
CK_ATTRIBUTE *base = NULL;
CK_ATTRIBUTE *value = NULL;
CK_RV rc;
rc = ber_decode_DSAPublicKey(data, total_length, &prime, &subprime,
&base, &value);
if (rc != CKR_OK) {
TRACE_DEVEL("ber_decode_DSAPublicKey failed\n");
return rc;
}
p11_attribute_trim(prime);
p11_attribute_trim(subprime);
p11_attribute_trim(base);
p11_attribute_trim(value);
rc = template_update_attribute(tmpl, prime);
if (rc != CKR_OK)
TRACE_DEVEL("template_update_attribute(CKA_PRIME) failed\n");
rc = template_update_attribute(tmpl, subprime);
if (rc != CKR_OK)
TRACE_DEVEL("template_update_attribute(CKA_SUBPRIME) failed\n");
rc = template_update_attribute(tmpl, base);
if (rc != CKR_OK)
TRACE_DEVEL("template_update_attribute(CKA_BASE) failed\n");
rc = template_update_attribute(tmpl, value);
if (rc != CKR_OK)
TRACE_DEVEL("template_update_attribute(CKA_VALUE) failed\n");
return CKR_OK;
}
// ecdsa_publ_check_required_attributes()
//
CK_RV ecdsa_publ_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_ECDSA_PARAMS, &attr);
if (!found) {
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_EC_POINT, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return publ_key_check_required_attributes(tmpl, mode);
}
// ecdsa_publ_set_default_attributes()
//
CK_RV ecdsa_publ_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *params_attr = NULL;
CK_ATTRIBUTE *ec_point_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
if (mode)
params_attr = NULL;
publ_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
params_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
ec_point_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
if (!type_attr || !params_attr || !ec_point_attr) {
if (type_attr)
free(type_attr);
if (params_attr)
free(params_attr);
if (ec_point_attr)
free(ec_point_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
params_attr->type = CKA_ECDSA_PARAMS;
params_attr->ulValueLen = 0;
params_attr->pValue = NULL;
ec_point_attr->type = CKA_EC_POINT;
ec_point_attr->ulValueLen = 0;
ec_point_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_ECDSA;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, params_attr);
template_update_attribute(tmpl, ec_point_attr);
return CKR_OK;
}
// ecdsa_publ_validate_attributes()
//
CK_RV ecdsa_publ_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_ECDSA_PARAMS:
if (mode == MODE_CREATE || mode == MODE_KEYGEN)
return CKR_OK;
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
case CKA_EC_POINT:
if (mode == MODE_CREATE)
return CKR_OK;
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
default:
return publ_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// ecdsa_priv_check_required_attributes()
//
CK_RV ecdsa_priv_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_ECDSA_PARAMS, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return priv_key_check_required_attributes(tmpl, mode);
}
// ecdsa_priv_set_default_attributes()
//
CK_RV ecdsa_priv_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *params_attr = NULL;
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
if (mode)
params_attr = NULL;
priv_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
params_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
if (!type_attr || !params_attr || !value_attr) {
if (type_attr)
free(type_attr);
if (params_attr)
free(params_attr);
if (value_attr)
free(value_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
params_attr->type = CKA_ECDSA_PARAMS;
params_attr->ulValueLen = 0;
params_attr->pValue = NULL;
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_ECDSA;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, params_attr);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
// ecdsa_priv_validate_attributes()
//
CK_RV ecdsa_priv_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_ECDSA_PARAMS:
if (mode == MODE_CREATE)
return CKR_OK;
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
case CKA_VALUE:
if (mode == MODE_CREATE) {
p11_attribute_trim(attr);
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
case CKA_EC_POINT:
if (mode == MODE_CREATE) {
p11_attribute_trim(attr);
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
default:
return priv_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// ecdsa_priv_check_exportability()
//
CK_BBOOL ecdsa_priv_check_exportability(CK_ATTRIBUTE_TYPE type)
{
switch (type) {
case CKA_VALUE:
return FALSE;
}
return TRUE;
}
/*
* create the ASN.1 encoding for the private key for wrapping as defined
* in PKCS #8
*
* ASN.1 type PrivateKeyInfo ::= SEQUENCE {
* version Version
* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier
* privateKey PrivateKey
* attributes OPTIONAL
* }
*
* Where PrivateKey is defined as follows for EC:
*
* ASN.1 type RSAPrivateKey
*
* ECPrivateKey ::= SEQUENCE {
* version Version
* privateKey OCTET STRING
* parameters [0] ECParameters (OPTIONAL)
* publicKey [1] BIT STRING (OPTIONAL)
* }
*/
CK_RV ecdsa_priv_wrap_get_data(TEMPLATE *tmpl,
CK_BBOOL length_only,
CK_BYTE **data, CK_ULONG *data_len)
{
CK_ATTRIBUTE *params = NULL;
CK_ATTRIBUTE *point = NULL;
CK_ATTRIBUTE *pubkey = NULL;
CK_RV rc;
// compute the total length of the BER-encoded data
//
if (template_attribute_find(tmpl, CKA_EC_PARAMS, ¶ms) == FALSE) {
TRACE_ERROR("Could not find CKA_EC_PARAMS for the key.\n");
return CKR_FUNCTION_FAILED;
}
if (template_attribute_find(tmpl, CKA_VALUE, &point) == FALSE) {
TRACE_ERROR("Could not find CKA_EC_POINT for the key.\n");
return CKR_FUNCTION_FAILED;
}
if (template_attribute_find(tmpl, CKA_VALUE, &point) == FALSE) {
TRACE_ERROR("Could not find EC Point for the key.\n");
return CKR_FUNCTION_FAILED;
}
/* check if optional public-key part was defined */
template_attribute_find(tmpl, CKA_EC_POINT, &pubkey);
rc = der_encode_ECPrivateKey(length_only, data, data_len, params,
point, pubkey);
if (rc != CKR_OK) {
TRACE_DEVEL("der_encode_ECPrivateKey failed\n");
}
return rc;
}
CK_RV ecdsa_priv_unwrap_get_data(TEMPLATE *tmpl,
CK_BYTE *data, CK_ULONG total_length)
{
CK_ATTRIBUTE *params = NULL;
CK_ATTRIBUTE *point = NULL;
CK_RV rc;
rc = der_decode_ECPublicKey(data, total_length, ¶ms, &point);
if (rc != CKR_OK) {
TRACE_DEVEL("der_decode_ECPublicKey failed\n");
return rc;
}
p11_attribute_trim(params);
p11_attribute_trim(point);
rc = template_update_attribute(tmpl, params);
if (rc != CKR_OK)
TRACE_DEVEL("template_update_attribute(CKA_EC_PARAMS) failed\n");
rc = template_update_attribute(tmpl, point);
if (rc != CKR_OK)
TRACE_DEVEL("template_update_attribute(CKA_EC_POINT) failed\n");
return CKR_OK;
}
//
//
CK_RV ec_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG total_length)
{
CK_ATTRIBUTE *pubkey = NULL;
CK_ATTRIBUTE *privkey = NULL;
CK_ATTRIBUTE *ecparam = NULL;
CK_RV rc;
rc = der_decode_ECPrivateKey(data, total_length, &ecparam,
&pubkey, &privkey);
if (rc != CKR_OK) {
TRACE_DEVEL("der_decode_ECPrivateKey failed\n");
return rc;
}
p11_attribute_trim(pubkey);
p11_attribute_trim(privkey);
if (pubkey)
template_update_attribute(tmpl, pubkey);
if (privkey)
template_update_attribute(tmpl, privkey);
template_update_attribute(tmpl, ecparam);
return CKR_OK;
}
// dh_publ_check_required_attributes()
//
CK_RV dh_publ_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_PRIME, &attr);
if (!found) {
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_BASE, &attr);
if (!found) {
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return publ_key_check_required_attributes(tmpl, mode);
}
// dh_publ_set_default_attributes()
//
CK_RV dh_publ_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *prime_attr = NULL;
CK_ATTRIBUTE *base_attr = NULL;
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
if (mode)
prime_attr = NULL;
publ_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
prime_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
base_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
if (!type_attr || !prime_attr || !base_attr || !value_attr) {
if (type_attr)
free(type_attr);
if (prime_attr)
free(prime_attr);
if (base_attr)
free(base_attr);
if (value_attr)
free(value_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
prime_attr->type = CKA_PRIME;
prime_attr->ulValueLen = 0;
prime_attr->pValue = NULL;
base_attr->type = CKA_BASE;
base_attr->ulValueLen = 0;
base_attr->pValue = NULL;
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_DH;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, prime_attr);
template_update_attribute(tmpl, base_attr);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
// dh_publ_validate_attribute()
//
CK_RV dh_publ_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_PRIME:
case CKA_BASE:
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
p11_attribute_trim(attr);
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
case CKA_VALUE:
if (mode == MODE_CREATE) {
p11_attribute_trim(attr);
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
default:
return publ_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// dh_priv_check_required_attributes()
//
CK_RV dh_priv_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_PRIME, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_BASE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_VALUE_BITS, &attr);
if (found) {
if (mode == MODE_CREATE || mode == MODE_UNWRAP) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
}
return priv_key_check_required_attributes(tmpl, mode);
}
// dh_priv_set_default_attributes()
//
CK_RV dh_priv_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *prime_attr = NULL;
CK_ATTRIBUTE *base_attr = NULL;
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *value_bits_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
CK_ULONG bits = 0L;
priv_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
prime_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
base_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
value_bits_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG));
if (!type_attr || !prime_attr || !base_attr || !value_attr
|| !value_bits_attr) {
if (type_attr)
free(type_attr);
if (prime_attr)
free(prime_attr);
if (base_attr)
free(base_attr);
if (value_attr)
free(value_attr);
if (value_bits_attr)
free(value_bits_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
prime_attr->type = CKA_PRIME;
prime_attr->ulValueLen = 0;
prime_attr->pValue = NULL;
base_attr->type = CKA_BASE;
base_attr->ulValueLen = 0;
base_attr->pValue = NULL;
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
value_bits_attr->type = CKA_VALUE_BITS;
value_bits_attr->ulValueLen = sizeof(CK_ULONG);
value_bits_attr->pValue =
(CK_BYTE *) value_bits_attr + sizeof(CK_ATTRIBUTE);
*(CK_ULONG *) value_bits_attr->pValue = bits;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_DH;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, prime_attr);
template_update_attribute(tmpl, base_attr);
template_update_attribute(tmpl, value_attr);
template_update_attribute(tmpl, value_bits_attr);
return CKR_OK;
}
// dh_priv_validate_attribute()
//
CK_RV dh_priv_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_PRIME:
case CKA_BASE:
case CKA_VALUE:
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
p11_attribute_trim(attr);
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
// I'm not sure what to do about VALUE_BITS...we don't really support
// Diffie-Hellman keys other than for storage...when the object is
// created, we're supposed to add CKA_VALUE_BITS outselves...which we
// don't do at this time. (we'd need to add code in C_CreateObject to
// call some sort of objecttype-specific callback)
//
// kapil 05/08/03 : Commented out error flagging, as CKA_VALUE_BITS is
// valid attribute for creating DH priv object. The
// above is an older comment.
case CKA_VALUE_BITS:
// TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
// return CKR_ATTRIBUTE_READ_ONLY;
return CKR_OK;
break;
default:
return priv_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// dh_priv_check_exportability()
//
CK_BBOOL dh_priv_check_exportability(CK_ATTRIBUTE_TYPE type)
{
switch (type) {
case CKA_VALUE:
return FALSE;
}
return TRUE;
}
//
//
CK_RV dh_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data, CK_ULONG total_length)
{
CK_ATTRIBUTE *prime = NULL;
CK_ATTRIBUTE *base = NULL;
CK_ATTRIBUTE *value = NULL;
CK_RV rc;
rc = ber_decode_DHPrivateKey(data, total_length, &prime, &base, &value);
if (rc != CKR_OK) {
TRACE_DEVEL("ber_decode_DHPrivateKey failed\n");
return rc;
}
p11_attribute_trim(prime);
p11_attribute_trim(base);
p11_attribute_trim(value);
template_update_attribute(tmpl, prime);
template_update_attribute(tmpl, base);
template_update_attribute(tmpl, value);
return CKR_OK;
}
CK_RV dh_priv_unwrap_get_data(TEMPLATE *tmpl,
CK_BYTE *data, CK_ULONG total_length)
{
CK_ATTRIBUTE *prime = NULL;
CK_ATTRIBUTE *base = NULL;
CK_ATTRIBUTE *value = NULL;
CK_RV rc;
rc = ber_decode_DHPublicKey(data, total_length, &prime, &base, &value);
if (rc != CKR_OK) {
TRACE_DEVEL("ber_decode_DHPublicKey failed\n");
return rc;
}
p11_attribute_trim(prime);
p11_attribute_trim(base);
p11_attribute_trim(value);
rc = template_update_attribute(tmpl, prime);
if (rc != CKR_OK)
TRACE_DEVEL("template_update_attribute(CKA_PRIME) failed\n");
rc = template_update_attribute(tmpl, base);
if (rc != CKR_OK)
TRACE_DEVEL("template_update_attribute(CKA_BASE) failed\n");
rc = template_update_attribute(tmpl, value);
if (rc != CKR_OK)
TRACE_DEVEL("template_update_attribute(CKA_VALUE) failed\n");
return CKR_OK;
}
// create the ASN.1 encoding for the private key for wrapping as defined
// in PKCS #8
//
// ASN.1 type PrivateKeyInfo ::= SEQUENCE {
// version Version
// privateKeyAlgorithm PrivateKeyAlgorithmIdentifier
// privateKey PrivateKey
// attributes OPTIONAL
// }
//
// PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
//
// AlgorithmIdentifier ::= SEQUENCE {
// algorithm OBJECT IDENTIFIER
// parameters ANY DEFINED BY algorithm OPTIONAL
// }
//
// paramters ::= SEQUENCE {
// p INTEGER
// g INTEGER
// }
//
// privateKey ::= INTEGER
//
//
CK_RV dh_priv_wrap_get_data(TEMPLATE *tmpl,
CK_BBOOL length_only,
CK_BYTE **data, CK_ULONG *data_len)
{
CK_ATTRIBUTE *prime = NULL;
CK_ATTRIBUTE *base = NULL;
CK_ATTRIBUTE *value = NULL;
CK_RV rc;
// compute the total length of the BER-encoded data
if (template_attribute_find(tmpl, CKA_PRIME, &prime) == FALSE) {
TRACE_ERROR("Could not find CKA_PRIME for the key.\n");
return CKR_FUNCTION_FAILED;
}
if (template_attribute_find(tmpl, CKA_BASE, &base) == FALSE) {
TRACE_ERROR("Could not find CKA_BASE for the key.\n");
return CKR_FUNCTION_FAILED;
}
if (template_attribute_find(tmpl, CKA_VALUE, &value) == FALSE) {
TRACE_ERROR("Could not find CKA_VALUE for the key.\n");
return CKR_FUNCTION_FAILED;
}
rc = ber_encode_DHPrivateKey(length_only, data, data_len,
prime, base, value);
if (rc != CKR_OK)
TRACE_DEVEL("ber_encode_DHPrivateKey failed\n");
return rc;
}
// kea_publ_check_required_attributes()
//
CK_RV kea_publ_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_PRIME, &attr);
if (!found) {
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_SUBPRIME, &attr);
if (!found) {
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_BASE, &attr);
if (!found) {
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return publ_key_check_required_attributes(tmpl, mode);
}
// kea_publ_set_default_attributes()
//
CK_RV kea_publ_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *prime_attr = NULL;
CK_ATTRIBUTE *subprime_attr = NULL;
CK_ATTRIBUTE *base_attr = NULL;
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
if (mode)
prime_attr = NULL;
publ_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
prime_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
subprime_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
base_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
if (!type_attr || !prime_attr || !subprime_attr || !base_attr
|| !value_attr) {
if (type_attr)
free(type_attr);
if (prime_attr)
free(prime_attr);
if (subprime_attr)
free(subprime_attr);
if (base_attr)
free(base_attr);
if (value_attr)
free(value_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
prime_attr->type = CKA_PRIME;
prime_attr->ulValueLen = 0;
prime_attr->pValue = NULL;
subprime_attr->type = CKA_SUBPRIME;
subprime_attr->ulValueLen = 0;
subprime_attr->pValue = NULL;
base_attr->type = CKA_BASE;
base_attr->ulValueLen = 0;
base_attr->pValue = NULL;
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_KEA;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, prime_attr);
template_update_attribute(tmpl, subprime_attr);
template_update_attribute(tmpl, base_attr);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
// kea_publ_validate_attribute()
//
CK_RV kea_publ_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_PRIME:
case CKA_SUBPRIME:
case CKA_BASE:
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
p11_attribute_trim(attr);
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
case CKA_VALUE:
if (mode == MODE_CREATE) {
p11_attribute_trim(attr);
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
default:
return publ_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// kea_priv_check_required_attributes()
//
CK_RV kea_priv_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_PRIME, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_SUBPRIME, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_BASE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return priv_key_check_required_attributes(tmpl, mode);
}
// kea_priv_set_default_attributes()
//
CK_RV kea_priv_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *prime_attr = NULL;
CK_ATTRIBUTE *subprime_attr = NULL;
CK_ATTRIBUTE *base_attr = NULL;
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
if (mode)
prime_attr = NULL;
priv_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
prime_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
subprime_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
base_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
if (!type_attr || !prime_attr || !base_attr || !value_attr
|| !subprime_attr) {
if (type_attr)
free(type_attr);
if (prime_attr)
free(prime_attr);
if (subprime_attr)
free(subprime_attr);
if (base_attr)
free(base_attr);
if (value_attr)
free(value_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
prime_attr->type = CKA_PRIME;
prime_attr->ulValueLen = 0;
prime_attr->pValue = NULL;
subprime_attr->type = CKA_SUBPRIME;
subprime_attr->ulValueLen = 0;
subprime_attr->pValue = NULL;
base_attr->type = CKA_BASE;
base_attr->ulValueLen = 0;
base_attr->pValue = NULL;
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_KEA;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, prime_attr);
template_update_attribute(tmpl, subprime_attr);
template_update_attribute(tmpl, base_attr);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
// kea_priv_validate_attribute()
//
CK_RV kea_priv_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_PRIME:
case CKA_SUBPRIME:
case CKA_BASE:
case CKA_VALUE:
if (mode == MODE_CREATE) {
p11_attribute_trim(attr);
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
default:
return priv_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// kea_priv_check_exportability()
//
CK_BBOOL kea_priv_check_exportability(CK_ATTRIBUTE_TYPE type)
{
switch (type) {
case CKA_VALUE:
return FALSE;
}
return TRUE;
}
// ibm_dilithium_publ_set_default_attributes()
//
CK_RV ibm_dilithium_publ_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *type_attr = NULL;
CK_ATTRIBUTE *rho_attr = NULL;
CK_ATTRIBUTE *t1_attr = NULL;
CK_ATTRIBUTE *keyform_attr = NULL;
publ_key_set_default_attributes(tmpl, mode);
type_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
keyform_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG));
rho_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
t1_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
if (!type_attr || !rho_attr || !t1_attr || !keyform_attr) {
if (type_attr)
free(type_attr);
if (rho_attr)
free(rho_attr);
if (t1_attr)
free(t1_attr);
if (keyform_attr)
free(keyform_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_IBM_PQC_DILITHIUM;
keyform_attr->type = CKA_IBM_DILITHIUM_KEYFORM;
keyform_attr->ulValueLen = sizeof(CK_ULONG);
keyform_attr->pValue = (CK_BYTE *) keyform_attr + sizeof(CK_ATTRIBUTE);
*(CK_ULONG *) keyform_attr->pValue = 1;
rho_attr->type = CKA_IBM_DILITHIUM_RHO;
rho_attr->ulValueLen = 0;
rho_attr->pValue = NULL;
t1_attr->type = CKA_IBM_DILITHIUM_T1;
t1_attr->ulValueLen = 0;
t1_attr->pValue = NULL;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, rho_attr);
template_update_attribute(tmpl, t1_attr);
template_update_attribute(tmpl, keyform_attr);
return CKR_OK;
}
// ibm_dilithium_priv_set_default_attributes()
//
CK_RV ibm_dilithium_priv_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *type_attr = NULL;
CK_ATTRIBUTE *rho_attr = NULL;
CK_ATTRIBUTE *seed_attr = NULL;
CK_ATTRIBUTE *tr_attr = NULL;
CK_ATTRIBUTE *s1_attr = NULL;
CK_ATTRIBUTE *s2_attr = NULL;
CK_ATTRIBUTE *t0_attr = NULL;
CK_ATTRIBUTE *t1_attr = NULL;
CK_ATTRIBUTE *keyform_attr = NULL;
priv_key_set_default_attributes(tmpl, mode);
type_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
keyform_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG));
rho_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
seed_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
tr_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
s1_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
s2_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
t0_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
t1_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
if (!type_attr || !rho_attr || !seed_attr || !tr_attr || !s1_attr
|| !s2_attr || !t0_attr || !t1_attr || !keyform_attr) {
if (type_attr)
free(type_attr);
if (rho_attr)
free(rho_attr);
if (seed_attr)
free(seed_attr);
if (tr_attr)
free(tr_attr);
if (s1_attr)
free(s1_attr);
if (s2_attr)
free(s2_attr);
if (t0_attr)
free(t0_attr);
if (t1_attr)
free(t1_attr);
if (keyform_attr)
free(keyform_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_IBM_PQC_DILITHIUM;
keyform_attr->type = CKA_IBM_DILITHIUM_KEYFORM;
keyform_attr->ulValueLen = sizeof(CK_ULONG);
keyform_attr->pValue = (CK_BYTE *) keyform_attr + sizeof(CK_ATTRIBUTE);
*(CK_ULONG *) keyform_attr->pValue = 1;
rho_attr->type = CKA_IBM_DILITHIUM_RHO;
rho_attr->ulValueLen = 0;
rho_attr->pValue = NULL;
seed_attr->type = CKA_IBM_DILITHIUM_SEED;
seed_attr->ulValueLen = 0;
seed_attr->pValue = NULL;
tr_attr->type = CKA_IBM_DILITHIUM_TR;
tr_attr->ulValueLen = 0;
tr_attr->pValue = NULL;
s1_attr->type = CKA_IBM_DILITHIUM_S1;
s1_attr->ulValueLen = 0;
s1_attr->pValue = NULL;
s2_attr->type = CKA_IBM_DILITHIUM_S2;
s2_attr->ulValueLen = 0;
s2_attr->pValue = NULL;
t0_attr->type = CKA_IBM_DILITHIUM_T0;
t0_attr->ulValueLen = 0;
t0_attr->pValue = NULL;
t1_attr->type = CKA_IBM_DILITHIUM_T1;
t1_attr->ulValueLen = 0;
t1_attr->pValue = NULL;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, keyform_attr);
template_update_attribute(tmpl, rho_attr);
template_update_attribute(tmpl, seed_attr);
template_update_attribute(tmpl, tr_attr);
template_update_attribute(tmpl, s1_attr);
template_update_attribute(tmpl, s2_attr);
template_update_attribute(tmpl, t0_attr);
template_update_attribute(tmpl, t1_attr);
return CKR_OK;
}
// ibm_dilithium_publ_check_required_attributes()
//
CK_RV ibm_dilithium_publ_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
static CK_ULONG req_attrs[] = {
CKA_IBM_DILITHIUM_KEYFORM,
CKA_IBM_DILITHIUM_RHO,
CKA_IBM_DILITHIUM_T1,
};
CK_ULONG i;
/* MODE_KEYGEN: attrs are added during keygen */
if (mode == MODE_KEYGEN || mode == MODE_UNWRAP)
return publ_key_check_required_attributes(tmpl, mode);
/* MODE_CREATE (key import) or MODE_COPY: check if all attrs present */
for (i = 0; i < sizeof(req_attrs) / sizeof(req_attrs[0]); i++) {
if (!(template_attribute_find(tmpl, req_attrs[i], &attr))) {
TRACE_ERROR("%s, attribute %08lX missing.\n",
ock_err(ERR_TEMPLATE_INCOMPLETE), req_attrs[i]);
return CKR_TEMPLATE_INCOMPLETE;
}
}
/* All required attrs found, check them */
return publ_key_check_required_attributes(tmpl, mode);
}
// ibm_dilithium_priv_check_required_attributes()
//
CK_RV ibm_dilithium_priv_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
static CK_ULONG req_attrs[] = {
CKA_IBM_DILITHIUM_KEYFORM,
CKA_IBM_DILITHIUM_RHO,
CKA_IBM_DILITHIUM_SEED,
CKA_IBM_DILITHIUM_TR,
CKA_IBM_DILITHIUM_S1,
CKA_IBM_DILITHIUM_S2,
CKA_IBM_DILITHIUM_T0,
CKA_IBM_DILITHIUM_T1,
};
CK_ULONG i;
/* MODE_KEYGEN: attrs are added during keygen */
if (mode == MODE_KEYGEN || mode == MODE_UNWRAP)
return priv_key_check_required_attributes(tmpl, mode);
/* MODE_CREATE (key import) or MODE_COPY: check if all attrs present */
for (i = 0; i < sizeof(req_attrs) / sizeof(req_attrs[0]); i++) {
if (!(template_attribute_find(tmpl, req_attrs[i], &attr))) {
TRACE_ERROR("%s, attribute %08lX missing.\n",
ock_err(ERR_TEMPLATE_INCOMPLETE), req_attrs[i]);
return CKR_TEMPLATE_INCOMPLETE;
}
}
/* All required attrs found, check them */
return priv_key_check_required_attributes(tmpl, mode);
}
// ibm_dilithium_publ_validate_attribute()
//
CK_RV ibm_dilithium_publ_validate_attribute(STDLL_TokData_t *tokdata,
TEMPLATE *tmpl, CK_ATTRIBUTE *attr,
CK_ULONG mode)
{
switch (attr->type) {
case CKA_IBM_DILITHIUM_RHO:
case CKA_IBM_DILITHIUM_T1:
if (mode == MODE_CREATE)
return CKR_OK;
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
case CKA_IBM_DILITHIUM_KEYFORM:
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
switch (*((CK_ULONG *)attr->pValue)) {
case IBM_DILITHIUM_KEYFORM_ROUND2:
return CKR_OK;
default:
TRACE_ERROR("%s\n", ock_err(CKR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
default:
return publ_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// ibm_dilithium_priv_validate_attribute()
//
CK_RV ibm_dilithium_priv_validate_attribute(STDLL_TokData_t *tokdata,
TEMPLATE *tmpl, CK_ATTRIBUTE *attr,
CK_ULONG mode)
{
switch (attr->type) {
case CKA_IBM_DILITHIUM_RHO:
case CKA_IBM_DILITHIUM_SEED:
case CKA_IBM_DILITHIUM_TR:
case CKA_IBM_DILITHIUM_S1:
case CKA_IBM_DILITHIUM_S2:
case CKA_IBM_DILITHIUM_T0:
case CKA_IBM_DILITHIUM_T1:
if (mode == MODE_CREATE)
return CKR_OK;
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
case CKA_IBM_DILITHIUM_KEYFORM:
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
switch (*((CK_ULONG *)attr->pValue)) {
case IBM_DILITHIUM_KEYFORM_ROUND2:
return CKR_OK;
default:
TRACE_ERROR("%s\n", ock_err(CKR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
default:
return priv_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// generic_secret_check_required_attributes()
//
CK_RV generic_secret_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_VALUE_LEN, &attr);
if (!found) {
// here's another place where PKCS #11 deviates from its own
// specification.
// the spec states that VALUE_LEN must be present for KEYGEN but later
// it's merely optional if the mechanism is CKM_SSL3_PRE_MASTER_KEY_GEN.
// Unfortunately, we can't check the mechanism at this point
//
return CKR_OK;
} else {
// Another contradiction within the spec: When describing the key types
// the spec says that VALUE_LEN must not be specified when unwrapping
// a key. In the section describing the mechanisms, though, it's allowed
// for most unwrapping mechanisms. Netscape DOES does specify this
// attribute when unwrapping.
//
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
}
return secret_key_check_required_attributes(tmpl, mode);
}
// generic_secret_set_default_attributes()
//
CK_RV generic_secret_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *value_len_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
CK_ATTRIBUTE *class_attr = NULL;
CK_ATTRIBUTE *sensitive_attr = NULL;
CK_ATTRIBUTE *encrypt_attr = NULL;
CK_ATTRIBUTE *decrypt_attr = NULL;
CK_ATTRIBUTE *sign_attr = NULL;
CK_ATTRIBUTE *verify_attr = NULL;
CK_ATTRIBUTE *wrap_attr = NULL;
CK_ATTRIBUTE *unwrap_attr = NULL;
CK_ATTRIBUTE *extractable_attr = NULL;
CK_ATTRIBUTE *never_extr_attr = NULL;
CK_ATTRIBUTE *always_sens_attr = NULL;
CK_ATTRIBUTE *id_attr = NULL;
CK_ATTRIBUTE *sdate_attr = NULL;
CK_ATTRIBUTE *edate_attr = NULL;
CK_ATTRIBUTE *derive_attr = NULL;
CK_ATTRIBUTE *local_attr = NULL;
CK_ULONG len = 0L;
if (mode) {
value_attr = NULL;
id_attr = NULL;
}
/* First set the Common Key Attributes's defaults for Generic Secret Keys */
id_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
sdate_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
edate_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
derive_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
local_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
if (!id_attr || !sdate_attr || !edate_attr || !derive_attr || !local_attr) {
if (id_attr)
free(id_attr);
if (sdate_attr)
free(sdate_attr);
if (edate_attr)
free(edate_attr);
if (derive_attr)
free(derive_attr);
if (local_attr)
free(local_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
id_attr->type = CKA_ID;
id_attr->ulValueLen = 0;
id_attr->pValue = NULL;
sdate_attr->type = CKA_START_DATE;
sdate_attr->ulValueLen = 0;
sdate_attr->pValue = NULL;
edate_attr->type = CKA_END_DATE;
edate_attr->ulValueLen = 0;
edate_attr->pValue = NULL;
derive_attr->type = CKA_DERIVE;
derive_attr->ulValueLen = sizeof(CK_BBOOL);
derive_attr->pValue = (CK_BYTE *) derive_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) derive_attr->pValue = TRUE;
/* should be safe to set CKA_LOCAL here... */
local_attr->type = CKA_LOCAL;
local_attr->ulValueLen = sizeof(CK_BBOOL);
local_attr->pValue = (CK_BYTE *) local_attr + sizeof(CK_ATTRIBUTE);
if (mode == MODE_KEYGEN)
*(CK_BBOOL *) local_attr->pValue = TRUE;
else
*(CK_BBOOL *) local_attr->pValue = FALSE;
template_update_attribute(tmpl, id_attr);
template_update_attribute(tmpl, sdate_attr);
template_update_attribute(tmpl, edate_attr);
template_update_attribute(tmpl, derive_attr);
template_update_attribute(tmpl, local_attr);
/* Next, set the Common Secret Key Attributes and defaults for
* Generic Secret Keys.
*/
class_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS));
sensitive_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
encrypt_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
decrypt_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
sign_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
verify_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
wrap_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
unwrap_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
extractable_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
never_extr_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
always_sens_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL));
if (!class_attr || !sensitive_attr || !encrypt_attr || !decrypt_attr
|| !sign_attr || !verify_attr | !wrap_attr || !unwrap_attr
|| !extractable_attr || !never_extr_attr || !always_sens_attr) {
if (class_attr)
free(class_attr);
if (sensitive_attr)
free(sensitive_attr);
if (encrypt_attr)
free(encrypt_attr);
if (decrypt_attr)
free(decrypt_attr);
if (sign_attr)
free(sign_attr);
if (verify_attr)
free(verify_attr);
if (wrap_attr)
free(wrap_attr);
if (unwrap_attr)
free(unwrap_attr);
if (extractable_attr)
free(extractable_attr);
if (never_extr_attr)
free(never_extr_attr);
if (always_sens_attr)
free(always_sens_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
class_attr->type = CKA_CLASS;
class_attr->ulValueLen = sizeof(CK_OBJECT_CLASS);
class_attr->pValue = (CK_BYTE *) class_attr + sizeof(CK_ATTRIBUTE);
*(CK_OBJECT_CLASS *) class_attr->pValue = CKO_SECRET_KEY;
sensitive_attr->type = CKA_SENSITIVE;
sensitive_attr->ulValueLen = sizeof(CK_BBOOL);
sensitive_attr->pValue = (CK_BYTE *) sensitive_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) sensitive_attr->pValue = FALSE;
encrypt_attr->type = CKA_ENCRYPT;
encrypt_attr->ulValueLen = sizeof(CK_BBOOL);
encrypt_attr->pValue = (CK_BYTE *) encrypt_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) encrypt_attr->pValue = FALSE;
decrypt_attr->type = CKA_DECRYPT;
decrypt_attr->ulValueLen = sizeof(CK_BBOOL);
decrypt_attr->pValue = (CK_BYTE *) decrypt_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) decrypt_attr->pValue = FALSE;
sign_attr->type = CKA_SIGN;
sign_attr->ulValueLen = sizeof(CK_BBOOL);
sign_attr->pValue = (CK_BYTE *) sign_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) sign_attr->pValue = TRUE;
verify_attr->type = CKA_VERIFY;
verify_attr->ulValueLen = sizeof(CK_BBOOL);
verify_attr->pValue = (CK_BYTE *) verify_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) verify_attr->pValue = TRUE;
wrap_attr->type = CKA_WRAP;
wrap_attr->ulValueLen = sizeof(CK_BBOOL);
wrap_attr->pValue = (CK_BYTE *) wrap_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) wrap_attr->pValue = FALSE;
unwrap_attr->type = CKA_UNWRAP;
unwrap_attr->ulValueLen = sizeof(CK_BBOOL);
unwrap_attr->pValue = (CK_BYTE *) unwrap_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) unwrap_attr->pValue = FALSE;
extractable_attr->type = CKA_EXTRACTABLE;
extractable_attr->ulValueLen = sizeof(CK_BBOOL);
extractable_attr->pValue =
(CK_BYTE *) extractable_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) extractable_attr->pValue = TRUE;
/* by default, we'll set NEVER_EXTRACTABLE == FALSE and
* ALWAYS_SENSITIVE == FALSE
* If the key is being created with KEYGEN, it will adjust as necessary.
*/
always_sens_attr->type = CKA_ALWAYS_SENSITIVE;
always_sens_attr->ulValueLen = sizeof(CK_BBOOL);
always_sens_attr->pValue =
(CK_BYTE *) always_sens_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) always_sens_attr->pValue = FALSE;
never_extr_attr->type = CKA_NEVER_EXTRACTABLE;
never_extr_attr->ulValueLen = sizeof(CK_BBOOL);
never_extr_attr->pValue =
(CK_BYTE *) never_extr_attr + sizeof(CK_ATTRIBUTE);
*(CK_BBOOL *) never_extr_attr->pValue = FALSE;
template_update_attribute(tmpl, class_attr);
template_update_attribute(tmpl, sensitive_attr);
template_update_attribute(tmpl, encrypt_attr);
template_update_attribute(tmpl, decrypt_attr);
template_update_attribute(tmpl, sign_attr);
template_update_attribute(tmpl, verify_attr);
template_update_attribute(tmpl, wrap_attr);
template_update_attribute(tmpl, unwrap_attr);
template_update_attribute(tmpl, extractable_attr);
template_update_attribute(tmpl, never_extr_attr);
template_update_attribute(tmpl, always_sens_attr);
/* Now set the type, value and value_len */
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
value_len_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG));
if (!type_attr || !value_attr || !value_len_attr) {
if (type_attr)
free(type_attr);
if (value_attr)
free(value_attr);
if (value_len_attr)
free(value_len_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
value_len_attr->type = CKA_VALUE_LEN;
value_len_attr->ulValueLen = sizeof(CK_ULONG);
value_len_attr->pValue = (CK_BYTE *) value_len_attr + sizeof(CK_ATTRIBUTE);
*(CK_ULONG *) value_len_attr->pValue = len;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_GENERIC_SECRET;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, value_attr);
template_update_attribute(tmpl, value_len_attr);
return CKR_OK;
}
// generic_secret_validate_attribute()
//
CK_RV generic_secret_validate_attribute(STDLL_TokData_t *tokdata,
TEMPLATE *tmpl, CK_ATTRIBUTE *attr,
CK_ULONG mode)
{
switch (attr->type) {
case CKA_VALUE:
if (mode == MODE_CREATE)
return CKR_OK;
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
// Another contradiction within the spec: When describing the key types
// the spec says that VALUE_LEN must not be specified when unwrapping
// a key. In the section describing the mechanisms, though, it's allowed
// for most unwrapping mechanisms. Netscape DOES does specify this
// attribute when unwrapping.
//
case CKA_VALUE_LEN:
if (mode == MODE_KEYGEN || mode == MODE_DERIVE)
return CKR_OK;
if (mode == MODE_UNWRAP) {
if (tokdata->nv_token_data->tweak_vector.netscape_mods == TRUE)
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
default:
return secret_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// generic_secret_check_exportability()
//
CK_BBOOL generic_secret_check_exportability(CK_ATTRIBUTE_TYPE type)
{
switch (type) {
case CKA_VALUE:
return FALSE;
}
return TRUE;
}
//
//
CK_RV generic_secret_wrap_get_data(TEMPLATE *tmpl,
CK_BBOOL length_only,
CK_BYTE **data, CK_ULONG *data_len)
{
CK_ATTRIBUTE *attr = NULL;
CK_BYTE *ptr = NULL;
CK_RV rc;
if (!tmpl || !data_len) {
TRACE_ERROR("Invalid function arguments.\n");
return CKR_FUNCTION_FAILED;
}
rc = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (rc == FALSE) {
TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE));
return CKR_KEY_NOT_WRAPPABLE;
}
*data_len = attr->ulValueLen;
if (length_only == FALSE) {
ptr = (CK_BYTE *) malloc(attr->ulValueLen);
if (!ptr) {
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
memcpy(ptr, attr->pValue, attr->ulValueLen);
*data = ptr;
}
return CKR_OK;
}
//
//
CK_RV generic_secret_unwrap(TEMPLATE *tmpl,
CK_BYTE *data,
CK_ULONG data_len,
CK_BBOOL fromend)
{
CK_ATTRIBUTE *attr = NULL;
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *value_len_attr = NULL;
CK_BYTE *ptr = NULL;
CK_ULONG rc, len = 0;
if (fromend == TRUE)
ptr = data + data_len;
else
ptr = data;
// it's possible that the user specified CKA_VALUE_LEN in the
// template. if so, try to use it. by default, CKA_VALUE_LEN is 0
//
rc = template_attribute_find(tmpl, CKA_VALUE_LEN, &attr);
if (rc) {
len = *(CK_ULONG *) attr->pValue;
if (len > data_len) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
rc = CKR_ATTRIBUTE_VALUE_INVALID;
goto error;
}
if (len != 0)
data_len = len;
}
if (fromend == TRUE)
ptr -= data_len;
rc = build_attribute(CKA_VALUE, ptr, data_len, &value_attr);
if (rc != CKR_OK) {
TRACE_DEVEL("build_attribute failed\n");
goto error;
}
if (data_len != len) {
rc = build_attribute(CKA_VALUE_LEN, (CK_BYTE *) & data_len,
sizeof(CK_ULONG), &value_len_attr);
if (rc != CKR_OK) {
TRACE_DEVEL("build_attribute failed\n");
goto error;
}
}
template_update_attribute(tmpl, value_attr);
if (data_len != len)
template_update_attribute(tmpl, value_len_attr);
return CKR_OK;
error:
if (value_attr)
free(value_attr);
if (value_len_attr)
free(value_len_attr);
return rc;
}
// rc2_check_required_attributes()
//
CK_RV rc2_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_VALUE_LEN, &attr);
if (!found) {
if (mode == MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return secret_key_check_required_attributes(tmpl, mode);
}
// rc2_set_default_attributes()
//
CK_RV rc2_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *value_len_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
CK_ULONG len = 0L;
secret_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
value_len_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG));
if (!type_attr || !value_attr || !value_len_attr) {
if (type_attr)
free(type_attr);
if (value_attr)
free(value_attr);
if (value_len_attr)
free(value_len_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
value_len_attr->type = CKA_VALUE_LEN;
value_len_attr->ulValueLen = sizeof(CK_ULONG);
value_len_attr->pValue = (CK_BYTE *) value_len_attr + sizeof(CK_ATTRIBUTE);
*(CK_ULONG *) value_len_attr->pValue = len;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_RC2;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, value_attr);
template_update_attribute(tmpl, value_len_attr);
return CKR_OK;
}
// rc2_validate_attribute()
//
CK_RV rc2_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_VALUE:
if (mode != MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
// rc2 key length <= 128 bytes
//
if (attr->ulValueLen > 128)
return CKR_ATTRIBUTE_VALUE_INVALID;
return CKR_OK;
case CKA_VALUE_LEN:
{
CK_ULONG len;
if (mode != MODE_KEYGEN && mode != MODE_DERIVE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
len = *(CK_ULONG *) attr->pValue;
if (len > 128) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
}
default:
return secret_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// rc4_set_default_attributes()
//
CK_RV rc4_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *value_len_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
CK_ULONG len = 0L;
secret_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
value_len_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG));
if (!type_attr || !value_attr || !value_len_attr) {
if (type_attr)
free(type_attr);
if (value_attr)
free(value_attr);
if (value_len_attr)
free(value_len_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
value_len_attr->type = CKA_VALUE_LEN;
value_len_attr->ulValueLen = sizeof(CK_ULONG);
value_len_attr->pValue = (CK_BYTE *) value_len_attr + sizeof(CK_ATTRIBUTE);
*(CK_ULONG *) value_len_attr->pValue = len;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_RC4;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, value_attr);
template_update_attribute(tmpl, value_len_attr);
return CKR_OK;
}
// rc4_check_required_attributes()
//
CK_RV rc4_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_VALUE_LEN, &attr);
if (!found) {
if (mode == MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return secret_key_check_required_attributes(tmpl, mode);
}
// rc4_validate_attribute()
//
CK_RV rc4_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_VALUE:
if (mode != MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
// key length <= 256 bytes
//
if (attr->ulValueLen > 256) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
case CKA_VALUE_LEN:
{
CK_ULONG len;
if (mode != MODE_KEYGEN && mode != MODE_DERIVE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
len = *(CK_ULONG *) attr->pValue;
if (len > 255) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
}
default:
return secret_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// rc5_check_required_attributes()
//
CK_RV rc5_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_VALUE_LEN, &attr);
if (!found) {
if (mode == MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return secret_key_check_required_attributes(tmpl, mode);
}
// rc5_set_default_attributes()
//
CK_RV rc5_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *value_len_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
CK_ULONG len = 0L;
secret_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
value_len_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG));
if (!type_attr || !value_attr || !value_len_attr) {
if (type_attr)
free(type_attr);
if (value_attr)
free(value_attr);
if (value_len_attr)
free(value_len_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
value_len_attr->type = CKA_VALUE_LEN;
value_len_attr->ulValueLen = sizeof(CK_ULONG);
value_len_attr->pValue = (CK_BYTE *) value_len_attr + sizeof(CK_ATTRIBUTE);
*(CK_ULONG *) value_len_attr->pValue = len;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_RC5;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, value_attr);
template_update_attribute(tmpl, value_len_attr);
return CKR_OK;
}
// rc5_validate_attribute()
//
CK_RV rc5_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_VALUE:
if (mode != MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
// key length <= 256 bytes
//
if (attr->ulValueLen > 255) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
case CKA_VALUE_LEN:
{
CK_ULONG len;
if (mode != MODE_KEYGEN && mode != MODE_DERIVE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
len = *(CK_ULONG *) attr->pValue;
if (len > 255) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
}
default:
return secret_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
//
//
CK_RV des_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return secret_key_check_required_attributes(tmpl, mode);
}
//
//
CK_BBOOL des_check_weak_key(CK_BYTE *key)
{
CK_ULONG i;
for (i = 0; i < des_weak_count; i++) {
if (memcmp(key, des_weak_keys[i], DES_KEY_SIZE) == 0)
return TRUE;
}
for (i = 0; i < des_semi_weak_count; i++) {
if (memcmp(key, des_semi_weak_keys[i], DES_KEY_SIZE) == 0)
return TRUE;
}
for (i = 0; i < des_possibly_weak_count; i++) {
if (memcmp(key, des_possibly_weak_keys[i], DES_KEY_SIZE) == 0)
return TRUE;
}
return FALSE;
}
//
//
CK_RV des_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
if (mode)
value_attr = NULL;
secret_key_set_default_attributes(tmpl, mode);
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
if (!value_attr || !type_attr) {
if (value_attr)
free(value_attr);
if (type_attr)
free(type_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_DES;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
//
//
CK_RV des_unwrap(STDLL_TokData_t *tokdata,
TEMPLATE *tmpl,
CK_BYTE *data,
CK_ULONG data_len, CK_BBOOL fromend)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_BYTE *ptr = NULL;
CK_ULONG i;
if (data_len < DES_BLOCK_SIZE) {
TRACE_ERROR("%s\n", ock_err(ERR_WRAPPED_KEY_INVALID));
return CKR_WRAPPED_KEY_INVALID;
}
if (fromend == TRUE)
ptr = data + data_len - DES_BLOCK_SIZE;
else
ptr = data;
if (tokdata->nv_token_data->tweak_vector.check_des_parity == TRUE) {
for (i = 0; i < DES_KEY_SIZE; i++) {
if (parity_is_odd(ptr[i]) == FALSE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
}
}
value_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + DES_BLOCK_SIZE);
if (!value_attr) {
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = DES_BLOCK_SIZE;
value_attr->pValue = (CK_BYTE *) value_attr + sizeof(CK_ATTRIBUTE);
memcpy(value_attr->pValue, ptr, DES_BLOCK_SIZE);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
// des_validate_attribute()
//
CK_RV des_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
CK_BYTE *ptr = NULL;
CK_ULONG i;
switch (attr->type) {
case CKA_VALUE:
// key length always 8 bytes
//
if (mode == MODE_CREATE) {
if (attr->ulValueLen != DES_KEY_SIZE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
if (tokdata->nv_token_data->tweak_vector.check_des_parity == TRUE) {
ptr = attr->pValue;
for (i = 0; i < DES_KEY_SIZE; i++) {
if (parity_is_odd(ptr[i]) == FALSE) {
TRACE_ERROR("%s\n",
ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
}
}
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
case CKA_VALUE_LEN:
// Cryptoki doesn't allow this but Netscape tries uses it
//
if (tokdata->nv_token_data->tweak_vector.netscape_mods == TRUE) {
if (mode == MODE_CREATE || mode == MODE_DERIVE ||
mode == MODE_KEYGEN || mode == MODE_UNWRAP) {
CK_ULONG len = *(CK_ULONG *) attr->pValue;
if (len != DES_KEY_SIZE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT));
return CKR_TEMPLATE_INCONSISTENT;
default:
return secret_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
//
//
CK_RV des_wrap_get_data(TEMPLATE *tmpl,
CK_BBOOL length_only,
CK_BYTE **data, CK_ULONG *data_len)
{
CK_ATTRIBUTE *attr = NULL;
CK_BYTE *ptr = NULL;
CK_RV rc;
if (!tmpl || !data_len) {
TRACE_ERROR("Invalid function arguments.\n");
return CKR_FUNCTION_FAILED;
}
rc = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (rc == FALSE) {
TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE));
return CKR_KEY_NOT_WRAPPABLE;
}
*data_len = attr->ulValueLen;
if (length_only == FALSE) {
ptr = (CK_BYTE *) malloc(attr->ulValueLen);
if (!ptr) {
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
memcpy(ptr, attr->pValue, attr->ulValueLen);
*data = ptr;
}
return CKR_OK;
}
// des2_check_required_attributes()
//
CK_RV des2_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return secret_key_check_required_attributes(tmpl, mode);
}
// des2_set_default_attributes()
//
CK_RV des2_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
if (mode)
value_attr = NULL;
secret_key_set_default_attributes(tmpl, mode);
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
if (!value_attr || !type_attr) {
if (value_attr)
free(value_attr);
if (type_attr)
free(type_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_DES2;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
// des2_validate_attribute()
//
CK_RV des2_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
CK_BYTE *ptr = NULL;
CK_ULONG i;
switch (attr->type) {
case CKA_VALUE:
// key length always 16 bytes
//
if (mode == MODE_CREATE) {
if (attr->ulValueLen != (2 * DES_KEY_SIZE)) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
if (tokdata->nv_token_data->tweak_vector.check_des_parity == TRUE) {
ptr = attr->pValue;
for (i = 0; i < 2 * DES_KEY_SIZE; i++) {
if (parity_is_odd(ptr[i]) == FALSE) {
TRACE_ERROR("%s\n",
ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
}
}
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
case CKA_VALUE_LEN:
// Cryptoki doesn't allow this but Netscape tries uses it
//
if (tokdata->nv_token_data->tweak_vector.netscape_mods == TRUE) {
if (mode == MODE_CREATE || mode == MODE_DERIVE ||
mode == MODE_KEYGEN || mode == MODE_UNWRAP) {
CK_ULONG len = *(CK_ULONG *) attr->pValue;
if (len != (2 * DES_KEY_SIZE)) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT));
return CKR_TEMPLATE_INCONSISTENT;
default:
return secret_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// des3_check_required_attributes()
//
CK_RV des3_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return secret_key_check_required_attributes(tmpl, mode);
}
// des3_set_default_attributes()
//
CK_RV des3_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
if (mode)
value_attr = NULL;
secret_key_set_default_attributes(tmpl, mode);
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
if (!value_attr || !type_attr) {
if (value_attr)
free(value_attr);
if (type_attr)
free(type_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_DES3;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
//
//
CK_RV des3_unwrap(STDLL_TokData_t *tokdata,
TEMPLATE *tmpl,
CK_BYTE *data,
CK_ULONG data_len, CK_BBOOL fromend)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_BYTE *ptr = NULL;
CK_ULONG i;
if (data_len < 3 * DES_BLOCK_SIZE) {
TRACE_ERROR("%s\n", ock_err(ERR_WRAPPED_KEY_INVALID));
return CKR_WRAPPED_KEY_INVALID;
}
if (fromend == TRUE)
ptr = data + data_len - (3 * DES_BLOCK_SIZE);
else
ptr = data;
if (tokdata->nv_token_data->tweak_vector.check_des_parity == TRUE) {
for (i = 0; i < 3 * DES_KEY_SIZE; i++) {
if (parity_is_odd(ptr[i]) == FALSE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
}
}
value_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + (3 * DES_BLOCK_SIZE));
if (!value_attr) {
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 3 * DES_BLOCK_SIZE;
value_attr->pValue = (CK_BYTE *) value_attr + sizeof(CK_ATTRIBUTE);
memcpy(value_attr->pValue, ptr, 3 * DES_BLOCK_SIZE);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
//
//
CK_RV des3_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
CK_BYTE *ptr = NULL;
CK_ULONG i;
switch (attr->type) {
case CKA_VALUE:
// key length always 24 bytes
//
if (mode == MODE_CREATE) {
if (attr->ulValueLen != (3 * DES_KEY_SIZE)) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
if (tokdata->nv_token_data->tweak_vector.check_des_parity == TRUE) {
ptr = attr->pValue;
for (i = 0; i < 3 * DES_KEY_SIZE; i++) {
if (parity_is_odd(ptr[i]) == FALSE) {
TRACE_ERROR("%s\n",
ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
}
}
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
case CKA_VALUE_LEN:
// Cryptoki doesn't allow this but Netscape tries uses it
//
if (tokdata->nv_token_data->tweak_vector.netscape_mods == TRUE) {
if (mode == MODE_CREATE || mode == MODE_DERIVE ||
mode == MODE_KEYGEN || mode == MODE_UNWRAP) {
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT));
return CKR_TEMPLATE_INCONSISTENT;
default:
return secret_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
//
//
CK_RV des3_wrap_get_data(TEMPLATE *tmpl,
CK_BBOOL length_only,
CK_BYTE **data, CK_ULONG *data_len)
{
CK_ATTRIBUTE *attr = NULL;
CK_BYTE *ptr = NULL;
CK_RV rc;
if (!tmpl || !data_len) {
TRACE_ERROR("Invalid function arguments.\n");
return CKR_FUNCTION_FAILED;
}
rc = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (rc == FALSE) {
TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE));
return CKR_KEY_NOT_WRAPPABLE;
}
*data_len = attr->ulValueLen;
if (length_only == FALSE) {
ptr = (CK_BYTE *) malloc(attr->ulValueLen);
if (!ptr) {
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
memcpy(ptr, attr->pValue, attr->ulValueLen);
*data = ptr;
}
return CKR_OK;
}
// cast_check_required_attributes()
//
CK_RV cast_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_VALUE_LEN, &attr);
if (!found) {
if (mode == MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return secret_key_check_required_attributes(tmpl, mode);
}
// cast_set_default_attributes()
//
CK_RV cast_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *value_len_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
CK_ULONG len = 0L;
secret_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
value_len_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG));
if (!type_attr || !value_attr || !value_len_attr) {
if (type_attr)
free(type_attr);
if (value_attr)
free(value_attr);
if (value_len_attr)
free(value_len_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
value_len_attr->type = CKA_VALUE_LEN;
value_len_attr->ulValueLen = sizeof(CK_ULONG);
value_len_attr->pValue = (CK_BYTE *) value_len_attr + sizeof(CK_ATTRIBUTE);
*(CK_ULONG *) value_len_attr->pValue = len;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_CAST;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, value_attr);
template_update_attribute(tmpl, value_len_attr);
return CKR_OK;
}
// cast_validate_attribute()
//
CK_RV cast_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
CK_ULONG len;
switch (attr->type) {
case CKA_VALUE:
if (mode != MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
if (attr->ulValueLen > 8 || attr->ulValueLen < 1) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
case CKA_VALUE_LEN:
if (mode != MODE_KEYGEN && mode != MODE_DERIVE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
len = *(CK_ULONG *) attr->pValue;
if (len > 8 || len < 1) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
default:
return secret_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// cast3_check_required_attributes()
//
CK_RV cast3_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_VALUE_LEN, &attr);
if (!found) {
if (mode == MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return secret_key_check_required_attributes(tmpl, mode);
}
// cast3_set_default_attributes()
//
CK_RV cast3_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *value_len_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
CK_ULONG len = 0L;
if (mode)
value_attr = NULL;
secret_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
value_len_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG));
if (!type_attr || !value_attr || !value_len_attr) {
if (type_attr)
free(type_attr);
if (value_attr)
free(value_attr);
if (value_len_attr)
free(value_len_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
value_len_attr->type = CKA_VALUE_LEN;
value_len_attr->ulValueLen = sizeof(CK_ULONG);
value_len_attr->pValue = (CK_BYTE *) value_len_attr + sizeof(CK_ATTRIBUTE);
*(CK_ULONG *) value_len_attr->pValue = len;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_CAST3;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, value_attr);
template_update_attribute(tmpl, value_len_attr);
return CKR_OK;
}
// cast3_validate_attribute()
//
CK_RV cast3_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
CK_ULONG len;
switch (attr->type) {
case CKA_VALUE:
if (mode != MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
if (attr->ulValueLen > 8 || attr->ulValueLen < 1) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
case CKA_VALUE_LEN:
if (mode != MODE_KEYGEN && mode != MODE_DERIVE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
len = *(CK_ULONG *) attr->pValue;
if (len > 8 || len < 1) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
default:
return secret_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// cast5_check_required_attributes()
//
CK_RV cast5_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
found = template_attribute_find(tmpl, CKA_VALUE_LEN, &attr);
if (!found) {
if (mode == MODE_KEYGEN) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return secret_key_check_required_attributes(tmpl, mode);
}
// cast5_set_default_attributes()
//
CK_RV cast5_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *value_len_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
CK_ULONG len = 0L;
secret_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
value_len_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG));
if (!type_attr || !value_attr || !value_len_attr) {
if (type_attr)
free(type_attr);
if (value_attr)
free(value_attr);
if (value_len_attr)
free(value_len_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
value_len_attr->type = CKA_VALUE_LEN;
value_len_attr->ulValueLen = sizeof(CK_ULONG);
value_len_attr->pValue = (CK_BYTE *) value_len_attr + sizeof(CK_ATTRIBUTE);
*(CK_ULONG *) value_len_attr->pValue = len;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_CAST5;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, value_attr);
template_update_attribute(tmpl, value_len_attr);
return CKR_OK;
}
// cast5_validate_attribute()
//
CK_RV cast5_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
CK_ULONG len;
switch (attr->type) {
case CKA_VALUE:
if (mode != MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
if (attr->ulValueLen > 16 || attr->ulValueLen < 1) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
case CKA_VALUE_LEN:
if (mode != MODE_KEYGEN && mode != MODE_DERIVE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
len = *(CK_ULONG *) attr->pValue;
if (len < 1 || len > 16) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
default:
return secret_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// idea_check_required_attributes()
//
CK_RV idea_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return secret_key_check_required_attributes(tmpl, mode);
}
// idea_set_default_attributes()
//
CK_RV idea_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
if (mode)
value_attr = NULL;
secret_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
if (!type_attr || !value_attr) {
if (type_attr)
free(type_attr);
if (value_attr)
free(value_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_IDEA;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
// idea_validate_attribute()
//
CK_RV idea_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_VALUE:
if (mode != MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
if (attr->ulValueLen != 16) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
default:
return secret_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// cdmf_check_required_attributes()
//
CK_RV cdmf_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return secret_key_check_required_attributes(tmpl, mode);
}
#if !(NOCDMF)
// cdmf_set_default_attributes()
//
CK_RV cdmf_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
if (mode)
value_attr = NULL;
secret_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
if (!type_attr || !value_attr) {
if (type_attr)
free(type_attr);
if (value_attr)
free(value_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_CDMF;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
// cdmf_validate_attribute()
//
CK_RV cdmf_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
CK_ULONG len;
switch (attr->type) {
case CKA_VALUE:
#if 0
CDMF_Transform_Args args;
#endif
CK_ULONG req_len, repl_len;
CK_BYTE cdmf_key[DES_KEY_SIZE];
CK_RV rc;
if (mode != MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
if (attr->ulValueLen != DES_KEY_SIZE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
#if 0
req_len = sizeof(args);
repl_len = DES_KEY_SIZE;
memcpy(args.des_key, attr->pValue, DES_KEY_SIZE);
rc = communicate(PK_CDMF_TRANSFORM_KEY,
&args, req_len, cdmf_key, &repl_len, NULL, 0, NULL, 0);
if (rc != CKR_OK)
return rc;
if (rc == CKR_OK) {
if (repl_len != DES_KEY_SIZE)
return CKR_GENERAL_ERROR;
memcpy(attr->pValue, cdmf_key, DES_KEY_SIZE);
}
return CKR_OK;
#else
return tok_cdmf_transform(attr->pValue, DES_KEY_SIZE);
#endif
case CKA_VALUE_LEN:
if (tokdata->nv_token_data->tweak_vector.netscape_mods == TRUE) {
if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
len = *(CK_ULONG *) attr->pValue;
if (len != DES_KEY_SIZE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT));
return CKR_TEMPLATE_INCONSISTENT;
default:
return secret_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
#endif
// skipjack_check_required_attributes()
//
CK_RV skipjack_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return secret_key_check_required_attributes(tmpl, mode);
}
// skipjack_set_default_attributes()
//
CK_RV skipjack_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
if (mode)
value_attr = NULL;
secret_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
if (!type_attr || !value_attr) {
if (type_attr)
free(type_attr);
if (value_attr)
free(value_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_SKIPJACK;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
// skipjack_validate_attribute()
//
CK_RV skipjack_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_VALUE:
if (mode != MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
if (attr->ulValueLen != 20) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
default:
return secret_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// baton_check_required_attributes()
//
CK_RV baton_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return secret_key_check_required_attributes(tmpl, mode);
}
// baton_set_default_attributes()
//
CK_RV baton_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
if (mode)
value_attr = NULL;
secret_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
if (!type_attr || !value_attr) {
if (type_attr)
free(type_attr);
if (value_attr)
free(value_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_BATON;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
// baton_validate_attribute()
//
CK_RV baton_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_VALUE:
if (mode != MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
if (attr->ulValueLen != 40) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
default:
return secret_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// juniper_check_required_attributes()
//
CK_RV juniper_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return secret_key_check_required_attributes(tmpl, mode);
}
// juniper_set_default_attributes()
//
CK_RV juniper_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
if (mode)
value_attr = NULL;
secret_key_set_default_attributes(tmpl, mode);
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
if (!type_attr || !value_attr) {
if (type_attr)
free(type_attr);
if (value_attr)
free(value_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_JUNIPER;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
// juniper_validate_attribute()
//
CK_RV juniper_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
switch (attr->type) {
case CKA_VALUE:
if (mode != MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
}
if (attr->ulValueLen != 40) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
default:
return secret_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
// aes_set_default_attributes()
//
CK_RV aes_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *type_attr = NULL;
if (mode)
value_attr = NULL;
secret_key_set_default_attributes(tmpl, mode);
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
type_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
if (!value_attr || !type_attr) {
if (value_attr)
free(value_attr);
if (type_attr)
free(type_attr);
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = 0;
value_attr->pValue = NULL;
type_attr->type = CKA_KEY_TYPE;
type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
*(CK_KEY_TYPE *) type_attr->pValue = CKK_AES;
template_update_attribute(tmpl, type_attr);
template_update_attribute(tmpl, value_attr);
return CKR_OK;
}
// aes_check_required_attributes()
//
CK_RV aes_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
{
CK_ATTRIBUTE *attr = NULL;
CK_BBOOL found;
found = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (!found) {
if (mode == MODE_CREATE) {
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
return CKR_TEMPLATE_INCOMPLETE;
}
}
return secret_key_check_required_attributes(tmpl, mode);
}
//
//
CK_RV aes_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
CK_ATTRIBUTE *attr, CK_ULONG mode)
{
CK_ULONG val;
switch (attr->type) {
case CKA_VALUE:
// key length is either 16, 24 or 32 bytes
//
if (mode == MODE_CREATE) {
if (attr->ulValueLen != AES_KEY_SIZE_128 &&
attr->ulValueLen != AES_KEY_SIZE_192 &&
attr->ulValueLen != AES_KEY_SIZE_256) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
return CKR_ATTRIBUTE_VALUE_INVALID;
}
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_ATTRIBUTE_READ_ONLY;
case CKA_VALUE_LEN:
if (mode == MODE_CREATE || mode == MODE_DERIVE ||
mode == MODE_KEYGEN || mode == MODE_UNWRAP) {
val = *(CK_ULONG *) attr->pValue;
if (val != AES_KEY_SIZE_128 &&
val != AES_KEY_SIZE_192 && val != AES_KEY_SIZE_256) {
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
return CKR_TEMPLATE_INCONSISTENT;
}
return CKR_OK;
}
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT));
return CKR_TEMPLATE_INCONSISTENT;
default:
return secret_key_validate_attribute(tokdata, tmpl, attr, mode);
}
}
//
//
CK_RV aes_wrap_get_data(TEMPLATE *tmpl,
CK_BBOOL length_only,
CK_BYTE **data, CK_ULONG *data_len)
{
CK_ATTRIBUTE *attr = NULL;
CK_BYTE *ptr = NULL;
CK_RV rc;
if (!tmpl || !data_len) {
TRACE_ERROR("Invalid function arguments.\n");
return CKR_FUNCTION_FAILED;
}
rc = template_attribute_find(tmpl, CKA_VALUE, &attr);
if (rc == FALSE) {
TRACE_ERROR("%s\n", ock_err(ERR_KEY_NOT_WRAPPABLE));
return CKR_KEY_NOT_WRAPPABLE;
}
*data_len = attr->ulValueLen;
if (length_only == FALSE) {
ptr = (CK_BYTE *) malloc(attr->ulValueLen);
if (!ptr) {
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
memcpy(ptr, attr->pValue, attr->ulValueLen);
*data = ptr;
}
return CKR_OK;
}
//
//
CK_RV aes_unwrap(STDLL_TokData_t *tokdata,
TEMPLATE *tmpl,
CK_BYTE *data,
CK_ULONG data_len, CK_BBOOL fromend)
{
CK_ATTRIBUTE *value_attr = NULL;
CK_ATTRIBUTE *val_len_attr = NULL;
CK_BYTE *ptr = NULL;
CK_ULONG key_size;
CK_BBOOL found = FALSE;
UNUSED(tokdata);
/* accept CKA_VALUE_LEN. pkcs11v2.20 doesn't want this attribute when
* unwrapping an AES key, but we need it for several reasons:
* - because some mechanisms may have added padding
* - AES keys come in several sizes
* If not a available, try datalen and see if matches an aes key size.
* Otherwise, fail because we need to return CKA_VALUE_LEN and we cannot
* unless user tells us what it is.
*/
found = template_attribute_find(tmpl, CKA_VALUE_LEN, &val_len_attr);
if (found)
key_size = *(CK_ULONG *) val_len_attr->pValue;
else
key_size = data_len;
/* key_size should be one of AES's possible sizes */
if (key_size != AES_KEY_SIZE_128 &&
key_size != AES_KEY_SIZE_192 && key_size != AES_KEY_SIZE_256) {
TRACE_ERROR("%s\n", ock_err(ERR_WRAPPED_KEY_LEN_RANGE));
return CKR_WRAPPED_KEY_LEN_RANGE;
}
if (fromend == TRUE)
ptr = data + data_len - key_size;
else
ptr = data;
value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + key_size);
if (!value_attr) {
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
value_attr->type = CKA_VALUE;
value_attr->ulValueLen = key_size;
value_attr->pValue = (CK_BYTE *) value_attr + sizeof(CK_ATTRIBUTE);
memcpy(value_attr->pValue, ptr, key_size);
template_update_attribute(tmpl, value_attr);
/* pkcs11v2-20: CKA_VALUE and CKA_VALUE_LEN given for aes key object. */
if (!found) {
val_len_attr =
(CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG));
if (!val_len_attr) {
TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
return CKR_HOST_MEMORY;
}
val_len_attr->type = CKA_VALUE_LEN;
val_len_attr->ulValueLen = sizeof(CK_ULONG);
val_len_attr->pValue = (CK_BYTE *) val_len_attr + sizeof(CK_ATTRIBUTE);
*((CK_ULONG *) val_len_attr->pValue) = key_size;
template_update_attribute(tmpl, val_len_attr);
}
return CKR_OK;
}