/* * 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 #include #include // 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; }