static void show_initial_puk(sc_card_t *card) { sc_path_t p; sc_file_t *f; struct sc_apdu a; u8 buf1[128], buf2[128]; int i; printf("\nReading crypted Initial-PUK-file: "); sc_format_path("3F004350",&p); if((i=sc_select_file(card,&p,&f))<0){ printf("Cannot select crypted Initial-PUK-file, %s\n", sc_strerror(i)); return; } if((i=sc_read_binary(card,0,buf1,128,0))!=128){ printf("Cannot read crypted Initial-PUK-file, %s\n", sc_strerror(i)); return; } printf("OK\nDecrypting crypted Initial-PUK-file: "); sc_format_path("3F00DF01",&p); if((i=sc_select_file(card,&p,&f))<0){ printf("Cannot select DF01, %s\n", sc_strerror(i)); return; } sc_format_apdu(card, &a, SC_APDU_CASE_3_SHORT, 0x22, 0xC1, 0xB8); buf2[0]=0x80, buf2[1]=0x01, buf2[2]=0x10, buf2[3]=0x84, buf2[4]=0x01, buf2[5]=0x81; a.data=buf2, a.lc=a.datalen=6; if((i=sc_transmit_apdu(card, &a))<0){ printf("sc_transmit_apdu(MSE) failed, %s\n", sc_strerror(i)); return; } if(a.sw1!=0x90 && a.sw2!=0x00){ printf("MSE=%02X%02X\n", a.sw1, a.sw2); return; } sc_format_apdu(card, &a, SC_APDU_CASE_4_SHORT, 0x2A, 0x84, 0x80); a.data=buf1, a.lc=a.datalen=128; a.resp=buf2, a.le=a.resplen=128; if((i=sc_transmit_apdu(card, &a))<0){ printf("sc_transmit_apdu(PSO) failed, %s\n", sc_strerror(i)); return; } if(a.sw1!=0x90 && a.sw2!=0x00){ printf("PSO=%02X%02X\n", a.sw1, a.sw2); return; } printf("OK ==> Initial-PUK:"); for(i=120;i<128;++i) printf("%c",buf2[i]); printf("\n"); }
int sc_read_binary(sc_card_t *card, unsigned int idx, unsigned char *buf, size_t count, unsigned long flags) { size_t max_le = card->max_recv_size; int r; assert(card != NULL && card->ops != NULL && buf != NULL); sc_log(card->ctx, "called; %d bytes at index %d", count, idx); if (count == 0) return 0; #ifdef ENABLE_SM if (card->sm_ctx.ops.read_binary) { r = card->sm_ctx.ops.read_binary(card, idx, buf, count); if (r) LOG_FUNC_RETURN(card->ctx, r); } #endif if (card->ops->read_binary == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); if (count > max_le) { int bytes_read = 0; unsigned char *p = buf; r = sc_lock(card); LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); while (count > 0) { size_t n = count > max_le ? max_le : count; r = sc_read_binary(card, idx, p, n, flags); if (r < 0) { sc_unlock(card); LOG_TEST_RET(card->ctx, r, "sc_read_binary() failed"); } p += r; idx += r; bytes_read += r; count -= r; if (r == 0) { sc_unlock(card); LOG_FUNC_RETURN(card->ctx, bytes_read); } } sc_unlock(card); LOG_FUNC_RETURN(card->ctx, bytes_read); } r = card->ops->read_binary(card, idx, buf, count, flags); LOG_FUNC_RETURN(card->ctx, r); }
/* * This function pretty much follows what find_tlv in the GNUpg * code does. */ static int read_file(sc_card_t *card, const char *path_name, void *buf, size_t len) { sc_path_t path; sc_file_t *file; int r; sc_format_path(path_name, &path); if ((r = sc_select_file(card, &path, &file)) < 0) return r; if (file->size < len) len = file->size; return sc_read_binary(card, 0, (u8 *) buf, len, 0); }
static int sc_pkcs15emu_sc_hsm_add_pubkey(sc_pkcs15_card_t *p15card, sc_pkcs15_prkey_info_t *key_info, char *label) { sc_card_t *card = p15card->card; sc_pkcs15_pubkey_info_t pubkey_info; sc_pkcs15_object_t pubkey_obj; struct sc_pkcs15_pubkey pubkey; u8 efbin[1024]; sc_cvc_t cvc; u8 *cvcpo; size_t cvclen; int r; // EF.CERT is selected r = sc_read_binary(p15card->card, 0, efbin, sizeof(efbin), 0); LOG_TEST_RET(card->ctx, r, "Could not read CSR from EF"); cvcpo = efbin; cvclen = r; memset(&cvc, 0, sizeof(cvc)); r = sc_pkcs15emu_sc_hsm_decode_cvc(p15card, (const u8 **)&cvcpo, &cvclen, &cvc); LOG_TEST_RET(card->ctx, r, "Could decode certificate signing request"); if (cvc.publicPoint || cvc.publicPointlen) { // ToDo implement support for EC Public Keys return SC_SUCCESS; } else { pubkey.algorithm = SC_ALGORITHM_RSA; pubkey.u.rsa.modulus.data = cvc.primeOrModulus; pubkey.u.rsa.modulus.len = cvc.primeOrModuluslen; pubkey.u.rsa.exponent.data = cvc.coefficientAorExponent; pubkey.u.rsa.exponent.len = cvc.coefficientAorExponentlen; } memset(&pubkey_info, 0, sizeof(pubkey_info)); memset(&pubkey_obj, 0, sizeof(pubkey_obj)); sc_pkcs15_encode_pubkey(p15card->card->ctx, &pubkey, &pubkey_obj.content.value, &pubkey_obj.content.len); pubkey_info.id = key_info->id; strlcpy(pubkey_obj.label, label, sizeof(pubkey_obj.label)); r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); LOG_TEST_RET(card->ctx, r, "Could not add public key"); sc_pkcs15emu_sc_hsm_free_cvc(&cvc); return SC_SUCCESS; }
static int dump_ef(sc_card_t * card, const char *path, u8 * buf, size_t * buf_len) { int rv; sc_file_t *file = sc_file_new(); sc_format_path(path, &file->path); sc_select_file(card, &file->path, &file); if (file->size > *buf_len) return SC_ERROR_BUFFER_TOO_SMALL; rv = sc_read_binary(card, 0, buf, file->size, 0); if (rv < 0) return rv; *buf_len = rv; return SC_SUCCESS; }
/* Select and read a transparent EF */ static int read_transp(sc_card_t *card, const char *pathstring, unsigned char *buf, int buflen) { sc_path_t path; int r; sc_format_path(pathstring, &path); r = sc_select_file(card, &path, NULL); if (r < 0) fprintf(stderr, "\nFailed to select file %s: %s\n", pathstring, sc_strerror(r)); else { r = sc_read_binary(card, 0, buf, buflen, 0); if (r < 0) fprintf(stderr, "\nFailed to read %s: %s\n", pathstring, sc_strerror(r)); } return r; }
static int do_userinfo(sc_card_t *card) { int i; /* FIXME there are no length checks on buf. */ unsigned char buf[2048]; for (i = 0; openpgp_data[i].ef != NULL; i++) { sc_path_t path; sc_file_t *file; size_t count; int r; sc_format_path(openpgp_data[i].ef, &path); r = sc_select_file(card, &path, &file); if (r) { fprintf(stderr, "Failed to select EF %s: %s\n", openpgp_data[i].ef, sc_strerror(r)); return EXIT_FAILURE; } count = file->size; if (!count) continue; if (count > sizeof(buf) - 1) { fprintf(stderr, "Too small buffer to read the OpenPGP data\n"); return EXIT_FAILURE; } r = sc_read_binary(card, 0, buf, count, 0); if (r < 0) { fprintf(stderr, "%s: read failed - %s\n", openpgp_data[i].ef, sc_strerror(r)); return EXIT_FAILURE; } if (r != (signed)count) { fprintf(stderr, "%s: expecting %"SC_FORMAT_LEN_SIZE_T"d, got only %d bytes\n", openpgp_data[i].ef, count, r); return EXIT_FAILURE; } buf[count] = '\0'; display_data(openpgp_data + i, (char *) buf); } return EXIT_SUCCESS; }
static int get_cert_len(sc_card_t *card, sc_path_t *path) { int r; u8 buf[8]; r = sc_select_file(card, path, NULL); if (r < 0) return 0; r = sc_read_binary(card, 0, buf, sizeof(buf), 0); if (r < 0) return 0; if (buf[0] != 0x30 || buf[1] != 0x82) return 0; path->index = 0; path->count = ((((size_t) buf[2]) << 8) | buf[3]) + 4; return 1; }
static void show_certs(sc_card_t *card) { sc_path_t p; sc_file_t *f; X509 *c; u8 buf[2000]; const u8 *q; int j; size_t i; printf("\n"); for(i=0;i<sizeof(certlist)/sizeof(certlist[0]);++i){ printf("Certificate %lu: %s", (unsigned long) i, certlist[i].label); fflush(stdout); sc_format_path(certlist[i].path,&p); if((j=sc_select_file(card,&p,&f))<0){ printf(", Cannot select Cert-file %s, is this a NetKey-Card ??\n", certlist[i].path ); continue; } if(f->type!=SC_FILE_TYPE_WORKING_EF || f->ef_structure!=SC_FILE_EF_TRANSPARENT){ printf(", Invald Cert-file: Type=%d, EF-Structure=%d\n", f->type, f->ef_structure); continue; } if((j=sc_read_binary(card,0,buf,f->size,0))<0){ printf(", Cannot read Cert-file, %s\n", sc_strerror(j)); continue; } printf(", Maxlen=%lu", (unsigned long) f->size); q=buf; if(q[0]==0x30 && q[1]==0x82){ if(q[4]==6 && q[5]<10 && q[q[5]+6]==0x30 && q[q[5]+7]==0x82) q+=q[5]+6; printf(", Len=%d\n", (q[2]<<8)|q[3]); if((c=d2i_X509(NULL,&q,f->size))){ char buf2[2000]; X509_NAME_get_text_by_NID(c->cert_info->subject, NID_commonName, buf2,sizeof(buf2)); printf(" Subject-CN: %s\n", buf2); X509_NAME_get_text_by_NID(c->cert_info->issuer, NID_commonName, buf2,sizeof(buf2)); printf(" Issuer-CN: %s\n", buf2); X509_free(c); } else printf(" Invalid Certificate-Data\n"); } else printf(", empty\n"); } }
/* * Add a unrelated certificate object and description in PKCS#15 format to the framework */ static int sc_pkcs15emu_sc_hsm_add_cd(sc_pkcs15_card_t * p15card, u8 id) { sc_card_t *card = p15card->card; sc_pkcs15_cert_info_t *cert_info; sc_pkcs15_object_t obj; sc_file_t *file = NULL; sc_path_t path; u8 fid[2]; u8 efbin[512]; const u8 *ptr; size_t len; int r; fid[0] = CD_PREFIX; fid[1] = id; /* Try to select a related EF containing the PKCS#15 description of the data */ sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, sizeof(fid), 0, 0); r = sc_select_file(card, &path, &file); if (r != SC_SUCCESS) { return SC_SUCCESS; } sc_file_free(file); r = sc_read_binary(p15card->card, 0, efbin, sizeof(efbin), 0); LOG_TEST_RET(card->ctx, r, "Could not read EF.DCOD"); memset(&obj, 0, sizeof(obj)); ptr = efbin; len = r; r = sc_pkcs15_decode_cdf_entry(p15card, &obj, &ptr, &len); LOG_TEST_RET(card->ctx, r, "Could not decode EF.CD"); cert_info = (sc_pkcs15_cert_info_t *)obj.data; r = sc_pkcs15emu_add_x509_cert(p15card, &obj, cert_info); LOG_TEST_RET(card->ctx, r, "Could not add data object to framework"); return SC_SUCCESS; }
int sc_read_binary(sc_card_t *card, unsigned int idx, unsigned char *buf, size_t count, unsigned long flags) { size_t max_le = card->max_recv_size > 0 ? card->max_recv_size : 256; int r; assert(card != NULL && card->ops != NULL && buf != NULL); sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "called; %d bytes at index %d\n", count, idx); if (count == 0) return 0; if (card->ops->read_binary == NULL) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED); if (count > max_le) { int bytes_read = 0; unsigned char *p = buf; r = sc_lock(card); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed"); while (count > 0) { size_t n = count > max_le ? max_le : count; r = sc_read_binary(card, idx, p, n, flags); if (r < 0) { sc_unlock(card); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_read_binary() failed"); } p += r; idx += r; bytes_read += r; count -= r; if (r == 0) { sc_unlock(card); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, bytes_read); } } sc_unlock(card); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, bytes_read); } r = card->ops->read_binary(card, idx, buf, count, flags); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); }
static int acos_detect_card(sc_pkcs15_card_t *p15card) { int r; u8 buf[128]; sc_path_t path; sc_card_t *card = p15card->card; /* check if we have the correct card OS */ if (strncmp(card->name, "A-TRUST ACOS", strlen("A-TRUST ACOS"))) return SC_ERROR_WRONG_CARD; /* read EF_CIN_CSN file */ sc_format_path("DF71D001", &path); r = sc_select_file(card, &path, NULL); if (r != SC_SUCCESS) return SC_ERROR_WRONG_CARD; r = sc_read_binary(card, 0, buf, 8, 0); if (r != 8) return SC_ERROR_WRONG_CARD; return SC_SUCCESS; }
static int sc_pkcs15emu_sc_hsm_read_tokeninfo (sc_pkcs15_card_t * p15card) { sc_card_t *card = p15card->card; sc_path_t path; int r; u8 efbin[512]; LOG_FUNC_CALLED(card->ctx); /* Read token info */ sc_path_set(&path, SC_PATH_TYPE_FILE_ID, (u8 *) "\x2F\x03", 2, 0, 0); r = sc_select_file(card, &path, NULL); LOG_TEST_RET(card->ctx, r, "Could not select EF.TokenInfo"); r = sc_read_binary(p15card->card, 0, efbin, sizeof(efbin), 0); LOG_TEST_RET(card->ctx, r, "Could not read EF.TokenInfo"); r = sc_pkcs15_parse_tokeninfo(card->ctx, p15card->tokeninfo, efbin, r); LOG_TEST_RET(card->ctx, r, "Could not decode EF.TokenInfo"); LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); }
static int starcert_detect_card(sc_pkcs15_card_t *p15card) { int r; u8 buf[128]; sc_path_t path; sc_card_t *card = p15card->card; /* check if we have the correct card OS */ if (strcmp(card->name, "STARCOS SPK 2.3")) return SC_ERROR_WRONG_CARD; /* read EF_Info file */ sc_format_path("3F00FE13", &path); r = sc_select_file(card, &path, NULL); if (r != SC_SUCCESS) return SC_ERROR_WRONG_CARD; r = sc_read_binary(card, 0, buf, 64, 0); if (r != 64) return SC_ERROR_WRONG_CARD; if (memcmp(buf + 24, STARCERT, strlen(STARCERT))) return SC_ERROR_WRONG_CARD; return SC_SUCCESS; }
static void handle_readcert(sc_card_t *card, int cert, char *file) { sc_path_t p; sc_file_t *f; FILE *fp; X509 *c; u8 buf[1536]; const u8 *q; int i, len; printf("\nReading Card-Certificate %d: ", cert); fflush(stdout); sc_format_path(certlist[cert].path,&p); if((i=sc_select_file(card,&p,&f))<0){ printf("cannot select certfile, %s\n", sc_strerror(i)); return; } if((len=sc_read_binary(card,0,buf,f->size,0))<0){ printf("Cannot read Cert, %s\n", sc_strerror(len)); return; } q=buf; if(q[0]==0x30 && q[1]==0x82 && q[4]==6 && q[5]<10 && q[q[5]+6]==0x30 && q[q[5]+7]==0x82) q+=q[5]+6; if((c=d2i_X509(NULL,&q,len))==NULL){ printf("cardfile contains %d bytes which are not a certificate\n", len); return; } printf("Writing Cert to %s: ", file); fflush(stdout); if((fp=fopen(file,"w"))==NULL) printf("Cannot open file, %s\n", strerror(errno)); else { fprintf(fp,"Certificate %d from Netkey E4 card\n\n", cert); PEM_write_X509(fp,c); printf("OK\n"); } X509_free(c); }
int do_genkey(sc_card_t *card, u8 key_id, unsigned int key_len) { int r; sc_cardctl_openpgp_keygen_info_t key_info; u8 fingerprints[60]; sc_path_t path; sc_file_t *file; if (key_id < 1 || key_id > 3) { printf("Unknown key ID %d.\n", key_id); return 1; } memset(&key_info, 0, sizeof(sc_cardctl_openpgp_keygen_info_t)); key_info.keytype = key_id; key_info.modulus_len = key_len; key_info.modulus = malloc(key_len/8); r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_GENERATE_KEY, &key_info); free(key_info.modulus); if (r < 0) { printf("Failed to generate key. Error %s.\n", sc_strerror(r)); return 1; } sc_format_path("006E007300C5", &path); r = sc_select_file(card, &path, &file); if (r < 0) { printf("Failed to retrieve fingerprints. Error %s.\n", sc_strerror(r)); return 1; } r = sc_read_binary(card, 0, fingerprints, 60, 0); if (r < 0) { printf("Failed to retrieve fingerprints. Error %s.\n", sc_strerror(r)); return 1; } printf("Fingerprint:\n%s\n", (char *)sc_dump_hex(fingerprints + 20*(key_id - 1), 20)); return 0; }
static int do_get(int argc, char **argv) { u8 buf[256]; int r, err = 1; size_t count = 0; unsigned int idx = 0; sc_path_t path; sc_file_t *file = NULL; char *filename; FILE *outf = NULL; if (argc < 1 || argc > 2) return usage(do_get); if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_get); filename = (argc == 2) ? argv[1] : path_to_filename(&path, '_'); outf = (strcmp(filename, "-") == 0) ? stdout : fopen(filename, "wb"); if (outf == NULL) { perror(filename); goto err; } r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); goto err; } if (file->type != SC_FILE_TYPE_WORKING_EF) { printf("only working EFs may be read\n"); goto err; } count = file->size; while (count) { int c = count > sizeof(buf) ? sizeof(buf) : count; r = sc_read_binary(card, idx, buf, c, 0); if (r < 0) { check_ret(r, SC_AC_OP_READ, "read failed", file); goto err; } if ((r != c) && (card->type != SC_CARD_TYPE_BELPIC_EID)) { printf("expecting %d, got only %d bytes.\n", c, r); goto err; } if ((r == 0) && (card->type == SC_CARD_TYPE_BELPIC_EID)) break; fwrite(buf, r, 1, outf); idx += r; count -= r; } if (outf == stdout) { fwrite("\n", 1, 1, outf); } else { printf("Total of %d bytes read from %s and saved to %s.\n", idx, argv[0], filename); } err = 0; err: if (file) sc_file_free(file); if (outf != NULL && outf != stdout) fclose(outf); select_current_path_or_die(); return -err; }
static int do_asn1(int argc, char **argv) { int r, err = 1; sc_path_t path; sc_file_t *file = NULL; int not_current = 1; size_t len; unsigned char *buf = NULL; if (argc > 1) return usage(do_asn1); /* select file */ if (argc) { if (arg_to_path(argv[0], &path, 0) != 0) { puts("Invalid file path"); return -1; } r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); goto err; } } else { path = current_path; file = current_file; not_current = 0; } if (file->type != SC_FILE_TYPE_WORKING_EF) { printf("only working EFs may be read\n"); goto err; } /* read */ if (file->ef_structure != SC_FILE_EF_TRANSPARENT) { printf("only transparent file type is supported at the moment\n"); goto err; } len = file->size; buf = calloc(1, len); if (!buf) { goto err; } r = sc_read_binary(card, 0, buf, len, 0); if (r < 0) { check_ret(r, SC_AC_OP_READ, "read failed", file); goto err; } if ((size_t)r != len) { printf("expecting %lu, got only %d bytes.\n", (unsigned long) len, r); goto err; } /* asn1 dump */ sc_asn1_print_tags(buf, len); err = 0; err: if (buf) free(buf); if (not_current) { if (file) sc_file_free(file); select_current_path_or_die(); } return -err; }
static void wrap_key(sc_card_t *card, u8 keyid, const char *outf, const char *pin) { sc_cardctl_sc_hsm_wrapped_key_t wrapped_key; struct sc_pin_cmd_data data; sc_file_t *file = NULL; sc_path_t path; FILE *out = NULL; u8 fid[2]; u8 ef_prkd[MAX_PRKD]; u8 ef_cert[MAX_CERT]; u8 keyblob[MAX_WRAPPED_KEY]; u8 *key; u8 *ptr; char *lpin = NULL; size_t key_len; int r, ef_prkd_len, ef_cert_len; if (pin == NULL) { printf("Enter User PIN : "); util_getpass(&lpin, NULL, stdin); printf("\n"); } else { lpin = (u8 *)pin; } memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_VERIFY; data.pin_type = SC_AC_CHV; data.pin_reference = ID_USER_PIN; data.pin1.data = lpin; data.pin1.len = strlen(lpin); r = sc_pin_cmd(card, &data, NULL); if (r < 0) { fprintf(stderr, "PIN verification failed with %s\n", sc_strerror(r)); return; } if (pin == NULL) { free(lpin); } wrapped_key.key_id = keyid; r = sc_card_ctl(card, SC_CARDCTL_SC_HSM_WRAP_KEY, (void *)&wrapped_key); if (r == SC_ERROR_INS_NOT_SUPPORTED) { // Not supported or not initialized for key shares return; } if (r < 0) { fprintf(stderr, "sc_card_ctl(*, SC_CARDCTL_SC_HSM_WRAP_KEY, *) failed with %s\n", sc_strerror(r)); return; } fid[0] = PRKD_PREFIX; fid[1] = keyid; ef_prkd_len = 0; /* Try to select a related EF containing the PKCS#15 description of the key */ sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, sizeof(fid), 0, 0); r = sc_select_file(card, &path, NULL); if (r == SC_SUCCESS) { ef_prkd_len = sc_read_binary(card, 0, ef_prkd, sizeof(ef_prkd), 0); if (ef_prkd_len < 0) { fprintf(stderr, "Error reading PRKD file %s. Skipping.\n", sc_strerror(ef_prkd_len)); ef_prkd_len = 0; } else { ef_prkd_len = determineLength(ef_prkd, ef_prkd_len); } } fid[0] = EE_CERTIFICATE_PREFIX; fid[1] = keyid; ef_cert_len = 0; /* Try to select a related EF containing the certificate for the key */ sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, sizeof(fid), 0, 0); r = sc_select_file(card, &path, NULL); if (r == SC_SUCCESS) { ef_cert_len = sc_read_binary(card, 0, ef_cert, sizeof(ef_cert), 0); if (ef_cert_len < 0) { fprintf(stderr, "Error reading certificate %s. Skipping\n", sc_strerror(ef_cert_len)); ef_cert_len = 0; } else { ef_cert_len = determineLength(ef_cert, ef_cert_len); } } ptr = keyblob; // Encode key in octet string object sc_asn1_write_element(card->ctx, SC_ASN1_OCTET_STRING, wrapped_key.wrapped_key, wrapped_key.wrapped_key_length, &key, &key_len); memcpy(ptr, key, key_len); ptr += key_len; free(key); // Add private key description if (ef_prkd_len > 0) { memcpy(ptr, ef_prkd, ef_prkd_len); ptr += ef_prkd_len; } // Add certificate if (ef_cert_len > 0) { memcpy(ptr, ef_cert, ef_cert_len); ptr += ef_cert_len; } // Encode key in octet string object sc_asn1_write_element(card->ctx, SC_ASN1_SEQUENCE|SC_ASN1_CONS, keyblob, ptr - keyblob, &key, &key_len); out = fopen(outf, "wb"); if (out == NULL) { perror(outf); free(key); return; } if (fwrite(key, 1, key_len, out) != key_len) { perror(outf); free(key); return; } free(key); fclose(out); }
static int sc_pkcs15_bind_internal(sc_pkcs15_card_t *p15card) { unsigned char *buf = NULL; int err, ok = 0; size_t len; sc_path_t tmppath; sc_card_t *card = p15card->card; sc_context_t *ctx = card->ctx; sc_pkcs15_tokeninfo_t tokeninfo; if (ctx->debug > 4) sc_debug(ctx, "trying normal pkcs15 processing\n"); /* Enumerate apps now */ if (card->app_count < 0) { err = sc_enum_apps(card); if (err < 0 && err != SC_ERROR_FILE_NOT_FOUND) { sc_error(ctx, "unable to enumerate apps: %s\n", sc_strerror(err)); goto end; } } p15card->file_app = sc_file_new(); if (p15card->file_app == NULL) { err = SC_ERROR_OUT_OF_MEMORY; goto end; } sc_format_path("3F005015", &p15card->file_app->path); if (card->app_count > 0) { const sc_app_info_t *info; info = sc_find_pkcs15_app(card); if (info != NULL) { if (info->path.len) p15card->file_app->path = info->path; if (info->ddo != NULL) parse_ddo(p15card, info->ddo, info->ddo_len); } } /* Check if pkcs15 directory exists */ sc_ctx_suppress_errors_on(card->ctx); err = sc_select_file(card, &p15card->file_app->path, NULL); #if 1 /* If the above test failed on cards without EF(DIR), * try to continue read ODF from 3F005031. -aet */ if ((err == SC_ERROR_FILE_NOT_FOUND) && (card->app_count < 1)) { sc_format_path("3F00", &p15card->file_app->path); err = SC_NO_ERROR; } #endif sc_ctx_suppress_errors_off(card->ctx); if (err < 0) goto end; if (p15card->file_odf == NULL) { /* check if an ODF is present; suppress errors as we * don't know yet whether we have a pkcs15 card */ tmppath = p15card->file_app->path; sc_append_path_id(&tmppath, (const u8 *) "\x50\x31", 2); sc_ctx_suppress_errors_on(card->ctx); err = sc_select_file(card, &tmppath, &p15card->file_odf); sc_ctx_suppress_errors_off(card->ctx); } else { tmppath = p15card->file_odf->path; sc_file_free(p15card->file_odf); p15card->file_odf = NULL; err = sc_select_file(card, &tmppath, &p15card->file_odf); } if (err != SC_SUCCESS) { char pbuf[SC_MAX_PATH_STRING_SIZE]; int r = sc_path_print(pbuf, sizeof(pbuf), &tmppath); if (r != SC_SUCCESS) pbuf[0] = '\0'; sc_debug(ctx, "EF(ODF) not found in '%s'\n", pbuf); goto end; } if ((len = p15card->file_odf->size) == 0) { sc_error(card->ctx, "EF(ODF) is empty\n"); goto end; } buf = malloc(len); if(buf == NULL) return SC_ERROR_OUT_OF_MEMORY; err = sc_read_binary(card, 0, buf, len, 0); if (err < 0) goto end; if (err < 2) { err = SC_ERROR_PKCS15_APP_NOT_FOUND; goto end; } len = err; if (parse_odf(buf, len, p15card)) { err = SC_ERROR_PKCS15_APP_NOT_FOUND; sc_error(card->ctx, "Unable to parse ODF\n"); goto end; } free(buf); buf = NULL; if (card->ctx->debug) { sc_pkcs15_df_t *df; sc_debug(card->ctx, "The following DFs were found:\n"); for (df = p15card->df_list; df; df = df->next) { char pbuf[SC_MAX_PATH_STRING_SIZE]; int r = sc_path_print(pbuf, sizeof(pbuf), &df->path); if (r != SC_SUCCESS) pbuf[0] = '\0'; sc_debug(card->ctx, " DF type %u, path %s, index %u, count %d\n", df->type, pbuf, df->path.index, df->path.count); } } if (p15card->file_tokeninfo == NULL) { tmppath = p15card->file_app->path; sc_append_path_id(&tmppath, (const u8 *) "\x50\x32", 2); } else { tmppath = p15card->file_tokeninfo->path; sc_file_free(p15card->file_tokeninfo); p15card->file_tokeninfo = NULL; } err = sc_select_file(card, &tmppath, &p15card->file_tokeninfo); if (err) goto end; if ((len = p15card->file_tokeninfo->size) == 0) { sc_error(card->ctx, "EF(TokenInfo) is empty\n"); goto end; } buf = malloc(len); if(buf == NULL) return SC_ERROR_OUT_OF_MEMORY; err = sc_read_binary(card, 0, buf, len, 0); if (err < 0) goto end; if (err <= 2) { err = SC_ERROR_PKCS15_APP_NOT_FOUND; goto end; } memset(&tokeninfo, 0, sizeof(tokeninfo)); err = sc_pkcs15_parse_tokeninfo(ctx, &tokeninfo, buf, (size_t)err); if (err != SC_SUCCESS) goto end; p15card->version = tokeninfo.version; p15card->label = tokeninfo.label; p15card->serial_number = tokeninfo.serial_number; p15card->manufacturer_id = tokeninfo.manufacturer_id; p15card->last_update = tokeninfo.last_update; p15card->flags = tokeninfo.flags; p15card->preferred_language = tokeninfo.preferred_language; p15card->seInfo = tokeninfo.seInfo; p15card->num_seInfo = tokeninfo.num_seInfo; /* for cardos cards initialized by Siemens: sign with decrypt */ if (strcmp(p15card->card->driver->short_name,"cardos") == 0 && ( strcmp(p15card->manufacturer_id,"Siemens AG (C)") == 0 || strcmp(p15card->manufacturer_id,"Prime") == 0 )) p15card->flags |= SC_PKCS15_CARD_FLAG_SIGN_WITH_DECRYPT; ok = 1; end: if(buf != NULL) free(buf); if (!ok) { sc_pkcs15_card_clear(p15card); return err; } return SC_SUCCESS; }
static int sc_pkcs15emu_atrust_acos_init(sc_pkcs15_card_t *p15card) { const cdata certs[] = { {"C.CH.EKEY", 0, "DF71C001","1", 0},/* Decryption Certificate */ {NULL, 0, NULL, NULL, 0} }; const pindata pins[] = { { "01", "PIN.DEC", "3F00DF71", 0x81, /* Decryption PIN */ SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 4, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL, -1, 0x00, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE }, { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; const prdata prkeys[] = { { "01", "SK.CH.EKEY", 1536, SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP, "", /* do not specify file here to prevent reset of security state */ 0x88, "01", SC_PKCS15_CO_FLAG_PRIVATE}, { NULL, NULL, 0, 0, NULL, 0, NULL, 0} }; int r, i; u8 buf[256]; char buf2[256]; sc_path_t path; sc_file_t *file = NULL; sc_card_t *card = p15card->card; /* get serial number */ /* read EF_CIN_CSN file */ sc_format_path("DF71D001", &path); r = sc_select_file(card, &path, NULL); if (r != SC_SUCCESS) return SC_ERROR_INTERNAL; r = sc_read_binary(card, 0, buf, 8, 0); if (r != 8) return SC_ERROR_INTERNAL; r = sc_bin_to_hex(buf, 8, buf2, sizeof(buf2), 0); if (r != SC_SUCCESS) return SC_ERROR_INTERNAL; if (p15card->tokeninfo->serial_number) free(p15card->tokeninfo->serial_number); p15card->tokeninfo->serial_number = malloc(strlen(buf2) + 1); if (!p15card->tokeninfo->serial_number) return SC_ERROR_INTERNAL; strcpy(p15card->tokeninfo->serial_number, buf2); /* manufacturer ID */ if (p15card->tokeninfo->manufacturer_id) free(p15card->tokeninfo->manufacturer_id); p15card->tokeninfo->manufacturer_id = malloc(strlen(MANU_ID) + 1); if (!p15card->tokeninfo->manufacturer_id) return SC_ERROR_INTERNAL; strcpy(p15card->tokeninfo->manufacturer_id, MANU_ID); /* card label */ if (p15card->tokeninfo->label) free(p15card->tokeninfo->label); p15card->tokeninfo->label = malloc(strlen(CARD_LABEL) + 1); if (!p15card->tokeninfo->label) return SC_ERROR_INTERNAL; strcpy(p15card->tokeninfo->label, CARD_LABEL); /* set certs */ for (i = 0; certs[i].label; i++) { 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)); sc_pkcs15_format_id(certs[i].id, &cert_info.id); cert_info.authority = certs[i].authority; sc_format_path(certs[i].path, &cert_info.path); if (!get_cert_len(card, &cert_info.path)) /* skip errors */ continue; strlcpy(cert_obj.label, certs[i].label, sizeof(cert_obj.label)); cert_obj.flags = certs[i].obj_flags; r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) return SC_ERROR_INTERNAL; } /* set pins */ for (i = 0; pins[i].label; i++) { 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)); sc_pkcs15_format_id(pins[i].id, &pin_info.auth_id); pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; pin_info.attrs.pin.reference = pins[i].ref; pin_info.attrs.pin.flags = pins[i].flags; pin_info.attrs.pin.type = pins[i].type; pin_info.attrs.pin.min_length = pins[i].minlen; pin_info.attrs.pin.stored_length = pins[i].storedlen; pin_info.attrs.pin.max_length = pins[i].maxlen; pin_info.attrs.pin.pad_char = pins[i].pad_char; sc_format_path(pins[i].path, &pin_info.path); pin_info.tries_left = -1; strlcpy(pin_obj.label, pins[i].label, sizeof(pin_obj.label)); pin_obj.flags = pins[i].obj_flags; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) return SC_ERROR_INTERNAL; } /* set private keys */ for (i = 0; prkeys[i].label; i++) { 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)); sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id); prkey_info.usage = prkeys[i].usage; prkey_info.native = 1; prkey_info.key_reference = prkeys[i].ref; prkey_info.modulus_length= prkeys[i].modulus_len; sc_format_path(prkeys[i].path, &prkey_info.path); strlcpy(prkey_obj.label, prkeys[i].label, sizeof(prkey_obj.label)); prkey_obj.flags = prkeys[i].obj_flags; if (prkeys[i].auth_id) sc_pkcs15_format_id(prkeys[i].auth_id, &prkey_obj.auth_id); r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); if (r < 0) return SC_ERROR_INTERNAL; } /* select the application DF */ sc_format_path("DF71", &path); r = sc_select_file(card, &path, &file); if (r != SC_SUCCESS || !file) return SC_ERROR_INTERNAL; /* set the application DF */ if (p15card->file_app) free(p15card->file_app); p15card->file_app = file; return SC_SUCCESS; }
static int sc_pkcs15emu_postecert_init(sc_pkcs15_card_t * p15card) { static int prkey_usage = SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; static int authprkey_usage = SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT; sc_card_t *card = p15card->card; sc_path_t path; sc_pkcs15_id_t id, auth_id; unsigned char certlen[2]; unsigned char *certi = NULL; int index_cert[4]; int count_cert[4]; int flags; int authority; size_t i, count; int r; int o = 0; const char *label = "User Non-repudiation Certificate"; const char *calabel = "CA Certificate"; const char *catmslabel = "CA TimeStamper Certificate"; const char *authlabel = "User Authentication Certificate"; const char *postecert_auth_cert_path = "504B0001"; const char *authPIN = "Authentication PIN"; const char *nonrepPIN = "Non-repudiation PIN"; const char *authPRKEY = "Authentication Key"; const char *nonrepPRKEY = "Non repudiation Key"; /* Get the non-repudiation certificate length */ sc_format_path(postecert_auth_cert_path, &path); if (sc_select_file(card, &path, NULL) < 0) { r = SC_ERROR_WRONG_CARD; goto failed; } set_string(&p15card->label, "Postecert & Cnipa Card"); set_string(&p15card->manufacturer_id, "Postecert"); set_string(&p15card->serial_number, "0000"); sc_read_binary(card, 0, certlen, 2, 0); /* Now set the certificate offset/len */ count = (certlen[0] << 8) + certlen[1]; if (count < 256) return SC_ERROR_INTERNAL; certi = (unsigned char *) malloc(count); if (!certi) return SC_ERROR_OUT_OF_MEMORY; sc_read_binary(card, 0, certi, count - 500, 0); for (i = 2; i < (count - 256); i++) { /* this file contain more than one certificate */ if (*(certi + i) == 0x30 && *(certi + i + 1) == 0x82 && *(certi + i + 4) == 0x30 && *(certi + i + 5) == 0x82 && *(certi + i + 2) > 1 && *(certi + i + 2) < 8 && *(certi + i + 6) <= *(certi + i + 2)) { index_cert[o] = i; count_cert[o] = (*(certi + i + 2) << 8) + *(certi + i + 3) + 4; o++; if (o > 4) break; i += (*(certi + i + 2) << 8) + *(certi + i + 3); } } free(certi); path.index = index_cert[0]; path.count = count_cert[0]; id.value[0] = 1; id.len = 1; authority = 1; sc_pkcs15emu_add_cert(p15card, SC_PKCS15_TYPE_CERT_X509, authority, &path, &id, calabel, SC_PKCS15_CO_FLAG_MODIFIABLE); path.index = index_cert[1]; path.count = count_cert[1]; id.value[0] = 2; id.len = 1; authority = 1; sc_pkcs15emu_add_cert(p15card, SC_PKCS15_TYPE_CERT_X509, authority, &path, &id, catmslabel, SC_PKCS15_CO_FLAG_MODIFIABLE); path.index = index_cert[2]; path.count = count_cert[2]; id.value[0] = 3; id.len = 1; authority = 0; sc_pkcs15emu_add_cert(p15card, SC_PKCS15_TYPE_CERT_X509, authority, &path, &id, label, SC_PKCS15_CO_FLAG_MODIFIABLE); path.index = index_cert[3]; path.count = count_cert[3]; id.value[0] = 4; id.len = 1; sc_pkcs15emu_add_cert(p15card, SC_PKCS15_TYPE_CERT_X509, authority, &path, &id, authlabel, SC_PKCS15_CO_FLAG_MODIFIABLE); flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_NEEDS_PADDING; /* add authentication PIN */ sc_format_path("3F00504B", &path); id.value[0] = 1; sc_pkcs15emu_add_pin(p15card, &id, authPIN, &path, 0x82, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 6, 14, flags, 3, 0, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE); /* add authentication private key */ id.value[0] = 4; auth_id.value[0] = 1; auth_id.len = 1; sc_pkcs15emu_add_prkey(p15card, &id, authPRKEY, SC_PKCS15_TYPE_PRKEY_RSA, 1024, authprkey_usage, &path, 0x06, &auth_id, SC_PKCS15_CO_FLAG_PRIVATE); /* add non repudiation PIN */ sc_format_path("3F00504B", &path); id.value[0] = 2; sc_pkcs15emu_add_pin(p15card, &id, nonrepPIN, &path, 0x82, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 6, 14, flags, 3, 0, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE); /* add non repudiation private key */ id.value[0] = 3; auth_id.value[0] = 2; sc_pkcs15emu_add_prkey(p15card, &id, nonrepPRKEY, SC_PKCS15_TYPE_PRKEY_RSA, 1024, prkey_usage, &path, 0x01, &auth_id, SC_PKCS15_CO_FLAG_PRIVATE); /* return to MF */ sc_format_path("3F00", &path); r = sc_select_file(card, &path, NULL); if (r != SC_SUCCESS) return r; { /* save old signature funcs */ set_security_env = card->ops->set_security_env; /* set new one */ card->ops->set_security_env = set_sec_env; card->ops->compute_signature = do_sign; } return 0; failed: sc_error(card->ctx, "Failed to initialize Postecert and Cnipa emulation: %s\n", sc_strerror(r)); return r; }
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; }
static int jpki_select_file(struct sc_card *card, const struct sc_path *path, struct sc_file **file_out) { struct jpki_private_data *drvdata = JPKI_DRVDATA(card); int rc; sc_apdu_t apdu; struct sc_file *file = NULL; LOG_FUNC_CALLED(card->ctx); sc_log(card->ctx, "jpki_select_file: path=%s, len=%"SC_FORMAT_LEN_SIZE_T"u", sc_print_path(path), path->len); if (path->len == 2 && memcmp(path->value, "\x3F\x00", 2) == 0) { drvdata->selected = SELECT_MF; if (file_out) { sc_file_dup(file_out, drvdata->mf); if (*file_out == NULL) { LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); } } return 0; } sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0, 0); switch (path->type) { case SC_PATH_TYPE_FILE_ID: apdu.p1 = 2; break; case SC_PATH_TYPE_DF_NAME: apdu.p1 = 4; break; default: LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); } apdu.p2 = 0x0C; apdu.data = path->value; apdu.datalen = path->len; apdu.lc = path->len; rc = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(card->ctx, rc, "APDU transmit failed"); rc = sc_check_sw(card, apdu.sw1, apdu.sw2); LOG_TEST_RET(card->ctx, rc, "SW Check failed"); if (!file_out) { LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); } /* read certificate file size */ if (path->len == 2 && ( memcmp(path->value, "\x00\x0A", 2) == 0 || memcmp(path->value, "\x00\x01", 2) == 0 || memcmp(path->value, "\x00\x0B", 2) == 0 || memcmp(path->value, "\x00\x02", 2) == 0 ) ) { u8 buf[4]; rc = sc_read_binary(card, 0, buf, 4, 0); LOG_TEST_RET(card->ctx, rc, "SW Check failed"); file = sc_file_new(); if (!file) { LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); } file->path = *path; file->size = (buf[2] << 8 | buf[3]) + 4; *file_out = file; } LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); }
static int sc_pkcs15emu_pteid_init(sc_pkcs15_card_t * p15card) { int r, i, type; unsigned char *buf = NULL; size_t len; sc_pkcs15_tokeninfo_t tokeninfo; sc_path_t tmppath; sc_card_t *card = p15card->card; sc_context_t *ctx = card->ctx; /* Parse the TokenInfo EF */ sc_format_path("3f004f005032", &tmppath); r = sc_select_file(card, &tmppath, &p15card->file_tokeninfo); if (r) goto end; if ( (len = p15card->file_tokeninfo->size) == 0) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "EF(TokenInfo) is empty\n"); goto end; } buf = malloc(len); if (buf == NULL) return SC_ERROR_OUT_OF_MEMORY; r = sc_read_binary(card, 0, buf, len, 0); if (r < 0) goto end; if (r <= 2) { r = SC_ERROR_PKCS15_APP_NOT_FOUND; goto end; } memset(&tokeninfo, 0, sizeof(tokeninfo)); r = sc_pkcs15_parse_tokeninfo(ctx, &tokeninfo, buf, (size_t) r); if (r != SC_SUCCESS) goto end; *(p15card->tokeninfo) = tokeninfo; /* Card type detection */ if (card->type == SC_CARD_TYPE_IAS_PTEID) type = IAS_CARD; else if (card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID) type = GEMSAFE_CARD; else { r = SC_ERROR_INTERNAL; goto end; } p15card->tokeninfo->flags = SC_PKCS15_TOKEN_PRN_GENERATION | SC_PKCS15_TOKEN_EID_COMPLIANT | SC_PKCS15_TOKEN_READONLY; /* TODO: Use the cardholder's name? */ /* TODO: Use Portuguese descriptions? */ /* Add X.509 Certificates */ for (i = 0; i < 4; i++) { static const char *pteid_cert_names[4] = { "AUTHENTICATION CERTIFICATE", "SIGNATURE CERTIFICATE", "SIGNATURE SUB CA", "AUTHENTICATION SUB CA" }; /* X.509 Certificate Paths */ static const char *pteid_cert_paths[4] = { "3f005f00ef09", /* Authentication Certificate path */ "3f005f00ef08", /* Digital Signature Certificate path */ "3f005f00ef0f", /* Signature sub CA path */ "3f005f00ef10" /* Authentication sub CA path */ }; /* X.509 Certificate IDs */ static const int pteid_cert_ids[4] = {0x45, 0x46, 0x51, 0x52}; 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] = pteid_cert_ids[i]; cert_info.id.len = 1; sc_format_path(pteid_cert_paths[i], &cert_info.path); strlcpy(cert_obj.label, pteid_cert_names[i], sizeof(cert_obj.label)); r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) { r = SC_ERROR_INTERNAL; goto end; } } /* Add PINs */ for (i = 0; i < 3; i++) { static const char *pteid_pin_names[3] = { "Auth PIN", "Sign PIN", "Address PIN" }; /* PIN References */ static const int pteid_pin_ref[2][3] = { {1, 130, 131}, {129, 130, 131} }; /* PIN Authentication IDs */ static const int pteid_pin_authid[3] = {1, 2, 3}; /* PIN Paths */ static const char *pteid_pin_paths[2][3] = { {NULL, "3f005f00", "3f005f00"}, {NULL, NULL, NULL} }; 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)); pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; pin_info.auth_id.len = 1; pin_info.auth_id.value[0] = pteid_pin_authid[i]; pin_info.attrs.pin.reference = pteid_pin_ref[type][i]; pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_CASE_SENSITIVE; pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; pin_info.attrs.pin.min_length = 4; pin_info.attrs.pin.stored_length = 8; pin_info.attrs.pin.max_length = 8; pin_info.attrs.pin.pad_char = type == IAS_CARD ? 0x2F : 0xFF; pin_info.tries_left = -1; if (pteid_pin_paths[type][i] != NULL) sc_format_path(pteid_pin_paths[type][i], &pin_info.path); strlcpy(pin_obj.label, pteid_pin_names[i], sizeof(pin_obj.label)); pin_obj.flags = 0; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) { r = SC_ERROR_INTERNAL; goto end; } } /* Add Private Keys */ for (i = 0; i < 2; i++) { /* Key reference */ static const int pteid_prkey_keyref[2][2] = { {1, 130}, {2, 1} }; /* RSA Private Key usage */ static int pteid_prkey_usage[2] = { SC_PKCS15_PRKEY_USAGE_SIGN, SC_PKCS15_PRKEY_USAGE_NONREPUDIATION}; /* RSA Private Key IDs */ static const int pteid_prkey_ids[2] = {0x45, 0x46}; static const char *pteid_prkey_names[2] = { "CITIZEN AUTHENTICATION KEY", "CITIZEN SIGNATURE KEY"}; /* RSA Private Key Paths */ static const char *pteid_prkey_paths[2][2] = { {NULL, "3f005f00"}, {NULL, NULL} }; 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] = pteid_prkey_ids[i]; prkey_info.usage = pteid_prkey_usage[i]; prkey_info.native = 1; prkey_info.key_reference = pteid_prkey_keyref[type][i]; prkey_info.modulus_length = 1024; if (pteid_prkey_paths[type][i] != NULL) sc_format_path(pteid_prkey_paths[type][i], &prkey_info.path); strlcpy(prkey_obj.label, pteid_prkey_names[i], sizeof(prkey_obj.label)); prkey_obj.auth_id.len = 1; prkey_obj.auth_id.value[0] = i + 1; prkey_obj.user_consent = (i == 1) ? 1 : 0; prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); if (r < 0) { r = SC_ERROR_INTERNAL; goto end; } } /* Add objects */ for (i = 0; i < 3; i++) { static const char *object_ids[3] = {"1", "2", "3"}; static const char *object_oids[3] = {"-1", "-1", "-1"}; static const char *object_labels[3] = {"Citizen Data", "Citizen Address Data", "Citizen Notepad"}; static const char *object_authids[3] = {NULL, "3", "1"}; static const char *object_paths[3] = {"3f005f00ef02", "3f005f00ef05", "3f005f00ef07"}; static const int object_flags[3] = {0, SC_PKCS15_CO_FLAG_PRIVATE, SC_PKCS15_CO_FLAG_MODIFIABLE}; struct sc_pkcs15_data_info obj_info; struct sc_pkcs15_object obj_obj; memset(&obj_info, 0, sizeof(obj_info)); memset(&obj_obj, 0, sizeof(obj_obj)); sc_pkcs15_format_id(object_ids[i], &obj_info.id); sc_format_path(object_paths[i], &obj_info.path); r = sc_format_oid(&obj_info.app_oid, object_oids[i]); if (r != SC_SUCCESS) goto end; strlcpy(obj_info.app_label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE); if (object_authids[i] != NULL) sc_pkcs15_format_id(object_authids[i], &obj_obj.auth_id); strlcpy(obj_obj.label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE); obj_obj.flags = object_flags[i]; r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info); if (r < 0) goto end; } end: if (buf != NULL) { free(buf); buf = NULL; } if (r) return r; return SC_SUCCESS; }
static int infocamere_1400_init(sc_pkcs15_card_t * p15card) { sc_card_t *card = p15card->card; sc_path_t path; sc_pkcs15_id_t id, auth_id; unsigned char serial[16]; int flags; int r; int hasAuthCert = 0; const char *certLabel[] = { "User Non-repudiation Certificate", "User Authentication Certificate", "CA Certificate" }; const char *certPath[] = { "300060000000", "300060000001", "300060000002" }; const char *pinLabel[] = { "Non-repudiation PIN", "Authentication PIN" }; int retries[] = { 3, -1 }; const char *keyPath[] = { "30004000001", "30004000002" }; const char *keyLabel[] = { "Non repudiation Key", "Authentication Key" }; static int usage[] = { SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT }; auth_id.len = 1; id.len = 1; /* OpenSC doesn't define constants to identify BSOs for * restoring security environment, so we overload * the set_security_env function to support restore_sec_env */ set_security_env = card->ops->set_security_env; card->ops->set_security_env = infocamere_1400_set_sec_env; card->ops->compute_signature = do_sign; p15card->opts.use_cache = 1; sc_format_path("30000001", &path); r = sc_select_file(card, &path, NULL); if (r != SC_SUCCESS) return SC_ERROR_WRONG_CARD; sc_read_binary(card, 15, serial, 15, 0); serial[15] = '\0'; set_string(&p15card->serial_number, (char *)serial); set_string(&p15card->label, "Infocamere 1400 Card"); set_string(&p15card->manufacturer_id, "Infocamere"); if ((r = loadCertificate(p15card, 0, certPath[0], certLabel[0])) != SC_SUCCESS) { sc_error(p15card->card->ctx, "%s", sc_strerror(r)); return SC_ERROR_WRONG_CARD; } hasAuthCert = loadCertificate(p15card, 1, certPath[1], certLabel[1]) == SC_SUCCESS; loadCertificate(p15card, 2, certPath[2], certLabel[2]); flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_NEEDS_PADDING; /* adding PINs & private keys */ sc_format_path("30004000", &path); id.value[0] = 1; sc_pkcs15emu_add_pin(p15card, &id, pinLabel[0], &path, 1, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 5, 8, flags, retries[0], 0, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE); sc_format_path(keyPath[0], &path); auth_id.value[0] = 1; sc_pkcs15emu_add_prkey(p15card, &id, keyLabel[0], SC_PKCS15_TYPE_PRKEY_RSA, 1024, usage[0], &path, 1, &auth_id, SC_PKCS15_CO_FLAG_PRIVATE); if (hasAuthCert) { sc_format_path("30004000", &path); id.value[0] = 2; sc_pkcs15emu_add_pin(p15card, &id, pinLabel[1], &path, 2, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 5, 8, flags, retries[1], 0, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE); sc_format_path(keyPath[1], &path); auth_id.value[0] = 2; sc_pkcs15emu_add_prkey(p15card, &id, keyLabel[1], SC_PKCS15_TYPE_PRKEY_RSA, 1024, usage[1], &path, 2, &auth_id, SC_PKCS15_CO_FLAG_PRIVATE); } /* return to MF */ sc_format_path("3F00", &path); r = sc_select_file(card, &path, NULL); return r; }
static int infocamere_1200_init(sc_pkcs15_card_t * p15card) { const int prkey_usage = SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; const int authprkey_usage = SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT; sc_card_t *card = p15card->card; sc_path_t path; sc_file_t *file; sc_pkcs15_id_t id, auth_id; unsigned char buffer[256]; unsigned char ef_gdo[256]; char serial[256]; unsigned char certlen[2]; int authority, change_sign = 0; struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_object cert_obj; const char *label = "User Non-repudiation Certificate"; const char *calabel = "CA Certificate"; const char *authlabel = "User Authentication Certificate"; const char *infocamere_cert_path[2] = { "DF01C000", "3F00000011111A02" }; const char *infocamere_auth_certpath[2] = { "11111A02", "000011111B02" }; const char *infocamere_cacert_path[2] = { "DF01C008", "000011114101" }; const char *infocamere_auth_path[2] = { "3F001111", "3F0000001111" }; const char *infocamere_nrepud_path[2] = { "3F00DF01", "3F0000001111" }; const int infocamere_idpin_auth_obj[2] = { 0x95, 0x81 }; const int infocamere_idpin_nrepud_obj[2] = { 0x99, 0x81 }; const int infocamere_idprkey_auth_obj[2] = { 0x9B, 0x01 }; const int infocamere_idprkey_nrepud_obj[2] = { 0x84, 0x01 }; const char *authPIN = "Authentication PIN"; const char *nonrepPIN = "Non-repudiation PIN"; const char *authPRKEY = "Authentication Key"; const char *nonrepPRKEY = "Non repudiation Key"; const int flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_NEEDS_PADDING; int r, len_iccsn, len_chn; sc_format_path("3F002F02", &path); sc_ctx_suppress_errors_on(card->ctx); r = sc_select_file(card, &path, &file); sc_ctx_suppress_errors_off(card->ctx); if (r != SC_SUCCESS || file->size > 255) { /* Not EF.GDO */ return SC_ERROR_WRONG_CARD; } sc_read_binary(card, 0, ef_gdo, file->size, 0); if (ef_gdo[0] != 0x5A || file->size < 3) { /* Not EF.GDO */ return SC_ERROR_WRONG_CARD; } len_iccsn = ef_gdo[1]; memcpy(buffer, ef_gdo + 2, len_iccsn); sc_bin_to_hex(buffer, len_iccsn, serial, sizeof(serial), 0); if (file->size < (size_t) (len_iccsn + 5)) { /* Not CHN */ return SC_ERROR_WRONG_CARD; } if (! (ef_gdo[len_iccsn + 2] == 0x5F && ef_gdo[len_iccsn + 3] == 0x20)) { /* Not CHN */ return SC_ERROR_WRONG_CARD; } len_chn = ef_gdo[len_iccsn + 4]; if (len_chn < 2 || len_chn > 8) { /* Length CHN incorrect */ return SC_ERROR_WRONG_CARD; } if (! (ef_gdo[len_iccsn + 5] == 0x12 && (ef_gdo[len_iccsn + 6] == 0x02 || ef_gdo[len_iccsn + 6] == 0x03))) { /* Not Infocamere Card */ return SC_ERROR_WRONG_CARD; } set_string(&p15card->serial_number, serial); if (ef_gdo[len_iccsn + 6] == 0x02) set_string(&p15card->label, "Infocamere 1202 Card"); else { set_string(&p15card->label, "Infocamere 1203 Card"); change_sign = 1; } set_string(&p15card->manufacturer_id, "Infocamere"); authority = 0; /* Get the authentication certificate length */ sc_format_path(infocamere_auth_certpath[ef_gdo[len_iccsn+6]-2], &path); sc_ctx_suppress_errors_on(card->ctx); r = sc_select_file(card, &path, NULL); sc_ctx_suppress_errors_off(card->ctx); if (r >= 0) { sc_read_binary(card, 0, certlen, 2, 0); /* Now set the certificate offset/len */ path.index = 2; path.count = (certlen[1] << 8) + certlen[0]; memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); sc_pkcs15_format_id("1", &cert_info.id); cert_info.authority = authority; cert_info.path = path; strlcpy(cert_obj.label, authlabel, sizeof(cert_obj.label)); cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE; r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) return SC_ERROR_INTERNAL; /* XXX: the IDs for the key/pin in case of the 1203 type * are wrong, therefore I disable them for now -- Nils */ if (!change_sign) { /* add authentication PIN */ sc_format_path(infocamere_auth_path[ef_gdo[len_iccsn+6]-2], &path); sc_pkcs15_format_id("1", &id); sc_pkcs15emu_add_pin(p15card, &id, authPIN, &path, infocamere_idpin_auth_obj[ef_gdo[len_iccsn+6]-2], SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 5, 8, flags, 3, 0, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE); /* add authentication private key */ auth_id.value[0] = 1; auth_id.len = 1; sc_pkcs15emu_add_prkey(p15card, &id, authPRKEY, SC_PKCS15_TYPE_PRKEY_RSA, 1024, authprkey_usage, &path, infocamere_idprkey_auth_obj[ef_gdo[len_iccsn+6]-2], &auth_id, SC_PKCS15_CO_FLAG_PRIVATE); } } /* Get the non-repudiation certificate length */ sc_format_path(infocamere_cert_path[ef_gdo[len_iccsn+6]-2], &path); if (sc_select_file(card, &path, NULL) < 0) { return SC_ERROR_INTERNAL; } sc_read_binary(card, 0, certlen, 2, 0); /* Now set the certificate offset/len */ path.index = 2; path.count = (certlen[1] << 8) + certlen[0]; memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); sc_pkcs15_format_id("2", &cert_info.id); cert_info.authority = authority; cert_info.path = path; strlcpy(cert_obj.label, label, sizeof(cert_obj.label)); cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE; r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) return SC_ERROR_INTERNAL; /* Get the CA certificate length */ authority = 1; sc_format_path(infocamere_cacert_path[ef_gdo[len_iccsn+6]-2], &path); sc_ctx_suppress_errors_on(card->ctx); r = sc_select_file(card, &path, NULL); sc_ctx_suppress_errors_off(card->ctx); if (r >= 0) { size_t len; sc_read_binary(card, 0, certlen, 2, 0); len = (certlen[1] << 8) + certlen[0]; if (len != 0) { /* Now set the certificate offset/len */ path.index = 2; path.count = len; memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); sc_pkcs15_format_id("3", &cert_info.id); cert_info.authority = authority; cert_info.path = path; strlcpy(cert_obj.label, calabel, sizeof(cert_obj.label)); cert_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE; r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) return SC_ERROR_INTERNAL; } } /* add non repudiation PIN */ sc_format_path(infocamere_nrepud_path[ef_gdo[len_iccsn+6]-2], &path); sc_pkcs15_format_id("2", &id); sc_pkcs15emu_add_pin(p15card, &id, nonrepPIN, &path, infocamere_idpin_nrepud_obj[ef_gdo[len_iccsn+6]-2], SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 5, 8, flags, 3, 0, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE); /* add non repudiation private key */ auth_id.value[0] = 2; auth_id.len = 1; sc_pkcs15emu_add_prkey(p15card, &id, nonrepPRKEY, SC_PKCS15_TYPE_PRKEY_RSA, 1024, prkey_usage, &path, infocamere_idprkey_nrepud_obj[ef_gdo[len_iccsn+6]-2], &auth_id, SC_PKCS15_CO_FLAG_PRIVATE); /* return to MF */ sc_format_path("3F00", &path); r = sc_select_file(card, &path, NULL); if (r != SC_SUCCESS) return r; if (change_sign) { /* save old signature funcs */ set_security_env = card->ops->set_security_env; /* set new one */ card->ops->set_security_env = set_sec_env; card->ops->compute_signature = do_sign; } return SC_SUCCESS; }
/** * Select a file from card, process fci and read data * This is done by mean of iso_select_file() and iso_read_binary() *@param card pointer to sc_card data *@param path pathfile *@param file pointer to resulting file descriptor *@param buffer pointer to buffer where to store file contents *@param length length of buffer data *@return SC_SUCCESS if ok; else error code */ int dnie_read_file(sc_card_t * card, const sc_path_t * path, sc_file_t ** file, u8 ** buffer, size_t * length) { u8 *data; char *msg = NULL; int res = SC_SUCCESS; unsigned int fsize = 0; /* file size */ sc_context_t *ctx = NULL; if (!card || !card->ctx) return SC_ERROR_INVALID_ARGUMENTS; ctx = card->ctx; LOG_FUNC_CALLED(card->ctx); if (!buffer || !length || !path) /* check received arguments */ LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); /* select file by mean of iso7816 ops */ res = card->ops->select_file(card, path, file); if (res != SC_SUCCESS) { msg = "select_file failed"; goto dnie_read_file_err; } /* iso's select file calls if needed process_fci, so arriving here * we have file structure filled. */ if ((*file)->type == SC_FILE_TYPE_DF) { /* just a DF, no need to read_binary() */ *buffer = NULL; *length = 0; res = SC_SUCCESS; msg = "File is a DF: no need to read_binary()"; goto dnie_read_file_end; } fsize = (*file)->size; /* reserve enought space to read data from card */ if (fsize <= 0) { res = SC_ERROR_FILE_TOO_SMALL; msg = "provided buffer size is too small"; goto dnie_read_file_err; } data = calloc(fsize, sizeof(u8)); if (data == NULL) { res = SC_ERROR_OUT_OF_MEMORY; msg = "cannot reserve requested buffer size"; goto dnie_read_file_err; } /* call sc_read_binary() to retrieve data */ sc_log(ctx, "read_binary(): expected '%d' bytes", fsize); res = sc_read_binary(card, 0, data, fsize, 0L); if (res < 0) { /* read_binary returns number of bytes readed */ res = SC_ERROR_CARD_CMD_FAILED; msg = "read_binary() failed"; goto dnie_read_file_err; } *buffer = data; *length = res; /* arriving here means success */ res = SC_SUCCESS; goto dnie_read_file_end; dnie_read_file_err: if (*file) sc_file_free(*file); dnie_read_file_end: if (msg) sc_log(ctx, msg); LOG_FUNC_RETURN(ctx, res); }
static int infocamere_1600_init(sc_pkcs15_card_t * p15card) { sc_card_t *card = p15card->card; sc_path_t path; sc_pkcs15_id_t id, auth_id; unsigned char serial[17]; int flags; int r; int hasAuthCert = 0; const char *certLabel[] = { "User Non-repudiation Certificate", "User Authentication Certificate" }; const char *certPath[] = { "200020010008", "20002001000E" }; const char *pinLabel[] = { "Non-repudiation PIN", "Authentication PIN" }; int retries[] = { 3, -1 }; const char *keyPath[] = { "200020010004", "20002001000A" }; const char *keyLabel[] = { "Non repudiation Key", "Authentication Key" }; static int usage[] = { SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT }; auth_id.len = 1; id.len = 1; /* OpenSC doesn't define constants to identify BSOs for * restoring security environment, so we overload * the set_security_env function to support restore_sec_env */ set_security_env = card->ops->set_security_env; card->ops->set_security_env = infocamere_1400_set_sec_env; card->ops->compute_signature = do_sign; sc_format_path("200020012002", &path); r = sc_select_file(card, &path, NULL); if (r != SC_SUCCESS) return SC_ERROR_WRONG_CARD; sc_read_binary(card, 30, serial, 16, 0); serial[16] = '\0'; set_string(&p15card->serial_number, (char *) serial); set_string(&p15card->label, "Infocamere 1600 Card"); set_string(&p15card->manufacturer_id, "Infocamere"); /* Adding certificates. * Certificates are stored in a ZLib compressed form with * a 4 byte header, so we extract, decompress and cache * them. */ sc_format_path(certPath[0], &path); if (sc_select_file(card, &path, NULL) != SC_SUCCESS) return SC_ERROR_WRONG_CARD; id.value[0] = 1; sc_pkcs15emu_add_cert(p15card, SC_PKCS15_TYPE_CERT_X509, 0, &path, &id, certLabel[0], SC_PKCS15_CO_FLAG_MODIFIABLE); sc_format_path(certPath[1], &path); if (sc_select_file(card, &path, NULL) == SC_SUCCESS) { hasAuthCert = 1; id.value[0] = 2; sc_pkcs15emu_add_cert(p15card, SC_PKCS15_TYPE_CERT_X509, 1, &path, &id, certLabel[1], SC_PKCS15_CO_FLAG_MODIFIABLE); } flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_NEEDS_PADDING; /* adding PINs & private keys */ sc_format_path("2000", &path); id.value[0] = 1; sc_pkcs15emu_add_pin(p15card, &id, pinLabel[0], &path, 1, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 5, 8, flags, retries[0], 0, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE); sc_format_path(keyPath[0], &path); auth_id.value[0] = 1; sc_pkcs15emu_add_prkey(p15card, &id, keyLabel[0], SC_PKCS15_TYPE_PRKEY_RSA, 1024, usage[0], &path, 1, &auth_id, SC_PKCS15_CO_FLAG_PRIVATE); if (hasAuthCert) { id.value[0] = 2; sc_pkcs15emu_add_pin(p15card, &id, pinLabel[1], &path, 2, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 5, 8, flags, retries[1], 0, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE); sc_format_path(keyPath[1], &path); auth_id.value[0] = 2; sc_pkcs15emu_add_prkey(p15card, &id, keyLabel[1], SC_PKCS15_TYPE_PRKEY_RSA, 1024, usage[1], &path, 2, &auth_id, SC_PKCS15_CO_FLAG_PRIVATE); } /* return to MF */ sc_format_path("3F00", &path); r = sc_select_file(card, &path, NULL); 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); }