int card_sync_card_to_virtual_fs_data_file_callback( sc_card_t *card, struct _virtual_file_t *virtual_file, virtual_fs_t *virtual_fs ) { int r = SC_SUCCESS; unsigned char *card_data = NULL; size_t card_data_length = 0; sc_path_t *path=NULL; SC_FUNC_CALLED(card->ctx, 1); if(!card || !virtual_file) return SC_ERROR_INVALID_ARGUMENTS; path = map_path_to_path_find(DRVDATA(card)->virtual_fs_to_card_path_map, &virtual_file->path); if(!path) { r = SC_ERROR_OBJECT_NOT_FOUND; goto end; } /* get file */ r = card_helper_read_file(card, path, &card_data, &card_data_length); if (r!=SC_SUCCESS) goto end; if (card_data_length>0) { r = virtual_file_data_update(virtual_file, 0, card_data, card_data_length); if(r != SC_SUCCESS) goto end; } end: if(card_data) { free(card_data); card_data = NULL; } SC_FUNC_RETURN(card->ctx, 1, r); }
/* Return the DF_info for the current path. If does not yet exist, create it. Returns NULL on error. */ static struct df_info_s *get_df_info(sc_card_t * card) { sc_context_t *ctx = card->ctx; struct mcrd_priv_data *priv = DRVDATA(card); struct df_info_s *dfi; assert(!priv->is_ef); if (!priv->curpathlen) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "no current path to find the df_info\n"); return NULL; } for (dfi = priv->df_infos; dfi; dfi = dfi->next) { if (dfi->pathlen == priv->curpathlen && !memcmp(dfi->path, priv->curpath, dfi->pathlen * sizeof *dfi->path)) return dfi; } /* Not found, create it. */ dfi = calloc(1, sizeof *dfi); if (!dfi) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "out of memory while allocating df_info\n"); return NULL; } dfi->pathlen = priv->curpathlen; memcpy(dfi->path, priv->curpath, dfi->pathlen * sizeof *dfi->path); dfi->next = priv->df_infos; priv->df_infos = dfi; return dfi; }
static int esteid_set_security_env(sc_card_t *card, const sc_security_env_t *env, int se_num) { struct esteid_priv_data *priv; struct sc_apdu apdu; // XXX: could be const unsigned char cse_crt_aut[] = {0x80, 0x04, 0xFF, 0x20, 0x08, 0x00, 0x84, 0x01, 0x81}; unsigned char cse_crt_sig[] = {0x80, 0x04, 0xFF, 0x15, 0x08, 0x00, 0x84, 0x01, 0x9F}; unsigned char cse_crt_dec[] = {0x80, 0x04, 0xFF, 0x30, 0x04, 0x00, 0x84, 0x01, 0x81}; LOG_FUNC_CALLED(card->ctx); if (card == NULL || env == NULL || env->key_ref_len != 1) LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); sc_log(card->ctx, "algo: %d operation: %d keyref: %d", env->algorithm, env->operation, env->key_ref[0]); if (env->algorithm == SC_ALGORITHM_EC && env->operation == SC_SEC_OPERATION_SIGN && env->key_ref[0] == 1) { sc_format_apdu_ex(card, &apdu, 0x22, 0x41, 0xA4, cse_crt_aut, sizeof(cse_crt_aut), NULL, 0); } else if (env->algorithm == SC_ALGORITHM_EC && env->operation == SC_SEC_OPERATION_SIGN && env->key_ref[0] == 2) { sc_format_apdu_ex(card, &apdu, 0x22, 0x41, 0xB6, cse_crt_sig, sizeof(cse_crt_sig), NULL, 0); } else if (env->algorithm == SC_ALGORITHM_EC && env->operation == SC_SEC_OPERATION_DERIVE && env->key_ref[0] == 1) { sc_format_apdu_ex(card, &apdu, 0x22, 0x41, 0xB8, cse_crt_dec, sizeof(cse_crt_dec), NULL, 0); } else { LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); } SC_TRANSMIT_TEST_RET(card, apdu, "SET SECURITY ENV failed"); priv = DRVDATA(card); priv->sec_env = *env; LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); }
static int itacns_match_cns_card(sc_card_t *card, unsigned int i) { unsigned char *atr = card->atr.value; sc_context_t *ctx; ctx = card->ctx; itacns_atr_match(i, 0x01); /* H7 */ i += 2; /* H8, H9 */ itacns_atr_match(i, 'C'); /* H10 */ itacns_atr_match(i, 'N'); /* H11 */ itacns_atr_match(i, 'S'); /* H12 */ /* H13 */ /* Version byte: h.l, h in the high nibble, l in the low nibble. */ if(card->driver) { DRVDATA(card)->cns_version = atr[i]; } /* Warn if the version is not 1.0. */ if(atr[i] != 0x10) { char version[8]; _snprintf(version, sizeof(version), "%d.%d", (atr[i] >> 4) & 0x0f, atr[i] & 0x0f); sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "CNS card version %s; no official specifications " "are published. Proceeding anyway.\n", version); }
static int esteid_compute_signature(sc_card_t *card, const u8 *data, size_t datalen, u8 *out, size_t outlen) { struct esteid_priv_data *priv = DRVDATA(card); struct sc_security_env *env = NULL; struct sc_apdu apdu; u8 sbuf[SIGNATURE_PAYLOAD_SIZE]; int le = MIN(SC_MAX_APDU_RESP_SIZE, MIN(SIGNATURE_PAYLOAD_SIZE * 2, outlen)); LOG_FUNC_CALLED(card->ctx); if (data == NULL || out == NULL || datalen > SIGNATURE_PAYLOAD_SIZE) LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); env = &priv->sec_env; // left-pad if necessary memcpy(&sbuf[SIGNATURE_PAYLOAD_SIZE - datalen], data, MIN(datalen, SIGNATURE_PAYLOAD_SIZE)); memset(sbuf, 0x00, SIGNATURE_PAYLOAD_SIZE - datalen); datalen = SIGNATURE_PAYLOAD_SIZE; switch (env->key_ref[0]) { case 1: /* authentication key */ sc_format_apdu_ex(card, &apdu, 0x88, 0, 0, sbuf, datalen, out, le); break; default: sc_format_apdu_ex(card, &apdu, 0x2A, 0x9E, 0x9A, sbuf, datalen, out, le); } SC_TRANSMIT_TEST_RET(card, apdu, "PSO CDS/INTERNAL AUTHENTICATE failed"); LOG_FUNC_RETURN(card->ctx, (int)apdu.resplen); }
int card_sync_virtual_fs_to_card_filter_pukey( sc_card_t *card, struct _virtual_file_t *virtual_file, virtual_fs_t *virtual_fs, sc_pkcs15_object_t *obj ) { int r = SC_SUCCESS; struct sc_pkcs15_pubkey_info *pukey = NULL; sc_pkcs15_der_t *der = NULL; sc_path_t *path = NULL; sc_pkcs15_id_t *ckaid = NULL; SC_FUNC_CALLED(card->ctx, 1); if(!card || !virtual_file) return SC_ERROR_INVALID_ARGUMENTS; pukey = (struct sc_pkcs15_pubkey_info *) obj->data; if(pukey) { sc_pkcs15_free_object_content(obj); /* try to find an old der if present */ der = map_id_to_der_find(DRVDATA(card)->pukdf_card_ckaid_to_card_der_map, &pukey->id); if(der) { sc_der_copy(&obj->content, der); } path = map_path_to_path_find(DRVDATA(card)->virtual_fs_to_card_path_map, &pukey->path); if(path) { /* replace path data */ memcpy(&pukey->path, path, sizeof(sc_path_t)); } ckaid = map_opensc_id_to_id_find(DRVDATA(card)->virtual_fs_to_card_ckaid_map, &pukey->id); if(ckaid) { /* replace ckaid */ memcpy(&pukey->id, ckaid, sizeof(struct sc_pkcs15_id)); } /* add manual flags */ pukey->native = 0x01; pukey->access_flags |= SC_PKCS15_PRKEY_ACCESS_LOCAL; pukey->access_flags |= SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE; pukey->key_reference = pukey->path.value[pukey->path.len-1]; } else { sc_debug(card->ctx,SC_LOG_DEBUG_VERBOSE, "Pointer to pukey info was empty"); } SC_FUNC_RETURN(card->ctx, 1, r); }
static int isoApplet_finish(sc_card_t *card) { struct isoApplet_drv_data *drvdata=DRVDATA(card); LOG_FUNC_CALLED(card->ctx); if (drvdata) { free(drvdata); card->drv_data=NULL; } LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); }
static int belpic_pin_cmd_usage(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left, int pin_usage) { #ifdef BELPIC_PIN_PAD sc_apdu_t apdu; int r; struct belpic_priv_data *priv = DRVDATA(card); int lang = belpic_calculate_lang(card); if (card->reader->capabilities & SC_READER_CAP_PIN_PAD && priv->scr_init != NULL) { LONG r; SCR_Card scr_card = { priv->pcsc_card, lang_codes[lang], {NULL, 0} , NULL }; scr_app_belpic.longString = app_id_longstr[lang]; switch (data->cmd) { case SC_PIN_CMD_VERIFY: r = belpic_pp_verify(card, &scr_card, priv, data->pin_reference, pin_usage, tries_left); break; case SC_PIN_CMD_CHANGE: r = belpic_pp_change(card, &scr_card, priv, data->pin_reference, tries_left); break; default: r = SC_ERROR_NOT_SUPPORTED; } if (r == SC_ERROR_AUTH_METHOD_BLOCKED && (priv->options & PP_MSG_PIN_BLOCKED)) scgui_ask_message(app_msg[lang], " ", pin_blocked_msgs[lang], btn_msg_close[lang], NULL, card->reader->name); return r; } #endif /* BELPIC_PIN_PAD */ data->pin1.encoding = data->pin2.encoding = BELPIC_PIN_ENCODING; data->pin1.pad_char = data->pin2.pad_char = BELPIC_PAD_CHAR; data->pin1.min_length = data->pin2.min_length = BELPIC_MIN_USER_PIN_LEN; data->pin1.max_length = data->pin2.max_length = BELPIC_MAX_USER_PIN_LEN; data->apdu = NULL; return iso_ops->pin_cmd(card, data, tries_left); }
static int mcrd_finish(sc_card_t * card) { struct mcrd_priv_data *priv; if (card == NULL) return 0; priv = DRVDATA(card); while (priv->df_infos) { struct df_info_s *tmp = priv->df_infos->next; clear_special_files(priv->df_infos); priv->df_infos = tmp; } free(priv); return 0; }
static int isoApplet_compute_signature(struct sc_card *card, const u8 *data, size_t datalen, u8 *out, size_t outlen) { struct sc_context *ctx = card->ctx; struct isoApplet_drv_data *drvdata = DRVDATA(card); int r; LOG_FUNC_CALLED(ctx); r = iso_ops->compute_signature(card, data, datalen, out, outlen); if(r < 0) { LOG_FUNC_RETURN(ctx, r); } /* If ECDSA was used, the ASN.1 sequence of integers R,S returned by the * card needs to be converted to the raw concatenation of R,S for PKCS#11. */ if(drvdata->sec_env_alg_ref == ISOAPPLET_ALG_REF_ECDSA) { u8* p = NULL; size_t len = (drvdata->sec_env_ec_field_length + 7) / 8 * 2; if (len > outlen) LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL); p = calloc(1,len); if (!p) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); r = sc_asn1_sig_value_sequence_to_rs(ctx, out, r, p, len); if (!r) { memcpy(out, p, len); r = len; } free(p); } LOG_FUNC_RETURN(ctx, r); }
int card_sync_card_to_virtual_fs_filter_pukey( sc_card_t *card, struct _virtual_file_t *virtual_file, virtual_fs_t *virtual_fs, sc_pkcs15_object_t *obj ) { int r = SC_SUCCESS; struct sc_pkcs15_pubkey_info *pukey = NULL; sc_path_t def_path; /* This flag identifies the FIRMA public key */ u8 flag_id[1] = "F"; SC_FUNC_CALLED(card->ctx, 1); memset(&def_path, 0, sizeof(struct sc_path)); if(!card || !virtual_file) return SC_ERROR_INVALID_ARGUMENTS; pukey = (struct sc_pkcs15_pubkey_info *) obj->data; if(pukey) { /* set asn1 to map */ r = map_id_to_der_set_item(DRVDATA(card)->pukdf_card_ckaid_to_card_der_map, &pukey->id, &obj->content); if(r != SC_SUCCESS) goto end; if(pukey->path.len > 0) { if(pukey->path.len == 4) { sc_format_path("3F00", &def_path); r = sc_append_path(&def_path, &pukey->path); if(r!=SC_SUCCESS) goto end; memcpy(pukey->path.value, def_path.value, def_path.len); pukey->path.len = 6; } else { memcpy(&def_path, &pukey->path, sizeof(pukey->path)); } /* append empty file */ r = virtual_fs_append_new_virtual_file(virtual_fs, &def_path, obj->content.value, obj->content.len, obj->content.len, 1, virtual_file_sync_state_unknown, NULL, virtual_file_sync_state_unknown, NULL); if(r != SC_SUCCESS) goto end; /* correct length in PKCS#15 */ pukey->path.count = 0; /* Fixed key usage for FIRMA public key */ if(memcmp(pukey->id.value, flag_id, 1)==0) pukey->usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; } else { sc_debug(card->ctx,SC_LOG_DEBUG_VERBOSE, "Path length is 0"); } } else { sc_debug(card->ctx,SC_LOG_DEBUG_VERBOSE, "Pointer to pukey info was empty"); } end: SC_FUNC_RETURN(card->ctx, 1, r); }
/* Called by belpic_set_security_env() when a NonRep signature will be done, * or by belpic-compute_signature the first fime an auth signature is done * and the allow_sso is true */ static int belpic_askpin_verify(sc_card_t *card, int pin_usage) { struct sc_pin_cmd_data data; sc_apdu_t apdu; u8 pin_data[BELPIC_MAX_USER_PIN_LEN + 1]; int pin_len; int tries_left; int r; struct belpic_priv_data *priv = DRVDATA(card); int lang = belpic_calculate_lang(card); char *enter_pin_msg = (pin_usage == SCR_USAGE_AUTH ? enter_pin_msg_auth[lang] : enter_pin_msg_sign[lang]); scgui_param_t icon = (pin_usage == SCR_USAGE_AUTH ? SCGUI_NO_ICON : SCGUI_SIGN_ICON); data.pin1.encoding = BELPIC_PIN_ENCODING; data.pin1.pad_char = BELPIC_PAD_CHAR; data.pin1.min_length = BELPIC_MIN_USER_PIN_LEN; data.pin1.max_length = BELPIC_MAX_USER_PIN_LEN; data.cmd = SC_PIN_CMD_VERIFY; data.flags = 0; data.pin_type = SC_AC_CHV; data.pin_reference = 1; #ifdef BELPIC_PIN_PAD /* In case of a pinpad reader */ if (card->reader->capabilities & SC_READER_CAP_PIN_PAD && priv->scr_init != NULL) { data.pin1.data = NULL; data.pin1.len = 0; return belpic_pin_cmd_usage(card, &data, &tries_left, pin_usage); } #endif pin_len = BELPIC_MAX_USER_PIN_LEN + 1; r = scgui_enterpin(app_msg[lang], enter_pin_msg, pin_data, &pin_len, btn_msg_ok[lang], btn_msg_cancel[lang], wrong_pin_len_msgs[lang], icon); if (r == SCGUI_CANCEL) return SC_ERROR_KEYPAD_CANCELLED; if (r != SCGUI_OK) return SC_ERROR_INTERNAL; data.pin1.data = pin_data; data.pin1.len = pin_len; r = belpic_pin_cmd_usage(card, &data, &tries_left, pin_usage); /* card->ctx->allow_sso = true: we do PIN mgmnt ourselves */ while (r == SC_ERROR_PIN_CODE_INCORRECT && SSO_OK(card->ctx)) { int r1; char msg[200]; sprintf(msg, wrong_pin_msgs[lang], tries_left); r1 = scgui_ask_message(app_msg[lang], pin_usg_auth[lang], msg, btn_msg_retry[lang], btn_msg_cancel[lang], card->reader->name); if (r1 == SCGUI_CANCEL) return r; else if (r1 != SCGUI_OK) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "scgui_ask_message returned %d\n", r1); return SC_ERROR_INTERNAL; } pin_len = BELPIC_MAX_USER_PIN_LEN + 1; r = scgui_enterpin(app_msg[lang], enter_pin_msg, pin_data, &pin_len, btn_msg_ok[lang], btn_msg_cancel[lang], wrong_pin_len_msgs[lang], icon); if (r == SCGUI_CANCEL) return SC_ERROR_KEYPAD_CANCELLED; if (r != SCGUI_OK) return SC_ERROR_INTERNAL; data.pin1.data = pin_data; data.pin1.len = pin_len; r = belpic_pin_cmd_usage(card, &data, &tries_left, pin_usage); if (tries_left == 0) r = SC_ERROR_AUTH_METHOD_BLOCKED; } if (r == SC_ERROR_AUTH_METHOD_BLOCKED && SSO_OK(card->ctx)) scgui_ask_message(app_msg[lang], " ", pin_blocked_msgs[lang], btn_msg_close[lang], NULL, card->reader->name); return r; }
static int belpic_calculate_lang(sc_card_t *card) { struct belpic_priv_data *priv = DRVDATA(card); int lang = priv->lang; return lang; }
int card_sync_virtual_fs_to_card_certificate_file_callback( sc_card_t *card, struct _virtual_file_t *virtual_file, virtual_fs_t *virtual_fs ) { int r = SC_SUCCESS; unsigned char *compressed_data = NULL; size_t compressed_data_length = 0; struct _virtual_file_t *certificate_virtual_file=NULL; sc_pkcs15_id_t *card_ckaid=NULL; sc_path_t *cert_path=NULL; SC_FUNC_CALLED(card->ctx, 1); if(!card || !virtual_file) return SC_ERROR_INVALID_ARGUMENTS; r = file_compress_data(card, virtual_file->data, virtual_file->data_size, &compressed_data, &compressed_data_length); if(r!=SC_SUCCESS) goto cert_vfs2c_end; /* create certificate file into card */ r = card_helper_create_cert_file(card, virtual_file, compressed_data_length, &certificate_virtual_file); if(r!=SC_SUCCESS) goto cert_vfs2c_end; /* set file data to card */ r = card_helper_update_file(card, &certificate_virtual_file->path, compressed_data, compressed_data_length); if(r!=SC_SUCCESS) goto cert_vfs2c_end; /* add path_to_path */ r = map_path_to_path_set_item(DRVDATA(card)->virtual_fs_to_card_path_map, &virtual_file->path, &certificate_virtual_file->path); if(r != SC_SUCCESS) goto cert_vfs2c_end; /* get ckaid from certificate (computeing a sha1 form public key modulus) */ card_ckaid = calloc(1, sizeof(struct sc_pkcs15_id)); if (!card_ckaid) { r = SC_ERROR_OUT_OF_MEMORY; goto cert_vfs2c_end; } r = get_ckaid_from_certificate( card, virtual_file->data, virtual_file->data_size, card_ckaid ); if(r!=SC_SUCCESS) goto cert_vfs2c_end; cert_path = calloc(1, sizeof(struct sc_path)); if(!cert_path) { r = SC_ERROR_OUT_OF_MEMORY; goto cert_vfs2c_end; } memcpy(cert_path, &certificate_virtual_file->path, sizeof(struct sc_path)); r = map_path_to_id_set_item(DRVDATA(card)->card_path_to_card_ckaid_map, cert_path, card_ckaid); if(r!=SC_SUCCESS) goto cert_vfs2c_end; /* ownership regards to vfs */ certificate_virtual_file=NULL; card_ckaid=NULL; cert_path=NULL; cert_vfs2c_end: if(compressed_data) { free(compressed_data); compressed_data = NULL; } if(certificate_virtual_file) { free(certificate_virtual_file); certificate_virtual_file=NULL; } if(card_ckaid) { free(card_ckaid); card_ckaid=NULL; } if(cert_path) { free(cert_path); cert_path=NULL; } SC_FUNC_RETURN(card->ctx, 1, r); }
static int belpic_finish(sc_card_t *card) { free(DRVDATA(card)); return 0; }
int card_sync_virtual_fs_to_card_filter_cert( sc_card_t *card, struct _virtual_file_t *virtual_file, virtual_fs_t *virtual_fs, sc_pkcs15_object_t *obj ) { int r = SC_SUCCESS; struct sc_pkcs15_cert_info *cert = NULL; sc_pkcs15_der_t *der = NULL; sc_path_t *path = NULL; sc_pkcs15_id_t *ckaid = NULL; struct _virtual_file_t *tmp_vf=NULL; unsigned char *compressed_data = NULL; size_t compressed_data_length = 0; SC_FUNC_CALLED(card->ctx, 1); if(!card || !virtual_file) return SC_ERROR_INVALID_ARGUMENTS; cert = (struct sc_pkcs15_cert_info *) obj->data; if(cert) { sc_pkcs15_free_object_content(obj); /* try to find an old der if present */ der = map_id_to_der_find(DRVDATA(card)->cdf_card_ckaid_to_card_der_map, &cert->id); if(der) { sc_der_copy(&obj->content, der); } path = map_path_to_path_find(DRVDATA(card)->virtual_fs_to_card_path_map, &cert->path); if(path) { /* replace path data */ memcpy(&cert->path, path, sizeof(sc_path_t)); tmp_vf=virtual_fs_find_by_path(virtual_fs, &cert->path); if(!tmp_vf) { r = SC_ERROR_INVALID_DATA; goto end; } r = file_compress_data(card, tmp_vf->data, tmp_vf->data_size, &compressed_data, &compressed_data_length); if(r!=SC_SUCCESS) goto end; /* certificate file has an info header */ cert->path.count = compressed_data_length+8; } ckaid = map_opensc_id_to_id_find(DRVDATA(card)->virtual_fs_to_card_ckaid_map, &cert->id); if(ckaid) { /* replace ckaid */ memcpy(&cert->id, ckaid, sizeof(struct sc_pkcs15_id)); } else { ckaid = map_path_to_id_find(DRVDATA(card)->card_path_to_card_ckaid_map, &cert->path); if (ckaid) { /* replace ckaid */ memcpy(&cert->id, ckaid, sizeof(struct sc_pkcs15_id)); } } } end: if(compressed_data) { free(compressed_data); compressed_data = NULL; } SC_FUNC_RETURN(card->ctx, 1, r); }
static int isoApplet_set_security_env(sc_card_t *card, const sc_security_env_t *env, int se_num) { sc_apdu_t apdu; u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 *p; int r; struct isoApplet_drv_data *drvdata = DRVDATA(card); LOG_FUNC_CALLED(card->ctx); if(se_num != 0) { LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "IsoApplet does not support storing of security environments."); } assert(card != NULL && env != NULL); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0); switch (env->operation) { case SC_SEC_OPERATION_DECIPHER: apdu.p2 = 0xB8; break; case SC_SEC_OPERATION_SIGN: apdu.p2 = 0xB6; break; default: return SC_ERROR_INVALID_ARGUMENTS; } p = sbuf; if (env->flags & SC_SEC_ENV_ALG_PRESENT) { switch(env->algorithm) { case SC_ALGORITHM_RSA: if( env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1 ) { drvdata->sec_env_alg_ref = ISOAPPLET_ALG_REF_RSA_PAD_PKCS1; } else { LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "IsoApplet only supports RSA with PKCS1 padding."); } break; case SC_ALGORITHM_EC: if( env->algorithm_flags & SC_ALGORITHM_ECDSA_RAW ) { drvdata->sec_env_alg_ref = ISOAPPLET_ALG_REF_ECDSA; drvdata->sec_env_ec_field_length = env->algorithm_ref; } else { LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "IsoApplet only supports raw ECDSA."); } break; default: LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported algorithm."); } *p++ = 0x80; /* algorithm reference */ *p++ = 0x01; *p++ = drvdata->sec_env_alg_ref; } if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) { *p++ = 0x81; *p++ = env->file_ref.len; assert(sizeof(sbuf) - (p - sbuf) >= env->file_ref.len); memcpy(p, env->file_ref.value, env->file_ref.len); p += env->file_ref.len; } if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) { if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC) *p++ = 0x83; else *p++ = 0x84; *p++ = env->key_ref_len; assert(sizeof(sbuf) - (p - sbuf) >= env->key_ref_len); memcpy(p, env->key_ref, env->key_ref_len); p += env->key_ref_len; } r = p - sbuf; apdu.lc = r; apdu.datalen = r; apdu.data = sbuf; if (apdu.datalen != 0) { r = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); r = sc_check_sw(card, apdu.sw1, apdu.sw2); LOG_TEST_RET(card->ctx, r, "Card returned error"); } LOG_FUNC_RETURN(card->ctx, r); }
static int esteid_finish(sc_card_t *card) { if (card != NULL) free(DRVDATA(card)); return 0; }
/* 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; struct mcrd_priv_data *priv = DRVDATA(card); int r, recno; struct df_info_s *dfi; struct rule_record_s *rule; struct keyd_record_s *keyd; assert(!priv->is_ef); /* 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, 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, 2, r); } else { rule = (struct rule_record_s *)malloc(sizeof *rule + r); if (!rule) SC_FUNC_RETURN(ctx, 0, 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, "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, "no EF_KeyD file available\n"); return 0; /* That is okay. */ } SC_TEST_RET(ctx, 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, 2, r); } else { keyd = (struct keyd_record_s *)malloc(sizeof *keyd + r); if (!keyd) SC_FUNC_RETURN(ctx, 0, 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, "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; }
int card_sync_card_to_virtual_fs_filter_data_object( sc_card_t *card, struct _virtual_file_t *virtual_file, virtual_fs_t *virtual_fs, sc_pkcs15_object_t *obj ) { int r = SC_SUCCESS; struct sc_pkcs15_data_info *data = NULL; unsigned char *card_data = NULL; virtual_file_t *data_virtual_file = NULL; virtual_file_t *data_virtual_file_weak_link = NULL; sc_path_t abs_data_path, data_card_path, def_path; SC_FUNC_CALLED(card->ctx, 1); /* we need to correct certificate length in path */ data = (struct sc_pkcs15_data_info *) obj->data; if(data) { if(data->path.len > 0) { data_virtual_file = virtual_file_new(); if(!data_virtual_file) { r = SC_ERROR_OUT_OF_MEMORY; goto end; } memset(&abs_data_path, 0, sizeof(struct sc_path)); memset(&data_card_path, 0, sizeof(struct sc_path)); memset(&def_path, 0, sizeof(struct sc_path)); if(data->path.len == 4) { sc_format_path("3F00", &def_path); r = sc_append_path(&def_path, &data->path); if(r!=SC_SUCCESS) goto end; memcpy(data->path.value, def_path.value, def_path.len); data->path.len = 6; } else { memcpy(&def_path, &data->path, sizeof(data->path)); } r = sc_append_path(&abs_data_path, &def_path); if(r!=SC_SUCCESS) goto end; if(abs_data_path.len==6) { r = sc_append_path(&data_card_path, &def_path); if(r!=SC_SUCCESS) goto end; } memcpy(&data_virtual_file->path, &abs_data_path, sizeof(data_virtual_file->path)); r = map_path_to_path_set_item(DRVDATA(card)->virtual_fs_to_card_path_map, &data_virtual_file->path, &data_card_path); if(r != SC_SUCCESS) goto end; data_virtual_file->is_ef = 1; data_virtual_file->card_to_virtual_fs.sync_state = virtual_file_sync_state_sync_pending; data_virtual_file->card_to_virtual_fs.sync_callback = card_sync_card_to_virtual_fs_data_file_callback; data_virtual_file->virtual_fs_to_card.sync_state = virtual_file_sync_state_unknown; data_virtual_file->virtual_fs_to_card.sync_callback = NULL; /* append file to virtual_fs */ r = virtual_fs_append(virtual_fs, data_virtual_file); if(r != SC_SUCCESS) goto end; /* we don't have ownership of virtual_file now, so we don't need to free it */ data_virtual_file_weak_link = data_virtual_file; data_virtual_file = NULL; /* we now synchronize file because this gets a correct size for it */ r = virtual_file_data_synchronize(data_virtual_file_weak_link, card, virtual_file_sync_type_card_to_virtual_fs, DRVDATA(card)->virtual_fs); if (r != SC_SUCCESS) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Synchronization failed\n"); goto end; } /* correct length in PKCS#15 */ data->path.count = data_virtual_file_weak_link->data_size; obj->auth_id.value[0]=0x01; obj->auth_id.len=0x01; } else { sc_debug(card->ctx,SC_LOG_DEBUG_VERBOSE, "Path length is 0"); } } else { sc_debug(card->ctx,SC_LOG_DEBUG_VERBOSE, "Pointer to data info was empty"); } end: if(card_data) { free(card_data); card_data = NULL; } if(data_virtual_file) { virtual_file_free(data_virtual_file); data_virtual_file = NULL; } SC_FUNC_RETURN(card->ctx, 1, r); }
int card_sync_card_to_virtual_fs_filter_cert( sc_card_t *card, struct _virtual_file_t *virtual_file, virtual_fs_t *virtual_fs, sc_pkcs15_object_t *obj ) { int r = SC_SUCCESS; struct sc_pkcs15_cert_info *cert = NULL; unsigned char *card_data = NULL; virtual_file_t *certificate_virtual_file = NULL; virtual_file_t *certificate_virtual_file_weak_link = NULL; sc_path_t abs_cert_path, cert_card_path; SC_FUNC_CALLED(card->ctx, 1); /* we need to correct certificate length in path */ cert = (struct sc_pkcs15_cert_info *) obj->data; if(cert) { /* set asn1 to map */ r = map_id_to_der_set_item(DRVDATA(card)->cdf_card_ckaid_to_card_der_map, &cert->id, &obj->content); if(r != SC_SUCCESS) goto end; if(cert->path.len > 0) { certificate_virtual_file = virtual_file_new(); if(!certificate_virtual_file) { r = SC_ERROR_OUT_OF_MEMORY; goto end; } memset(&abs_cert_path, 0, sizeof(struct sc_path)); memset(&cert_card_path, 0, sizeof(struct sc_path)); if(cert->path.len==2) { sc_format_path("3F005015", &abs_cert_path); r = sc_append_path(&abs_cert_path, &cert->path); if(r!=SC_SUCCESS) goto end; sc_format_path("3F006061", &cert_card_path); r = sc_append_path(&cert_card_path, &cert->path); if(r!=SC_SUCCESS) goto end; } else if(cert->path.len==4) { sc_format_path("3F00", &abs_cert_path); r = sc_append_path(&abs_cert_path, &cert->path); if(r!=SC_SUCCESS) goto end; sc_format_path("3F00", &cert_card_path); r = sc_append_path(&cert_card_path, &cert->path); if(r!=SC_SUCCESS) goto end; memcpy(cert->path.value, cert_card_path.value, cert_card_path.len); cert->path.len = 6; } else { r = sc_append_path(&abs_cert_path, &cert->path); if(r!=SC_SUCCESS) goto end; if(abs_cert_path.len==6) { r = sc_append_path(&cert_card_path, &cert->path); if(r!=SC_SUCCESS) goto end; } } memcpy(&certificate_virtual_file->path, &abs_cert_path, sizeof(certificate_virtual_file->path)); r = map_path_to_path_set_item(DRVDATA(card)->virtual_fs_to_card_path_map, &certificate_virtual_file->path, &cert_card_path); if(r != SC_SUCCESS) goto end; certificate_virtual_file->is_ef = 1; certificate_virtual_file->card_to_virtual_fs.sync_state = virtual_file_sync_state_sync_pending; certificate_virtual_file->card_to_virtual_fs.sync_callback = card_sync_card_to_virtual_fs_certificate_file_callback; certificate_virtual_file->virtual_fs_to_card.sync_state = virtual_file_sync_state_unknown; certificate_virtual_file->virtual_fs_to_card.sync_callback = NULL; /* append file to virtual_fs */ r = virtual_fs_append(virtual_fs, certificate_virtual_file); if(r != SC_SUCCESS) goto end; /* we don't have ownership of virtual_file now, so we don't need to free it */ certificate_virtual_file_weak_link = certificate_virtual_file; certificate_virtual_file = NULL; /* we now synchronize file because this gets a correct size for it */ r = virtual_file_data_synchronize(certificate_virtual_file_weak_link, card, virtual_file_sync_type_card_to_virtual_fs, DRVDATA(card)->virtual_fs); if (r != SC_SUCCESS) { sc_debug(card->ctx,SC_LOG_DEBUG_NORMAL, "Synchronization failed\n"); goto end; } /* correct length in PKCS#15 */ cert->path.count = certificate_virtual_file_weak_link->data_size; } else { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,"Path length is 0"); } } else { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE,"Pointer to cert info was empty"); } end: if(card_data) { free(card_data); card_data = NULL; } if(certificate_virtual_file) { virtual_file_free(certificate_virtual_file); certificate_virtual_file = NULL; } SC_FUNC_RETURN(card->ctx, 1, r); }
int card_helper_create_cert_file(sc_card_t *card, struct _virtual_file_t *virtual_file, size_t fcert_len, struct _virtual_file_t **certificate_virtual_file) { int r = SC_SUCCESS; sc_path_t fcert_path; sc_pkcs15_unusedspace_t *unused_space=NULL; sc_pkcs15_card_t *temp_p15card = NULL; int old_use_virtual_fs; /*!< backup of use_virtual_fs */ assert(card!=NULL && virtual_file!=NULL && certificate_virtual_file!=NULL); SC_FUNC_CALLED(card->ctx, 1); /* we backup use_virtual_fs */ old_use_virtual_fs = card_is_virtual_fs_active(card); /* we want to use card without virtual fs */ card_set_virtual_fs_state(card, 0); if(*certificate_virtual_file) { virtual_file_free(*certificate_virtual_file); *certificate_virtual_file = NULL; } memset(&fcert_path, 0, sizeof(struct sc_path)); /* 2. Look for a suitable file on UnusedSpace struct which fits the final certificate file size. 2.1 If found, take file's path to reuse it. 2.2 If not, create a file on Certificate Directory with final certificate len as its size */ /* we create a fake p15card structure */ temp_p15card = sc_pkcs15_card_new(); temp_p15card->card = card; r = sc_find_free_unusedspace( temp_p15card, fcert_len, &unused_space ); if (r!=SC_SUCCESS) goto chccf_end; if(unused_space) { /* we got a path */ r = sc_path_set_dnie ( &fcert_path, unused_space->path.type, unused_space->path.value, unused_space->path.len, unused_space->path.index, unused_space->path.count ); if (r!=SC_SUCCESS) goto chccf_end; } else { sc_path_t temp_path; /* move to certificate DF */ sc_format_path("3F006061", &temp_path); r = card_select_file(card, &temp_path, NULL); if(r != SC_SUCCESS) goto chccf_end; /* we start at 0x7001 file ID */ sc_format_path("7001", &fcert_path); do { r = card_create_cert_file( card, &fcert_path, fcert_len ); if (r == SC_ERROR_OBJECT_ALREADY_EXISTS) { fcert_path.value[1]++; } if(r!=SC_SUCCESS && r!=SC_ERROR_OBJECT_ALREADY_EXISTS) goto chccf_end; } while (r!=SC_SUCCESS); r = SC_SUCCESS; } /* create certificate file into vfs */ r = virtual_fs_append_new_virtual_file( DRVDATA(card)->virtual_fs, &fcert_path, virtual_file->data, virtual_file->data_size, virtual_file->data_size, 1, virtual_file_sync_state_synced, card_sync_card_to_virtual_fs_certificate_file_callback, virtual_file_sync_state_sync_pending, card_sync_virtual_fs_to_card_certificate_file_callback ); if(r != SC_SUCCESS) goto chccf_end; /* retrieve just created virtual file */ *certificate_virtual_file = virtual_fs_find_by_path( DRVDATA(card)->virtual_fs, &fcert_path ); chccf_end: /* we restore use_virtual_fs */ card_set_virtual_fs_state(card, old_use_virtual_fs); if (unused_space) { /* Delete UnusedSpace object if reused and also frees reserved memory */ sc_pkcs15_remove_unusedspace(temp_p15card, unused_space); } if (temp_p15card) { /* set to NULL without freeing because we reused structure */ temp_p15card->card = NULL; /* now free temp structure */ sc_pkcs15_card_free(temp_p15card); temp_p15card = NULL; } SC_FUNC_RETURN(card->ctx, 1, r); }