📄 framework-pkcs15.c
字号:
kpgen_done: sc_unlock(p11card->card); sc_pkcs15init_unbind(profile); return rv;}#endifstruct sc_pkcs11_framework_ops framework_pkcs15 = { pkcs15_bind, pkcs15_unbind, pkcs15_create_tokens, pkcs15_release_token, pkcs15_login, pkcs15_logout, pkcs15_change_pin, NULL, /* init_token */#ifdef USE_PKCS15_INIT pkcs15_init_pin, pkcs15_create_object, pkcs15_gen_keypair,#else NULL, NULL#endif};CK_RV pkcs15_set_attrib(struct sc_pkcs11_session *session, struct sc_pkcs15_object *p15_object, CK_ATTRIBUTE_PTR attr){#ifndef USE_PKCS15_INIT return CKR_FUNCTION_NOT_SUPPORTED;#else struct sc_profile *profile = NULL; struct sc_pkcs11_card *p11card = session->slot->card; struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data; struct pkcs15_slot_data *p15_data = slot_data(session->slot->fw_data); struct sc_pkcs15_id id; int rc = 0; CK_RV rv = CKR_OK; rc = sc_pkcs15init_bind(p11card->card, "pkcs15", NULL, &profile); if (rc < 0) return sc_to_cryptoki_error(rc, p11card->reader); rc = sc_lock(p11card->card); if (rc < 0) { sc_pkcs15init_unbind(profile); return sc_to_cryptoki_error(rc, p11card->reader); } /* 2. Add the PINs the user presented so far. Some initialization * routines need to present these PINs again because some * card operations may clobber the authentication state * (the GPK for instance) */ if (p15_data->pin[CKU_SO].len) sc_pkcs15init_set_pin_data(profile, SC_PKCS15INIT_SO_PIN, p15_data->pin[CKU_SO].value, p15_data->pin[CKU_SO].len); if (p15_data->pin[CKU_USER].len) sc_pkcs15init_set_pin_data(profile, SC_PKCS15INIT_USER_PIN, p15_data->pin[CKU_USER].value, p15_data->pin[CKU_USER].len); switch(attr->type) { case CKA_LABEL: rc = sc_pkcs15init_change_attrib(fw_data->p15_card, profile, p15_object, P15_ATTR_TYPE_LABEL, attr->pValue, attr->ulValueLen); break; case CKA_ID: if (attr->ulValueLen > SC_PKCS15_MAX_ID_SIZE) { rc = SC_ERROR_INVALID_ARGUMENTS; break; } memcpy(id.value, attr->pValue, attr->ulValueLen); id.len = attr->ulValueLen; rc = sc_pkcs15init_change_attrib(fw_data->p15_card, profile, p15_object, P15_ATTR_TYPE_ID, &id, sizeof(id)); break; case CKA_SUBJECT: rc = SC_SUCCESS; break; default: rv = CKR_ATTRIBUTE_READ_ONLY; goto set_attr_done; } rv = sc_to_cryptoki_error(rc, p11card->reader);set_attr_done: sc_unlock(p11card->card); sc_pkcs15init_unbind(profile); return rv;#endif}/* * PKCS#15 Certificate Object */void pkcs15_cert_release(void *obj){ struct pkcs15_cert_object *cert = (struct pkcs15_cert_object *) obj; struct sc_pkcs15_cert *cert_data = cert->cert_data; if (__pkcs15_release_object((struct pkcs15_any_object *) obj) == 0) sc_pkcs15_free_certificate(cert_data);}CK_RV pkcs15_cert_set_attribute(struct sc_pkcs11_session *session, void *object, CK_ATTRIBUTE_PTR attr){ struct pkcs15_cert_object *cert = (struct pkcs15_cert_object*) object; return pkcs15_set_attrib(session, cert->base.p15_object, attr);}CK_RV pkcs15_cert_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ATTRIBUTE_PTR attr){ struct pkcs15_cert_object *cert = (struct pkcs15_cert_object*) object; size_t len; switch (attr->type) { case CKA_CLASS: check_attribute_buffer(attr, sizeof(CK_OBJECT_CLASS)); *(CK_OBJECT_CLASS*)attr->pValue = CKO_CERTIFICATE; break; case CKA_TOKEN: check_attribute_buffer(attr, sizeof(CK_BBOOL)); *(CK_BBOOL*)attr->pValue = TRUE; break; case CKA_PRIVATE: case CKA_MODIFIABLE: check_attribute_buffer(attr, sizeof(CK_BBOOL)); *(CK_BBOOL*)attr->pValue = FALSE; break; case CKA_LABEL: len = strlen(cert->cert_p15obj->label); check_attribute_buffer(attr, len); memcpy(attr->pValue, cert->cert_p15obj->label, len); break; case CKA_CERTIFICATE_TYPE: check_attribute_buffer(attr, sizeof(CK_CERTIFICATE_TYPE)); *(CK_CERTIFICATE_TYPE*)attr->pValue = CKC_X_509; break; case CKA_ID: /* Not sure why CA certs should be reported with an * ID of 00. --okir 20030413 */ if (cert->cert_info->authority) { check_attribute_buffer(attr, 1); *(unsigned char*)attr->pValue = 0; } else { check_attribute_buffer(attr, cert->cert_info->id.len); memcpy(attr->pValue, cert->cert_info->id.value, cert->cert_info->id.len); } break; case CKA_TRUSTED: check_attribute_buffer(attr, sizeof(CK_BBOOL)); *(CK_BBOOL*)attr->pValue = cert->cert_info->authority?TRUE:FALSE; break; case CKA_VALUE: check_attribute_buffer(attr, cert->cert_data->data_len); memcpy(attr->pValue, cert->cert_data->data, cert->cert_data->data_len); break; case CKA_SERIAL_NUMBER: check_attribute_buffer(attr, cert->cert_data->serial_len); memcpy(attr->pValue, cert->cert_data->serial, cert->cert_data->serial_len); break; case CKA_SUBJECT: return asn1_sequence_wrapper(cert->cert_data->subject, cert->cert_data->subject_len, attr); case CKA_ISSUER: return asn1_sequence_wrapper(cert->cert_data->issuer, cert->cert_data->issuer_len, attr); default: return CKR_ATTRIBUTE_TYPE_INVALID; } return CKR_OK;}static intpkcs15_cert_cmp_attribute(struct sc_pkcs11_session *session, void *object, CK_ATTRIBUTE_PTR attr){ struct pkcs15_cert_object *cert = (struct pkcs15_cert_object*) object; u8 *data; size_t len; switch (attr->type) { /* Check the issuer. Some pkcs11 callers (i.e. netscape) will pass * in the ASN.1 encoded SEQUENCE OF SET ... while OpenSC just * keeps the SET in the issuer field. */ case CKA_ISSUER: if (cert->cert_data->issuer_len == 0) break; data = (u8 *) attr->pValue; len = attr->ulValueLen; /* SEQUENCE is tag 0x30, SET is 0x31 * I know this code is icky, but hey... this is netscape * we're dealing with :-) */ if (cert->cert_data->issuer[0] == 0x31 && data[0] == 0x30 && len >= 2) { /* skip the length byte(s) */ len = (data[1] & 0x80)? (data[1] & 0x7F) : 0; if (attr->ulValueLen < len + 2) break; data += len + 2; len = attr->ulValueLen - len - 2; } if (len == cert->cert_data->issuer_len && !memcmp(cert->cert_data->issuer, data, len)) return 1; break; default: return sc_pkcs11_any_cmp_attribute(session, object, attr); } return 0;}struct sc_pkcs11_object_ops pkcs15_cert_ops = { pkcs15_cert_release, pkcs15_cert_set_attribute, pkcs15_cert_get_attribute, pkcs15_cert_cmp_attribute, NULL, NULL, NULL};/* * PKCS#15 Private Key Object */void pkcs15_prkey_release(void *object){ __pkcs15_release_object((struct pkcs15_any_object *) object);}CK_RV pkcs15_prkey_set_attribute(struct sc_pkcs11_session *session, void *object, CK_ATTRIBUTE_PTR attr){ struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object*) object; return pkcs15_set_attrib(session, prkey->base.p15_object, attr);}CK_RV pkcs15_prkey_get_attribute(struct sc_pkcs11_session *session, void *object, CK_ATTRIBUTE_PTR attr){ struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object*) object; struct sc_pkcs15_pubkey *key = NULL; unsigned int usage; size_t len; if (prkey->prv_cert && prkey->prv_cert->cert_data) key = &prkey->prv_cert->cert_data->key; else if (prkey->prv_pubkey) key = prkey->prv_pubkey->pub_data; switch (attr->type) { case CKA_CLASS: check_attribute_buffer(attr, sizeof(CK_OBJECT_CLASS)); *(CK_OBJECT_CLASS*)attr->pValue = CKO_PRIVATE_KEY; break; case CKA_TOKEN: case CKA_LOCAL: case CKA_SENSITIVE: case CKA_ALWAYS_SENSITIVE: case CKA_NEVER_EXTRACTABLE: case CKA_PRIVATE: check_attribute_buffer(attr, sizeof(CK_BBOOL)); *(CK_BBOOL*)attr->pValue = TRUE; break; case CKA_MODIFIABLE: case CKA_EXTRACTABLE: check_attribute_buffer(attr, sizeof(CK_BBOOL)); *(CK_BBOOL*)attr->pValue = FALSE; break; case CKA_LABEL: len = strlen(prkey->prv_p15obj->label); check_attribute_buffer(attr, len); memcpy(attr->pValue, prkey->prv_p15obj->label, len); break; case CKA_KEY_TYPE: check_attribute_buffer(attr, sizeof(CK_KEY_TYPE)); *(CK_KEY_TYPE*)attr->pValue = CKK_RSA; break; case CKA_ID: check_attribute_buffer(attr, prkey->prv_info->id.len); memcpy(attr->pValue, prkey->prv_info->id.value, prkey->prv_info->id.len); break; case CKA_KEY_GEN_MECHANISM: check_attribute_buffer(attr, sizeof(CK_MECHANISM_TYPE)); *(CK_MECHANISM_TYPE*)attr->pValue = CK_UNAVAILABLE_INFORMATION; break; case CKA_ENCRYPT: case CKA_DECRYPT: case CKA_SIGN: case CKA_SIGN_RECOVER: case CKA_WRAP: case CKA_UNWRAP: case CKA_VERIFY: case CKA_VERIFY_RECOVER: case CKA_DERIVE: /* Combine the usage bits of all split keys */ for (usage = 0; prkey; prkey = prkey->prv_next) usage |= prkey->prv_info->usage; return get_usage_bit(usage, attr); case CKA_MODULUS: return get_modulus(key, attr); case CKA_MODULUS_BITS: check_attribute_buffer(attr, sizeof(CK_ULONG)); *(CK_ULONG *) attr->pValue = prkey->prv_info->modulus_length; return CKR_OK; case CKA_PUBLIC_EXPONENT: return get_public_exponent(key, attr); case CKA_PRIVATE_EXPONENT: case CKA_PRIME_1: case CKA_PRIME_2: case CKA_EXPONENT_1: case CKA_EXPONENT_2: case CKA_COEFFICIENT: return CKR_ATTRIBUTE_SENSITIVE; case CKA_SUBJECT: case CKA_START_DATE: case CKA_END_DATE: attr->ulValueLen = 0; return CKR_OK; default: return CKR_ATTRIBUTE_TYPE_INVALID; } return CKR_OK;}CK_RV pkcs15_prkey_sign(struct sc_pkcs11_session *ses, void *obj, CK_MECHANISM_PTR pMechanism, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulDataLen){ struct pkcs15_prkey_object *prkey = (struct pkcs15_prkey_object *) obj; struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) ses->slot->card->fw_data; struct pkcs15_slot_data *data = slot_data(ses->slot->fw_data); int rv, flags = 0; sc_debug(context, "Initiating signing operation, mechanism 0x%x.\n", pMechanism->mechanism); /* If this key requires user consent for every N operations, * we may have to present the PIN again and again. * For now, we require that either the terminal has a key pad, * or the user allows pin caching. We may want to add GUI * function pointers though. */ if (prkey->prv_p15obj->user_consent) { /* XXX we should really keep track how often the key * is used, and how often we need to ask the user for * her PIN. * For now, we just assume user_consent is 1. */ /* XXX - do we require an sc_lock here? */ rv = revalidate_pin(data, ses); if (rv < 0) return sc_to_cryptoki_error(rv, ses->slot->card->reader); } /* See which of the alternative keys supports signing */ while (prkey && !(prkey->prv_info->usage & (SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER| SC_PKCS15_PRKEY_USAGE_NONREPUDIATION))) prkey = prkey->prv_next; if (prkey == NULL) return CKR_KEY_FUNCTION_NOT_PERMITTED; switch (pMechanism->mechanism) { case CKM_RSA_PKCS: /* Um. We need to guess what netscape is trying to * sign here. We're lucky that all these things have * different sizes. */ flags = SC_ALGORITHM_RSA_PAD_PKCS1; switch (ulDataLen) { case 34:flags |= SC_ALGORITHM_RSA_HASH_MD5; /* MD5 + header */ pData += 18; ulDataLen -= 18; break; case 35: if (pData[7] == 0x24) flags |= SC_ALGORITHM_RSA_HASH_RIPEMD160; /* RIPEMD160 + hdr */ else flags |= SC_ALGORITHM_RSA_HASH_SHA1; /* SHA1 + hdr */ pData += 15; ulDataLen -= 15; break; case 36:flags |= SC_ALGORITHM_RSA_HASH_MD5_SHA1; /* SSL hash */ break; case 20: flags |= SC_ALGORITHM_RSA_HASH_SHA1; /* SHA1 */ break; case 16: flags |= SC_ALGORITHM_RSA_HASH_MD5; /* MD5 */ break; default: flags |= SC_ALGORITHM_RSA_HASH_NONE; } break; case CKM_MD5_RSA_PKCS: flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_MD5; break; case CKM_SHA1_RSA_PKCS: flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA1; break; case CKM_RIPEMD160_RSA_PKCS: flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_RIPEMD160; break; case CKM_RSA_X_509: flags = SC_ALGORITHM_RSA_RAW; break; default: return CKR_MECHANISM_INVALID; } sc_debug(context, "Selected flags %X. Now computing signature for %d bytes. %d bytes reserved.\n", flags, ulDataLen, *pulDataLen); rv = sc_pkcs15_compute_signature(fw_data->p15_card, prkey->prv_p15obj, flags, pData, ulDataLen, pSignature, *pulDataLen); /* Do we have to try a re-login and then try to sign again? */ if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) { /* Ensure that revalidate_pin() doesn't do a final sc_unlock() that would clear the card's current_path */ rv = sc_lock(ses->slot->card->card); if (rv < 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -