/* * Common code for generating or storing a private key. * If pubkey == NULL and prkey != NULL, we have to store a private key * In the oposite case, we have to generate a private key */ static int myeid_generate_store_key(sc_profile_t *profile, sc_card_t *card, unsigned int index, /* keynumber: 0 for 1st priv key, ... */ unsigned int keybits, sc_pkcs15_pubkey_t *pubkey, sc_pkcs15_prkey_t *prkey, sc_pkcs15_prkey_info_t *info) { struct sc_cardctl_myeid_gen_store_key_info args; int r; sc_file_t *prkf = NULL; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); /* Parameter check */ if ( (keybits < 1024) || (keybits > 2048) || (keybits & 0X7)) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unsupported key size [%u]: 1024-2048 bit + 8-multiple\n", keybits); return SC_ERROR_INVALID_ARGUMENTS; } /* Get the private key file */ r = myeid_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, index, &prkf); if (r < 0) goto done; /* Take enough room for a 1024 bit key */ if (prkf->size < 1024) prkf->size = 1024; /* Now create the key file */ r = sc_pkcs15init_create_file(profile, card, prkf); if (r < 0) goto done; /* Fill in data structure */ memset(&args, 0, sizeof(args)); args.mod_len = keybits; if (prkey == NULL) { args.op_type = OP_TYPE_GENERATE; args.pubexp_len = MYEID_DEFAULT_PUBKEY_LEN; args.pubexp = MYEID_DEFAULT_PUBKEY; } else { args.op_type = OP_TYPE_STORE; args.pubexp_len = prkey->u.rsa.exponent.len; args.pubexp = prkey->u.rsa.exponent.data; args.primep_len = prkey->u.rsa.p.len; args.primep = prkey->u.rsa.p.data; args.primeq_len = prkey->u.rsa.q.len; args.primeq = prkey->u.rsa.q.data; args.dp1_len = prkey->u.rsa.dmp1.len; args.dp1 = prkey->u.rsa.dmp1.data; args.dq1_len = prkey->u.rsa.dmq1.len; args.dq1 = prkey->u.rsa.dmq1.data; args.invq_len = prkey->u.rsa.iqmp.len; args.invq = prkey->u.rsa.iqmp.data; args.mod_len = prkey->u.rsa.modulus.len; args.mod = prkey->u.rsa.modulus.data; } /* Authenticate */ r = sc_pkcs15init_authenticate(profile, card, prkf, SC_AC_OP_UPDATE); if (r < 0) goto done; /* Generate/store rsa key */ r = sc_card_ctl(card, SC_CARDCTL_MYEID_GENERATE_KEY, &args); if (r < 0) goto done; info->key_reference = 0; info->path = prkf->path; done: if (prkf) sc_file_free(prkf); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); }
static int mcrd_init(sc_card_t * card) { unsigned long flags; struct mcrd_priv_data *priv; int r; sc_path_t tmppath; sc_apdu_t apdu; priv = calloc(1, sizeof *priv); if (!priv) return SC_ERROR_OUT_OF_MEMORY; card->drv_data = priv; card->cla = 0x00; card->caps = SC_CARD_CAP_RNG; if (is_esteid_card(card)) { /* Reset the MULTOS card to get to a known state */ if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V11) sc_reset(card, 0); /* Select the EstEID AID to get to a known state. * For some reason a reset is required as well... */ if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V30) { flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_SHA1 | SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA256; /* EstEID v3.0 has 2048 bit keys */ _sc_card_add_rsa_alg(card, 2048, flags, 0); sc_reset(card, 0); sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xA4, 0x04, 0x00); apdu.lc = sizeof(EstEID_v3_AID); apdu.data = EstEID_v3_AID; apdu.datalen = sizeof(EstEID_v3_AID); apdu.resplen = 0; apdu.le = 0; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "SELECT AID: %02X%02X", apdu.sw1, apdu.sw2); if(apdu.sw1 != 0x90 && apdu.sw2 != 0x00) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_CARD_CMD_FAILED); } else { /* EstEID v1.0 and 1.1 have 1024 bit keys */ flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA1; _sc_card_add_rsa_alg(card, 1024, flags, 0); } } else { flags = SC_ALGORITHM_RSA_RAW |SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE; _sc_card_add_rsa_alg(card, 512, flags, 0); _sc_card_add_rsa_alg(card, 768, flags, 0); _sc_card_add_rsa_alg(card, 1024, flags, 0); } priv->curpath[0] = MFID; priv->curpathlen = 1; sc_format_path ("3f00", &tmppath); sc_select_file (card, &tmppath, NULL); /* Not needed for the fixed EstEID profile */ if (!is_esteid_card(card)) load_special_files(card); return SC_SUCCESS; }
/* Process an ARR (7816-9/8.5.4) and setup the ACL. */ static void process_arr(sc_card_t * card, sc_file_t * file, const u8 * buf, size_t buflen) { sc_context_t *ctx = card->ctx; struct df_info_s *dfi; struct rule_record_s *rule; size_t left, taglen; unsigned int cla, tag; const u8 *p; int skip; char dbgbuf[2048]; /* Currently we support only the short for. */ if (buflen != 1) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "can't handle long ARRs\n"); return; } dfi = get_df_info(card); for (rule = dfi ? dfi->rule_file : NULL; rule && rule->recno != *buf; rule = rule->next) ; if (!rule) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "referenced EF_rule record %d not found\n", *buf); return; } sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, rule->data, rule->datalen, dbgbuf, sizeof dbgbuf); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "rule for record %d:\n%s", *buf, dbgbuf); p = rule->data; left = rule->datalen; skip = 1; /* Skip over initial unknown SC DOs. */ for (;;) { buf = p; if (sc_asn1_read_tag(&p, left, &cla, &tag, &taglen) != SC_SUCCESS) break; left -= (p - buf); tag |= cla; if (tag == 0x80 && taglen != 1) { skip = 1; } else if (tag == 0x80) { /* AM byte. */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " AM_DO: %02x\n", *p); skip = 0; } else if (tag >= 0x81 && tag <= 0x8f) { /* Cmd description */ sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, p, taglen, dbgbuf, sizeof dbgbuf); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " AM_DO: cmd[%s%s%s%s] %s", (tag & 8) ? "C" : "", (tag & 4) ? "I" : "", (tag & 2) ? "1" : "", (tag & 1) ? "2" : "", dbgbuf); skip = 0; } else if (tag == 0x9C) { /* Proprietary state machine descrip. */ skip = 1; } else if (!skip) { sc_hex_dump(ctx, SC_LOG_DEBUG_NORMAL, p, taglen, dbgbuf, sizeof dbgbuf); switch (tag) { case 0x90: /* Always */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " SC: always\n"); break; case 0x97: /* Never */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " SC: never\n"); break; case 0xA4: /* Authentication, value is a CRT. */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " SC: auth %s", dbgbuf); break; case 0xB4: case 0xB6: case 0xB8: /* Cmd or resp with SM, value is a CRT. */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " SC: cmd/resp %s", dbgbuf); break; case 0x9E: /* Security Condition byte. */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " SC: condition %s", dbgbuf); break; case 0xA0: /* OR template. */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " SC: OR\n"); break; case 0xAF: /* AND template. */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " SC: AND\n"); break; } } left -= taglen; p += taglen; } }
int sc_pkcs15_encode_pukdf_entry(sc_context_t *ctx, const struct sc_pkcs15_object *obj, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_com_key_attr[6], asn1_com_pubkey_attr[1]; struct sc_asn1_entry asn1_rsakey_value_choice[3]; struct sc_asn1_entry asn1_rsakey_attr[4], asn1_rsa_type_attr[2]; struct sc_asn1_entry asn1_dsakey_attr[2], asn1_dsa_type_attr[2]; struct sc_asn1_entry asn1_gostr3410key_attr[5], asn1_gostr3410_type_attr[2]; struct sc_asn1_entry asn1_pubkey_choice[4]; struct sc_asn1_entry asn1_pubkey[2]; struct sc_pkcs15_pubkey_info *pubkey = (struct sc_pkcs15_pubkey_info *) obj->data; struct sc_asn1_pkcs15_object rsakey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_rsa_type_attr }; struct sc_asn1_pkcs15_object dsakey_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_dsa_type_attr }; struct sc_asn1_pkcs15_object gostr3410key_obj = { (struct sc_pkcs15_object *) obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_gostr3410_type_attr }; struct sc_pkcs15_keyinfo_gostparams *keyinfo_gostparams; int r; size_t af_len, usage_len; sc_copy_asn1_entry(c_asn1_pubkey, asn1_pubkey); sc_copy_asn1_entry(c_asn1_pubkey_choice, asn1_pubkey_choice); sc_copy_asn1_entry(c_asn1_rsa_type_attr, asn1_rsa_type_attr); sc_copy_asn1_entry(c_asn1_rsakey_value_choice, asn1_rsakey_value_choice); sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr); sc_copy_asn1_entry(c_asn1_dsa_type_attr, asn1_dsa_type_attr); sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr); sc_copy_asn1_entry(c_asn1_gostr3410_type_attr, asn1_gostr3410_type_attr); sc_copy_asn1_entry(c_asn1_gostr3410key_attr, asn1_gostr3410key_attr); sc_copy_asn1_entry(c_asn1_com_pubkey_attr, asn1_com_pubkey_attr); sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr); switch (obj->type) { case SC_PKCS15_TYPE_PUBKEY_RSA: sc_format_asn1_entry(asn1_pubkey_choice + 0, &rsakey_obj, NULL, 1); sc_format_asn1_entry(asn1_rsa_type_attr + 0, asn1_rsakey_attr, NULL, 1); if (pubkey->path.len || !obj->content.value) sc_format_asn1_entry(asn1_rsakey_value_choice + 0, &pubkey->path, NULL, 1); else sc_format_asn1_entry(asn1_rsakey_value_choice + 1, obj->content.value, (void *)&obj->content.len, 1); sc_format_asn1_entry(asn1_rsakey_attr + 0, asn1_rsakey_value_choice, NULL, 1); sc_format_asn1_entry(asn1_rsakey_attr + 1, &pubkey->modulus_length, NULL, 1); break; case SC_PKCS15_TYPE_PUBKEY_DSA: sc_format_asn1_entry(asn1_pubkey_choice + 1, &dsakey_obj, NULL, 1); sc_format_asn1_entry(asn1_dsa_type_attr + 0, asn1_dsakey_attr, NULL, 1); sc_format_asn1_entry(asn1_dsakey_attr + 0, &pubkey->path, NULL, 1); break; case SC_PKCS15_TYPE_PUBKEY_GOSTR3410: sc_format_asn1_entry(asn1_pubkey_choice + 2, &gostr3410key_obj, NULL, 1); sc_format_asn1_entry(asn1_gostr3410_type_attr + 0, asn1_gostr3410key_attr, NULL, 1); sc_format_asn1_entry(asn1_gostr3410key_attr + 0, &pubkey->path, NULL, 1); if (pubkey->params.len == sizeof(*keyinfo_gostparams)) { keyinfo_gostparams = pubkey->params.data; sc_format_asn1_entry(asn1_gostr3410key_attr + 1, &keyinfo_gostparams->gostr3410, NULL, 1); sc_format_asn1_entry(asn1_gostr3410key_attr + 2, &keyinfo_gostparams->gostr3411, NULL, 1); sc_format_asn1_entry(asn1_gostr3410key_attr + 3, &keyinfo_gostparams->gost28147, NULL, 1); } break; default: /* TODO: -DEE Should add ECC but don't have PKCS15 card with ECC */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unsupported public key type: %X\n", obj->type); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INTERNAL); break; } sc_format_asn1_entry(asn1_com_key_attr + 0, &pubkey->id, NULL, 1); usage_len = sizeof(pubkey->usage); sc_format_asn1_entry(asn1_com_key_attr + 1, &pubkey->usage, &usage_len, 1); if (pubkey->native == 0) sc_format_asn1_entry(asn1_com_key_attr + 2, &pubkey->native, NULL, 1); if (pubkey->access_flags) { af_len = sizeof(pubkey->access_flags); sc_format_asn1_entry(asn1_com_key_attr + 3, &pubkey->access_flags, &af_len, 1); } if (pubkey->key_reference >= 0) sc_format_asn1_entry(asn1_com_key_attr + 4, &pubkey->key_reference, NULL, 1); sc_format_asn1_entry(asn1_pubkey + 0, asn1_pubkey_choice, NULL, 1); r = sc_asn1_encode(ctx, asn1_pubkey, buf, buflen); return r; }
/* * can be used as an SC_ASN1_CALLBACK while parsing a certificate, * or can be called from the sc_pkcs15_pubkey_from_spki_filename */ int sc_pkcs15_pubkey_from_spki(sc_context_t *ctx, sc_pkcs15_pubkey_t ** outpubkey, u8 *buf, size_t buflen, int depth) { int r; sc_pkcs15_pubkey_t * pubkey = NULL; sc_pkcs15_der_t pk = { NULL, 0 }; struct sc_algorithm_id pk_alg; struct sc_asn1_entry asn1_pkinfo[3]; struct sc_asn1_entry asn1_ec_pointQ[2]; sc_debug(ctx,SC_LOG_DEBUG_NORMAL,"sc_pkcs15_pubkey_from_spki %p:%d", buf, buflen); memset(&pk_alg, 0, sizeof(pk_alg)); pubkey = calloc(1, sizeof(sc_pkcs15_pubkey_t)); if (pubkey == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto err; } sc_copy_asn1_entry(c_asn1_pkinfo, asn1_pkinfo); sc_format_asn1_entry(asn1_pkinfo + 0, &pk_alg, NULL, 0); sc_format_asn1_entry(asn1_pkinfo + 1, &pk.value, &pk.len, 0); r = sc_asn1_decode(ctx, asn1_pkinfo, buf, buflen, NULL, NULL); if (r < 0) goto err; pubkey->alg_id = calloc(1, sizeof(struct sc_algorithm_id)); if (pubkey->alg_id == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto err; } memcpy(pubkey->alg_id, &pk_alg, sizeof(struct sc_algorithm_id)); pubkey->algorithm = pk_alg.algorithm; sc_debug(ctx,SC_LOG_DEBUG_NORMAL,"DEE pk_alg.algorithm=%d",pk_alg.algorithm); /* pk.len is in bits at this point */ switch (pk_alg.algorithm) { case SC_ALGORITHM_EC: /* * For most keys, the above ASN.1 parsing of a key works, but for EC keys, * the ec_pointQ in a certificate is stored in a bitstring, but * in PKCS#11 it is an octet string and we just decoded its * contents from the bitstring in the certificate. So we need to encode it * back to an octet string so we can store it as an octet string. */ pk.len >>= 3; /* Assume it is multiple of 8 */ // pubkey->u.ec.field_length = (pk.len - 1)/2 * 8; sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); sc_format_asn1_entry(&asn1_ec_pointQ[0], pk.value, &pk.len, 1); r = sc_asn1_encode(ctx, asn1_ec_pointQ, &pubkey->data.value, &pubkey->data.len); sc_debug(ctx,SC_LOG_DEBUG_NORMAL,"DEE r=%d data=%p:%d", r,pubkey->data.value, pubkey->data.len); break; default: pk.len >>= 3; /* convert number of bits to bytes */ pubkey->data = pk; /* save in publey */ pk.value = NULL; break; } /* Now decode what every is in pk as it depends on the key algorthim */ r = sc_pkcs15_decode_pubkey(ctx, pubkey, pubkey->data.value, pubkey->data.len); if (r < 0) goto err; *outpubkey = pubkey; pubkey = NULL; return 0; err: if (pubkey) free(pubkey); if (pk.value) free(pk.value); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "ASN.1 parsing of subjectPubkeyInfo failed"); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
/* Do the PIN command */ static int part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot, struct sc_pin_cmd_data *data) { struct pcsc_private_data *priv = GET_PRIV_DATA(reader); u8 rbuf[SC_MAX_APDU_BUFFER_SIZE], sbuf[SC_MAX_APDU_BUFFER_SIZE]; char dbuf[SC_MAX_APDU_BUFFER_SIZE * 3]; size_t rcount = sizeof(rbuf), scount = 0; int r; DWORD ioctl = 0; sc_apdu_t *apdu; struct pcsc_slot_data *pslot = (struct pcsc_slot_data *) slot->drv_data; SC_FUNC_CALLED(reader->ctx, 3); assert(pslot != NULL); if (priv->gpriv->SCardControl == NULL) return SC_ERROR_NOT_SUPPORTED; /* The APDU must be provided by the card driver */ if (!data->apdu) { sc_error(reader->ctx, "No APDU provided for PC/SC v2 pinpad verification!"); return SC_ERROR_NOT_SUPPORTED; } apdu = data->apdu; switch (data->cmd) { case SC_PIN_CMD_VERIFY: if (!(pslot->verify_ioctl || (pslot->verify_ioctl_start && pslot->verify_ioctl_finish))) { sc_error(reader->ctx, "Pinpad reader does not support verification!"); return SC_ERROR_NOT_SUPPORTED; } r = part10_build_verify_pin_block(sbuf, &scount, slot, data); ioctl = pslot->verify_ioctl ? pslot->verify_ioctl : pslot->verify_ioctl_start; break; case SC_PIN_CMD_CHANGE: case SC_PIN_CMD_UNBLOCK: if (!(pslot->modify_ioctl || (pslot->modify_ioctl_start && pslot->modify_ioctl_finish))) { sc_error(reader->ctx, "Pinpad reader does not support modification!"); return SC_ERROR_NOT_SUPPORTED; } r = part10_build_modify_pin_block(sbuf, &scount, slot, data); ioctl = pslot->modify_ioctl ? pslot->modify_ioctl : pslot->modify_ioctl_start; break; default: sc_error(reader->ctx, "Unknown PIN command %d", data->cmd); return SC_ERROR_NOT_SUPPORTED; } /* If PIN block building failed, we fail too */ SC_TEST_RET(reader->ctx, r, "PC/SC v2 pinpad block building failed!"); /* If not, debug it, just for fun */ sc_bin_to_hex(sbuf, scount, dbuf, sizeof(dbuf), ':'); sc_debug(reader->ctx, "PC/SC v2 pinpad block: %s", dbuf); r = pcsc_internal_transmit(reader, slot, sbuf, scount, rbuf, &rcount, ioctl); SC_TEST_RET(reader->ctx, r, "PC/SC v2 pinpad: block transmit failed!"); /* finish the call if it was a two-phase operation */ if ((ioctl == pslot->verify_ioctl_start) || (ioctl == pslot->modify_ioctl_start)) { if (rcount != 0) { SC_FUNC_RETURN(reader->ctx, 2, SC_ERROR_UNKNOWN_DATA_RECEIVED); } ioctl = (ioctl == pslot->verify_ioctl_start) ? pslot->verify_ioctl_finish : pslot->modify_ioctl_finish; rcount = sizeof(rbuf); r = pcsc_internal_transmit(reader, slot, sbuf, 0, rbuf, &rcount, ioctl); SC_TEST_RET(reader->ctx, r, "PC/SC v2 pinpad: finish operation failed!"); } /* We expect only two bytes of result data (SW1 and SW2) */ if (rcount != 2) { SC_FUNC_RETURN(reader->ctx, 2, SC_ERROR_UNKNOWN_DATA_RECEIVED); } /* Extract the SWs for the result APDU */ apdu->sw1 = (unsigned int) rbuf[rcount - 2]; apdu->sw2 = (unsigned int) rbuf[rcount - 1]; r = SC_SUCCESS; switch (((unsigned int) apdu->sw1 << 8) | apdu->sw2) { case 0x6400: /* Input timed out */ r = SC_ERROR_KEYPAD_TIMEOUT; break; case 0x6401: /* Input cancelled */ r = SC_ERROR_KEYPAD_CANCELLED; break; case 0x6402: /* PINs don't match */ r = SC_ERROR_KEYPAD_PIN_MISMATCH; break; case 0x6B80: /* Wrong data in the buffer, rejected by firmware */ r = SC_ERROR_READER; break; } SC_TEST_RET(reader->ctx, r, "PIN command failed"); /* PIN command completed, all is good */ return SC_SUCCESS; }
static int pcsc_detect_readers(sc_context_t *ctx, void *prv_data) { struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) prv_data; LONG rv; DWORD reader_buf_size; char *reader_buf = NULL, *reader_name; const char *mszGroups = NULL; int ret = SC_ERROR_INTERNAL; SC_FUNC_CALLED(ctx, 3); if (!gpriv) { ret = SC_ERROR_NO_READERS_FOUND; goto out; } sc_debug(ctx, "Probing pcsc readers"); do { if (gpriv->pcsc_ctx == -1) { /* * Cannot call SCardListReaders with -1 * context as in Windows ERROR_INVALID_HANDLE * is returned instead of SCARD_E_INVALID_HANDLE */ rv = SCARD_E_INVALID_HANDLE; } else { rv = gpriv->SCardListReaders(gpriv->pcsc_ctx, NULL, NULL, (LPDWORD) &reader_buf_size); } if (rv != SCARD_S_SUCCESS) { if (rv != SCARD_E_INVALID_HANDLE) { PCSC_ERROR(ctx, "SCardListReaders failed", rv); ret = pcsc_ret_to_error(rv); goto out; } sc_debug(ctx, "Establish pcsc context"); rv = gpriv->SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &gpriv->pcsc_ctx); if (rv != SCARD_S_SUCCESS) { PCSC_ERROR(ctx, "SCardEstablishContext failed", rv); ret = pcsc_ret_to_error(rv); goto out; } rv = SCARD_E_INVALID_HANDLE; } } while (rv != SCARD_S_SUCCESS); reader_buf = (char *) malloc(sizeof(char) * reader_buf_size); if (!reader_buf) { ret = SC_ERROR_OUT_OF_MEMORY; goto out; } rv = gpriv->SCardListReaders(gpriv->pcsc_ctx, mszGroups, reader_buf, (LPDWORD) &reader_buf_size); if (rv != SCARD_S_SUCCESS) { PCSC_ERROR(ctx, "SCardListReaders failed", rv); ret = pcsc_ret_to_error(rv); goto out; } for (reader_name = reader_buf; *reader_name != '\x0'; reader_name += strlen (reader_name) + 1) { sc_reader_t *reader = NULL; struct pcsc_private_data *priv = NULL; struct pcsc_slot_data *pslot = NULL; sc_slot_info_t *slot = NULL; unsigned int i; int found = 0; for (i=0;i < sc_ctx_get_reader_count (ctx) && !found;i++) { sc_reader_t *reader2 = sc_ctx_get_reader (ctx, i); if (reader2 == NULL) { ret = SC_ERROR_INTERNAL; goto err1; } if (reader2->ops == &pcsc_ops && !strcmp (reader2->name, reader_name)) { found = 1; } } /* Reader already available, skip */ if (found) { continue; } sc_debug(ctx, "Found new pcsc reader '%s'", reader_name); if ((reader = (sc_reader_t *) calloc(1, sizeof(sc_reader_t))) == NULL) { ret = SC_ERROR_OUT_OF_MEMORY; goto err1; } if ((priv = (struct pcsc_private_data *) malloc(sizeof(struct pcsc_private_data))) == NULL) { ret = SC_ERROR_OUT_OF_MEMORY; goto err1; } if ((pslot = (struct pcsc_slot_data *) malloc(sizeof(struct pcsc_slot_data))) == NULL) { ret = SC_ERROR_OUT_OF_MEMORY; goto err1; } reader->drv_data = priv; reader->ops = &pcsc_ops; reader->driver = &pcsc_drv; reader->slot_count = 1; if ((reader->name = strdup(reader_name)) == NULL) { ret = SC_ERROR_OUT_OF_MEMORY; goto err1; } priv->gpriv = gpriv; if ((priv->reader_name = strdup(reader_name)) == NULL) { ret = SC_ERROR_OUT_OF_MEMORY; goto err1; } slot = &reader->slot[0]; memset(slot, 0, sizeof(*slot)); slot->drv_data = pslot; memset(pslot, 0, sizeof(*pslot)); if (_sc_add_reader(ctx, reader)) { ret = SC_SUCCESS; /* silent ignore */ goto err1; } refresh_slot_attributes(reader, slot); continue; err1: if (priv != NULL) { if (priv->reader_name) free(priv->reader_name); free(priv); } if (reader != NULL) { if (reader->name) free(reader->name); free(reader); } if (slot != NULL) free(pslot); goto out; } ret = SC_SUCCESS; out: if (reader_buf != NULL) free (reader_buf); SC_FUNC_RETURN(ctx, 3, ret); }
/* * Store a PIN or PUK */ static int cardos_store_pin(sc_profile_t *profile, sc_card_t *card, sc_pkcs15_pin_info_t *pin_info, int puk_id, const u8 *pin, size_t pin_len) { struct sc_cardctl_cardos_obj_info args; unsigned char buffer[256]; unsigned char pinpadded[256]; struct tlv tlv; unsigned int attempts, minlen, maxlen; int r; /* We need to do padding because pkcs15-lib.c does it. * Would be nice to have a flag in the profile that says * "no padding required". */ maxlen = MIN(profile->pin_maxlen, sizeof(pinpadded)); if (pin_len > maxlen) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "invalid pin length: %u (max %u)\n", pin_len, maxlen); return SC_ERROR_INVALID_ARGUMENTS; } memcpy(pinpadded, pin, pin_len); while (pin_len < maxlen) pinpadded[pin_len++] = profile->pin_pad_char; pin = pinpadded; attempts = pin_info->tries_left; minlen = pin_info->min_length; tlv_init(&tlv, buffer, sizeof(buffer)); /* object address: class, id */ tlv_next(&tlv, 0x83); tlv_add(&tlv, 0x00); /* class byte: usage TEST, k=0 */ tlv_add(&tlv, pin_info->reference); /* parameters */ tlv_next(&tlv, 0x85); tlv_add(&tlv, 0x02); /* options byte */ tlv_add(&tlv, attempts & 0xf); /* flags byte */ tlv_add(&tlv, CARDOS_ALGO_PIN); /* algorithm = pin-test */ tlv_add(&tlv, attempts & 0xf); /* errcount = attempts */ /* usecount: not documented, but seems to work like this: * - value of 0xff means pin can be presented any number * of times * - anything less: max # of times before BS object is blocked. */ tlv_add(&tlv, 0xff); /* DEK: not documented, no idea what it means */ tlv_add(&tlv, 0xff); /* ARA counter: number of times the test object can be used before * another verification is required (~ user consent) * (0x00 unlimited usage) */ tlv_add(&tlv, 0x00); tlv_add(&tlv, minlen); /* minlen */ /* AC conditions */ tlv_next(&tlv, 0x86); tlv_add(&tlv, 0x00); /* use: always */ tlv_add(&tlv, pin_info->reference); /* change: PIN */ tlv_add(&tlv, puk_id); /* unblock: PUK */ /* data: PIN */ tlv_next(&tlv, 0x8f); while (pin_len--) tlv_add(&tlv, *pin++); args.data = buffer; args.len = tlv_len(&tlv); /* ensure we are in the correct lifecycle */ r = sc_pkcs15init_set_lifecycle(card, SC_CARDCTRL_LIFECYCLE_ADMIN); if (r < 0 && r != SC_ERROR_NOT_SUPPORTED) return r; return sc_card_ctl(card, SC_CARDCTL_CARDOS_PUT_DATA_OCI, &args); }
static void _use_item(struct game* self, struct gate_client* c, struct UM_BASE* um) { struct player* p; struct room* ro; struct member* me; if (_locate_player(self, c, &p, &ro, &me)) return; UM_CAST(UM_USEITEM, useitem, um); const struct item_tplt* titem = _get_item_tplt(self, useitem->itemid); if (titem == NULL) { sc_debug("not found use item: %u", useitem->itemid); return; } const struct item_tplt* oriitem = titem; const struct map_tplt* tmap = _maptplt(ro->gattri.mapid); if (tmap == NULL) { return; } switch (titem->type) { case ITEM_T_OXYGEN: me->noxygenitem += 1; break; case ITEM_T_FIGHT: if (titem->subtype == 0) { titem = _rand_fightitem(self, tmap); if (titem == NULL) { return; } me->nitem += 1; } break; case ITEM_T_TRAP: if (titem->subtype == 0) { titem = _rand_trapitem(self, tmap); if (titem == NULL) { return; } } break; case ITEM_T_BAO: { uint32_t baoid = _rand_baoitem(self, titem, tmap); if (baoid > 0) { me->nbao += 1; } } break; } struct member* tars[MEMBER_MAX]; int ntar = _get_effect_members(ro, me, titem->target, tars); if (ntar <= 0) { return; } int delay = titem->delay + titem->uptime; if (delay > 0) { _item_delay(self, ro, me, titem, delay); } else { struct member* onetar; int i; for (i=0; i<ntar; ++i) { onetar = tars[i]; _item_effect_member(self, ro, onetar, titem, 0); } } UM_DEFFIX(UM_ITEMEFFECT, ie); ie->spellid = me->detail.charid; ie->oriitem = oriitem->id; ie->itemid = titem->id; struct member* onetar; int i; for (i=0; i<ntar; ++i) { onetar = tars[i]; ie->charid = onetar->detail.charid; _multicast_msg(ro, (void*)ie, 0); } }
int npa_translate_apdus(sc_card_t *card, FILE *input) { u8 buf[4 + 3 + 0xffff + 3]; char *read = NULL; size_t readlen = 0, apdulen; sc_apdu_t apdu; ssize_t linelen; int r; memset(&apdu, 0, sizeof apdu); while (1) { if (input == stdin) printf("Enter unencrypted C-APDU (empty line to exit)\n"); linelen = getline(&read, &readlen, input); if (linelen <= 1) { if (linelen < 0) { r = SC_ERROR_INTERNAL; sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE_TOOL, "Could not read line"); } else { r = SC_SUCCESS; printf("Thanks for flying with ccid\n"); } break; } read[linelen - 1] = 0; apdulen = sizeof buf; if (sc_hex_to_bin(read, buf, &apdulen) < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE_TOOL, "Could not format binary string"); continue; } if (input != stdin) bin_print(stdout, "Unencrypted C-APDU", buf, apdulen); r = sc_bytes2apdu(card->ctx, buf, apdulen, &apdu); if (r < 0) { bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Invalid C-APDU", buf, apdulen); continue; } apdu.resp = buf; apdu.resplen = sizeof buf; r = sc_transmit_apdu(card, &apdu); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE_TOOL, "Could not send C-APDU: %s", sc_strerror(r)); continue; } printf("Decrypted R-APDU sw1=%02x sw2=%02x\n", apdu.sw1, apdu.sw2); bin_print(stdout, "Decrypted R-APDU response data", apdu.resp, apdu.resplen); printf("======================================================================\n"); } if (read) free(read); return r; }
/* * Key generation */ static int cardos_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj, sc_pkcs15_pubkey_t *pubkey) { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_prkey_info *key_info = (sc_pkcs15_prkey_info_t *) obj->data; struct sc_pkcs15_prkey_rsa key_obj; struct sc_cardctl_cardos_genkey_info args; struct sc_file *temp; u8 abignum[256]; int algorithm = 0, r, delete_it = 0, use_ext_rsa = 0; size_t keybits, rsa_max_size; int pin_id = -1; if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) return SC_ERROR_NOT_SUPPORTED; rsa_max_size = (p15card->card->caps & SC_CARD_CAP_RSA_2048) ? 2048 : 1024; keybits = key_info->modulus_length & ~7UL; if (keybits > rsa_max_size) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Unable to generate key, max size is %lu", (unsigned long) rsa_max_size); return SC_ERROR_INVALID_ARGUMENTS; } if (keybits > 1024) use_ext_rsa = 1; if (cardos_key_algorithm(key_info->usage, keybits, &algorithm) < 0) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "CardOS does not support keys " "that can both sign _and_ decrypt."); return SC_ERROR_NOT_SUPPORTED; } if (sc_profile_get_file(profile, "tempfile", &temp) < 0) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Profile doesn't define temporary file " "for key generation."); return SC_ERROR_NOT_SUPPORTED; } pin_id = sc_pkcs15init_get_pin_reference(p15card, profile, SC_AC_SYMBOLIC, SC_PKCS15INIT_USER_PIN); if (pin_id >= 0) { r = sc_pkcs15init_verify_secret(profile, p15card, NULL, SC_AC_CHV, pin_id); if (r < 0) return r; } if (use_ext_rsa == 0) temp->ef_structure = SC_FILE_EF_LINEAR_VARIABLE_TLV; else temp->ef_structure = SC_FILE_EF_TRANSPARENT; if ((r = sc_pkcs15init_create_file(profile, p15card, temp)) < 0) goto out; delete_it = 1; init_key_object(&key_obj, abignum, keybits >> 3); r = cardos_put_key(profile, p15card, algorithm, key_info, &key_obj); if (r < 0) goto out; memset(&args, 0, sizeof(args)); args.key_id = key_info->key_reference; args.key_bits = keybits; args.fid = temp->id; r = sc_card_ctl(p15card->card, SC_CARDCTL_CARDOS_GENERATE_KEY, &args); if (r < 0) goto out; r = cardos_extract_pubkey(p15card->card, pubkey, temp, use_ext_rsa); out: if (delete_it != 0) sc_pkcs15init_rmdir(p15card, profile, temp); sc_file_free(temp); if (r < 0) { if (pubkey->u.rsa.modulus.data) free (pubkey->u.rsa.modulus.data); if (pubkey->u.rsa.exponent.data) free (pubkey->u.rsa.exponent.data); } return r; }
static int match_atr_table(sc_context_t *ctx, struct sc_atr_table *table, struct sc_atr *atr) { u8 *card_atr_bin = atr->value; size_t card_atr_bin_len = atr->len; char card_atr_hex[3 * SC_MAX_ATR_SIZE]; size_t card_atr_hex_len; unsigned int i = 0; if (ctx == NULL || table == NULL || atr == NULL) return -1; sc_bin_to_hex(card_atr_bin, card_atr_bin_len, card_atr_hex, sizeof(card_atr_hex), ':'); card_atr_hex_len = strlen(card_atr_hex); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "ATR : %s", card_atr_hex); for (i = 0; table[i].atr != NULL; i++) { const char *tatr = table[i].atr; const char *matr = table[i].atrmask; size_t tatr_len = strlen(tatr); u8 mbin[SC_MAX_ATR_SIZE], tbin[SC_MAX_ATR_SIZE]; size_t mbin_len, tbin_len, s, matr_len; size_t fix_hex_len = card_atr_hex_len; size_t fix_bin_len = card_atr_bin_len; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "ATR try : %s", tatr); if (tatr_len != fix_hex_len) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "ignored - wrong length"); continue; } if (matr != NULL) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "ATR mask: %s", matr); matr_len = strlen(matr); if (tatr_len != matr_len) continue; tbin_len = sizeof(tbin); sc_hex_to_bin(tatr, tbin, &tbin_len); mbin_len = sizeof(mbin); sc_hex_to_bin(matr, mbin, &mbin_len); if (mbin_len != fix_bin_len) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "length of atr and atr mask do not match - ignored: %s - %s", tatr, matr); continue; } for (s = 0; s < tbin_len; s++) { /* reduce tatr with mask */ tbin[s] = (tbin[s] & mbin[s]); /* create copy of card_atr_bin masked) */ mbin[s] = (card_atr_bin[s] & mbin[s]); } if (memcmp(tbin, mbin, tbin_len) != 0) continue; } else { if (strncasecmp(tatr, card_atr_hex, tatr_len) != 0) continue; } return i; } return -1; }
int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out) { sc_card_t *card; sc_context_t *ctx; struct sc_card_driver *driver; int i, r = 0, idx, connected = 0; if (card_out == NULL || reader == NULL) return SC_ERROR_INVALID_ARGUMENTS; ctx = reader->ctx; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (reader->ops->connect == NULL) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED); card = sc_card_new(ctx); if (card == NULL) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY); r = reader->ops->connect(reader); if (r) goto err; connected = 1; card->reader = reader; card->ctx = ctx; memcpy(&card->atr, &reader->atr, sizeof(card->atr)); _sc_parse_atr(reader); /* See if the ATR matches any ATR specified in the config file */ if ((driver = ctx->forced_driver) == NULL) { sc_debug(ctx, SC_LOG_DEBUG_MATCH, "matching configured ATRs"); for (i = 0; ctx->card_drivers[i] != NULL; i++) { driver = ctx->card_drivers[i]; if (driver->atr_map == NULL || !strcmp(driver->short_name, "default")) { driver = NULL; continue; } sc_debug(ctx, SC_LOG_DEBUG_MATCH, "trying driver: %s", driver->short_name); idx = _sc_match_atr(card, driver->atr_map, NULL); if (idx >= 0) { struct sc_atr_table *src = &driver->atr_map[idx]; sc_debug(ctx, SC_LOG_DEBUG_MATCH, "matched: %s", driver->name); /* It's up to card driver to notice these correctly */ card->name = src->name; card->type = src->type; card->flags = src->flags; break; } driver = NULL; } } if (driver != NULL) { /* Forced driver, or matched via ATR mapping from * config file */ card->driver = driver; memcpy(card->ops, card->driver->ops, sizeof(struct sc_card_operations)); if (card->ops->init != NULL) { r = card->ops->init(card); if (r) { sc_debug(ctx, SC_LOG_DEBUG_MATCH, "driver '%s' init() failed: %s", card->driver->name, sc_strerror(r)); goto err; } } } else { sc_debug(ctx, SC_LOG_DEBUG_MATCH, "matching built-in ATRs"); for (i = 0; ctx->card_drivers[i] != NULL; i++) { struct sc_card_driver *drv = ctx->card_drivers[i]; const struct sc_card_operations *ops = drv->ops; sc_debug(ctx, SC_LOG_DEBUG_MATCH, "trying driver: %s", drv->short_name); if (ops == NULL || ops->match_card == NULL) continue; /* Needed if match_card() needs to talk with the card (e.g. card-muscle) */ *card->ops = *ops; if (ops->match_card(card) != 1) continue; sc_debug(ctx, SC_LOG_DEBUG_MATCH, "matched: %s", drv->name); memcpy(card->ops, ops, sizeof(struct sc_card_operations)); card->driver = drv; r = ops->init(card); if (r) { sc_debug(ctx, SC_LOG_DEBUG_MATCH, "driver '%s' init() failed: %s", drv->name, sc_strerror(r)); if (r == SC_ERROR_INVALID_CARD) { card->driver = NULL; continue; } goto err; } break; } } if (card->driver == NULL) { sc_debug(ctx, SC_LOG_DEBUG_MATCH, "unable to find driver for inserted card"); r = SC_ERROR_INVALID_CARD; goto err; } if (card->name == NULL) card->name = card->driver->name; *card_out = card; /* Override card limitations with reader limitations. * Note that zero means no limitations at all. */ if ((card->max_recv_size == 0) || ((reader->driver->max_recv_size != 0) && (reader->driver->max_recv_size < card->max_recv_size))) { card->max_recv_size = reader->driver->max_recv_size; } if ((card->max_send_size == 0) || ((reader->driver->max_send_size != 0) && (reader->driver->max_send_size < card->max_send_size))) { card->max_send_size = reader->driver->max_send_size; } sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "card info name:'%s', type:%i, flags:0x%X, max_send/recv_size:%i/%i", card->name, card->type, card->flags, card->max_send_size, card->max_recv_size); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, 0); err: if (connected) reader->ops->disconnect(reader); if (card != NULL) sc_card_free(card); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
static int myeid_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object, struct sc_pkcs15_pubkey *pubkey) { struct sc_context *ctx = p15card->card->ctx; struct sc_card *card = p15card->card; struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data; struct sc_cardctl_myeid_gen_store_key_info args; struct sc_file *file = NULL; int r; size_t keybits = key_info->modulus_length; unsigned char raw_pubkey[256]; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (object->type != SC_PKCS15_TYPE_PRKEY_RSA) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED, "Store key failed: RSA only supported"); /* Check that the card supports the requested modulus length */ if (sc_card_find_rsa_alg(p15card->card, keybits) == NULL) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS, "Unsupported key size"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "store MyEID key with ID:%s and path:%s", sc_pkcs15_print_id(&key_info->id), sc_print_path(&key_info->path)); r = sc_select_file(card, &key_info->path, &file); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot store MyEID key: select key file failed"); r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_GENERATE); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "No authorisation to generate MyEID private key"); /* Fill in data structure */ memset(&args, 0, sizeof(args)); args.mod_len = keybits; args.op_type = OP_TYPE_GENERATE; args.pubexp_len = MYEID_DEFAULT_PUBKEY_LEN; args.pubexp = MYEID_DEFAULT_PUBKEY; /* Generate RSA key */ r = sc_card_ctl(card, SC_CARDCTL_MYEID_GENERATE_STORE_KEY, &args); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Card control 'MYEID_GENERATE_STORE_KEY' failed"); /* Keypair generation -> collect public key info */ /* FIXME: was not preset in original Aventra version. Need to be tested. (VT) */ if (pubkey != NULL) { struct sc_cardctl_myeid_data_obj data_obj; pubkey->algorithm = SC_ALGORITHM_RSA; pubkey->u.rsa.modulus.len = (keybits + 7) / 8; pubkey->u.rsa.modulus.data = malloc(pubkey->u.rsa.modulus.len); pubkey->u.rsa.exponent.len = MYEID_DEFAULT_PUBKEY_LEN; pubkey->u.rsa.exponent.data = malloc(MYEID_DEFAULT_PUBKEY_LEN); memcpy(pubkey->u.rsa.exponent.data, MYEID_DEFAULT_PUBKEY, MYEID_DEFAULT_PUBKEY_LEN); /* Get public key modulus */ r = sc_select_file(card, &file->path, NULL); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot get key modulus: select key file failed"); data_obj.P1 = 0x01; data_obj.P2 = 0x01; data_obj.Data = raw_pubkey; data_obj.DataLen = sizeof(raw_pubkey); r = sc_card_ctl(card, SC_CARDCTL_MYEID_GETDATA, &data_obj); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot get key modulus: 'MYEID_GETDATA' failed"); if ((data_obj.DataLen * 8) != key_info->modulus_length) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_PKCS15INIT, "Cannot get key modulus: invalid key-size"); memcpy (pubkey->u.rsa.modulus.data, raw_pubkey, pubkey->u.rsa.modulus.len); } if (file) sc_file_free(file); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
int sc_context_create(sc_context_t **ctx_out, const sc_context_param_t *parm) { sc_context_t *ctx; struct _sc_ctx_options opts; int r; if (ctx_out == NULL || parm == NULL) return SC_ERROR_INVALID_ARGUMENTS; ctx = calloc(1, sizeof(sc_context_t)); if (ctx == NULL) return SC_ERROR_OUT_OF_MEMORY; memset(&opts, 0, sizeof(opts)); /* set the application name if set in the parameter options */ if (parm->app_name != NULL) ctx->app_name = strdup(parm->app_name); else ctx->app_name = strdup("default"); if (ctx->app_name == NULL) { sc_release_context(ctx); return SC_ERROR_OUT_OF_MEMORY; } set_defaults(ctx, &opts); list_init(&ctx->readers); list_attributes_seeker(&ctx->readers, reader_list_seeker); /* set thread context and create mutex object (if specified) */ if (parm->thread_ctx != NULL) ctx->thread_ctx = parm->thread_ctx; r = sc_mutex_create(ctx, &ctx->mutex); if (r != SC_SUCCESS) { sc_release_context(ctx); return r; } process_config_file(ctx, &opts); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "==================================="); /* first thing in the log */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "opensc version: %s", sc_get_version()); #ifdef HAVE_LTDL_H /* initialize ltdl, if available. See scdl.c for more information */ if (lt_dlinit() != 0) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "lt_dlinit() failed"); sc_release_context(ctx); return SC_ERROR_INTERNAL; } #endif #ifdef ENABLE_PCSC ctx->reader_driver = sc_get_pcsc_driver(); /* XXX: remove cardmod pseudoreader driver */ #ifdef ENABLE_MINIDRIVER if(strcmp(ctx->app_name, "cardmod") == 0) { ctx->reader_driver = sc_get_cardmod_driver(); } #endif #elif ENABLE_CTAPI ctx->reader_driver = sc_get_ctapi_driver(); #elif ENABLE_OPENCT ctx->reader_driver = sc_get_openct_driver(); #endif load_reader_driver_options(ctx); ctx->reader_driver->ops->init(ctx); load_card_drivers(ctx, &opts); load_card_atrs(ctx); if (opts.forced_card_driver) { /* FIXME: check return value? */ sc_set_card_driver(ctx, opts.forced_card_driver); free(opts.forced_card_driver); } del_drvs(&opts); sc_ctx_detect_readers(ctx); *ctx_out = ctx; return SC_SUCCESS; }
static int sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path, unsigned char **out, size_t *out_len, int verify_pin) { struct sc_context *ctx = p15card->card->ctx; struct sc_card *card = p15card->card; struct sc_file *file = NULL; struct sc_path path; size_t sz; int rv; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (!in_path || !out || !out_len) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS, "Cannot read oberthur file"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "read file '%s'; verify_pin:%i", in_path, verify_pin); *out = NULL; *out_len = 0; sc_format_path(in_path, &path); rv = sc_select_file(card, &path, &file); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "Cannot select oberthur file to read"); if (file->ef_structure == SC_FILE_EF_TRANSPARENT) sz = file->size; else sz = (file->record_length + 2) * file->record_count; *out = calloc(sz, 1); if (*out == NULL) SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_MEMORY_FAILURE, "Cannot read oberthur file"); if (file->ef_structure == SC_FILE_EF_TRANSPARENT) { rv = sc_read_binary(card, 0, *out, sz, 0); } else { int rec; int offs = 0; int rec_len = file->record_length; for (rec = 1; ; rec++) { rv = sc_read_record(card, rec, *out + offs + 2, rec_len, SC_RECORD_BY_REC_NR); if (rv == SC_ERROR_RECORD_NOT_FOUND) { rv = 0; break; } else if (rv < 0) { break; } rec_len = rv; *(*out + offs) = 'R'; *(*out + offs + 1) = rv; offs += rv + 2; } sz = offs; } sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "read oberthur file result %i", rv); if (verify_pin && rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) { struct sc_pkcs15_object *objs[0x10], *pin_obj = NULL; const struct sc_acl_entry *acl = sc_file_get_acl_entry(file, SC_AC_OP_READ); int ii; rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 0x10); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "Cannot read oberthur file: get AUTH objects error"); for (ii=0; ii<rv; ii++) { struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *) objs[ii]->data; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "compare PIN/ACL refs:%i/%i, method:%i/%i", auth_info->attrs.pin.reference, acl->key_ref, auth_info->auth_method, acl->method); if (auth_info->attrs.pin.reference == (int)acl->key_ref && auth_info->auth_method == (unsigned)acl->method) { pin_obj = objs[ii]; break; } } if (!pin_obj || !pin_obj->content.value) { rv = SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; } else { rv = sc_pkcs15_verify_pin(p15card, pin_obj, pin_obj->content.value, pin_obj->content.len); if (!rv) rv = sc_oberthur_read_file(p15card, in_path, out, out_len, 0); } }; sc_file_free(file); if (rv < 0) { free(*out); *out = NULL; *out_len = 0; } *out_len = sz; SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, rv); }
/* * Allocate a file */ static int miocos_new_file(struct sc_profile *profile, sc_card_t *card, unsigned int type, unsigned int num, sc_file_t **out) { struct sc_file *file; struct sc_path *p; char name[64]; const char *tag = NULL, *desc = NULL; while (1) { switch (type) { case SC_PKCS15_TYPE_PRKEY_RSA: desc = "RSA private key"; tag = "private-key"; break; case SC_PKCS15_TYPE_PUBKEY_RSA: desc = "RSA public key"; tag = "public-key"; break; case SC_PKCS15_TYPE_PRKEY: desc = "extractable private key"; tag = "extractable-key"; break; case SC_PKCS15_TYPE_CERT: desc = "certificate"; tag = "certificate"; break; case SC_PKCS15_TYPE_DATA_OBJECT: desc = "data object"; tag = "data"; break; } if (tag) break; /* If this is a specific type such as * SC_PKCS15_TYPE_CERT_FOOBAR, fall back to * the generic class (SC_PKCS15_TYPE_CERT) */ if (!(type & ~SC_PKCS15_TYPE_CLASS_MASK)) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "File type not supported by card driver"); return SC_ERROR_INVALID_ARGUMENTS; } type &= SC_PKCS15_TYPE_CLASS_MASK; } _snprintf(name, sizeof(name), "template-%s", tag); if (sc_profile_get_file(profile, name, &file) < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Profile doesn't define %s template (%s)", desc, name); return SC_ERROR_NOT_SUPPORTED; } /* Now construct file from template */ file->id += num; p = &file->path; *p = profile->df_info->file->path; p->value[p->len++] = file->id >> 8; p->value[p->len++] = file->id; *out = file; return 0; }
static int sc_oberthur_parse_privateinfo (struct sc_pkcs15_card *p15card, unsigned char *buff, size_t len, int postpone_allowed) { struct sc_context *ctx = p15card->card->ctx; size_t ii; int rv; int no_more_private_keys = 0, no_more_private_data = 0; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); for (ii=0; ii<len; ii+=5) { unsigned int file_id, size; if(*(buff+ii) != 0xFF) continue; file_id = 0x100 * *(buff+ii + 1) + *(buff+ii + 2); size = 0x100 * *(buff+ii + 3) + *(buff+ii + 4); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "add private object (file-id:%04X, size:%X)", file_id, size); switch (*(buff+ii + 1)) { case BASE_ID_PRV_RSA : if (no_more_private_keys) break; rv = sc_pkcs15emu_oberthur_add_prvkey(p15card, file_id, size); if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED && postpone_allowed) { struct sc_path path; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "postpone adding of the private keys"); sc_format_path("5011A5A5", &path); rv = sc_pkcs15_add_df(p15card, SC_PKCS15_PRKDF, &path); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Add PrkDF error"); no_more_private_keys = 1; } SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Cannot parse private key info"); break; case BASE_ID_PRV_DES : break; case BASE_ID_PRV_DATA : sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "*(buff+ii + 1):%X", *(buff+ii + 1)); if (no_more_private_data) break; rv = sc_pkcs15emu_oberthur_add_data(p15card, file_id, size, 1); if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED && postpone_allowed) { struct sc_path path; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "postpone adding of the private data"); sc_format_path("5011A6A6", &path); rv = sc_pkcs15_add_df(p15card, SC_PKCS15_DODF, &path); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Add DODF error"); no_more_private_data = 1; } SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Cannot parse private data info"); break; default: SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Private object parse error"); } } SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS); }
static int pcsc_connect(sc_reader_t *reader, sc_slot_info_t *slot) { DWORD active_proto, protocol; SCARDHANDLE card_handle; LONG rv; struct pcsc_private_data *priv = GET_PRIV_DATA(reader); struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot); int r; u8 feature_buf[256], rbuf[SC_MAX_APDU_BUFFER_SIZE]; size_t rcount; DWORD i, feature_len, display_ioctl = 0; PCSC_TLV_STRUCTURE *pcsc_tlv; r = refresh_slot_attributes(reader, slot); if (r) return r; if (!(slot->flags & SC_SLOT_CARD_PRESENT)) return SC_ERROR_CARD_NOT_PRESENT; /* Always connect with whatever protocol possible */ rv = priv->gpriv->SCardConnect(priv->gpriv->pcsc_ctx, priv->reader_name, priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED, SCARD_PROTOCOL_ANY, &card_handle, &active_proto); if (rv != SCARD_S_SUCCESS) { PCSC_ERROR(reader->ctx, "SCardConnect failed", rv); return pcsc_ret_to_error(rv); } slot->active_protocol = pcsc_proto_to_opensc(active_proto); pslot->pcsc_card = card_handle; /* after connect reader is not locked yet */ pslot->locked = 0; sc_debug(reader->ctx, "After connect protocol = %d", slot->active_protocol); /* If we need a specific protocol, reconnect if needed */ if (_sc_check_forced_protocol(reader->ctx, slot->atr, slot->atr_len, (unsigned int *) &protocol)) { /* If current protocol differs from the protocol we want to force */ if (slot->active_protocol != protocol) { sc_debug(reader->ctx, "Protocol difference, forcing protocol (%d)", protocol); /* Reconnect with a reset. pcsc_reconnect figures out the right forced protocol */ rv = pcsc_reconnect(reader, slot, 1); if (rv != SCARD_S_SUCCESS) { PCSC_ERROR(reader->ctx, "SCardReconnect (to force protocol) failed", rv); return pcsc_ret_to_error(rv); } sc_debug(reader->ctx, "Proto after reconnect = %d", slot->active_protocol); } } /* check for pinpad support */ if (priv->gpriv->SCardControl != NULL) { sc_debug(reader->ctx, "Requesting reader features ... "); rv = priv->gpriv->SCardControl(pslot->pcsc_card, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0, feature_buf, sizeof(feature_buf), &feature_len); if (rv != SCARD_S_SUCCESS) { sc_debug(reader->ctx, "SCardControl failed %08x", rv); } else { if ((feature_len % sizeof(PCSC_TLV_STRUCTURE)) != 0) { sc_debug(reader->ctx, "Inconsistent TLV from reader!"); } else { char *log_disabled = "but it's disabled in configuration file"; /* get the number of elements instead of the complete size */ feature_len /= sizeof(PCSC_TLV_STRUCTURE); pcsc_tlv = (PCSC_TLV_STRUCTURE *)feature_buf; for (i = 0; i < feature_len; i++) { if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_DIRECT) { pslot->verify_ioctl = ntohl(pcsc_tlv[i].value); } else if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_START) { pslot->verify_ioctl_start = ntohl(pcsc_tlv[i].value); } else if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_FINISH) { pslot->verify_ioctl_finish = ntohl(pcsc_tlv[i].value); } else if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_DIRECT) { pslot->modify_ioctl = ntohl(pcsc_tlv[i].value); } else if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_START) { pslot->modify_ioctl_start = ntohl(pcsc_tlv[i].value); } else if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_FINISH) { pslot->modify_ioctl_finish = ntohl(pcsc_tlv[i].value); } else if (pcsc_tlv[i].tag == FEATURE_IFD_PIN_PROPERTIES) { display_ioctl = ntohl(pcsc_tlv[i].value); } else { sc_debug(reader->ctx, "Reader feature %02x is not supported", pcsc_tlv[i].tag); } } /* Set slot capabilities based on detected IOCTLs */ if (pslot->verify_ioctl || (pslot->verify_ioctl_start && pslot->verify_ioctl_finish)) { char *log_text = "Reader supports pinpad PIN verification"; if (priv->gpriv->enable_pinpad) { sc_debug(reader->ctx, log_text); slot->capabilities |= SC_SLOT_CAP_PIN_PAD; } else { sc_debug(reader->ctx, "%s %s", log_text, log_disabled); } } if (pslot->modify_ioctl || (pslot->modify_ioctl_start && pslot->modify_ioctl_finish)) { char *log_text = "Reader supports pinpad PIN modification"; if (priv->gpriv->enable_pinpad) { sc_debug(reader->ctx, log_text); slot->capabilities |= SC_SLOT_CAP_PIN_PAD; } else { sc_debug(reader->ctx, "%s %s", log_text, log_disabled); } } if (display_ioctl) { rcount = sizeof(rbuf); r = pcsc_internal_transmit(reader, slot, NULL, 0, rbuf, &rcount, display_ioctl); if (r == SC_SUCCESS) { if (rcount != sizeof(PIN_PROPERTIES_STRUCTURE)) { PIN_PROPERTIES_STRUCTURE *caps = (PIN_PROPERTIES_STRUCTURE *)rbuf; if (caps->wLcdLayout > 0) { sc_debug(reader->ctx, "Reader has a display: %04X", caps->wLcdLayout); slot->capabilities |= SC_SLOT_CAP_DISPLAY; } else sc_debug(reader->ctx, "Reader does not have a display."); } else { sc_debug(reader->ctx, "Returned PIN properties structure has bad length (%d)", rcount); } } } } } } return SC_SUCCESS; }
/* Public key info: * flags:2, * CN(len:2,value:<variable length>), * ID(len:2,value:(SHA1 value)), * StartDate(Ascii:8) * EndDate(Ascii:8) * ??(0x00:2) */ static int sc_pkcs15emu_oberthur_add_pubkey(struct sc_pkcs15_card *p15card, unsigned int file_id, unsigned int size) { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_pubkey_info key_info; struct sc_pkcs15_object key_obj; char ch_tmp[0x100]; unsigned char *info_blob; size_t len, info_len, offs; unsigned flags; int rv; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "public key(file-id:%04X,size:%X)", file_id, size); memset(&key_info, 0, sizeof(key_info)); memset(&key_obj, 0, sizeof(key_obj)); snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PUB, file_id | 0x100); rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Failed to add public key: read oberthur file error"); /* Flags */ offs = 2; if (offs > info_len) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add public key: no 'tag'"); flags = *(info_blob + 0) * 0x100 + *(info_blob + 1); key_info.usage = sc_oberthur_decode_usage(flags); if (flags & OBERTHUR_ATTR_MODIFIABLE) key_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Public key key-usage:%04X", key_info.usage); /* Label */ if (offs + 2 > info_len) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add public key: no 'Label'"); len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100; if (len) { if (len > sizeof(key_obj.label) - 1) len = sizeof(key_obj.label) - 1; memcpy(key_obj.label, info_blob + offs + 2, len); } offs += 2 + len; /* ID */ if (offs > info_len) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add public key: no 'ID'"); len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100; if (!len || len > sizeof(key_info.id.value)) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_DATA, "Failed to add public key: invalie 'ID' length"); memcpy(key_info.id.value, info_blob + offs + 2, len); key_info.id.len = len; /* Ignore Start/End dates */ snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PUB, file_id); sc_format_path(ch_tmp, &key_info.path); key_info.native = 1; key_info.key_reference = file_id & 0xFF; key_info.modulus_length = size; rv = sc_pkcs15emu_add_rsa_pubkey(p15card, &key_obj, &key_info); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, rv); }
int sc_pkcs15_decode_pukdf_entry(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj, const u8 ** buf, size_t *buflen) { sc_context_t *ctx = p15card->card->ctx; struct sc_pkcs15_pubkey_info info; int r, gostr3410_params[3]; struct sc_pkcs15_keyinfo_gostparams *keyinfo_gostparams; size_t usage_len = sizeof(info.usage); size_t af_len = sizeof(info.access_flags); struct sc_pkcs15_der *der = &obj->content; struct sc_asn1_entry asn1_com_key_attr[6], asn1_com_pubkey_attr[1]; struct sc_asn1_entry asn1_rsakey_value_choice[3]; struct sc_asn1_entry asn1_rsakey_attr[4], asn1_rsa_type_attr[2]; struct sc_asn1_entry asn1_dsakey_attr[2], asn1_dsa_type_attr[2]; struct sc_asn1_entry asn1_gostr3410key_attr[5], asn1_gostr3410_type_attr[2]; struct sc_asn1_entry asn1_pubkey_choice[4]; struct sc_asn1_entry asn1_pubkey[2]; struct sc_asn1_pkcs15_object rsakey_obj = { obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_rsa_type_attr }; struct sc_asn1_pkcs15_object dsakey_obj = { obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_dsa_type_attr }; struct sc_asn1_pkcs15_object gostr3410key_obj = { obj, asn1_com_key_attr, asn1_com_pubkey_attr, asn1_gostr3410_type_attr }; sc_copy_asn1_entry(c_asn1_pubkey, asn1_pubkey); sc_copy_asn1_entry(c_asn1_pubkey_choice, asn1_pubkey_choice); sc_copy_asn1_entry(c_asn1_rsa_type_attr, asn1_rsa_type_attr); sc_copy_asn1_entry(c_asn1_rsakey_value_choice, asn1_rsakey_value_choice); sc_copy_asn1_entry(c_asn1_rsakey_attr, asn1_rsakey_attr); sc_copy_asn1_entry(c_asn1_dsa_type_attr, asn1_dsa_type_attr); sc_copy_asn1_entry(c_asn1_dsakey_attr, asn1_dsakey_attr); sc_copy_asn1_entry(c_asn1_gostr3410_type_attr, asn1_gostr3410_type_attr); sc_copy_asn1_entry(c_asn1_gostr3410key_attr, asn1_gostr3410key_attr); sc_copy_asn1_entry(c_asn1_com_pubkey_attr, asn1_com_pubkey_attr); sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr); sc_format_asn1_entry(asn1_pubkey_choice + 0, &rsakey_obj, NULL, 0); sc_format_asn1_entry(asn1_pubkey_choice + 1, &dsakey_obj, NULL, 0); sc_format_asn1_entry(asn1_pubkey_choice + 2, &gostr3410key_obj, NULL, 0); sc_format_asn1_entry(asn1_rsa_type_attr + 0, asn1_rsakey_attr, NULL, 0); sc_format_asn1_entry(asn1_rsakey_value_choice + 0, &info.path, NULL, 0); sc_format_asn1_entry(asn1_rsakey_value_choice + 1, &der->value, &der->len, 0); sc_format_asn1_entry(asn1_rsakey_attr + 0, asn1_rsakey_value_choice, NULL, 0); sc_format_asn1_entry(asn1_rsakey_attr + 1, &info.modulus_length, NULL, 0); sc_format_asn1_entry(asn1_dsa_type_attr + 0, asn1_dsakey_attr, NULL, 0); sc_format_asn1_entry(asn1_dsakey_attr + 0, &info.path, NULL, 0); sc_format_asn1_entry(asn1_gostr3410_type_attr + 0, asn1_gostr3410key_attr, NULL, 0); sc_format_asn1_entry(asn1_gostr3410key_attr + 0, &info.path, NULL, 0); sc_format_asn1_entry(asn1_gostr3410key_attr + 1, &gostr3410_params[0], NULL, 0); sc_format_asn1_entry(asn1_gostr3410key_attr + 2, &gostr3410_params[1], NULL, 0); sc_format_asn1_entry(asn1_gostr3410key_attr + 3, &gostr3410_params[2], NULL, 0); sc_format_asn1_entry(asn1_com_key_attr + 0, &info.id, NULL, 0); sc_format_asn1_entry(asn1_com_key_attr + 1, &info.usage, &usage_len, 0); sc_format_asn1_entry(asn1_com_key_attr + 2, &info.native, NULL, 0); sc_format_asn1_entry(asn1_com_key_attr + 3, &info.access_flags, &af_len, 0); sc_format_asn1_entry(asn1_com_key_attr + 4, &info.key_reference, NULL, 0); sc_format_asn1_entry(asn1_pubkey + 0, asn1_pubkey_choice, NULL, 0); /* Fill in defaults */ memset(&info, 0, sizeof(info)); info.key_reference = -1; info.native = 1; memset(gostr3410_params, 0, sizeof(gostr3410_params)); r = sc_asn1_decode(ctx, asn1_pubkey, *buf, *buflen, buf, buflen); if (r == SC_ERROR_ASN1_END_OF_CONTENTS) return r; SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "ASN.1 decoding failed"); if (asn1_pubkey_choice[0].flags & SC_ASN1_PRESENT) { obj->type = SC_PKCS15_TYPE_PUBKEY_RSA; } else if (asn1_pubkey_choice[2].flags & SC_ASN1_PRESENT) { obj->type = SC_PKCS15_TYPE_PUBKEY_GOSTR3410; assert(info.modulus_length == 0); info.modulus_length = SC_PKCS15_GOSTR3410_KEYSIZE; assert(info.params.len == 0); info.params.len = sizeof(struct sc_pkcs15_keyinfo_gostparams); info.params.data = malloc(info.params.len); if (info.params.data == NULL) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY); assert(sizeof(*keyinfo_gostparams) == info.params.len); keyinfo_gostparams = info.params.data; keyinfo_gostparams->gostr3410 = (unsigned int)gostr3410_params[0]; keyinfo_gostparams->gostr3411 = (unsigned int)gostr3410_params[1]; keyinfo_gostparams->gost28147 = (unsigned int)gostr3410_params[2]; } else { obj->type = SC_PKCS15_TYPE_PUBKEY_DSA; } if (!p15card->app || !p15card->app->ddo.aid.len) { r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &info.path); if (r < 0) { sc_pkcs15_free_key_params(&info.params); return r; } } else { info.path.aid = p15card->app->ddo.aid; } sc_debug(ctx, SC_LOG_DEBUG_ASN1, "PubKey path '%s'", sc_print_path(&info.path)); /* OpenSC 0.11.4 and older encoded "keyReference" as a negative value. Fixed in 0.11.5 we need to add a hack, so old cards continue to work. */ if (info.key_reference < -1) info.key_reference += 256; obj->data = malloc(sizeof(info)); if (obj->data == NULL) { sc_pkcs15_free_key_params(&info.params); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY); } memcpy(obj->data, &info, sizeof(info)); return 0; }
/* Certificate info: * flags:2, * Label(len:2,value:), * ID(len:2,value:(SHA1 value)), * Subject in ASN.1(len:2,value:) * Issuer in ASN.1(len:2,value:) * Serial encoded in LV or ASN.1 FIXME */ static int sc_pkcs15emu_oberthur_add_cert(struct sc_pkcs15_card *p15card, unsigned int file_id) { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_cert_info cinfo; struct sc_pkcs15_object cobj; unsigned char *info_blob, *cert_blob; size_t info_len, cert_len, len, offs; unsigned flags; int rv; char ch_tmp[0x20]; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "add certificate(file-id:%04X)", file_id); memset(&cinfo, 0, sizeof(cinfo)); memset(&cobj, 0, sizeof(cobj)); snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PUB, file_id | 0x100); rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Failed to add certificate: read oberthur file error"); if (info_len < 2) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'tag'"); flags = *(info_blob + 0) * 0x100 + *(info_blob + 1); offs = 2; /* Label */ if (offs + 2 > info_len) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'CN'"); len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100; if (len) { if (len > sizeof(cobj.label) - 1) len = sizeof(cobj.label) - 1; memcpy(cobj.label, info_blob + offs + 2, len); } offs += 2 + len; /* ID */ if (offs > info_len) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'ID'"); len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100; if (len > sizeof(cinfo.id.value)) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_DATA, "Failed to add certificate: invalie 'ID' length"); memcpy(cinfo.id.value, info_blob + offs + 2, len); cinfo.id.len = len; /* Ignore subject, issuer and serial */ snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PUB, file_id); sc_format_path(ch_tmp, &cinfo.path); rv = sc_oberthur_read_file(p15card, ch_tmp, &cert_blob, &cert_len, 1); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Failed to add certificate: read certificate error"); cinfo.value.value = cert_blob; cinfo.value.len = cert_len; rv = sc_oberthur_get_certificate_authority(&cinfo.value, &cinfo.authority); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Failed to add certificate: get certificate attributes error"); if (flags & OBERTHUR_ATTR_MODIFIABLE) cobj.flags |= SC_PKCS15_CO_FLAG_MODIFIABLE; rv = sc_pkcs15emu_add_x509_cert(p15card, &cobj, &cinfo); SC_FUNC_RETURN(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, rv); }
static int sc_pkcs15_read_der_file(sc_context_t *ctx, char * filename, u8 ** buf, size_t * buflen) { int r; int f = -1; size_t len; u8 tagbuf[16]; /* enough to read in the tag and length */ u8 * rbuf = NULL; size_t rbuflen; const u8 * body; size_t bodylen; unsigned int cla_out, tag_out; *buf = NULL; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); f = open(filename, O_RDONLY); if (f < 0) { r = SC_ERROR_FILE_NOT_FOUND; goto out; } r = read(f, tagbuf, sizeof(tagbuf)); /* get tag and length */ if (r < 2) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"Problem with \"%s\"\n",filename); r = SC_ERROR_DATA_OBJECT_NOT_FOUND; goto out; } len = r; body = tagbuf; if (sc_asn1_read_tag(&body, 0xfffff, &cla_out, &tag_out, &bodylen) != SC_SUCCESS) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "DER problem\n"); r = SC_ERROR_INVALID_ASN1_OBJECT; goto out; } rbuflen = body - tagbuf + bodylen; rbuf = malloc(rbuflen); if (rbuf == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto out; } memcpy(rbuf, tagbuf, len); /* copy first or only part */ if (rbuflen > len) { /* read rest of file */ r = read(f, rbuf + len, rbuflen - len); if (r < (int)(rbuflen - len)) { r = SC_ERROR_INVALID_ASN1_OBJECT; free (rbuf); rbuf = NULL; goto out; } } *buflen = rbuflen; *buf = rbuf; rbuf = NULL; r = rbuflen; out: if (rbuf) free(rbuf); if (f > 0) close(f); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
/* Private key info: * flags:2, * CN(len:2,value:), * ID(len:2,value:(SHA1 value)), * StartDate(Ascii:8) * EndDate(Ascii:8) * Subject in ASN.1(len:2,value:) * modulus(value:) * exponent(length:1, value:3) */ static int sc_pkcs15emu_oberthur_add_prvkey(struct sc_pkcs15_card *p15card, unsigned int file_id, unsigned int size) { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_prkey_info kinfo; struct sc_pkcs15_object kobj; struct crypto_container ccont; unsigned char *info_blob = NULL; size_t info_len = 0; unsigned flags; size_t offs, len; char ch_tmp[0x100]; int rv; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "add private key(file-id:%04X,size:%04X)", file_id, size); memset(&kinfo, 0, sizeof(kinfo)); memset(&kobj, 0, sizeof(kobj)); memset(&ccont, 0, sizeof(ccont)); rv = sc_oberthur_get_friends (file_id, &ccont); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Failed to add private key: get friends error"); if (ccont.id_cert) { struct sc_pkcs15_object *objs[32]; int ii; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "friend certificate %04X", ccont.id_cert); rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_CERT_X509, objs, 32); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Failed to add private key: get certificates error"); for (ii=0; ii<rv; ii++) { struct sc_pkcs15_cert_info *cert = (struct sc_pkcs15_cert_info *)objs[ii]->data; struct sc_path path = cert->path; unsigned int id = path.value[path.len - 2] * 0x100 + path.value[path.len - 1]; if (id == ccont.id_cert) { strncpy(kobj.label, objs[ii]->label, sizeof(kobj.label) - 1); break; } } if (ii == rv) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INCONSISTENT_PROFILE, "Failed to add private key: friend not found"); } snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PRV, file_id | 0x100); rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Failed to add private key: read oberthur file error"); if (info_len < 2) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'tag'"); flags = *(info_blob + 0) * 0x100 + *(info_blob + 1); offs = 2; /* CN */ if (offs > info_len) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'CN'"); len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100; if (len && !strlen(kobj.label)) { if (len > sizeof(kobj.label) - 1) len = sizeof(kobj.label) - 1; strncpy(kobj.label, (char *)(info_blob + offs + 2), len); } offs += 2 + len; /* ID */ if (offs > info_len) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'ID'"); len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100; if (!len) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: zero length ID"); else if (len > sizeof(kinfo.id.value)) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_DATA, "Failed to add private key: invalid ID length"); memcpy(kinfo.id.value, info_blob + offs + 2, len); kinfo.id.len = len; offs += 2 + len; /* Ignore Start/End dates */ offs += 16; /* Subject encoded in ASN1 */ if (offs > info_len) return SC_ERROR_UNKNOWN_DATA_RECEIVED; len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100; if (len) { kinfo.subject.value = malloc(len); if (!kinfo.subject.value) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_MEMORY_FAILURE, "Failed to add private key: memory allocation error"); kinfo.subject.len = len; memcpy(kinfo.subject.value, info_blob + offs + 2, len); } /* Modulus and exponent are ignored */ snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PRV, file_id); sc_format_path(ch_tmp, &kinfo.path); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Private key info path %s", ch_tmp); kinfo.modulus_length = size; kinfo.native = 1; kinfo.access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE | SC_PKCS15_PRKEY_ACCESS_LOCAL; kinfo.key_reference = file_id & 0xFF; kinfo.usage = sc_oberthur_decode_usage(flags); kobj.flags = SC_PKCS15_CO_FLAG_PRIVATE; if (flags & OBERTHUR_ATTR_MODIFIABLE) kobj.flags |= SC_PKCS15_CO_FLAG_MODIFIABLE; kobj.auth_id.len = sizeof(PinDomainID) > sizeof(kobj.auth_id.value) ? sizeof(kobj.auth_id.value) : sizeof(PinDomainID); memcpy(kobj.auth_id.value, PinDomainID, kobj.auth_id.len); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Parsed private key(reference:%i,usage:%X,flags:%X)", kinfo.key_reference, kinfo.usage, kobj.flags); rv = sc_pkcs15emu_add_rsa_prkey(p15card, &kobj, &kinfo); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, rv); }
int sc_pkcs15_fix_ec_parameters(struct sc_context *ctx, struct sc_pkcs15_ec_parameters *ecparams) { int rv, ii; LOG_FUNC_CALLED(ctx); /* In PKCS#11 EC parameters arrives in DER encoded form */ if (ecparams->der.value && ecparams->der.len) { for (ii=0; ec_curve_infos[ii].name; ii++) { struct sc_object_id id; unsigned char *buf = NULL; size_t len = 0; sc_format_oid(&id, ec_curve_infos[ii].oid_str); sc_encode_oid (ctx, &id, &buf, &len); if (ecparams->der.len == len && !memcmp(ecparams->der.value, buf, len)) { free(buf); break; } free(buf); } /* TODO: support of explicit EC parameters form */ if (!ec_curve_infos[ii].name) LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported named curve"); sc_debug(ctx,SC_LOG_DEBUG_NORMAL, "Found known curve '%s'", ec_curve_infos[ii].name); if (!ecparams->named_curve) { ecparams->named_curve = strdup(ec_curve_infos[ii].name); if (!ecparams->named_curve) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY); sc_debug(ctx,SC_LOG_DEBUG_NORMAL, "Curve name: '%s'", ecparams->named_curve); } if (ecparams->id.value[0] <=0 || ecparams->id.value[1] <=0) sc_format_oid(&ecparams->id, ec_curve_infos[ii].oid_str); ecparams->field_length = ec_curve_infos[ii].size; sc_debug(ctx,SC_LOG_DEBUG_NORMAL, "Curve length %i", ecparams->field_length); } else if (ecparams->named_curve) { /* it can be name of curve or OID in ASCII form */ for (ii=0; ec_curve_infos[ii].name; ii++) { if (!strcmp(ec_curve_infos[ii].name, ecparams->named_curve)) break; if (!strcmp(ec_curve_infos[ii].oid_str, ecparams->named_curve)) break; } if (!ec_curve_infos[ii].name) LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported named curve"); rv = sc_format_oid(&ecparams->id, ec_curve_infos[ii].oid_str); LOG_TEST_RET(ctx, rv, "Invalid OID format"); ecparams->field_length = ec_curve_infos[ii].size; if (!ecparams->der.value || !ecparams->der.len) { rv = sc_encode_oid (ctx, &ecparams->id, &ecparams->der.value, &ecparams->der.len); LOG_TEST_RET(ctx, rv, "Cannot encode object ID"); } } else if (ecparams->id.value[0] > 0 && ecparams->id.value[1] > 0) { LOG_TEST_RET(ctx, SC_ERROR_NOT_IMPLEMENTED, "EC parameters has to be presented as a named curve or explicit data"); } LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
/** * find library module for provided driver in configuration file * if not found assume library name equals to module name */ static const char *find_library(sc_context_t *ctx, const char *name) { int i; const char *libname = NULL; scconf_block **blocks, *blk; for (i = 0; ctx->conf_blocks[i]; i++) { blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i], "card_driver", name); if (!blocks) continue; blk = blocks[0]; free(blocks); if (blk == NULL) continue; libname = scconf_get_str(blk, "module", name); #ifdef _WIN32 if (libname && libname[0] != '\\' ) { #else if (libname && libname[0] != '/' ) { #endif sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "warning: relative path to driver '%s' used", libname); } break; } return libname; } /** * load card/reader driver modules * Every module should contain a function " void * sc_module_init(char *) " * that returns a pointer to the function _sc_get_xxxx_driver() * used to initialize static modules * Also, an exported "char *sc_module_version" variable should exist in module */ static void *load_dynamic_driver(sc_context_t *ctx, void **dll, const char *name) { const char *version, *libname; void *handle; void *(*modinit)(const char *) = NULL; void *(**tmodi)(const char *) = &modinit; const char *(*modversion)(void) = NULL; const char *(**tmodv)(void) = &modversion; if (name == NULL) { /* should not occurr, but... */ sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"No module specified",name); return NULL; } libname = find_library(ctx, name); if (libname == NULL) return NULL; handle = sc_dlopen(libname); if (handle == NULL) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Module %s: cannot load %s library: %s", name, libname, sc_dlerror()); return NULL; } /* verify correctness of module */ *(void **)tmodi = sc_dlsym(handle, "sc_module_init"); *(void **)tmodv = sc_dlsym(handle, "sc_driver_version"); if (modinit == NULL || modversion == NULL) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "dynamic library '%s' is not a OpenSC module",libname); sc_dlclose(handle); return NULL; } /* verify module version */ version = modversion(); /* XXX: We really need to have ABI version for each interface */ if (version == NULL || strncmp(version, PACKAGE_VERSION, strlen(PACKAGE_VERSION)) != 0) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"dynamic library '%s': invalid module version",libname); sc_dlclose(handle); return NULL; } *dll = handle; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "successfully loaded card driver '%s'", name); return modinit(name); } static int load_card_driver_options(sc_context_t *ctx, struct sc_card_driver *driver) { scconf_block **blocks, *blk; int i; for (i = 0; ctx->conf_blocks[i]; i++) { blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i], "card_driver", driver->short_name); if (!blocks) continue; blk = blocks[0]; free(blocks); if (blk == NULL) continue; /* no options at the moment */ } return SC_SUCCESS; }
/* Load the rule and keyd file into our private data. Return 0 on success */ static int load_special_files(sc_card_t * card) { sc_context_t *ctx = card->ctx; int r, recno; struct df_info_s *dfi; struct rule_record_s *rule; struct keyd_record_s *keyd; /* First check whether we already cached it. */ dfi = get_df_info(card); if (dfi && dfi->rule_file) return 0; /* yes. */ clear_special_files(dfi); /* Read rule file. Note that we bypass our cache here. */ r = select_part(card, MCRD_SEL_EF, EF_Rule, NULL); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "selecting EF_Rule failed"); for (recno = 1;; recno++) { u8 recbuf[256]; r = sc_read_record(card, recno, recbuf, sizeof(recbuf), SC_RECORD_BY_REC_NR); if (r == SC_ERROR_RECORD_NOT_FOUND) break; else if (r < 0) { SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r); } else { rule = malloc(sizeof *rule + r); if (!rule) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY); rule->recno = recno; rule->datalen = r; memcpy(rule->data, recbuf, r); rule->next = dfi->rule_file; dfi->rule_file = rule; } } sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "new EF_Rule file loaded (%d records)\n", recno - 1); /* Read the KeyD file. Note that we bypass our cache here. */ r = select_part(card, MCRD_SEL_EF, EF_KeyD, NULL); if (r == SC_ERROR_FILE_NOT_FOUND) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "no EF_KeyD file available\n"); return 0; /* That is okay. */ } SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "selecting EF_KeyD failed"); for (recno = 1;; recno++) { u8 recbuf[256]; r = sc_read_record(card, recno, recbuf, sizeof(recbuf), SC_RECORD_BY_REC_NR); if (r == SC_ERROR_RECORD_NOT_FOUND) break; else if (r < 0) { SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r); } else { keyd = malloc(sizeof *keyd + r); if (!keyd) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY); keyd->recno = recno; keyd->datalen = r; memcpy(keyd->data, recbuf, r); keyd->next = dfi->keyd_file; dfi->keyd_file = keyd; } } sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "new EF_KeyD file loaded (%d records)\n", recno - 1); /* FIXME: Do we need to restore the current DF? I guess it is not required, but we could try to do so by selecting 3fff? */ return 0; }
static void process_config_file(sc_context_t *ctx, struct _sc_ctx_options *opts) { int i, r, count = 0; scconf_block **blocks; const char *conf_path = NULL; #ifdef _WIN32 char temp_path[PATH_MAX]; DWORD temp_len; long rc; HKEY hKey; #endif memset(ctx->conf_blocks, 0, sizeof(ctx->conf_blocks)); #ifdef _WIN32 conf_path = getenv("OPENSC_CONF"); if (!conf_path) { rc = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey); if (rc == ERROR_SUCCESS) { temp_len = PATH_MAX; rc = RegQueryValueEx( hKey, "ConfigFile", NULL, NULL, (LPBYTE) temp_path, &temp_len); if ((rc == ERROR_SUCCESS) && (temp_len < PATH_MAX)) conf_path = temp_path; RegCloseKey(hKey); } } if (!conf_path) { rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\OpenSC Project\\OpenSC", 0, KEY_QUERY_VALUE, &hKey ); if (rc == ERROR_SUCCESS) { temp_len = PATH_MAX; rc = RegQueryValueEx( hKey, "ConfigFile", NULL, NULL, (LPBYTE) temp_path, &temp_len); if ((rc == ERROR_SUCCESS) && (temp_len < PATH_MAX)) conf_path = temp_path; RegCloseKey(hKey); } } if (!conf_path) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "process_config_file doesn't find opensc config file. Please set the registry key."); return; } #else conf_path = getenv("OPENSC_CONF"); if (!conf_path) conf_path = OPENSC_CONF_PATH; #endif ctx->conf = scconf_new(conf_path); if (ctx->conf == NULL) return; r = scconf_parse(ctx->conf); #ifdef OPENSC_CONFIG_STRING /* Parse the string if config file didn't exist */ if (r < 0) r = scconf_parse_string(ctx->conf, OPENSC_CONFIG_STRING); #endif if (r < 1) { /* A negative return value means the config file isn't * there, which is not an error. Nevertheless log this * fact. */ if (r < 0) sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "scconf_parse failed: %s", ctx->conf->errmsg); else sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "scconf_parse failed: %s", ctx->conf->errmsg); scconf_free(ctx->conf); ctx->conf = NULL; return; } blocks = scconf_find_blocks(ctx->conf, NULL, "app", ctx->app_name); if (blocks[0]) ctx->conf_blocks[count++] = blocks[0]; free(blocks); if (strcmp(ctx->app_name, "default") != 0) { blocks = scconf_find_blocks(ctx->conf, NULL, "app", "default"); if (blocks[0]) ctx->conf_blocks[count] = blocks[0]; free(blocks); } /* Above we add 2 blocks at most, but conf_blocks has 3 elements, * so at least one is NULL */ for (i = 0; ctx->conf_blocks[i]; i++) load_parameters(ctx, ctx->conf_blocks[i], opts); }
static void process_fcp(sc_card_t * card, sc_file_t * file, const u8 * buf, size_t buflen) { sc_context_t *ctx = card->ctx; size_t taglen, len = buflen; const u8 *tag = NULL, *p = buf; int bad_fde = 0; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "processing FCI bytes\n"); /* File identifier. */ tag = sc_asn1_find_tag(ctx, p, len, 0x83, &taglen); if (tag != NULL && taglen == 2) { file->id = (tag[0] << 8) | tag[1]; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " file identifier: 0x%02X%02X\n", tag[0], tag[1]); } /* Number of data bytes in the file including structural information. */ tag = sc_asn1_find_tag(ctx, p, len, 0x81, &taglen); if (!tag) { /* My card does not encode the filelength in 0x81 but in 0x85 which is the file descriptor extension in TCOS. Assume that this is the case when the regular file size tag is not encoded. */ tag = sc_asn1_find_tag(ctx, p, len, 0x85, &taglen); bad_fde = !!tag; } if (tag != NULL && taglen >= 2) { int bytes = (tag[0] << 8) + tag[1]; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " bytes in file: %d\n", bytes); file->size = bytes; } if (tag == NULL) { tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen); if (tag != NULL && taglen >= 2) { int bytes = (tag[0] << 8) + tag[1]; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " bytes in file: %d\n", bytes); file->size = bytes; } } /* File descriptor byte(s). */ tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen); if (tag != NULL) { /* Fixme, this might actual be up to 6 bytes. */ if (taglen > 0) { unsigned char byte = tag[0]; const char *type; file->shareable = byte & 0x40 ? 1 : 0; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " shareable: %s\n", (byte & 0x40) ? "yes" : "no"); file->ef_structure = byte & 0x07; switch ((byte >> 3) & 7) { case 0: type = "working EF"; file->type = SC_FILE_TYPE_WORKING_EF; break; case 1: type = "internal EF"; file->type = SC_FILE_TYPE_INTERNAL_EF; break; case 7: type = "DF"; file->type = SC_FILE_TYPE_DF; break; default: type = "unknown"; break; } sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " type: %s\n", type); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, " EF structure: %d\n", byte & 0x07); } }
/* * Unblock a PIN. */ int sc_pkcs15_unblock_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pin_obj, const u8 *puk, size_t puklen, const u8 *newpin, size_t newpinlen) { int r; sc_card_t *card; struct sc_pin_cmd_data data; struct sc_pkcs15_object *puk_obj; struct sc_pkcs15_pin_info *puk_info = NULL; struct sc_pkcs15_pin_info *pin_info = (struct sc_pkcs15_pin_info *)pin_obj->data; /* make sure the pins are in valid range */ if ((r = _validate_pin(p15card, pin_info, newpinlen)) != SC_SUCCESS) return r; card = p15card->card; /* get pin_info object of the puk (this is a little bit complicated * as we don't have the id of the puk (at least now)) * note: for compatibility reasons we give no error if no puk object * is found */ /* first step: try to get the pkcs15 object of the puk */ r = sc_pkcs15_find_pin_by_auth_id(p15card, &pin_obj->auth_id, &puk_obj); if (r >= 0 && puk_obj) { /* second step: get the pkcs15 info object of the puk */ puk_info = (struct sc_pkcs15_pin_info *)puk_obj->data; } if (!puk_info) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unable to get puk object, using pin object instead!"); puk_info = pin_info; } /* make sure the puk is in valid range */ if ((r = _validate_pin(p15card, puk_info, puklen)) != SC_SUCCESS) return r; r = sc_lock(card); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed"); /* the path in the pin object is optional */ if (pin_info->path.len > 0) { r = sc_select_file(card, &pin_info->path, NULL); if (r) goto out; } /* set pin_cmd data */ memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_UNBLOCK; data.pin_type = SC_AC_CHV; data.pin_reference = pin_info->reference; data.pin1.data = puk; data.pin1.len = puklen; data.pin1.pad_char = pin_info->pad_char; data.pin1.min_length = pin_info->min_length; data.pin1.max_length = pin_info->max_length; data.pin1.pad_length = pin_info->stored_length; data.pin2.data = newpin; data.pin2.len = newpinlen; data.pin2.pad_char = puk_info->pad_char; data.pin2.min_length = puk_info->min_length; data.pin2.max_length = puk_info->max_length; data.pin2.pad_length = puk_info->stored_length; if (pin_info->flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING) data.flags |= SC_PIN_CMD_NEED_PADDING; switch (pin_info->type) { case SC_PKCS15_PIN_TYPE_BCD: data.pin1.encoding = SC_PIN_ENCODING_BCD; break; case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: data.pin1.encoding = SC_PIN_ENCODING_ASCII; break; } switch (puk_info->type) { case SC_PKCS15_PIN_TYPE_BCD: data.pin2.encoding = SC_PIN_ENCODING_BCD; break; case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: data.pin2.encoding = SC_PIN_ENCODING_ASCII; break; } if(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) { data.flags |= SC_PIN_CMD_USE_PINPAD; if (pin_info->flags & SC_PKCS15_PIN_FLAG_SO_PIN) { data.pin1.prompt = "Please enter PUK"; data.pin2.prompt = "Please enter new SO PIN"; } else { data.pin1.prompt = "Please enter PUK"; data.pin2.prompt = "Please enter new PIN"; } } r = sc_pin_cmd(card, &data, &pin_info->tries_left); if (r == SC_SUCCESS) sc_pkcs15_pincache_add(p15card, pin_obj, newpin, newpinlen); out: sc_unlock(card); return r; }