📄 framework-pkcs15.c
字号:
if (pool_is_present(&slot->object_pool, obj)) return; pool_insert(&slot->object_pool, obj, pHandle); obj->base.flags |= SC_PKCS11_OBJECT_SEEN; obj->refcount++; /* Add related objects * XXX prevent infinite recursion when a card specifies two certificates * referring to each other. */ obj->base.flags |= SC_PKCS11_OBJECT_RECURS; switch (__p15_type(obj)) { case SC_PKCS15_TYPE_PRKEY_RSA: if (obj->related_cert == NULL) pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_pubkey, NULL); pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_cert, NULL); break; case SC_PKCS15_TYPE_CERT_X509: pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_pubkey, NULL); pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_cert, NULL); break; } obj->base.flags &= ~SC_PKCS11_OBJECT_RECURS;}static void pkcs15_init_slot(struct sc_pkcs15_card *card, struct sc_pkcs11_slot *slot, struct sc_pkcs15_object *auth){ struct pkcs15_slot_data *fw_data; struct sc_pkcs15_pin_info *pin_info = NULL; char tmp[64]; pkcs15_init_token_info(card, &slot->token_info); slot->token_info.flags |= CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED; if (card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD) { slot->token_info.flags |= CKF_PROTECTED_AUTHENTICATION_PATH; sc_pkcs11_conf.cache_pins = 0; } if (card->card->caps & SC_CARD_CAP_RNG) slot->token_info.flags |= CKF_RNG; slot->fw_data = fw_data = (struct pkcs15_slot_data *) calloc(1, sizeof(*fw_data)); fw_data->auth_obj = auth; if (auth != NULL) { pin_info = (struct sc_pkcs15_pin_info*) auth->data; if (auth->label[0]) { snprintf(tmp, sizeof(tmp), "%s (%s)", card->label, auth->label); } else { snprintf(tmp, sizeof(tmp), "%s", card->label); } slot->token_info.flags |= CKF_LOGIN_REQUIRED; } else sprintf(tmp, card->label); strcpy_bp(slot->token_info.label, tmp, 32); if (pin_info && pin_info->magic == SC_PKCS15_PIN_MAGIC) { slot->token_info.ulMaxPinLen = pin_info->max_length; slot->token_info.ulMinPinLen = pin_info->min_length; } else { /* choose reasonable defaults */ slot->token_info.ulMaxPinLen = 8; slot->token_info.ulMinPinLen = 4; } sc_debug(context, "Initialized token '%s'\n", tmp);}static CK_RV pkcs15_create_slot(struct sc_pkcs11_card *p11card, struct sc_pkcs15_object *auth, struct sc_pkcs11_slot **out){ struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data; struct sc_pkcs11_slot *slot; int rv; rv = slot_allocate(&slot, p11card); if (rv != CKR_OK) return rv; /* There's a token in this slot */ slot->slot_info.flags |= CKF_TOKEN_PRESENT; /* Fill in the slot/token info from pkcs15 data */ pkcs15_init_slot(fw_data->p15_card, slot, auth); *out = slot; return CKR_OK;}static CK_RV pkcs15_create_tokens(struct sc_pkcs11_card *p11card){ struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data; struct sc_pkcs15_object *auths[MAX_OBJECTS]; struct sc_pkcs11_slot *slot; int i, rv, reader = p11card->reader; int auth_count; unsigned int j; rv = sc_pkcs15_get_objects(fw_data->p15_card, SC_PKCS15_TYPE_AUTH_PIN, auths, SC_PKCS15_MAX_PINS); if (rv < 0) return sc_to_cryptoki_error(rv, reader); sc_debug(context, "Found %d authentication objects\n", rv); auth_count = rv; rv = pkcs15_create_pkcs11_objects(fw_data, SC_PKCS15_TYPE_PRKEY_RSA, "private key", __pkcs15_create_prkey_object); if (rv < 0) return sc_to_cryptoki_error(rv, reader); rv = pkcs15_create_pkcs11_objects(fw_data, SC_PKCS15_TYPE_PUBKEY_RSA, "public key", __pkcs15_create_pubkey_object); if (rv < 0) return sc_to_cryptoki_error(rv, reader); rv = pkcs15_create_pkcs11_objects(fw_data, SC_PKCS15_TYPE_CERT_X509, "certificate", __pkcs15_create_cert_object); if (rv < 0) return sc_to_cryptoki_error(rv, reader); /* Match up related keys and certificates */ pkcs15_bind_related_objects(fw_data); for (i = 0; i < auth_count; i++) { struct sc_pkcs15_pin_info *pin_info = NULL; pin_info = (struct sc_pkcs15_pin_info*) auths[i]->data; /* Ignore any non-authentication PINs */ if ((pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) || (pin_info->flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN)) continue; /* Add all the private keys related to this pin */ rv = pkcs15_create_slot(p11card, auths[i], &slot); if (rv != CKR_OK) return rv; for (j=0; j < fw_data->num_objects; j++) { struct pkcs15_any_object *obj = fw_data->objects[j]; if (!is_privkey(obj) || !sc_pkcs15_compare_id(&pin_info->auth_id, &obj->p15_object->auth_id)) continue; sc_debug(context, "Adding private key %d to PIN %d\n", j, i); pkcs15_add_object(slot, obj, NULL); } } /* Add all public objects to a virtual slot without pin protection */ slot = NULL; /* Add all the remaining objects */ for (j = 0; j < fw_data->num_objects; j++) { struct pkcs15_any_object *obj = fw_data->objects[j]; if (!(obj->base.flags & SC_PKCS11_OBJECT_SEEN)) { sc_debug(context, "Object %d was not seen previously\n", j); if (!slot) { rv = pkcs15_create_slot(p11card, NULL, &slot); if (rv != CKR_OK) return rv; } pkcs15_add_object(slot, obj, NULL); } } /* Create read/write slots */ while (slot_allocate(&slot, p11card) == CKR_OK) { if (!sc_pkcs11_conf.hide_empty_tokens) { slot->slot_info.flags |= CKF_TOKEN_PRESENT; pkcs15_init_token_info(fw_data->p15_card, &slot->token_info); strcpy_bp(slot->token_info.label, fw_data->p15_card->label, 32); slot->token_info.flags |= CKF_TOKEN_INITIALIZED; } } sc_debug(context, "All tokens created\n"); return CKR_OK;}static CK_RV pkcs15_release_token(struct sc_pkcs11_card *p11card, void *fw_token){ unlock_card((struct pkcs15_fw_data *) p11card->fw_data); return CKR_OK;}static CK_RV pkcs15_login(struct sc_pkcs11_card *p11card, void *fw_token, CK_USER_TYPE userType, CK_CHAR_PTR pPin, CK_ULONG ulPinLen){ int rc; struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data; struct sc_pkcs15_card *card = fw_data->p15_card; struct sc_pkcs15_object *auth_object; struct sc_pkcs15_pin_info *pin; switch (userType) { case CKU_USER: auth_object = slot_data_auth(fw_token); if (auth_object == NULL) return CKR_USER_PIN_NOT_INITIALIZED; break; case CKU_SO: /* A card with no SO PIN is treated as if no SO login * is required */ rc = sc_pkcs15_find_so_pin(card, &auth_object); /* If there's no SO PIN on the card, silently * accept any PIN, and lock the card if required */ if (rc == SC_ERROR_OBJECT_NOT_FOUND && sc_pkcs11_conf.lock_login) rc = lock_card(fw_data); if (rc < 0) return sc_to_cryptoki_error(rc, p11card->reader); break; default: return CKR_USER_TYPE_INVALID; } pin = (struct sc_pkcs15_pin_info *) auth_object->data; if (p11card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD) { /* pPin should be NULL in case of a pin pad reader, but * some apps (e.g. older Netscapes) don't know about it. * So we don't require that pPin == NULL, but set it to * NULL ourselves. This way, you can supply an empty (if * possible) or fake PIN if an application asks a PIN). */ pPin = NULL; ulPinLen = 0; } else if (ulPinLen < pin->min_length || ulPinLen > pin->max_length) return CKR_ARGUMENTS_BAD; /* By default, we make the pcsc daemon keep other processes * from accessing the card while we're logged in. Otherwise * an attacker could perform some crypto operation after * we've authenticated with the card */ if (sc_pkcs11_conf.lock_login && (rc = lock_card(fw_data)) < 0) return sc_to_cryptoki_error(rc, p11card->reader); rc = sc_pkcs15_verify_pin(card, pin, pPin, ulPinLen); sc_debug(context, "PIN verification returned %d\n", rc); if (rc >= 0) cache_pin(fw_token, userType, pPin, ulPinLen); return sc_to_cryptoki_error(rc, p11card->reader);}static CK_RV pkcs15_logout(struct sc_pkcs11_card *p11card, void *fw_token){ struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data; int rc = 0; cache_pin(fw_token, CKU_SO, NULL, 0); cache_pin(fw_token, CKU_USER, NULL, 0); sc_logout(fw_data->p15_card->card); if (sc_pkcs11_conf.lock_login) rc = unlock_card(fw_data); return sc_to_cryptoki_error(rc, p11card->reader);}static CK_RV pkcs15_change_pin(struct sc_pkcs11_card *p11card, void *fw_token, CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen){ int rc; struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data; struct sc_pkcs15_pin_info *pin; if (!(pin = slot_data_pin_info(fw_token))) return CKR_USER_PIN_NOT_INITIALIZED; if (p11card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD) { /* pPin should be NULL in case of a pin pad reader, but * some apps (e.g. older Netscapes) don't know about it. * So we don't require that pPin == NULL, but set it to * NULL ourselves. This way, you can supply an empty (if * possible) or fake PIN if an application asks a PIN). */ pOldPin = pNewPin = NULL; ulOldLen = ulNewLen = 0; } else if (ulNewLen < pin->min_length || ulNewLen > pin->max_length) return CKR_PIN_LEN_RANGE; rc = sc_pkcs15_change_pin(fw_data->p15_card, pin, pOldPin, ulOldLen, pNewPin, ulNewLen); sc_debug(context, "PIN verification returned %d\n", rc); if (rc >= 0) cache_pin(fw_token, CKU_USER, pNewPin, ulNewLen); return sc_to_cryptoki_error(rc, p11card->reader);}#ifdef USE_PKCS15_INITstatic CK_RV pkcs15_init_pin(struct sc_pkcs11_card *p11card, struct sc_pkcs11_slot *slot, CK_CHAR_PTR pPin, CK_ULONG ulPinLen){ struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data; struct sc_pkcs15init_pinargs args; struct sc_profile *profile; struct sc_pkcs15_object *auth_obj; int rc; rc = sc_pkcs15init_bind(p11card->card, "pkcs15", NULL, &profile); if (rc < 0) return sc_to_cryptoki_error(rc, p11card->reader); memset(&args, 0, sizeof(args)); args.label = "User PIN"; args.pin = pPin; args.pin_len = ulPinLen; rc = sc_pkcs15init_store_pin(fw_data->p15_card, profile, &args); sc_pkcs15init_unbind(profile); if (rc < 0) return sc_to_cryptoki_error(rc, p11card->reader); rc = sc_pkcs15_find_pin_by_auth_id(fw_data->p15_card, &args.auth_id, &auth_obj); if (rc < 0) return sc_to_cryptoki_error(rc, p11card->reader); /* Re-initialize the slot */ free(slot->fw_data); pkcs15_init_slot(fw_data->p15_card, slot, auth_obj); cache_pin(slot->fw_data, CKU_USER, pPin, ulPinLen); return CKR_OK;}static CK_RV pkcs15_create_private_key(struct sc_pkcs11_card *p11card, struct sc_pkcs11_slot *slot, struct sc_profile *profile, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject){ struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data; struct sc_pkcs15init_prkeyargs args; struct pkcs15_any_object *key_any_obj; struct sc_pkcs15_object *key_obj; struct sc_pkcs15_pin_info *pin; CK_KEY_TYPE key_type; struct sc_pkcs15_prkey_rsa *rsa; int rc, rv; memset(&args, 0, sizeof(args)); /* See if the "slot" is pin protected. If so, get the * PIN id */ if ((pin = slot_data_pin_info(slot->fw_data)) != NULL) args.auth_id = pin->auth_id; /* Get the key type */ rv = attr_find(pTemplate, ulCount, CKA_KEY_TYPE, &key_type, NULL); if (rv != CKR_OK) return rv; if (key_type != CKK_RSA) return CKR_ATTRIBUTE_VALUE_INVALID; args.key.algorithm = SC_ALGORITHM_RSA; rsa = &args.key.u.rsa; rv = CKR_OK; while (ulCount--) { CK_ATTRIBUTE_PTR attr = pTemplate++; sc_pkcs15_bignum_t *bn = NULL; switch (attr->type) { /* Skip attrs we already know or don't care for */ case CKA_CLASS: case CKA_KEY_TYPE: case CKA_MODULUS_BITS: case CKA_PRIVATE: break; case CKA_LABEL: args.label = (char *) attr->pValue; break; case CKA_ID: args.id.len = sizeof(args.id.value); rv = attr_extract(attr, args.id.value, &args.id.len); if (rv != CKR_OK) goto out; break; case CKA_MODULUS: bn = &rsa->modulus; break; case CKA_PUBLIC_EXPONENT: bn = &rsa->exponent; break; case CKA_PRIVATE_EXPONENT: bn = &rsa->d; break; case CKA_PRIME_1: bn = &rsa->p; break; case CKA_PRIME_2: bn = &rsa->q; break; default: /* ignore unknown attrs, or flag error? */ continue; } if (bn) { if (attr->ulValueLen > 1024) return CKR_ATTRIBUTE_VALUE_INVALID; bn->len = attr->ulValueLen; bn->data = (u8 *) attr->pValue; } } if (!rsa->modulus.len || !rsa->exponent.len || !rsa->d.len || !rsa->p.len || !rsa->q.len) { rv = CKR_TEMPLATE_INCOMPLETE; goto out; } rc = sc_pkcs15init_store_private_key(fw_data->p15_card, profile, &args, &key_obj); if (rc < 0) { rv = sc_to_cryptoki_error(rc, p11card->reader); goto out; } /* Create a new pkcs11 object for it */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -