static int iso7816_update_record(sc_card_t *card, unsigned int rec_nr, const u8 *buf, size_t count, unsigned long flags) { sc_apdu_t apdu; int r; if (count > 256) { sc_error(card->ctx, "Trying to send too many bytes\n"); return SC_ERROR_INVALID_ARGUMENTS; } sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xDC, rec_nr, 0); apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3; if (flags & SC_RECORD_BY_REC_NR) apdu.p2 |= 0x04; apdu.lc = count; apdu.datalen = count; apdu.data = buf; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "Card returned error"); SC_FUNC_RETURN(card->ctx, 3, count); }
/* * Erase the card. */ static int myeid_erase_card(struct sc_profile *profile, struct sc_pkcs15_card *p15card) { struct sc_context *ctx = p15card->card->ctx; struct sc_cardctl_myeid_data_obj data_obj; struct sc_file *mf = NULL; unsigned char data[8]; int r; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); r = myeid_get_init_applet_data(profile, p15card, data, sizeof(data)); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Get init applet date error"); /* Select parent DF and verify PINs/key as necessary */ r = sc_select_file(p15card->card, sc_get_mf_path(), &mf); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot select MF"); /* ACLs are not actives if file is not in the operational state */ if (mf->status == SC_FILE_STATUS_ACTIVATED) r = sc_pkcs15init_authenticate(profile, p15card, mf, SC_AC_OP_DELETE); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "'DELETE' authentication failed on MF"); data_obj.P1 = 0x01; data_obj.P2 = 0xE0; data_obj.Data = data; data_obj.DataLen = sizeof(data); r = sc_card_ctl(p15card->card, SC_CARDCTL_MYEID_PUTDATA, &data_obj); SC_FUNC_RETURN(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r); }
static int iso7816_update_binary(sc_card_t *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) { sc_apdu_t apdu; int r; assert(count <= card->max_send_size); if (idx > 0x7fff) { sc_error(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx); return SC_ERROR_OFFSET_TOO_LARGE; } sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD6, (idx >> 8) & 0x7F, idx & 0xFF); apdu.lc = count; apdu.datalen = count; apdu.data = buf; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "Card returned error"); SC_FUNC_RETURN(card->ctx, 3, count); }
static int sc_awp_parse_df(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df) { struct sc_context *ctx = p15card->card->ctx; unsigned char *buf = NULL; size_t buf_len; int rv; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (df->type != SC_PKCS15_PRKDF && df->type != SC_PKCS15_DODF) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED); if (df->enumerated) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS); rv = sc_oberthur_read_file(p15card, AWP_OBJECTS_LIST_PRV, &buf, &buf_len, 1); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Parse DF: read pribate objects info failed"); rv = sc_oberthur_parse_privateinfo(p15card, buf, buf_len, 0); if (buf) free(buf); if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Parse DF: private info parse error"); df->enumerated = 1; SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, rv); }
/* * Store a private key */ static int myeid_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object, struct sc_pkcs15_prkey *prkey) { 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, keybits = key_info->modulus_length; 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_UPDATE); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "No authorisation to store MyEID private key"); if (file) sc_file_free(file); /* Fill in data structure */ memset(&args, 0, sizeof(args)); args.mod_len = keybits; 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; /* Store 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"); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
static int gemsafe_compute_signature(struct sc_card *card, const u8 * data, size_t data_len, u8 * out, size_t outlen) { int r, len; struct sc_apdu apdu; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; sc_context_t *ctx = card->ctx; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (data_len > 36) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "error: input data too long: %lu bytes\n", data_len); return SC_ERROR_INVALID_ARGUMENTS; } /* the Portuguese eID card requires a two-phase exchange */ if(card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID) { sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A, 0x90, 0xA0); } else { sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0xAC); apdu.cla |= 0x80; apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); apdu.le = 256; } /* we sign a digestInfo object => tag 0x90 */ sbuf[0] = 0x90; sbuf[1] = (u8)data_len; memcpy(sbuf + 2, data, data_len); apdu.data = sbuf; apdu.lc = data_len + 2; apdu.datalen = data_len + 2; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) { if(card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID) { /* finalize the exchange */ sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x2A, 0x9E, 0x9A); apdu.le = 128; /* 1024 bit keys */ apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); if(apdu.sw1 != 0x90 || apdu.sw2 != 0x00) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2)); } len = apdu.resplen > outlen ? outlen : apdu.resplen; memcpy(out, apdu.resp, len); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, len); } SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2)); }
/* * Create a new PIN */ static int setcos_create_pin(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *df, sc_pkcs15_object_t *pin_obj, const u8 *pin, size_t pin_len, const u8 *puk, size_t puk_len) { struct sc_context *ctx = p15card->card->ctx; sc_pkcs15_auth_info_t *auth_info = (sc_pkcs15_auth_info_t *) pin_obj->data; sc_file_t *pinfile = NULL; int r, ignore_ac = 0; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) return SC_ERROR_OBJECT_NOT_VALID; /* Create the global pin file if it doesn't exist yet */ r = sc_profile_get_file(profile, "pinfile", &pinfile); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "No 'pinfile' template in profile"); r = sc_select_file(p15card->card, &pinfile->path, &pinfile); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot select 'pinfile'"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "pinfile->status:%X", pinfile->status); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "create PIN with reference:%X, flags:%X, path:%s", auth_info->attrs.pin.reference, auth_info->attrs.pin.flags, sc_print_path(&auth_info->path)); if (pinfile->status == SC_FILE_STATUS_CREATION) ignore_ac = 1; r = setcos_create_pin_internal(profile, p15card, ignore_ac, auth_info, pin, pin_len, puk, puk_len); /* If pinfile is in 'Creation' state and SOPIN has been created, * change status of MF and 'pinfile' to 'Operational:Activated' */ if (ignore_ac && (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN)) { sc_file_t *mf = profile->mf_info->file; r = sc_card_ctl(p15card->card, SC_CARDCTL_SETCOS_ACTIVATE_FILE, NULL); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot set 'pinfile' into the activated state"); r = sc_select_file(p15card->card, &mf->path, NULL); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot select MF"); r = sc_card_ctl(p15card->card, SC_CARDCTL_SETCOS_ACTIVATE_FILE, NULL); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot set MF into the activated state"); } sc_file_free(pinfile); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
static int entersafe_generate_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj, sc_pkcs15_pubkey_t *pubkey) { int r; sc_entersafe_gen_key_data gendat; sc_pkcs15_prkey_info_t *kinfo = (sc_pkcs15_prkey_info_t *) obj->data; sc_card_t *card = p15card->card; sc_file_t *tfile; const sc_acl_entry_t *acl_entry; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); if (obj->type != SC_PKCS15_TYPE_PRKEY_RSA) return SC_ERROR_NOT_SUPPORTED; r = sc_profile_get_file(profile, "PKCS15-AODF", &tfile); if (r < 0) return r; acl_entry = sc_file_get_acl_entry(tfile, SC_AC_OP_UPDATE); if (acl_entry->method != SC_AC_NONE) { r = sc_pkcs15init_authenticate(profile, p15card, tfile, SC_AC_OP_UPDATE); if(r<0) r = SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; } sc_file_free(tfile); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "cant verify pin"); /* generate key pair */ gendat.key_id = (u8) kinfo->key_reference; gendat.key_length = (size_t) kinfo->modulus_length; gendat.modulus = NULL; r = sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_GENERATE_KEY, &gendat); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "EnterSafe generate RSA key pair failed"); /* get the modulus via READ PUBLIC KEY */ if (pubkey) { u8 *buf; struct sc_pkcs15_pubkey_rsa *rsa = &pubkey->u.rsa; /* set the modulus */ rsa->modulus.data = gendat.modulus; rsa->modulus.len = kinfo->modulus_length >> 3; /* set the exponent (always 0x10001) */ buf = malloc(3); if (!buf) return SC_ERROR_OUT_OF_MEMORY; buf[0] = 0x01; buf[1] = 0x00; buf[2] = 0x01; rsa->exponent.data = buf; rsa->exponent.len = 3; pubkey->algorithm = SC_ALGORITHM_RSA; } else
static int incrypto34_list_files(sc_card_t *card, u8 *buf, size_t buflen) { sc_apdu_t apdu; u8 rbuf[256]; int r; size_t fids; u8 offset; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); fids=0; offset=0; /* INS 0xFC: SCAN DF*/ /* P1 0x00: list both DF and EF */ /* P2 0x00/0x01: first/next element */ /* LE 0x03*/ /* returns 3 bytes: FILE_TYPE + FID_HI_BYTE + FID_LO_BYTE */ get_next_part: sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xFC, 0x00, offset?0x01:0x00); apdu.cla = 0xB0; apdu.le = 3; apdu.resplen = sizeof(rbuf); apdu.resp = rbuf; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); if (apdu.sw1 == 0x6a && apdu.sw2 == 0x82) goto end; /* no more files */ r = sc_check_sw(card, apdu.sw1, apdu.sw2); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "DIRECTORY command returned error"); if (apdu.resplen >= 3 && ((rbuf[0] >= 0x01 && rbuf[0] <= 0x07) || 0x38 == rbuf[0]) && fids + 2 >= buflen) { buf[fids++] = rbuf[1]; buf[fids++] = rbuf[2]; } ++offset; goto get_next_part; end: r = fids; SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); }
static int iso_rm_sm(struct iso_sm_ctx *sctx, sc_card_t *card, sc_apdu_t *sm_apdu, sc_apdu_t *apdu) { if (sctx->post_transmit) SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sctx->post_transmit(card, sctx, sm_apdu), "Could not complete SM specific post transmit routine"); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sm_decrypt(sctx, card, sm_apdu, apdu), "Could not decrypt APDU"); if (sctx->finish) SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sctx->finish(card, sctx, apdu), "Could not complete SM specific post transmit routine"); return SC_SUCCESS; }
/* * Store a private key */ static int setcos_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object, struct sc_pkcs15_prkey *prkey) { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *)object->data; struct sc_cardctl_setcos_gen_store_key_info args; struct sc_file *file = NULL; int r, keybits = key_info->modulus_length; 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"); /* Parameter check */ if ( (keybits < 512) || (keybits > 1024) || (keybits & 0x7)) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS, "Invalid key length"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "store key with ID:%s and path:%s\n", sc_pkcs15_print_id(&key_info->id), sc_print_path(&key_info->path)); r = sc_select_file(p15card->card, &key_info->path, &file); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Cannot store key: select key file failed"); r = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "No authorisation to store private key"); /* Fill in data structure */ memset(&args, 0, sizeof(args)); args.mod_len = keybits; args.op_type = OP_TYPE_STORE; args.pubexp_len = prkey->u.rsa.exponent.len * 8; args.pubexp = prkey->u.rsa.exponent.data; args.primep_len = prkey->u.rsa.p.len * 8; args.primep = prkey->u.rsa.p.data; args.primeq_len = prkey->u.rsa.q.len * 8; args.primeq = prkey->u.rsa.q.data; /* Generate/store rsa key */ r = sc_card_ctl(p15card->card, SC_CARDCTL_SETCOS_GENERATE_STORE_KEY, &args); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Card control 'GENERATE_STORE_KEY' failed"); if (file) sc_file_free(file); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
int sc_pkcs15_encode_pubkey_dsa(sc_context_t *ctx, struct sc_pkcs15_pubkey_dsa *key, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_public_key[2]; struct sc_asn1_entry asn1_dsa_pub_coeff[5]; int r; sc_copy_asn1_entry(c_asn1_public_key, asn1_public_key); sc_copy_asn1_entry(c_asn1_dsa_pub_coefficients, asn1_dsa_pub_coeff); sc_format_asn1_entry(asn1_public_key + 0, asn1_dsa_pub_coeff, NULL, 1); sc_format_asn1_entry(asn1_dsa_pub_coeff + 0, key->pub.data, &key->pub.len, 1); sc_format_asn1_entry(asn1_dsa_pub_coeff + 1, key->g.data, &key->g.len, 1); sc_format_asn1_entry(asn1_dsa_pub_coeff + 2, key->p.data, &key->p.len, 1); sc_format_asn1_entry(asn1_dsa_pub_coeff + 3, key->q.data, &key->q.len, 1); r = sc_asn1_encode(ctx, asn1_public_key, buf, buflen); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "ASN.1 encoding failed"); return 0; }
static int cardos_have_2048bit_package(sc_card_t *card) { sc_apdu_t apdu; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; int r; const u8 *p = rbuf, *q; size_t len, tlen = 0, ilen = 0; sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x88); apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); apdu.lc = 0; apdu.le = 256; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); if ((len = apdu.resplen) == 0) /* looks like no package has been installed */ return 0; while (len != 0) { p = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen); if (p == NULL) return 0; q = sc_asn1_find_tag(card->ctx, p, tlen, 0x01, &ilen); if (q == NULL || ilen != 4) return 0; if (q[0] == 0x1c) return 1; p += tlen; len -= tlen + 2; } return 0; }
static int sc_oberthur_parse_tokeninfo (struct sc_pkcs15_card *p15card, unsigned char *buff, size_t len, int postpone_allowed) { struct sc_context *ctx = p15card->card->ctx; char label[0x21]; unsigned flags; int ii; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (!buff || len < 0x24) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS, "Cannot parse token info"); memset(label, 0, sizeof(label)); memcpy(label, buff, 0x20); ii = 0x20; while (*(label + --ii)==' ' && ii) ; *(label + ii + 1) = '\0'; flags = *(buff + 0x22) * 0x100 + *(buff + 0x23); p15card->tokeninfo->label = strdup(label); p15card->tokeninfo->manufacturer_id = strdup("Oberthur/OpenSC"); if (flags & 0x01) p15card->tokeninfo->flags |= SC_PKCS15_TOKEN_PRN_GENERATION; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "label %s", p15card->tokeninfo->label); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "manufacturer_id %s", p15card->tokeninfo->manufacturer_id); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS); }
static int iso7816_read_record(sc_card_t *card, unsigned int rec_nr, u8 *buf, size_t count, unsigned long flags) { sc_apdu_t apdu; u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE]; int r; sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xB2, rec_nr, 0); apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3; if (flags & SC_RECORD_BY_REC_NR) apdu.p2 |= 0x04; apdu.le = count; apdu.resplen = count; apdu.resp = recvbuf; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); if (apdu.resplen == 0) SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2)); memcpy(buf, recvbuf, apdu.resplen); SC_FUNC_RETURN(card->ctx, 3, apdu.resplen); }
static int belpic_logout(sc_card_t *card) { sc_apdu_t apdu; int r; sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0xE6, 0x00, 0x00); apdu.cla = 0x80; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "LOGOFF: APDU transmit failed"); r = sc_check_sw(card, apdu.sw1, apdu.sw2); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "LOGOFF returned error"); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); }
static int entersafe_read_binary(sc_card_t *card, unsigned int idx, u8 *buf, size_t count, unsigned long flags) { sc_apdu_t apdu; u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE]; int r; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); assert(count <= card->max_recv_size); sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xB0, (idx >> 8) & 0xFF, idx & 0xFF); apdu.cla=idx > 0x7fff ? 0x80:0x00; apdu.le = count; apdu.resplen = count; apdu.resp = recvbuf; r = entersafe_transmit_apdu(card, &apdu,0,0,0,0); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); if (apdu.resplen == 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2)); memcpy(buf, recvbuf, apdu.resplen); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, apdu.resplen); }
/* * We are storing the ec_pointQ as a octet string. * Thus we will just copy the string. * But to get the field length we decode it. */ int sc_pkcs15_decode_pubkey_ec(sc_context_t *ctx, struct sc_pkcs15_pubkey_ec *key, const u8 *buf, size_t buflen) { int r; u8 * ecpoint_data; size_t ecpoint_len; struct sc_asn1_entry asn1_ec_pointQ[2]; sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ); sc_format_asn1_entry(asn1_ec_pointQ + 0, &ecpoint_data, &ecpoint_len, 1); r = sc_asn1_decode(ctx, asn1_ec_pointQ, buf, buflen, NULL, NULL); if (r < 0) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "ASN.1 encoding failed"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"DEE-EC key=%p, buf=%p, buflen=%d", key, buf, buflen); key->ecpointQ.value = malloc(buflen); if (key->ecpointQ.value == NULL) return SC_ERROR_OUT_OF_MEMORY; key->ecpointQ.len = buflen; memcpy(key->ecpointQ.value, buf, buflen); /* An uncompressed ecpoint is of the form 04||x||y * The 04 indicates uncompressed * x and y are same size, and field_length = sizeof(x) in bits. */ /* TODO: -DEE support more then uncompressed */ key->params.field_length = (ecpoint_len - 1)/2 * 8; if (ecpoint_data) free (ecpoint_data); return r; }
static int gp_select_applet(sc_card_t *card, const u8 *aid, size_t aid_len) { int r; u8 buf[SC_MAX_APDU_BUFFER_SIZE]; struct sc_context *ctx = card->ctx; struct sc_apdu apdu; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xa4, 0x04, 0x00); apdu.lc = aid_len; apdu.data = aid; apdu.datalen = aid_len; apdu.resp = buf; apdu.le = 256; apdu.resplen = sizeof(buf); r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); r = sc_check_sw(card, apdu.sw1, apdu.sw2); if (r) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r); return SC_SUCCESS; }
static int gemsafe_decipher(struct sc_card *card, const u8 * crgram, size_t crgram_len, u8 *out, size_t outlen) { int r; struct sc_apdu apdu; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; sc_context_t *ctx = card->ctx; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (crgram_len > 255) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS); sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x80, 0x84); apdu.cla |= 0x80; apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); apdu.le = crgram_len; apdu.data = crgram; apdu.lc = crgram_len; apdu.datalen = crgram_len; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) { int len = apdu.resplen > outlen ? outlen : apdu.resplen; memcpy(out, apdu.resp, len); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, len); } SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2)); }
static int encode_dir_record(sc_context_t *ctx, const sc_app_info_t *app, u8 **buf, size_t *buflen) { struct sc_asn1_entry asn1_dirrecord[5], asn1_dir[2]; sc_app_info_t tapp = *app; int r; size_t label_len; sc_copy_asn1_entry(c_asn1_dirrecord, asn1_dirrecord); sc_copy_asn1_entry(c_asn1_dir, asn1_dir); sc_format_asn1_entry(asn1_dir + 0, asn1_dirrecord, NULL, 1); sc_format_asn1_entry(asn1_dirrecord + 0, (void *) tapp.aid.value, (void *) &tapp.aid.len, 1); if (tapp.label != NULL) { label_len = strlen(tapp.label); sc_format_asn1_entry(asn1_dirrecord + 1, tapp.label, &label_len, 1); } if (tapp.path.len) sc_format_asn1_entry(asn1_dirrecord + 2, (void *) tapp.path.value, (void *) &tapp.path.len, 1); if (tapp.ddo.value != NULL && tapp.ddo.len) sc_format_asn1_entry(asn1_dirrecord + 3, (void *) tapp.ddo.value, (void *) &tapp.ddo.len, 1); r = sc_asn1_encode(ctx, asn1_dir, buf, buflen); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Encode DIR record error"); return SC_SUCCESS; }
static int entersafe_create_mf(sc_card_t *card, sc_entersafe_create_data * data) { int r; sc_apdu_t apdu; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); memcpy(data->data.df.init_key, init_key, sizeof(init_key)); sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xE0,0x00,0x00); apdu.cla=0x84; apdu.data=(u8*)&data->data.df; apdu.datalen=apdu.lc=sizeof(data->data.df); switch(card->type) { case SC_CARD_TYPE_ENTERSAFE_3K: { r = entersafe_transmit_apdu(card, &apdu,trans_code_3k,sizeof(trans_code_3k),0,1); }break; case SC_CARD_TYPE_ENTERSAFE_FTCOS_PK_01C: { r = entersafe_transmit_apdu(card, &apdu,trans_code_ftcos_pk_01c,sizeof(trans_code_ftcos_pk_01c),0,1); }break; default: { r = SC_ERROR_INTERNAL; }break; } SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); return sc_check_sw(card, apdu.sw1, apdu.sw2); }
static int entersafe_select_fid(sc_card_t *card, unsigned int id_hi, unsigned int id_lo, sc_file_t **file_out) { int r; sc_file_t *file=0; sc_path_t path; path.type=SC_PATH_TYPE_FILE_ID; path.value[0]=id_hi; path.value[1]=id_lo; path.len=2; r = iso_ops->select_file(card,&path,&file); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); /* update cache */ if (file->type == SC_FILE_TYPE_DF) { card->cache.current_path.type = SC_PATH_TYPE_PATH; card->cache.current_path.value[0] = 0x3f; card->cache.current_path.value[1] = 0x00; if (id_hi == 0x3f && id_lo == 0x00){ card->cache.current_path.len = 2; }else{ card->cache.current_path.len = 4; card->cache.current_path.value[2] = id_hi; card->cache.current_path.value[3] = id_lo; } } if (file_out) *file_out = file; SC_FUNC_RETURN(card->ctx, 2, SC_SUCCESS); }
static int entersafe_store_key(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *obj, sc_pkcs15_prkey_t *key) { sc_pkcs15_prkey_info_t *kinfo = (sc_pkcs15_prkey_info_t *) obj->data; sc_card_t *card = p15card->card; sc_entersafe_wkey_data data; sc_file_t *tfile; const sc_acl_entry_t *acl_entry; int r; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); if (key->algorithm != SC_ALGORITHM_RSA) /* ignore DSA keys */ SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_INVALID_ARGUMENTS); r = sc_profile_get_file(profile, "PKCS15-AODF", &tfile); if (r < 0) return r; acl_entry = sc_file_get_acl_entry(tfile, SC_AC_OP_UPDATE); if (acl_entry->method != SC_AC_NONE) { r = sc_pkcs15init_authenticate(profile, p15card, tfile, SC_AC_OP_UPDATE); if(r<0) r = SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; } sc_file_free(tfile); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "cant verify pin"); data.key_id = (u8) kinfo->key_reference; data.usage=0x22; data.key_data.rsa=&key->u.rsa; return sc_card_ctl(card, SC_CARDCTL_ENTERSAFE_WRITE_KEY, &data); }
static int asepcos_akn_to_fileid(sc_card_t *card, sc_cardctl_asepcos_akn2fileid_t *p) { int r; u8 sbuf[32], rbuf[SC_MAX_APDU_BUFFER_SIZE]; sc_apdu_t apdu; sbuf[0] = p->akn & 0xff; sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x28, 0x02, 0x01); apdu.cla |= 0x80; apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); apdu.le = 256; apdu.lc = 1; apdu.datalen = 1; apdu.data = sbuf; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); if (apdu.resplen != 4) return SC_ERROR_INTERNAL; p->fileid = (apdu.resp[1] << 16) | (apdu.resp[2] << 8) | apdu.resp[3]; return SC_SUCCESS; }
static int atrust_acos_logout(struct sc_card *card) { int r; struct sc_apdu apdu; const u8 mf_buf[2] = {0x3f, 0x00}; sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x00, 0x0C); apdu.le = 0; apdu.lc = 2; apdu.data = mf_buf; apdu.datalen = 2; apdu.resplen = 0; sc_ctx_suppress_errors_on(card->ctx); r = sc_transmit_apdu(card, &apdu); sc_ctx_suppress_errors_off(card->ctx); SC_TEST_RET(card->ctx, r, "APDU re-transmit failed"); if (apdu.sw1 == 0x69 && apdu.sw2 == 0x85) /* the only possible reason for this error here is, afaik, * that no MF exists, but then there's no need to logout * => return SC_SUCCESS */ return SC_SUCCESS; return sc_check_sw(card, apdu.sw1, apdu.sw2); }
static int update_single_record(sc_card_t *card, sc_app_info_t *app) { u8 *rec; size_t rec_size; int r; r = encode_dir_record(card->ctx, app, &rec, &rec_size); if (r) return r; if (app->rec_nr > 0) r = sc_update_record(card, (unsigned int)app->rec_nr, rec, rec_size, SC_RECORD_BY_REC_NR); else if (app->rec_nr == 0) { /* create new record entry */ r = sc_append_record(card, rec, rec_size, 0); if (r == SC_ERROR_NOT_SUPPORTED) { /* if the card doesn't support APPEND RECORD we try a * UPDATE RECORD on the next unused record (and hope * that there is a record with this index). */ int rec_nr = 0, i; for(i = 0; i < card->app_count; i++) if (card->app[i]->rec_nr > rec_nr) rec_nr = card->app[i]->rec_nr; rec_nr++; r = sc_update_record(card, (unsigned int)rec_nr, rec, rec_size, SC_RECORD_BY_REC_NR); } } else { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "invalid record number\n"); r = SC_ERROR_INTERNAL; } free(rec); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Unable to update EF(DIR) record"); return 0; }
static int itacns_add_pubkey(sc_pkcs15_card_t *p15card, const sc_path_t *path, const sc_pkcs15_id_t *id, const char *label, int usage, int ref, int obj_flags, int *modulus_len_out) { int r; sc_pkcs15_pubkey_info_t info; sc_pkcs15_object_t obj; SC_FUNC_CALLED(p15card->card->ctx, 1); memset(&info, 0, sizeof(info)); memset(&obj, 0, sizeof(obj)); info.id = *id; if (path) info.path = *path; info.usage = usage; info.key_reference = ref; strlcpy(obj.label, label, sizeof(obj.label)); obj.flags = obj_flags; /* * This is hard-coded, unless unforeseen versions of the CNS * turn up sometime. */ info.modulus_length = 1024; *modulus_len_out = info.modulus_length; r = sc_pkcs15emu_add_rsa_pubkey(p15card, &obj, &info); SC_TEST_RET(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, r, "Could not add pub key"); return r; }
static int mcrd_match_card(sc_card_t * card) { int i = 0, r = 0; sc_apdu_t apdu; i = _sc_match_atr(card, mcrd_atrs, &card->type); if (i >= 0) { card->name = mcrd_atrs[i].name; return 1; } sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xA4, 0x04, 0x00); apdu.lc = sizeof(EstEID_v35_AID); apdu.data = EstEID_v35_AID; apdu.datalen = sizeof(EstEID_v35_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_log(card->ctx, "AID found"); card->type = SC_CARD_TYPE_MCRD_ESTEID_V30; return 1; } return 0; }
static int acos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) { int r; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; sc_apdu_t apdu; if (!serial) return SC_ERROR_INVALID_ARGUMENTS; /* see if we have cached serial number */ if (card->serialnr.len) { memcpy(serial, &card->serialnr, sizeof(*serial)); return SC_SUCCESS; } /* get serial number via GET CARD DATA */ sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xf6, 0x00, 0x00); apdu.cla |= 0x80; apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); apdu.le = 256; apdu.lc = 0; apdu.datalen = 0; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, r, "APDU transmit failed"); if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) return SC_ERROR_INTERNAL; /* cache serial number */ memcpy(card->serialnr.value, apdu.resp, apdu.resplen); card->serialnr.len = apdu.resplen; /* copy and return serial number */ memcpy(serial, &card->serialnr, sizeof(*serial)); return SC_SUCCESS; }