static int gpk_read_rsa_key(sc_card_t *card, struct sc_pkcs15_pubkey_rsa *rsa) { int n, r; /* Read modulus and exponent */ for (n = 2; ; n++) { sc_pkcs15_bignum_t *bn; u8 buffer[256]; size_t m; r = sc_read_record(card, n, buffer, sizeof(buffer), SC_RECORD_BY_REC_NR); if (r < 1) break; if (buffer[0] == 0x01) bn = &rsa->modulus; else if (buffer[0] == 0x07) bn = &rsa->exponent; else continue; bn->len = r - 1; bn->data = malloc(bn->len); for (m = 0; m < bn->len; m++) bn->data[m] = buffer[bn->len - m]; } return 0; }
static int do_update_record(int argc, char **argv) { u8 buf[240]; size_t buflen; int r, i, err = 1; int rec, offs; sc_path_t path; sc_file_t *file; if (argc != 4) return usage(do_update_record); if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_update_record); rec = strtol(argv[1],NULL,10); offs = strtol(argv[2],NULL,10); printf("in: %i; %i; %s\n", rec, offs, argv[3]); r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); return -1; } if (file->ef_structure != SC_FILE_EF_LINEAR_VARIABLE) { printf("EF structure should be SC_FILE_EF_LINEAR_VARIABLE\n"); goto err; } else if (rec < 1 || rec > file->record_count) { printf("Invalid record number %i\n", rec); goto err; } r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR); if (r<0) { printf("Cannot read record %i; return %i\n", rec, r); goto err;; } buflen = sizeof(buf) - offs; i = parse_string_or_hexdata(argv[3], buf + offs, &buflen); if (!i) { printf("unable to parse data\n"); goto err; } r = sc_update_record(card, rec, buf, r, SC_RECORD_BY_REC_NR); if (r<0) { printf("Cannot update record %i; return %i\n", rec, r); goto err; } printf("Total of %d bytes written to record %i at %i offset.\n", i, rec, offs); err = 0; err: sc_file_free(file); select_current_path_or_die(); return -err; }
static int gpk_pkfile_update_public(struct sc_profile *profile, sc_pkcs15_card_t *p15card, struct pkpart *part) { struct sc_context *ctx = p15card->card->ctx; struct pkcomp *pe; unsigned char buffer[256]; unsigned int m, n, tag; int r = 0, found; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Updating public key elements\n"); /* If we've been given a key with public parts, write them now */ for (n = 2; n < 256; n++) { r = sc_read_record(p15card->card, n, buffer, sizeof(buffer), SC_RECORD_BY_REC_NR); if (r < 0) { r = 0; break; } /* Check for bad record */ if (r < 2) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "key file format error: " "record %u too small (%u bytes)\n", n, r); return SC_ERROR_OBJECT_NOT_VALID; } tag = buffer[0]; for (m = 0, found = 0; m < part->count; m++) { pe = part->components + m; if (pe->tag == tag) { r = sc_update_record(p15card->card, n, pe->data, pe->size, SC_RECORD_BY_REC_NR); if (r < 0) return r; pe->tag = 0; /* mark as stored */ found++; break; } } if (!found) sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "GPK unknown PK tag %u\n", tag); } /* Write all remaining elements */ for (m = 0; r >= 0 && m < part->count; m++) { pe = part->components + m; if (pe->tag != 0) r = sc_append_record(p15card->card, pe->data, pe->size, 0); } return r; }
static int mcrd_set_decipher_key_ref(sc_card_t * card, int key_reference) { sc_apdu_t apdu; sc_path_t path; int r; u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; u8 keyref_data[SC_ESTEID_KEYREF_FILE_RECLEN]; assert(card != NULL); sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xB8); /* track the active keypair */ sc_format_path("0033", &path); r = sc_select_file(card, &path, NULL); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Can't select keyref info file 0x0033"); r = sc_read_record(card, 1, keyref_data, SC_ESTEID_KEYREF_FILE_RECLEN, SC_RECORD_BY_REC_NR); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Can't read keyref info file!"); sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "authkey reference 0x%02x%02x\n", keyref_data[9], keyref_data[10]); sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "signkey reference 0x%02x%02x\n", keyref_data[19], keyref_data[20]); sbuf[0] = 0x83; sbuf[1] = 0x03; sbuf[2] = 0x80; switch (key_reference) { case 1: sbuf[3] = keyref_data[9]; sbuf[4] = keyref_data[10]; break; case 2: sbuf[3] = keyref_data[19]; sbuf[4] = keyref_data[20]; break; } apdu.data = sbuf; apdu.lc = 5; apdu.datalen = 5; r = sc_transmit_apdu(card, &apdu); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed"); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2)); }
static int read_and_print_record_file(sc_file_t *file, unsigned char sfi) { u8 buf[256]; int rec, r; for (rec = 1; ; rec++) { r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR | sfi); if (r == SC_ERROR_RECORD_NOT_FOUND) return 0; if (r < 0) { check_ret(r, SC_AC_OP_READ, "read failed", file); return -1; } printf("Record %d:\n", rec); util_hex_dump_asc(stdout, buf, r, 0); } }
/* * Extract a key component from the public key file populated by * GENERATE KEY PAIR */ static int incrypto34_extract_pubkey(sc_card_t *card, int nr, u8 tag, sc_pkcs15_bignum_t *bn) { u8 buf[256]; int r, count; r = sc_read_record(card, nr, buf, sizeof(buf), SC_RECORD_BY_REC_NR); if (r < 0) return r; count = r - 4; if (count <= 0 || buf[0] != tag || buf[1] != count + 2 || buf[2] != count + 1 || buf[3] != 0) return SC_ERROR_INTERNAL; bn->len = count; bn->data = malloc(count); memcpy(bn->data, buf + 4, count); return 0; }
static int read_and_print_record_file(sc_file_t *file) { u8 buf[256]; int rec, r; for (rec = 1; ; rec++) { ctx->suppress_errors++; r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR); ctx->suppress_errors--; if (r == SC_ERROR_RECORD_NOT_FOUND) return 0; if (r < 0) { check_ret(r, SC_AC_OP_READ, "read failed", file); return -1; } printf("Record %d:\n", rec); hex_dump_asc(stdout, buf, r, 0); } }
static int do_cardos_extract_pubkey(sc_card_t *card, int nr, u8 tag, sc_pkcs15_bignum_t *bn) { u8 buf[256]; int r, count; r = sc_read_record(card, nr, buf, sizeof(buf), SC_RECORD_BY_REC_NR); if (r < 0) return r; count = r - 4; if (count <= 0 || buf[0] != tag || buf[1] != count + 2 || buf[2] != count + 1 || buf[3] != 0) return SC_ERROR_INTERNAL; bn->len = count; bn->data = (u8 *) malloc(count); if (bn->data == NULL) return SC_ERROR_OUT_OF_MEMORY; memcpy(bn->data, buf + 4, count); 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); }
static int sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card) { sc_card_t *card = p15card->card; unsigned char buff[128]; int r, i; sc_path_t tmppath; set_string (&p15card->tokeninfo->label, "ID-kaart"); set_string (&p15card->tokeninfo->manufacturer_id, "AS Sertifitseerimiskeskus"); /* Select application directory */ sc_format_path ("3f00eeee5044", &tmppath); r = sc_select_file (card, &tmppath, NULL); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "select esteid PD failed"); /* read the serial (document number) */ r = sc_read_record (card, SC_ESTEID_PD_DOCUMENT_NR, buff, sizeof(buff), SC_RECORD_BY_REC_NR); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "read document number failed"); buff[r] = '\0'; set_string (&p15card->tokeninfo->serial_number, (const char *) buff); p15card->tokeninfo->flags = SC_PKCS15_TOKEN_PRN_GENERATION | SC_PKCS15_TOKEN_EID_COMPLIANT | SC_PKCS15_TOKEN_READONLY; /* add certificates */ for (i = 0; i < 2; i++) { static const char *esteid_cert_names[2] = { "Isikutuvastus", "Allkirjastamine"}; static char const *esteid_cert_paths[2] = { "3f00eeeeaace", "3f00eeeeddce"}; static int esteid_cert_ids[2] = {1, 2}; struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_object cert_obj; memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); cert_info.id.value[0] = esteid_cert_ids[i]; cert_info.id.len = 1; sc_format_path(esteid_cert_paths[i], &cert_info.path); strlcpy(cert_obj.label, esteid_cert_names[i], sizeof(cert_obj.label)); r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) return SC_ERROR_INTERNAL; #ifdef ENABLE_OPENSSL if (i == 0) { BIO *mem = NULL; X509 *x509 = NULL; sc_pkcs15_cert_t *cert; char cardholder_name[64]; unsigned char *tmp = NULL; r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert); if (r == SC_SUCCESS) { mem = BIO_new_mem_buf(cert->data.value, cert->data.len); if (!mem) { sc_pkcs15_free_certificate(cert); return SC_ERROR_INTERNAL; } x509 = d2i_X509_bio(mem, NULL); BIO_free(mem); sc_pkcs15_free_certificate(cert); if (!x509) return SC_ERROR_INTERNAL; r = X509_NAME_get_index_by_NID(X509_get_subject_name(x509), NID_commonName, -1); if (r >= 0) { X509_NAME_ENTRY *ne; ASN1_STRING *a_str; ne = X509_NAME_get_entry(X509_get_subject_name(x509), r); if (!ne) { X509_free(x509); return SC_ERROR_INTERNAL; } a_str = X509_NAME_ENTRY_get_data(ne); if (!a_str) { X509_free(x509); return SC_ERROR_INTERNAL; } r = ASN1_STRING_to_UTF8(&tmp, a_str); if (r > 0) { if ((unsigned)r > sizeof(cardholder_name) - 1) r = sizeof(cardholder_name) -1; memcpy(cardholder_name, tmp, r); cardholder_name[r] = '\0'; set_string(&p15card->tokeninfo->label, cardholder_name); OPENSSL_free(tmp); } } X509_free(x509); } } #endif } /* the file with key pin info (tries left) */ sc_format_path ("3f000016", &tmppath); r = sc_select_file (card, &tmppath, NULL); if (r < 0) return SC_ERROR_INTERNAL; /* add pins */ for (i = 0; i < 3; i++) { unsigned char tries_left; static const char *esteid_pin_names[3] = { "PIN1", "PIN2", "PUK" }; static const int esteid_pin_min[3] = {4, 5, 8}; static const int esteid_pin_ref[3] = {1, 2, 0}; static const int esteid_pin_authid[3] = {1, 2, 3}; static const int esteid_pin_flags[3] = {0, 0, SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN}; struct sc_pkcs15_auth_info pin_info; struct sc_pkcs15_object pin_obj; memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); /* read the number of tries left for the PIN */ r = sc_read_record (card, i + 1, buff, sizeof(buff), SC_RECORD_BY_REC_NR); if (r < 0) return SC_ERROR_INTERNAL; tries_left = buff[5]; pin_info.auth_id.len = 1; pin_info.auth_id.value[0] = esteid_pin_authid[i]; pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; pin_info.attrs.pin.reference = esteid_pin_ref[i]; pin_info.attrs.pin.flags = esteid_pin_flags[i]; pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; pin_info.attrs.pin.min_length = esteid_pin_min[i]; pin_info.attrs.pin.stored_length = 12; pin_info.attrs.pin.max_length = 12; pin_info.attrs.pin.pad_char = '\0'; pin_info.tries_left = (int)tries_left; pin_info.max_tries = 3; strlcpy(pin_obj.label, esteid_pin_names[i], sizeof(pin_obj.label)); pin_obj.flags = esteid_pin_flags[i]; /* Link normal PINs with PUK */ if (i < 2) { pin_obj.auth_id.len = 1; pin_obj.auth_id.value[0] = 3; } r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) return SC_ERROR_INTERNAL; } /* add private keys */ for (i = 0; i < 2; i++) { static int prkey_pin[2] = {1, 2}; static int prkey_usage[2] = { SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_SIGN, SC_PKCS15_PRKEY_USAGE_NONREPUDIATION}; static const char *prkey_name[2] = { "Isikutuvastus", "Allkirjastamine"}; struct sc_pkcs15_prkey_info prkey_info; struct sc_pkcs15_object prkey_obj; memset(&prkey_info, 0, sizeof(prkey_info)); memset(&prkey_obj, 0, sizeof(prkey_obj)); prkey_info.id.len = 1; prkey_info.id.value[0] = prkey_pin[i]; prkey_info.usage = prkey_usage[i]; prkey_info.native = 1; prkey_info.key_reference = i + 1; if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V30) prkey_info.modulus_length = 2048; else prkey_info.modulus_length = 1024; strlcpy(prkey_obj.label, prkey_name[i], sizeof(prkey_obj.label)); prkey_obj.auth_id.len = 1; prkey_obj.auth_id.value[0] = prkey_pin[i]; prkey_obj.user_consent = 0; prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); if (r < 0) return SC_ERROR_INTERNAL; } return SC_SUCCESS; }
/* * Set up the public key record for a signature only public key */ static int gpk_pkfile_init_public(sc_profile_t *profile, sc_pkcs15_card_t *p15card, sc_file_t *file, unsigned int algo, unsigned int bits, unsigned int usage) { struct sc_context *ctx = p15card->card->ctx; const sc_acl_entry_t *acl; sc_file_t *tmp = NULL; u8 sysrec[7], buffer[256]; unsigned int n, npins; int r, card_type; /* Find out what sort of GPK we're using */ if ((r = sc_card_ctl(p15card->card, SC_CARDCTL_GPK_VARIANT, &card_type)) < 0) return r; /* Set up the system record */ memset(sysrec, 0, sizeof(sysrec)); /* Mapping keyUsage to sysrec[2]: * 0x00 sign & unwrap * 0x10 sign only * 0x20 unwrap only * 0x30 CA key * * We start with a value of 0x30. * If the key allows decryption, clear the sign only bit. * Likewise, if it allows signing, clear the unwrap only bit. */ sysrec[2] = 0x30; if (usage & (SC_PKCS15_PRKEY_USAGE_DECRYPT|SC_PKCS15_PRKEY_USAGE_UNWRAP)) sysrec[2] &= ~0x10; if (usage & (SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_NONREPUDIATION)) sysrec[2] &= ~0x20; if (sysrec[2] == 0x30) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Key usage should specify at least one of sign or decipher"); return SC_ERROR_INVALID_ARGUMENTS; } /* Set the key size and algorithm */ if ((r = gpk_pkfile_keybits(bits, &sysrec[1])) < 0 || (r = gpk_pkfile_keyalgo(algo, &sysrec[5])) < 0) return r; /* Set PIN protection if requested. * As the crypto ACLs are stored inside the file, * we have to get them from the profile here. */ r = sc_profile_get_file_by_path(profile, &file->path, &tmp); if (r < 0) return r; /* Fix up PIN references in file ACL */ if ((r = sc_pkcs15init_fixup_file(profile, p15card, tmp)) < 0) goto out; acl = sc_file_get_acl_entry(tmp, SC_AC_OP_CRYPTO); for (npins = 0; acl; acl = acl->next) { if (acl->method == SC_AC_NONE || acl->method == SC_AC_NEVER) continue; if (acl->method != SC_AC_CHV) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Authentication method not " "supported for private key files.\n"); r = SC_ERROR_NOT_SUPPORTED; goto out; } if (++npins >= 2) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Too many pins for PrKEY file!\n"); r = SC_ERROR_NOT_SUPPORTED; goto out; } sysrec[2] += 0x40; sysrec[3] >>= 4; sysrec[3] |= acl->key_ref << 4; } /* compute checksum - yet another slightly different * checksum algorithm courtesy of Gemplus */ if (card_type >= SC_CARD_TYPE_GPK_GPK8000) { /* This is according to the gpk reference manual */ sysrec[6] = 0xA5; } else { /* And this is what you have to use for the GPK4000 */ sysrec[6] = 0xFF; } for (n = 0; n < 6; n++) sysrec[6] ^= sysrec[n]; r = sc_read_record(p15card->card, 1, buffer, sizeof(buffer), SC_RECORD_BY_REC_NR); if (r >= 0) { if (r != 7 || buffer[0] != 0) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "first record of public key file is not Lsys0"); r = SC_ERROR_OBJECT_NOT_VALID; goto out; } r = sc_update_record(p15card->card, 1, sysrec, sizeof(sysrec), SC_RECORD_BY_REC_NR); } else { r = sc_append_record(p15card->card, sysrec, sizeof(sysrec), 0); } out: if (tmp) sc_file_free(tmp); return r; }
static int insert_pin( sc_pkcs15_card_t *p15card, const char *path, unsigned char id, unsigned char auth_id, unsigned char pin_reference, int min_length, const char *label, int pin_flags ){ sc_card_t *card=p15card->card; sc_context_t *ctx=p15card->card->ctx; sc_file_t *f; struct sc_pkcs15_auth_info pin_info; struct sc_pkcs15_object pin_obj; int r; memset(&pin_info, 0, sizeof(pin_info)); pin_info.auth_id.len = 1; pin_info.auth_id.value[0] = id; pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; pin_info.attrs.pin.reference = pin_reference; pin_info.attrs.pin.flags = pin_flags; pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; pin_info.attrs.pin.min_length = min_length; pin_info.attrs.pin.stored_length = 16; pin_info.attrs.pin.max_length = 16; pin_info.attrs.pin.pad_char = '\0'; sc_format_path(path, &pin_info.path); memset(&pin_obj, 0, sizeof(pin_obj)); strlcpy(pin_obj.label, label, sizeof(pin_obj.label)); pin_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE; pin_obj.auth_id.len = auth_id ? 0 : 1; pin_obj.auth_id.value[0] = auth_id; if(card->type==SC_CARD_TYPE_TCOS_V3){ unsigned char buf[256]; int i, rec_no=0; if(pin_info.path.len>=2) pin_info.path.len-=2; sc_append_file_id(&pin_info.path, 0x5049); if(sc_select_file(card, &pin_info.path, NULL)!=SC_SUCCESS){ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Select(%s) failed\n", sc_print_path(&pin_info.path)); return 1; } sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Searching for PIN-Ref %02X\n", pin_reference); while((r=sc_read_record(card, ++rec_no, buf, sizeof(buf), SC_RECORD_BY_REC_NR))>0){ int found=0, fbz=-1; if(buf[0]!=0xA0) continue; for(i=2;i<buf[1]+2;i+=2+buf[i+1]){ if(buf[i]==0x83 && buf[i+1]==1 && buf[i+2]==pin_reference) ++found; if(buf[i]==0x90) fbz=buf[i+1+buf[i+1]]; } if(found) pin_info.tries_left=fbz; if(found) break; } if(r<=0){ sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"No EF_PWDD-Record found\n"); return 1; } } else { if(sc_select_file(card, &pin_info.path, &f)!=SC_SUCCESS){ sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"Select(%s) failed\n", path); return 1; } pin_info.tries_left=f->prop_attr[3]; sc_file_free(f); } r=sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if(r!=SC_SUCCESS){ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "sc_pkcs15emu_add_pin_obj(%s) failed\n", path); return 4; } sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "%s: OK, FBZ=%d\n", path, pin_info.tries_left); return 0; }
static int insert_key( sc_pkcs15_card_t *p15card, const char *path, unsigned char id, unsigned char key_reference, int key_length, unsigned char auth_id, const char *label ){ sc_card_t *card=p15card->card; sc_context_t *ctx=p15card->card->ctx; sc_file_t *f; struct sc_pkcs15_prkey_info prkey_info; struct sc_pkcs15_object prkey_obj; int r, can_sign, can_crypt; memset(&prkey_info, 0, sizeof(prkey_info)); prkey_info.id.len = 1; prkey_info.id.value[0] = id; prkey_info.native = 1; prkey_info.key_reference = key_reference; prkey_info.modulus_length = key_length; sc_format_path(path, &prkey_info.path); memset(&prkey_obj, 0, sizeof(prkey_obj)); strlcpy(prkey_obj.label, label, sizeof(prkey_obj.label)); prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; prkey_obj.auth_id.len = 1; prkey_obj.auth_id.value[0] = auth_id; can_sign=can_crypt=0; if(card->type==SC_CARD_TYPE_TCOS_V3){ unsigned char buf[256]; int i, rec_no=0; if(prkey_info.path.len>=2) prkey_info.path.len-=2; sc_append_file_id(&prkey_info.path, 0x5349); if(sc_select_file(card, &prkey_info.path, NULL)!=SC_SUCCESS){ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Select(%s) failed\n", sc_print_path(&prkey_info.path)); return 1; } sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Searching for Key-Ref %02X\n", key_reference); while((r=sc_read_record(card, ++rec_no, buf, sizeof(buf), SC_RECORD_BY_REC_NR))>0){ int found=0; if(buf[0]!=0xA0) continue; for(i=2;i<buf[1]+2;i+=2+buf[i+1]){ if(buf[i]==0x83 && buf[i+1]==1 && buf[i+2]==key_reference) ++found; } if(found) break; } if(r<=0){ sc_debug(ctx, SC_LOG_DEBUG_NORMAL,"No EF_KEYD-Record found\n"); return 1; } for(i=0;i<r;i+=2+buf[i+1]){ if(buf[i]==0xB6) can_sign++; if(buf[i]==0xB8) can_crypt++; } } else { if(sc_select_file(card, &prkey_info.path, &f)!=SC_SUCCESS){ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Select(%s) failed\n", sc_print_path(&prkey_info.path)); return 1; } if (f->prop_attr[1] & 0x04) can_crypt=1; if (f->prop_attr[1] & 0x08) can_sign=1; sc_file_free(f); } prkey_info.usage= SC_PKCS15_PRKEY_USAGE_SIGN; if(can_crypt) prkey_info.usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT|SC_PKCS15_PRKEY_USAGE_DECRYPT; if(can_sign) prkey_info.usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; r=sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); if(r!=SC_SUCCESS){ sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "sc_pkcs15emu_add_rsa_prkey(%s) failed\n", path); return 4; } sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "%s: OK%s%s\n", path, can_sign ? ", Sign" : "", can_crypt ? ", Crypt" : ""); return 0; }
static void do_esteid(sc_card_t *card) { sc_path_t path; int r, i; unsigned char buff[512]; if (stats) { int key_used[4]; sc_format_path("3f00eeee0013", &path); r = sc_select_file(card, &path, NULL); if (r) { fprintf(stderr, "Failed to select key counters: %s\n", sc_strerror(r)); goto out; } /* print the counters */ for (i = 1; i <= 4; i++) { r = sc_read_record(card, i, buff, 128, SC_RECORD_BY_REC_NR); key_used[i - 1] = 0xffffff - ((unsigned char) buff[0xc] * 65536 + (unsigned char) buff[0xd] * 256 + (unsigned char) buff[0xe]); } for (i = 0; i < 2; i++) { printf("Key generation #%d usage:\n\tsign: %d\n\tauth: %d\n", i, key_used[i], key_used[i + 2]); } exit_status = EXIT_SUCCESS; goto out; } /* Or just read the datafile */ sc_format_path("3f00eeee5044", &path); r = sc_select_file(card, &path, NULL); if (r) { fprintf(stderr, "Failed to select DF: %s\n", sc_strerror(r)); goto out; } for (i = 0; esteid_data[i].recno != 0; i++) { r = sc_read_record(card, esteid_data[i].recno, buff, 50, SC_RECORD_BY_REC_NR); if (r < 0) { fprintf (stderr, "Failed to read record %d from card: %s\n", esteid_data[i].recno, sc_strerror (r)); goto out; } buff[r] = '\0'; if (exec_program) { unsigned char * cp; cp = malloc(strlen(esteid_data[i].env_name) + strlen((char *) buff) + 2); if (cp) { strcpy((char *) cp,esteid_data[i].env_name); strcat((char *) cp,"="); strcat((char *) cp,(char *) buff); putenv((char *) cp); } } else { printf("%s: %s\n", esteid_data[i].name, buff); } } exit_status = EXIT_SUCCESS; out: return; }
static int do_update_record(int argc, char **argv) { u8 buf[240]; int r, i, err = 1; int rec, offs; sc_path_t path; sc_file_t *file; char *in_str; if (argc < 3 || argc > 4) goto usage; if (arg_to_path(argv[0], &path, 0) != 0) goto usage; rec = strtol(argv[1],NULL,10); offs = strtol(argv[2],NULL,10); in_str = argv[3]; printf("in: %i; %i; %s\n", rec, offs, in_str); r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); return -1; } if (file->ef_structure != SC_FILE_EF_LINEAR_VARIABLE) { printf("EF structure should be SC_FILE_EF_LINEAR_VARIABLE\n"); goto err; } else if (rec < 1 || rec > file->record_count) { printf("Invalid record number %i\n", rec); goto err; } r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR); if (r<0) { printf("Cannot read record %i; return %i\n", rec, r); goto err;; } i = hex2binary(buf + offs, sizeof(buf) - offs, in_str); if (!i) { printf("unable to parse hex value\n"); goto err; } r = sc_update_record(card, rec, buf, r, SC_RECORD_BY_REC_NR); if (r<0) { printf("Cannot update record %i; return %i\n", rec, r); goto err; } printf("Total of %d bytes written to record %i at %i offset.\n", i, rec, offs); err = 0; err: sc_file_free(file); select_current_path_or_die(); return -err; usage: printf("Usage: update_record <file id> rec_nr rec_offs <hex value>\n"); return -1; }
/* 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); if (!dfi) SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INTERNAL); /* 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; }
int sc_pkcs15_read_file(struct sc_pkcs15_card *p15card, const sc_path_t *in_path, u8 **buf, size_t *buflen, sc_file_t **file_out) { sc_file_t *file = NULL; u8 *data = NULL; size_t len = 0, offset = 0; int r; assert(p15card != NULL && in_path != NULL && buf != NULL); if (p15card->card->ctx->debug >= 1) { char pbuf[SC_MAX_PATH_STRING_SIZE]; r = sc_path_print(pbuf, sizeof(pbuf), in_path); if (r != SC_SUCCESS) pbuf[0] = '\0'; sc_debug(p15card->card->ctx, "called, path=%s, index=%u, count=%d\n", pbuf, in_path->index, in_path->count); } r = -1; /* file state: not in cache */ if (p15card->opts.use_cache) { r = sc_pkcs15_read_cached_file(p15card, in_path, &data, &len); } if (r) { r = sc_lock(p15card->card); SC_TEST_RET(p15card->card->ctx, r, "sc_lock() failed"); r = sc_select_file(p15card->card, in_path, &file); if (r) goto fail_unlock; /* Handle the case where the ASN.1 Path object specified * index and length values */ if (in_path->count < 0) { len = file->size; offset = 0; } else { offset = in_path->index; len = in_path->count; /* Make sure we're within proper bounds */ if (offset >= file->size || offset + len > file->size) { r = SC_ERROR_INVALID_ASN1_OBJECT; goto fail_unlock; } } data = (u8 *) malloc(len); if (data == NULL) { r = SC_ERROR_OUT_OF_MEMORY; goto fail_unlock; } if (file->ef_structure == SC_FILE_EF_LINEAR_VARIABLE_TLV) { int i; size_t l, record_len; unsigned char *head; head = data; for (i=1; ; i++) { l = len - (head - data); if (l > 256) { l = 256; } p15card->card->ctx->suppress_errors++; r = sc_read_record(p15card->card, i, head, l, SC_RECORD_BY_REC_NR); p15card->card->ctx->suppress_errors--; if (r == SC_ERROR_RECORD_NOT_FOUND) break; if (r < 0) { free(data); goto fail_unlock; } if (r < 2) break; record_len = head[1]; if (record_len != 0xff) { memmove(head,head+2,r-2); head += (r-2); } else { if (r < 4) break; record_len = head[2] * 256 + head[3]; memmove(head,head+4,r-4); head += (r-4); } } len = head-data; r = len; } else { r = sc_read_binary(p15card->card, offset, data, len, 0); if (r < 0) { free(data); goto fail_unlock; } /* sc_read_binary may return less than requested */ len = r; } sc_unlock(p15card->card); /* Return of release file */ if (file_out != NULL) *file_out = file; else sc_file_free(file); } *buf = data; *buflen = len; return 0; fail_unlock: if (file) sc_file_free(file); sc_unlock(p15card->card); return r; }
int sc_enum_apps(sc_card_t *card) { struct sc_context *ctx = card->ctx; sc_path_t path; int ef_structure; size_t file_size, jj; int r, ii, idx; LOG_FUNC_CALLED(ctx); if (card->app_count < 0) card->app_count = 0; sc_format_path("3F002F00", &path); sc_file_free(card->ef_dir); card->ef_dir = NULL; r = sc_select_file(card, &path, &card->ef_dir); LOG_TEST_RET(ctx, r, "Cannot select EF.DIR file"); if (card->ef_dir->type != SC_FILE_TYPE_WORKING_EF) { sc_file_free(card->ef_dir); card->ef_dir = NULL; LOG_TEST_RET(ctx, SC_ERROR_INVALID_CARD, "EF(DIR) is not a working EF."); } ef_structure = card->ef_dir->ef_structure; if (ef_structure == SC_FILE_EF_TRANSPARENT) { u8 *buf = NULL, *p; size_t bufsize; file_size = card->ef_dir->size; if (file_size == 0) LOG_FUNC_RETURN(ctx, 0); buf = malloc(file_size); if (buf == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); p = buf; r = sc_read_binary(card, 0, buf, file_size, 0); if (r < 0) { free(buf); LOG_TEST_RET(ctx, r, "sc_read_binary() failed"); } bufsize = r; while (bufsize > 0) { if (card->app_count == SC_MAX_CARD_APPS) { sc_log(ctx, "Too many applications on card"); break; } r = parse_dir_record(card, &p, &bufsize, -1); if (r) break; } if (buf) free(buf); } else { /* record structure */ unsigned char buf[256], *p; unsigned int rec_nr; size_t rec_size; /* Arbitrary set '16' as maximal number of records to check out: * to avoid endless loop because of some incomplete cards/drivers */ for (rec_nr = 1; rec_nr < 16; rec_nr++) { r = sc_read_record(card, rec_nr, buf, sizeof(buf), SC_RECORD_BY_REC_NR); if (r == SC_ERROR_RECORD_NOT_FOUND) break; LOG_TEST_RET(ctx, r, "read_record() failed"); if (card->app_count == SC_MAX_CARD_APPS) { sc_log(ctx, "Too many applications on card"); break; } rec_size = r; p = buf; parse_dir_record(card, &p, &rec_size, (int)rec_nr); } } /* Move known PKCS#15 applications to the head of the list */ for (ii=0, idx=0; ii<card->app_count; ii++) { for (jj=0; jj < sizeof(apps)/sizeof(apps[0]); jj++) { if (apps[jj].aid_len != card->app[ii]->aid.len) continue; if (memcmp(apps[jj].aid, card->app[ii]->aid.value, apps[jj].aid_len)) continue; break; } if (ii != idx && jj < sizeof(apps)/sizeof(apps[0])) { struct sc_app_info *tmp = card->app[idx]; card->app[idx] = card->app[ii]; card->app[ii] = tmp; idx++; } } LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
static int sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card) { sc_card_t *card = p15card->card; unsigned char buff[128]; int r, i; size_t field_length = 0, modulus_length = 0; sc_path_t tmppath; set_string (&p15card->tokeninfo->label, "ID-kaart"); set_string (&p15card->tokeninfo->manufacturer_id, "AS Sertifitseerimiskeskus"); /* Select application directory */ sc_format_path ("3f00eeee5044", &tmppath); r = sc_select_file (card, &tmppath, NULL); LOG_TEST_RET(card->ctx, r, "select esteid PD failed"); /* read the serial (document number) */ r = sc_read_record (card, SC_ESTEID_PD_DOCUMENT_NR, buff, sizeof(buff), SC_RECORD_BY_REC_NR); LOG_TEST_RET(card->ctx, r, "read document number failed"); buff[MIN((size_t) r, (sizeof buff)-1)] = '\0'; set_string (&p15card->tokeninfo->serial_number, (const char *) buff); p15card->tokeninfo->flags = SC_PKCS15_TOKEN_PRN_GENERATION | SC_PKCS15_TOKEN_EID_COMPLIANT | SC_PKCS15_TOKEN_READONLY; /* add certificates */ for (i = 0; i < 2; i++) { static const char *esteid_cert_names[2] = { "Isikutuvastus", "Allkirjastamine"}; static char const *esteid_cert_paths[2] = { "3f00eeeeaace", "3f00eeeeddce"}; static int esteid_cert_ids[2] = {1, 2}; struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_object cert_obj; memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); cert_info.id.value[0] = esteid_cert_ids[i]; cert_info.id.len = 1; sc_format_path(esteid_cert_paths[i], &cert_info.path); strlcpy(cert_obj.label, esteid_cert_names[i], sizeof(cert_obj.label)); r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) return SC_ERROR_INTERNAL; if (i != 0) continue; sc_pkcs15_cert_t *cert = NULL; r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert); if (r < 0) return SC_ERROR_INTERNAL; if (cert->key->algorithm == SC_ALGORITHM_EC) field_length = cert->key->u.ec.params.field_length; else modulus_length = cert->key->u.rsa.modulus.len * 8; static const struct sc_object_id cn_oid = {{ 2, 5, 4, 3, -1 }}; u8 *cn_name = NULL; size_t cn_len = 0; sc_pkcs15_get_name_from_dn(card->ctx, cert->subject, cert->subject_len, &cn_oid, &cn_name, &cn_len); if (cn_len > 0) { char *token_name = malloc(cn_len+1); if (token_name) { memcpy(token_name, cn_name, cn_len); token_name[cn_len] = '\0'; set_string(&p15card->tokeninfo->label, (const char*)token_name); free(token_name); } } free(cn_name); sc_pkcs15_free_certificate(cert); } /* the file with key pin info (tries left) */ sc_format_path ("3f000016", &tmppath); r = sc_select_file (card, &tmppath, NULL); if (r < 0) return SC_ERROR_INTERNAL; /* add pins */ for (i = 0; i < 3; i++) { unsigned char tries_left; static const char *esteid_pin_names[3] = { "PIN1", "PIN2", "PUK" }; static const int esteid_pin_min[3] = {4, 5, 8}; static const int esteid_pin_ref[3] = {1, 2, 0}; static const int esteid_pin_authid[3] = {1, 2, 3}; static const int esteid_pin_flags[3] = {0, 0, SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN}; struct sc_pkcs15_auth_info pin_info; struct sc_pkcs15_object pin_obj; memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); /* read the number of tries left for the PIN */ r = sc_read_record (card, i + 1, buff, sizeof(buff), SC_RECORD_BY_REC_NR); if (r < 0) return SC_ERROR_INTERNAL; tries_left = buff[5]; pin_info.auth_id.len = 1; pin_info.auth_id.value[0] = esteid_pin_authid[i]; pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; pin_info.attrs.pin.reference = esteid_pin_ref[i]; pin_info.attrs.pin.flags = esteid_pin_flags[i]; pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; pin_info.attrs.pin.min_length = esteid_pin_min[i]; pin_info.attrs.pin.stored_length = 12; pin_info.attrs.pin.max_length = 12; pin_info.attrs.pin.pad_char = '\0'; pin_info.tries_left = (int)tries_left; pin_info.max_tries = 3; strlcpy(pin_obj.label, esteid_pin_names[i], sizeof(pin_obj.label)); pin_obj.flags = esteid_pin_flags[i]; /* Link normal PINs with PUK */ if (i < 2) { pin_obj.auth_id.len = 1; pin_obj.auth_id.value[0] = 3; } r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) return SC_ERROR_INTERNAL; } /* add private keys */ for (i = 0; i < 2; i++) { static int prkey_pin[2] = {1, 2}; static const char *prkey_name[2] = { "Isikutuvastus", "Allkirjastamine"}; struct sc_pkcs15_prkey_info prkey_info; struct sc_pkcs15_object prkey_obj; memset(&prkey_info, 0, sizeof(prkey_info)); memset(&prkey_obj, 0, sizeof(prkey_obj)); prkey_info.id.len = 1; prkey_info.id.value[0] = prkey_pin[i]; prkey_info.native = 1; prkey_info.key_reference = i + 1; prkey_info.field_length = field_length; prkey_info.modulus_length = modulus_length; if (i == 1) prkey_info.usage = SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; else if(field_length > 0) // ECC has sign and derive usage prkey_info.usage = SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_DERIVE; else prkey_info.usage = SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT; strlcpy(prkey_obj.label, prkey_name[i], sizeof(prkey_obj.label)); prkey_obj.auth_id.len = 1; prkey_obj.auth_id.value[0] = prkey_pin[i]; prkey_obj.user_consent = 0; prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; if(field_length > 0) r = sc_pkcs15emu_add_ec_prkey(p15card, &prkey_obj, &prkey_info); else r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); if (r < 0) return SC_ERROR_INTERNAL; } return SC_SUCCESS; }
static int print_file(sc_card_t *in_card, const sc_file_t *file, const sc_path_t *path, int depth) { int r; const char *tmps; const char *ac_ops_df[] = { "select", "lock", "delete", "create", "rehab", "inval", "list" }; const char *ac_ops_ef[] = { "read", "update", "write", "erase", "rehab", "inval" }; for (r = 0; r < depth; r++) printf(" "); printf("%s ", sc_print_path(path)); if (file->namelen) { printf("["); print_binary(stdout, file->name, file->namelen); printf("] "); } switch (file->type) { case SC_FILE_TYPE_WORKING_EF: tmps = "wEF"; break; case SC_FILE_TYPE_INTERNAL_EF: tmps = "iEF"; break; case SC_FILE_TYPE_DF: tmps = " DF"; break; default: tmps = "unknown"; break; } printf("type: %-3s, ", tmps); if (file->type != SC_FILE_TYPE_DF) { const char *structs[] = { "unknown", "transpnt", "linrfix", "linrfix(TLV)", "linvar", "linvar(TLV)", "lincyc", "lincyc(TLV)" }; int ef_type = file->ef_structure; if (ef_type < 0 || ef_type > 7) ef_type = 0; /* invalid or unknow ef type */ printf("ef structure: %s, ", structs[ef_type]); } printf("size: %lu\n", (unsigned long) file->size); for (r = 0; r < depth; r++) printf(" "); if (file->type == SC_FILE_TYPE_DF) for (r = 0; r < (int) (sizeof(ac_ops_df)/sizeof(ac_ops_df[0])); r++) printf("%s[%s] ", ac_ops_df[r], acl_to_str(sc_file_get_acl_entry(file, r))); else for (r = 0; r < (int) (sizeof(ac_ops_ef)/sizeof(ac_ops_ef[0])); r++) printf("%s[%s] ", ac_ops_ef[r], acl_to_str(sc_file_get_acl_entry(file, r))); if (file->sec_attr_len) { printf("sec: "); /* Octets are as follows: * DF: select, lock, delete, create, rehab, inval * EF: read, update, write, erase, rehab, inval * 4 MSB's of the octet mean: * 0 = ALW, 1 = PIN1, 2 = PIN2, 4 = SYS, * 15 = NEV */ hex_dump(stdout, file->sec_attr, file->sec_attr_len, ":"); } if (file->prop_attr_len) { printf("\n"); for (r = 0; r < depth; r++) printf(" "); printf("prop: "); hex_dump(stdout, file->prop_attr, file->prop_attr_len, ":"); } printf("\n\n"); if (file->type == SC_FILE_TYPE_DF) return 0; if (file->ef_structure == SC_FILE_EF_TRANSPARENT) { unsigned char *buf; if (!(buf = (unsigned char *) malloc(file->size))) { fprintf(stderr, "out of memory"); return 1; } r = sc_read_binary(in_card, 0, buf, file->size, 0); if (r > 0) hex_dump_asc(stdout, buf, r, 0); free(buf); } else { unsigned char buf[256]; int i; for (i=0; i < file->record_count; i++) { printf("Record %d\n", i); r = sc_read_record(in_card, i, buf, 256, 0); if (r > 0) hex_dump_asc(stdout, buf, r, 0); } } return 0; }