static int list_readers(sc_context_t *ctx) { char card_atr[0x3e]; sc_card_t *card; sc_reader_t *reader; size_t i, rcount = sc_ctx_get_reader_count(ctx); if (rcount == 0) { printf("No smart card readers found.\n"); return 0; } printf("%-4s %-7s %s\n", "Nr.", "Driver", "Smart Card Reader"); for (i = 0; i < rcount; i++) { reader = sc_ctx_get_reader(ctx, i); memset(card_atr, '\0', sizeof card_atr); if (sc_detect_card_presence(reader) & SC_READER_CARD_PRESENT) { if (sc_connect_card(reader, &card) == SC_SUCCESS) { sc_bin_to_hex(card->atr.value, card->atr.len, card_atr, sizeof card_atr, ':'); } sc_disconnect_card(card); } else { strncpy(card_atr, "[no card present]", sizeof card_atr); } printf("%-4d %-7s %s\n", i, reader->driver->short_name, reader->name); printf(" ATR: %s\n", card_atr); } return 0; }
const char *sc_pkcs15_print_id(const struct sc_pkcs15_id *id) { static char buffer[256]; sc_bin_to_hex(id->value, id->len, buffer, sizeof(buffer), '\0'); return buffer; }
int sc_pkcs15emu_tcos_init_ex( sc_pkcs15_card_t *p15card, sc_pkcs15emu_opt_t *opts ){ sc_card_t *card = p15card->card; sc_context_t *ctx = p15card->card->ctx; sc_serial_number_t serialnr; char serial[30]; int i, r; /* check if we have the correct card OS unless SC_PKCS15EMU_FLAGS_NO_CHECK */ i=(opts && (opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)); if (!i && card->type!=SC_CARD_TYPE_TCOS_V2 && card->type!=SC_CARD_TYPE_TCOS_V3) return SC_ERROR_WRONG_CARD; /* get the card serial number */ r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serialnr); if (r < 0) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "unable to get ICCSN\n"); return SC_ERROR_WRONG_CARD; } sc_bin_to_hex(serialnr.value, serialnr.len , serial, sizeof(serial), 0); serial[19] = '\0'; p15card->tokeninfo->serial_number = strdup(serial); if(!detect_netkey(p15card)) return SC_SUCCESS; if(!detect_idkey(p15card)) return SC_SUCCESS; if(!detect_unicard(p15card)) return SC_SUCCESS; if(!detect_signtrust(p15card)) return SC_SUCCESS; if(!detect_datev(p15card)) return SC_SUCCESS; return SC_ERROR_INTERNAL; }
/* * Card initialization. * For the cryptoflex, read the card's serial number from 3F00 0002 */ static int cryptoflex_init_card(sc_profile_t *profile, sc_pkcs15_card_t *p15card) { sc_path_t path; sc_file_t *file; u8 buf[32]; char serial[128]; size_t len; int r; sc_format_path("3F000002", &path); if ((r = sc_select_file(p15card->card, &path, &file)) < 0) { if (r == SC_ERROR_FILE_NOT_FOUND) return 0; return r; } if ((len = file->size) > sizeof(buf)) len = sizeof(buf); sc_file_free(file); if ((r = sc_read_binary(p15card->card, 0, buf, len, 0)) < 0) return r; len = r; if (len == 0) return 0; if ((r = sc_bin_to_hex(buf, len, serial, sizeof(serial), '\0')) < 0) return r; sc_pkcs15init_set_serial(profile, serial); return 0; }
static int sc_pkcs15emu_entersafe_init( sc_pkcs15_card_t *p15card) { int r; char buf[256]; sc_card_t *card = p15card->card; sc_serial_number_t serial; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); /* get serial number */ r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial); if (r != SC_SUCCESS) return SC_ERROR_INTERNAL; r = sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 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(buf) + 1); if (!p15card->tokeninfo->serial_number) return SC_ERROR_INTERNAL; strcpy(p15card->tokeninfo->serial_number, buf); /* the manufacturer ID, in this case Giesecke & Devrient GmbH */ 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); return SC_SUCCESS; }
/* prettify hex */ static char *prettify_hex(u8 *data, size_t length, char *buffer, size_t buflen) { if (data != NULL) { int r = sc_bin_to_hex(data, length, buffer, buflen, ':'); if (r == SC_SUCCESS) return buffer; } return NULL; }
static const char *get_inserted_text(struct sc_pkcs15_card *p15card, struct sc_atr *atr) { static char text[3*SC_MAX_ATR_SIZE] = {0}; const char prefix[] = "ATR: "; if (p15card && p15card->card && p15card->card->name) { return p15card->card->name; } if (!atr) return NULL; strcpy(text, prefix); sc_bin_to_hex(atr->value, atr->len, text + (sizeof prefix) - 1, sizeof(text) - (sizeof prefix) - 1, ':'); return text; }
/* Do the PIN command */ static int part10_pin_cmd(sc_reader_t *reader, sc_slot_info_t *slot, struct sc_pin_cmd_data *data) { struct pcsc_private_data *priv = GET_PRIV_DATA(reader); u8 rbuf[SC_MAX_APDU_BUFFER_SIZE], sbuf[SC_MAX_APDU_BUFFER_SIZE]; char dbuf[SC_MAX_APDU_BUFFER_SIZE * 3]; size_t rcount = sizeof(rbuf), scount = 0; int r; DWORD ioctl = 0; sc_apdu_t *apdu; struct pcsc_slot_data *pslot = (struct pcsc_slot_data *) slot->drv_data; SC_FUNC_CALLED(reader->ctx, 3); assert(pslot != NULL); if (priv->gpriv->SCardControl == NULL) return SC_ERROR_NOT_SUPPORTED; /* The APDU must be provided by the card driver */ if (!data->apdu) { sc_error(reader->ctx, "No APDU provided for PC/SC v2 pinpad verification!"); return SC_ERROR_NOT_SUPPORTED; } apdu = data->apdu; switch (data->cmd) { case SC_PIN_CMD_VERIFY: if (!(pslot->verify_ioctl || (pslot->verify_ioctl_start && pslot->verify_ioctl_finish))) { sc_error(reader->ctx, "Pinpad reader does not support verification!"); return SC_ERROR_NOT_SUPPORTED; } r = part10_build_verify_pin_block(sbuf, &scount, slot, data); ioctl = pslot->verify_ioctl ? pslot->verify_ioctl : pslot->verify_ioctl_start; break; case SC_PIN_CMD_CHANGE: case SC_PIN_CMD_UNBLOCK: if (!(pslot->modify_ioctl || (pslot->modify_ioctl_start && pslot->modify_ioctl_finish))) { sc_error(reader->ctx, "Pinpad reader does not support modification!"); return SC_ERROR_NOT_SUPPORTED; } r = part10_build_modify_pin_block(sbuf, &scount, slot, data); ioctl = pslot->modify_ioctl ? pslot->modify_ioctl : pslot->modify_ioctl_start; break; default: sc_error(reader->ctx, "Unknown PIN command %d", data->cmd); return SC_ERROR_NOT_SUPPORTED; } /* If PIN block building failed, we fail too */ SC_TEST_RET(reader->ctx, r, "PC/SC v2 pinpad block building failed!"); /* If not, debug it, just for fun */ sc_bin_to_hex(sbuf, scount, dbuf, sizeof(dbuf), ':'); sc_debug(reader->ctx, "PC/SC v2 pinpad block: %s", dbuf); r = pcsc_internal_transmit(reader, slot, sbuf, scount, rbuf, &rcount, ioctl); SC_TEST_RET(reader->ctx, r, "PC/SC v2 pinpad: block transmit failed!"); /* finish the call if it was a two-phase operation */ if ((ioctl == pslot->verify_ioctl_start) || (ioctl == pslot->modify_ioctl_start)) { if (rcount != 0) { SC_FUNC_RETURN(reader->ctx, 2, SC_ERROR_UNKNOWN_DATA_RECEIVED); } ioctl = (ioctl == pslot->verify_ioctl_start) ? pslot->verify_ioctl_finish : pslot->modify_ioctl_finish; rcount = sizeof(rbuf); r = pcsc_internal_transmit(reader, slot, sbuf, 0, rbuf, &rcount, ioctl); SC_TEST_RET(reader->ctx, r, "PC/SC v2 pinpad: finish operation failed!"); } /* We expect only two bytes of result data (SW1 and SW2) */ if (rcount != 2) { SC_FUNC_RETURN(reader->ctx, 2, SC_ERROR_UNKNOWN_DATA_RECEIVED); } /* Extract the SWs for the result APDU */ apdu->sw1 = (unsigned int) rbuf[rcount - 2]; apdu->sw2 = (unsigned int) rbuf[rcount - 1]; r = SC_SUCCESS; switch (((unsigned int) apdu->sw1 << 8) | apdu->sw2) { case 0x6400: /* Input timed out */ r = SC_ERROR_KEYPAD_TIMEOUT; break; case 0x6401: /* Input cancelled */ r = SC_ERROR_KEYPAD_CANCELLED; break; case 0x6402: /* PINs don't match */ r = SC_ERROR_KEYPAD_PIN_MISMATCH; break; case 0x6B80: /* Wrong data in the buffer, rejected by firmware */ r = SC_ERROR_READER; break; } SC_TEST_RET(reader->ctx, r, "PIN command failed"); /* PIN command completed, all is good */ return SC_SUCCESS; }
static int cardos_info(void) { sc_apdu_t apdu; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; int r; if (verbose) { printf("Card ATR:\n"); util_hex_dump_asc(stdout, card->atr, card->atr_len, -1); } else { char tmp[SC_MAX_ATR_SIZE*3]; sc_bin_to_hex(card->atr, card->atr_len, tmp, sizeof(tmp) - 1, ':'); fprintf(stdout,"%s\n",tmp); } memset(&apdu, 0, sizeof(apdu)); apdu.cla = 0x00; apdu.ins = 0xca; apdu.p1 = 0x01; apdu.p2 = 0x80; apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); apdu.lc = 0; apdu.le = 256; apdu.cse = SC_APDU_CASE_2_SHORT; r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (apdu.sw1 != 0x90 || apdu.sw2 != 00 || verbose) { fprintf(stderr, "Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2, apdu.resplen ? ":" : ""); if (apdu.resplen) util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); return 1; } printf("Info : %s\n", apdu.resp); apdu.p2 = 0x81; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (apdu.sw1 != 0x90 || apdu.sw2 != 00 || verbose) { fprintf(stderr, "Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2, apdu.resplen ? ":" : ""); if (apdu.resplen) util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); return 1; } printf("Chip type: %d\n", apdu.resp[8]); printf("Serial number: %02x %02x %02x %02x %02x %02x\n", apdu.resp[10], apdu.resp[11], apdu.resp[12], apdu.resp[13], apdu.resp[14], apdu.resp[15]); printf("Full prom dump:\n"); if (apdu.resplen) util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); apdu.p2 = 0x82; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (apdu.sw1 != 0x90 || apdu.sw2 != 00 || verbose) { fprintf(stderr, "Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2, apdu.resplen ? ":" : ""); if (apdu.resplen) util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); return 1; } printf("OS Version: %d.%d", apdu.resp[0], apdu.resp[1]); if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x02) { printf(" (that's CardOS M4.0)\n"); } else if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x03) { printf(" (that's CardOS M4.01)\n"); } else if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x04) { printf(" (that's CardOS M4.01a)\n"); } else if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x06) { printf(" (that's CardOS M4.2)\n"); } else if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x07) { printf(" (that's CardOS M4.3)\n"); } else if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x08) { printf(" (that's CardOS M4.3B)\n"); } else if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x09) { printf(" (that's CardOS M4.2B)\n"); } else if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x0B) { printf(" (that's CardOS M4.2C)\n"); } else if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x0D) { printf(" (that's CardOS M4.4)\n"); } else { printf(" (unknown Version)\n"); } apdu.p2 = 0x83; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00 || verbose) { fprintf(stderr, "Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2, apdu.resplen ? ":" : ""); if (apdu.resplen) util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); return 1; } printf("Current life cycle: "); if (rbuf[0] == 0x34) { printf("%d (manufacturing)\n", rbuf[0]); } else if (rbuf[0] == 0x26) { printf("%d (initialization)\n", rbuf[0]); } else if (rbuf[0] == 0x24) { printf("%d (personalization)\n", rbuf[0]); } else if (rbuf[0] == 0x20) { printf("%d (administration)\n", rbuf[0]); } else if (rbuf[0] == 0x10) { printf("%d (operational)\n", rbuf[0]); } else if (rbuf[0] == 0x29) { printf("%d (erase in progress)\n", rbuf[0]); } else { printf("%d (unknown)\n", rbuf[0]); } apdu.p2 = 0x84; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (apdu.sw1 != 0x90 || apdu.sw2 != 00 || verbose) { fprintf(stderr, "Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2, apdu.resplen ? ":" : ""); if (apdu.resplen) util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); return 1; } printf("Security Status of current DF:\n"); util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); apdu.p2 = 0x85; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (apdu.sw1 != 0x90 || apdu.sw2 != 00 || verbose) { fprintf(stderr, "Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2, apdu.resplen ? ":" : ""); if (apdu.resplen) util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); return 1; } printf("Free memory : %d\n", rbuf[0]<<8|rbuf[1]); apdu.p2 = 0x86; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (apdu.sw1 != 0x90 || apdu.sw2 != 00 || verbose) { fprintf(stderr, "Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2, apdu.resplen ? ":" : ""); if (apdu.resplen) util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); return 1; } if (rbuf[0] == 0x00) { printf("ATR Status: 0x%d ROM-ATR\n",rbuf[0]); } else if (rbuf[0] == 0x90) { printf("ATR Status: 0x%d EEPROM-ATR\n",rbuf[0]); } else { printf("ATR Status: 0x%d unknown\n",rbuf[0]); } apdu.p2 = 0x88; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (apdu.sw1 != 0x90 || apdu.sw2 != 00 || verbose) { fprintf(stderr, "Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2, apdu.resplen ? ":" : ""); if (apdu.resplen) util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); return 1; } printf("Packages installed:\n"); util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); apdu.p2 = 0x89; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (apdu.sw1 != 0x90 || apdu.sw2 != 00 || verbose) { fprintf(stderr, "Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2, apdu.resplen ? ":" : ""); if (apdu.resplen) util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); return 1; } printf("Ram size: %d, Eeprom size: %d, cpu type: %x, chip config: %d\n", rbuf[0]<<8|rbuf[1], rbuf[2]<<8|rbuf[3], rbuf[4], rbuf[5]); apdu.p2 = 0x8a; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (apdu.sw1 != 0x90 || apdu.sw2 != 00 || verbose) { fprintf(stderr, "Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2, apdu.resplen ? ":" : ""); if (apdu.resplen) util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); return 1; } printf("Free eeprom memory: %d\n", rbuf[0]<<8|rbuf[1]); apdu.p2 = 0x96; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (apdu.sw1 != 0x90 || apdu.sw2 != 00 || verbose) { fprintf(stderr, "Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2, apdu.resplen ? ":" : ""); if (apdu.resplen) util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); return 1; } printf("System keys: PackageLoadKey (version 0x%02x, retries %d)\n", rbuf[0], rbuf[1]); printf("System keys: StartKey (version 0x%02x, retries %d)\n", rbuf[2], rbuf[3]); apdu.p2 = 0x87; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (apdu.sw1 != 0x90 || apdu.sw2 != 00 || verbose) { fprintf(stderr, "Unable to determine current DF:\n"); fprintf(stderr, "Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2, apdu.resplen ? ":" : ""); if (apdu.resplen) util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); return 1; } printf("Path to current DF:\n"); util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); return 0; }
static int sc_pkcs15emu_oberthur_init(struct sc_pkcs15_card * p15card) { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_auth_info auth_info; struct sc_pkcs15_object obj; struct sc_card *card = p15card->card; struct sc_path path; int rv, ii, tries_left; char serial[0x10]; unsigned char sopin_reference = 0x04; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); sc_bin_to_hex(card->serialnr.value, card->serialnr.len, serial, sizeof(serial), 0); p15card->tokeninfo->serial_number = strdup(serial); p15card->ops.parse_df = sc_awp_parse_df; p15card->ops.clear = sc_awp_clear; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Oberthur init: serial %s", p15card->tokeninfo->serial_number); sc_format_path(AWP_PIN_DF, &path); rv = sc_select_file(card, &path, NULL); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Oberthur init failed: cannot select PIN dir"); tries_left = -1; rv = sc_verify(card, SC_AC_CHV, sopin_reference, (unsigned char *)"", 0, &tries_left); if (rv && rv != SC_ERROR_PIN_CODE_INCORRECT) { sopin_reference = 0x84; rv = sc_verify(card, SC_AC_CHV, sopin_reference, (unsigned char *)"", 0, &tries_left); } if (rv && rv != SC_ERROR_PIN_CODE_INCORRECT) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Invalid state of SO-PIN"); /* add PIN */ memset(&auth_info, 0, sizeof(auth_info)); memset(&obj, 0, sizeof(obj)); auth_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; auth_info.auth_method = SC_AC_CHV; auth_info.auth_id.len = 1; auth_info.auth_id.value[0] = 0xFF; auth_info.attrs.pin.min_length = 4; auth_info.attrs.pin.max_length = 64; auth_info.attrs.pin.stored_length = 64; auth_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; auth_info.attrs.pin.reference = sopin_reference; auth_info.attrs.pin.pad_char = 0xFF; auth_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_SO_PIN; auth_info.tries_left = tries_left; strncpy(obj.label, "SO PIN", SC_PKCS15_MAX_LABEL_SIZE-1); obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Add PIN(%s,auth_id:%s,reference:%i)", obj.label, sc_pkcs15_print_id(&auth_info.auth_id), auth_info.attrs.pin.reference); rv = sc_pkcs15emu_add_pin_obj(p15card, &obj, &auth_info); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Oberthur init failed: cannot add PIN object"); tries_left = -1; rv = sc_verify(card, SC_AC_CHV, 0x81, (unsigned char *)"", 0, &tries_left); if (rv == SC_ERROR_PIN_CODE_INCORRECT) { /* add PIN */ memset(&auth_info, 0, sizeof(auth_info)); memset(&obj, 0, sizeof(obj)); auth_info.auth_id.len = sizeof(PinDomainID) > sizeof(auth_info.auth_id.value) ? sizeof(auth_info.auth_id.value) : sizeof(PinDomainID); memcpy(auth_info.auth_id.value, PinDomainID, auth_info.auth_id.len); auth_info.auth_method = SC_AC_CHV; auth_info.attrs.pin.min_length = 4; auth_info.attrs.pin.max_length = 64; auth_info.attrs.pin.stored_length = 64; auth_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; auth_info.attrs.pin.reference = 0x81; auth_info.attrs.pin.pad_char = 0xFF; auth_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL; auth_info.tries_left = tries_left; strncpy(obj.label, PIN_DOMAIN_LABEL, SC_PKCS15_MAX_LABEL_SIZE-1); obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE; sc_format_path(AWP_PIN_DF, &auth_info.path); auth_info.path.type = SC_PATH_TYPE_PATH; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Add PIN(%s,auth_id:%s,reference:%i)", obj.label, sc_pkcs15_print_id(&auth_info.auth_id), auth_info.attrs.pin.reference); rv = sc_pkcs15emu_add_pin_obj(p15card, &obj, &auth_info); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Oberthur init failed: cannot add PIN object"); } else if (rv != SC_ERROR_DATA_OBJECT_NOT_FOUND) { SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Oberthur init failed: cannot verify PIN"); } for (ii=0; oberthur_infos[ii].name; ii++) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Oberthur init: read %s file", oberthur_infos[ii].name); rv = sc_oberthur_read_file(p15card, oberthur_infos[ii].path, &oberthur_infos[ii].content, &oberthur_infos[ii].len, 1); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Oberthur init failed: read oberthur file error"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Oberthur init: parse %s file, content length %i", oberthur_infos[ii].name, oberthur_infos[ii].len); rv = oberthur_infos[ii].parser(p15card, oberthur_infos[ii].content, oberthur_infos[ii].len, oberthur_infos[ii].postpone_allowed); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, rv, "Oberthur init failed: parse error"); } SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS); }
static int sc_pkcs15emu_cac_init(sc_pkcs15_card_t *p15card) { static const pindata pins[] = { { "1", "PIN", "", 0x00, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 8, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_INITIALIZED , -1, 0xFF, SC_PKCS15_CO_FLAG_PRIVATE }, { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; /* oid for key usage */ static const struct sc_object_id usage_type = {{ 2, 5, 29, 15, -1 }}; unsigned int usage; /* * The size of the key or the algid is not really known * but can be derived from the certificates. * the cert, pubkey and privkey are a set. * Key usages bits taken from certificate key usage extension. */ int r, i; sc_card_t *card = p15card->card; sc_serial_number_t serial; char buf[SC_MAX_SERIALNR * 2 + 1]; int count; char *token_name = NULL; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); memset(&serial, 0, sizeof(serial)); /* could read this off card if needed */ p15card->tokeninfo->label = strdup(cac_get_name(card->type)); p15card->tokeninfo->manufacturer_id = strdup(MANU_ID); /* * get serial number */ r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial); if (r < 0) { sc_log(card->ctx, "sc_card_ctl rc=%d",r); p15card->tokeninfo->serial_number = strdup("00000000"); } else { sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0); p15card->tokeninfo->serial_number = strdup(buf); } /* set pins */ /* TODO we should not create PIN objects if it is not initialized * (opensc-tool -s 0020000000 returns 0x6A 0x88) */ sc_log(card->ctx, "CAC adding pins..."); for (i = 0; pins[i].id; i++) { struct sc_pkcs15_auth_info pin_info; struct sc_pkcs15_object pin_obj; const char * label; memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; sc_pkcs15_format_id(pins[i].id, &pin_info.auth_id); 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; label = pins[i].label; sc_log(card->ctx, "CAC Adding pin %d label=%s",i, label); strncpy(pin_obj.label, label, SC_PKCS15_MAX_LABEL_SIZE - 1); pin_obj.flags = pins[i].obj_flags; /* get the ACA path in case it needs to be selected before PIN verify */ r = sc_card_ctl(card, SC_CARDCTL_CAC_GET_ACA_PATH, &pin_info.path); if (r < 0) { LOG_FUNC_RETURN(card->ctx, r); } r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) LOG_FUNC_RETURN(card->ctx, r); } /* set other objects */ r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_INIT_GET_GENERIC_OBJECTS, &count); LOG_TEST_RET(card->ctx, r, "Can not initiate generic objects."); for (i = 0; i < count; i++) { struct sc_pkcs15_data_info obj_info; struct sc_pkcs15_object obj_obj; r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_GET_NEXT_GENERIC_OBJECT, &obj_info); if (r < 0) LOG_FUNC_RETURN(card->ctx, r); memset(&obj_obj, 0, sizeof(obj_obj)); memcpy(obj_obj.label, obj_info.app_label, sizeof(obj_obj.label)); r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info); if (r < 0) LOG_FUNC_RETURN(card->ctx, r); } r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_FINAL_GET_GENERIC_OBJECTS, &count); LOG_TEST_RET(card->ctx, r, "Can not finalize generic objects."); /* * certs, pubkeys and priv keys are related and we assume * they are in order * We need to read the cert, get modulus and keylen * We use those for the pubkey, and priv key objects. */ sc_log(card->ctx, "CAC adding certs, pub and priv keys..."); r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_INIT_GET_CERT_OBJECTS, &count); LOG_TEST_RET(card->ctx, r, "Can not initiate cert objects."); for (i = 0; i < count; i++) { struct sc_pkcs15_data_info obj_info; struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_pubkey_info pubkey_info; struct sc_pkcs15_prkey_info prkey_info; struct sc_pkcs15_object cert_obj; struct sc_pkcs15_object pubkey_obj; struct sc_pkcs15_object prkey_obj; sc_pkcs15_der_t cert_der; sc_pkcs15_cert_t *cert_out = NULL; r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_GET_NEXT_CERT_OBJECT, &obj_info); LOG_TEST_RET(card->ctx, r, "Can not get next object"); memset(&cert_info, 0, sizeof(cert_info)); memset(&pubkey_info, 0, sizeof(pubkey_info)); memset(&prkey_info, 0, sizeof(prkey_info)); memset(&cert_obj, 0, sizeof(cert_obj)); memset(&pubkey_obj, 0, sizeof(pubkey_obj)); memset(&prkey_obj, 0, sizeof(prkey_obj)); cert_info.id = obj_info.id; pubkey_info.id = obj_info.id; prkey_info.id = obj_info.id; cert_info.path = obj_info.path; prkey_info.path = obj_info.path; /* Add 0x3f00 to the front of prkey_info.path to make sc_key_file happy */ /* only do this if our path.len is 1 or 2 */ if (prkey_info.path.len && prkey_info.path.len <= 2) { prkey_info.path.value[2] = prkey_info.path.value[0]; prkey_info.path.value[3] = prkey_info.path.value[1]; prkey_info.path.value[0] = 0x3f; prkey_info.path.value[1] = 0x00; prkey_info.path.len += 2; } pubkey_info.native = 1; pubkey_info.key_reference = ((int)obj_info.id.value[0]) << 8 | obj_info.id.value[1]; prkey_info.key_reference = ((int)obj_info.id.value[0]) << 8 | obj_info.id.value[1]; prkey_info.native = 1; memcpy(cert_obj.label, obj_info.app_label, sizeof(obj_info.app_label)); memcpy(pubkey_obj.label, obj_info.app_label, sizeof(obj_info.app_label)); memcpy(prkey_obj.label, obj_info.app_label, sizeof(obj_info.app_label)); prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; sc_pkcs15_format_id(pins[0].id, &prkey_obj.auth_id); r = sc_pkcs15_read_file(p15card, &cert_info.path, &cert_der.value, &cert_der.len); if (r) { sc_log(card->ctx, "No cert found,i=%d", i); continue; } cert_info.path.count = cert_der.len; sc_log(card->ctx, "cert len=%"SC_FORMAT_LEN_SIZE_T"u, cert_info.path.count=%d r=%d\n", cert_der.len, cert_info.path.count, r); sc_log_hex(card->ctx, "cert", cert_der.value, cert_der.len); /* cache it using the PKCS15 emulation objects */ /* as it does not change */ if (cert_der.value) { cert_info.value.value = cert_der.value; cert_info.value.len = cert_der.len; cert_info.path.len = 0; /* use in mem cert from now on */ } /* following will find the cached cert in cert_info */ r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out); if (r < 0 || cert_out->key == NULL) { sc_log(card->ctx, "Failed to read/parse the certificate r=%d",r); if (cert_out != NULL) sc_pkcs15_free_certificate(cert_out); continue; } r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) { sc_log(card->ctx, " Failed to add cert obj r=%d",r); sc_pkcs15_free_certificate(cert_out); continue; } /* set the token name to the name of the CN of the first certificate */ if (!token_name) { u8 * cn_name = NULL; size_t cn_len = 0; static const struct sc_object_id cn_oid = {{ 2, 5, 4, 3, -1 }}; r = sc_pkcs15_get_name_from_dn(card->ctx, cert_out->subject, cert_out->subject_len, &cn_oid, &cn_name, &cn_len); if (r == SC_SUCCESS) { token_name = malloc (cn_len+1); if (!token_name) { free(cn_name); r = SC_ERROR_OUT_OF_MEMORY; goto fail; } memcpy(token_name, cn_name, cn_len); free(cn_name); token_name[cn_len] = 0; free(p15card->tokeninfo->label); p15card->tokeninfo->label = token_name; } } r = sc_pkcs15_encode_pubkey_as_spki(card->ctx, cert_out->key, &pubkey_info.direct.spki.value, &pubkey_info.direct.spki.len); if (r < 0) goto fail; pubkey_obj.emulated = cert_out->key; r = sc_pkcs15_get_bitstring_extension(card->ctx, cert_out, &usage_type, &usage, NULL); if (r < 0) { usage = 0xd9ULL; /* basic default usage */ } cac_map_usage(usage, cert_out->key->algorithm, &pubkey_info.usage, &prkey_info.usage, 1); sc_log(card->ctx, "cert %s: cert_usage=0x%x, pub_usage=0x%x priv_usage=0x%x\n", sc_dump_hex(cert_info.id.value, cert_info.id.len), usage, pubkey_info.usage, prkey_info.usage); if (cert_out->key->algorithm != SC_ALGORITHM_RSA) { sc_log(card->ctx, "unsupported key.algorithm %d", cert_out->key->algorithm); sc_pkcs15_free_certificate(cert_out); continue; } else { pubkey_info.modulus_length = cert_out->key->u.rsa.modulus.len * 8; prkey_info.modulus_length = cert_out->key->u.rsa.modulus.len * 8; r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); sc_log(card->ctx, "adding rsa public key r=%d usage=%x",r, pubkey_info.usage); if (r < 0) goto fail; r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); sc_log(card->ctx, "adding rsa private key r=%d usage=%x",r, prkey_info.usage); } cert_out->key = NULL; fail: sc_pkcs15_free_certificate(cert_out); if (r < 0) LOG_FUNC_RETURN(card->ctx, r); /* should not fail */ } r = (card->ops->card_ctl)(card, SC_CARDCTL_CAC_FINAL_GET_CERT_OBJECTS, &count); LOG_TEST_RET(card->ctx, r, "Can not finalize cert objects."); LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); }
static int sc_pkcs15emu_westcos_init(sc_pkcs15_card_t * p15card) { int i, r; int modulus_length = 0, usage = 0; char buf[256]; sc_card_t *card = p15card->card; sc_context_t *ctx = card->ctx; sc_serial_number_t serial; sc_path_t path; sc_file_t *file = NULL; sc_format_path("3F00", &path); r = sc_select_file(card, &path, &file); if (r) goto out; if (file) sc_file_free(file); file = NULL; if (p15card->label != NULL) free(p15card->label); p15card->label = strdup("westcos"); if (p15card->manufacturer_id != NULL) free(p15card->manufacturer_id); p15card->manufacturer_id = strdup("CEV"); /* get serial number */ r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial); r = sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0); if (r) goto out; if (p15card->serial_number != NULL) free(p15card->serial_number); p15card->serial_number = strdup(buf); p15card->version = buf[6]; p15card->flags = SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED; sc_format_path("AAAA", &path); r = sc_select_file(card, &path, &file); if (!r) { for (i = 0; i < 1; i++) { unsigned int flags; struct sc_pkcs15_pin_info pin_info; struct sc_pkcs15_object pin_obj; memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); flags = SC_PKCS15_PIN_FLAG_INITIALIZED; if (i == 1) { flags |= SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN; } pin_info.auth_id.len = 1; pin_info.auth_id.value[0] = i + 1; pin_info.reference = i; pin_info.flags = flags; pin_info.type = SC_PKCS15_PIN_TYPE_BCD; pin_info.min_length = 4; pin_info.stored_length = 8; pin_info.max_length = 8; pin_info.pad_char = 0xff; pin_info.path = path; pin_info.tries_left = -1; if (i == 1) strlcpy(pin_obj.label, "Unblock", sizeof(pin_obj.label)); else strlcpy(pin_obj.label, "User", sizeof(pin_obj.label)); pin_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r) goto out; } } if (file) sc_file_free(file); file = NULL; sc_format_path("0002", &path); r = sc_select_file(card, &path, &file); if (!r) { struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_object cert_obj; struct sc_pkcs15_pubkey_info pubkey_info; struct sc_pkcs15_object pubkey_obj; struct sc_pkcs15_pubkey *pkey = NULL; memset(&cert_info, 0, sizeof(cert_info)); memset(&cert_obj, 0, sizeof(cert_obj)); cert_info.id.len = 1; cert_info.id.value[0] = 0x45; cert_info.authority = 0; cert_info.path = path; r = sc_pkcs15_read_certificate(p15card, &cert_info, (sc_pkcs15_cert_t **) (&cert_obj.data)); if (!r) { sc_pkcs15_cert_t *cert = (sc_pkcs15_cert_t *) (cert_obj.data); strlcpy(cert_obj.label, "User certificat", 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) goto out; pkey = &cert->key; } memset(&pubkey_info, 0, sizeof(pubkey_info)); memset(&pubkey_obj, 0, sizeof(pubkey_obj)); pubkey_info.id.len = 1; pubkey_info.id.value[0] = 0x45; pubkey_info.modulus_length = modulus_length; pubkey_info.key_reference = 1; pubkey_info.native = 1; pubkey_info.usage = SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER | SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP; pubkey_info.path = path; strlcpy(pubkey_obj.label, "Public Key", sizeof(pubkey_obj.label)); pubkey_obj.auth_id.len = 1; pubkey_obj.auth_id.value[0] = 1; pubkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; pubkey_obj.type = SC_PKCS15_TYPE_PUBKEY_RSA; if (pkey == NULL) { pubkey_obj.data = &pubkey_info; r = sc_pkcs15_read_pubkey(p15card, &pubkey_obj, &pkey); if (r) goto out; //force rechargement clef et maj infos lors de sc_pkcs15emu_add_rsa_pubkey (sinon modulus = 0) pubkey_obj.flags = 0; } if (pkey->algorithm == SC_ALGORITHM_RSA) { modulus_length = (int)(pkey->u.rsa.modulus.len * 8); } pubkey_info.modulus_length = modulus_length; pubkey_obj.data = pkey; r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); if (r < 0) goto out; } if (!usage) { usage = SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; } if (file) sc_file_free(file); file = NULL; sc_format_path("0001", &path); r = sc_select_file(card, &path, &file); if (!r) { 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] = 0x45; prkey_info.usage = SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; prkey_info.native = 1; prkey_info.key_reference = 1; prkey_info.modulus_length = modulus_length; prkey_info.path = path; strlcpy(prkey_obj.label, "Private Key", sizeof(prkey_obj.label)); prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; prkey_obj.auth_id.len = 1; prkey_obj.auth_id.value[0] = 1; r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); if (r < 0) goto out; } r = 0; out:if (file) sc_file_free(file); return r; }
static int sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card) { sc_card_t *card = p15card->card; sc_context_t *ctx = card->ctx; char string[256]; u8 c4data[10]; u8 c5data[70]; int r, i; const pgp_pin_cfg_t *pin_cfg = (card->type == SC_CARD_TYPE_OPENPGP_V1) ? pin_cfg_v1 : pin_cfg_v2; sc_path_t path; sc_file_t *file = NULL; set_string(&p15card->tokeninfo->label, "OpenPGP card"); set_string(&p15card->tokeninfo->manufacturer_id, "OpenPGP project"); /* card->serialnr = 2 byte manufacturer_id + 4 byte serial_number */ if (card->serialnr.len > 0) { unsigned short manuf_id = bebytes2ushort(card->serialnr.value); int j; sc_bin_to_hex(card->serialnr.value, card->serialnr.len, string, sizeof(string)-1, 0); set_string(&p15card->tokeninfo->serial_number, string); for (j = 0; manuf_map[j].name != NULL; j++) { if (manuf_id == manuf_map[j].id) { set_string(&p15card->tokeninfo->manufacturer_id, manuf_map[j].name); break; } } } p15card->tokeninfo->flags = SC_PKCS15_TOKEN_PRN_GENERATION | SC_PKCS15_TOKEN_EID_COMPLIANT; /* Extract preferred language */ r = read_file(card, "0065:5f2d", string, sizeof(string)-1); if (r < 0) goto failed; string[r] = '\0'; set_string(&p15card->tokeninfo->preferred_language, string); /* Get CHV status bytes from DO 006E/0073/00C4: * 00: 1 == user consent for signature PIN * (i.e. PIN still valid for next PSO:CDS command) * 01-03: max length of pins 1-3 * 04-07: tries left for pins 1-3 */ if ((r = read_file(card, "006E:0073:00C4", c4data, sizeof(c4data))) < 0) goto failed; if (r != 7) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "CHV status bytes have unexpected length (expected 7, got %d)\n", r); return SC_ERROR_OBJECT_NOT_VALID; } /* Add PIN codes */ for (i = 0; i < 3; i++) { sc_pkcs15_auth_info_t pin_info; sc_pkcs15_object_t 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] = pin_cfg[i].reference; pin_info.attrs.pin.reference = pin_cfg[i].reference; pin_info.attrs.pin.flags = pin_cfg[i].flags; pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_UTF8; pin_info.attrs.pin.min_length = pin_cfg[i].min_length; pin_info.attrs.pin.stored_length = c4data[1 + pin_cfg[i].do_index]; pin_info.attrs.pin.max_length = c4data[1 + pin_cfg[i].do_index]; pin_info.attrs.pin.pad_char = '\0'; pin_info.tries_left = c4data[4 + pin_cfg[i].do_index]; pin_info.logged_in = SC_PIN_STATE_UNKNOWN; sc_format_path("3F00", &pin_info.path); strlcpy(pin_obj.label, pin_cfg[i].label, sizeof(pin_obj.label)); pin_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE; 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; } /* Get private key finger prints from DO 006E/0073/00C5: * 00-19: finger print for SIG key * 20-39: finger print for ENC key * 40-59: finger print for AUT key */ if ((r = read_file(card, "006E:0073:00C5", c5data, sizeof(c5data))) < 0) goto failed; if (r != 60) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "finger print bytes have unexpected length (expected 60, got %d)\n", r); return SC_ERROR_OBJECT_NOT_VALID; } /* XXX: check if "halfkeys" can be stored with gpg2. If not, add keypairs in one loop */ for (i = 0; i < 3; i++) { sc_pkcs15_prkey_info_t prkey_info; sc_pkcs15_object_t prkey_obj; u8 cxdata[10]; char path_template[] = "006E:0073:00Cx"; int j; memset(&prkey_info, 0, sizeof(prkey_info)); memset(&prkey_obj, 0, sizeof(prkey_obj)); path_template[13] = '1' + i; /* The needed tags are C1 C2 and C3 */ if ((r = read_file(card, path_template, cxdata, sizeof(cxdata))) < 0) goto failed; if (r != 6) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Key info bytes have unexpected length (expected 6, got %d)\n", r); return SC_ERROR_INTERNAL; } /* check validity using finger prints */ for (j = 19; j >= 0; j--) { if (c5data[20 * i + j] != '\0') break; } /* only add valid keys, i.e. those with a legal algorithm identifier & finger print */ if (j >= 0 && cxdata[0] != 0) { prkey_info.id.len = 1; prkey_info.id.value[0] = i + 1; prkey_info.usage = key_cfg[i].prkey_usage; prkey_info.native = 1; prkey_info.key_reference = i; prkey_info.modulus_length = bebytes2ushort(cxdata + 1); strlcpy(prkey_obj.label, key_cfg[i].label, sizeof(prkey_obj.label)); prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE | SC_PKCS15_CO_FLAG_MODIFIABLE; prkey_obj.auth_id.len = 1; prkey_obj.auth_id.value[0] = key_cfg[i].prkey_pin; r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); if (r < 0) return SC_ERROR_INTERNAL; } } /* Add public keys */ for (i = 0; i < 3; i++) { sc_pkcs15_pubkey_info_t pubkey_info; sc_pkcs15_object_t pubkey_obj; u8 cxdata[10]; char path_template[] = "006E:0073:00Cx"; int j; memset(&pubkey_info, 0, sizeof(pubkey_info)); memset(&pubkey_obj, 0, sizeof(pubkey_obj)); path_template[13] = '1' + i; /* The needed tags are C1 C2 and C3 */ if ((r = read_file(card, path_template, cxdata, sizeof(cxdata))) < 0) goto failed; if (r != 6) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Key info bytes have unexpected length (expected 6, got %d)\n", r); return SC_ERROR_INTERNAL; } /* check validity using finger prints */ for (j = 19; j >= 0; j--) { if (c5data[20 * i + j] != '\0') break; } /* only add valid keys, i.e. those with a legal algorithm identifier & finger print */ if (j >= 0 && cxdata[0] != 0) { pubkey_info.id.len = 1; pubkey_info.id.value[0] = i + 1; pubkey_info.modulus_length = bebytes2ushort(cxdata + 1); pubkey_info.usage = key_cfg[i].pubkey_usage; sc_format_path(key_cfg[i].pubkey_path, &pubkey_info.path); strlcpy(pubkey_obj.label, key_cfg[i].label, sizeof(pubkey_obj.label)); pubkey_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE; r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); if (r < 0) return SC_ERROR_INTERNAL; } } /* Check if certificate DO 7F21 holds data */ sc_format_path("7F21", &path); r = sc_select_file(card, &path, &file); if (r < 0) goto failed; /* If DO 7F21 holds data, we declare a cert object for pkcs15 */ if (file->size > 0) { 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)); /* Certificate ID. We use the same ID as the authentication key */ cert_info.id.value[0] = 3; cert_info.id.len = 1; /* Authority, flag is zero */ /* The path following which PKCS15 will find the content of the object */ sc_format_path("3F007F21", &cert_info.path); /* Object label */ strlcpy(cert_obj.label, "Cardholder certificate", sizeof(cert_obj.label)); r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) goto failed; } /* Add PKCS#15 DATA objects from other OpenPGP card DOs. The return * value is ignored, so this will not cause initialization to fail. */ sc_pkcs15emu_openpgp_add_data(p15card); failed: if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Failed to initialize OpenPGP emulation: %s\n", sc_strerror(r)); } sc_file_free(file); return r; }
int sc_pkcs15emu_tcos_init_ex(sc_pkcs15_card_t *p15card, sc_pkcs15emu_opt_t *opts) { static const struct { const char *card, *manufacturer; } cardlist[]= { {"Netkey E4 Card", "TeleSec GmbH"}, {"SignTrust Card", "Deutsche Post"}, {"DATEV classic", "DATEV"}, {"Smartkey Card TypA", "Kobil GmbH"}, {"Smartkey Card TypB", "Kobil GmbH"}, {"Chipkarte JLU Giessen", "Kobil GmbH"} }; static struct { int flags; const int type, id, writable; const char *path; const char *label; } certlist[]= { {0, 1, 0x45, 0, "DF01C000", "Telesec Signatur Zertifikat"}, {3, 1, 0x45, 1, "DF014331", "Signatur Zertifikat 1"}, {3, 1, 0x45, 1, "DF014332", "Signatur Zertifikat 2"}, {1, 1, 0x46, 0, "DF01C100", "Telesec Authentifizierungs Zertifikat"}, {3, 1, 0x46, 1, "DF014371", "Authentifizierungs Zertifikat 1"}, {3, 1, 0x46, 1, "DF014372", "Authentifizierungs Zertifikat 2"}, {1, 1, 0x47, 0, "DF01C200", "Telesec Verschluesselungs Zertifikat"}, {3, 1, 0x47, 1, "DF0143B1", "Verschluesselungs Zertifikat 1"}, {3, 1, 0x47, 1, "DF0143B2", "Verschluesselungs Zertifikat 2"}, {1, 1, 0x48, 1, "DF06C000", "SigG Zertifikat 1"}, {1, 1, 0x48, 1, "DF064331", "SigG Zertifikat 2"}, {1, 1, 0x48, 1, "DF064332", "SigG Zertifikat 3"}, {1, 1, 0x49, 1, "41014352", "W2K Logon Zertifikat"}, {0, 2, 0x45, 1, "8000DF01C000", "SignTrust Signatur Zertifikat"}, {1, 2, 0x46, 1, "800082008220", "SignTrust Verschluesselungs Zertifikat"}, {1, 2, 0x47, 1, "800083008320", "SignTrust Authentifizierungs Zertifikat"}, {0, 3, 0x45, 0, "3000C500", "DATEV Signatur Zertifikat"}, {1, 3, 0x46, 0, "DF02C200", "DATEV Verschluesselungs Zertifikat"}, {1, 3, 0x47, 0, "DF02C500", "DATEV Authentifizierungs Zertifikat"}, {0, 4, 0x45, 1, "41004352", "Smartkey Zertifikat 1"}, {0, 4, 0x46, 1, "41004353", "Smartkey Zertifikat 2"}, {0, 5, 0x45, 1, "41014352", "Smartkey Zertifikat 1"}, {0, 5, 0x46, 1, "41014353", "Smartkey Zertifikat 2"}, {0, 6, 0x45, 1, "41004352", "UniCard Giessen Zertifikat"}, {0, 0, 0, 0, NULL, NULL} }; static const struct { int type, id, auth_id; const char *path; unsigned char key_reference; const char *label; } keylist[]= { {1, 0x45, 4, "DF015331", 0x80, "Signatur Schluessel"}, {1, 0x46, 3, "DF015371", 0x82, "Authentifizierungs Schluessel"}, {1, 0x47, 3, "DF0153B1", 0x81, "Verschluesselungs Schluessel"}, {1, 0x48, 5, "DF065331", 0x80, "SigG Schluessel"}, {1, 0x49, 1, "41015103", 0x83, "W2K Logon Schluessel"}, {2, 0x45, 1, "8000DF015331", 0x80, "Signatur Schluessel"}, {2, 0x46, 2, "800082008210", 0x80, "Verschluesselungs Schluessel"}, {2, 0x47, 3, "800083008310", 0x80, "Authentifizierungs Schluessel"}, {3, 0x45, 1, "30005371", 0x82, "Signatur Schluessel"}, {3, 0x46, 1, "DF0253B1", 0x81, "Verschluesselungs Schluessel"}, {3, 0x47, 1, "DF025371", 0x82, "Authentifizierung Schluessel"}, {4, 0x45, 1, "41005103", 0x83, "Smartkey Schluessel 1"}, {4, 0x46, 1, "41005104", 0x84, "Smartkey Schluessel 2"}, {5, 0x45, 1, "41015103", 0x83, "Smartkey Schluessel 1"}, {5, 0x46, 1, "41015104", 0x84, "Smartkey Schluessel 2"}, {6, 0x45, 1, "3F004100", 0x83, "UniCard Giessen Schluessel"}, {0, 0, 0, NULL, 0, NULL} }; static const struct { int type, id, auth_id, min_length; unsigned char reference; const char *path; const char *label; int flags; } pinlist[]= { { 1, 1, 2, 6, 0x00, "5000", "globale PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN }, { 1, 2, 0, 8, 0x01, "5001", "globale PUK", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN | SC_PKCS15_PIN_FLAG_SO_PIN }, { 1, 3, 1, 6, 0x80, "DF015080", "Netkey PIN0", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED }, { 1, 4, 1, 6, 0x81, "DF015081", "Netkey PIN1", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED }, { 1, 5, 0, 6, 0x81, "DF065081", "SigG PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED }, { 2, 1, 0, 6, 0x81, "8000DF010000", "Signatur PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED }, { 2, 2, 0, 6, 0x81, "800082000040", "Verschluesselungs PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED }, { 2, 3, 0, 6, 0x81, "800083000040", "Authentifizierungs PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_INITIALIZED }, { 3, 1, 0, 6, 0x01, "5001", "globale PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN }, { 4, 1, 2, 6, 0x00, "5000", "globale PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN }, { 4, 2, 0, 8, 0x01, "5008", "globale PUK", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN | SC_PKCS15_PIN_FLAG_SO_PIN }, { 5, 1, 2, 6, 0x00, "5000", "globale PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN }, { 5, 2, 0, 8, 0x01, "5008", "globale PUK", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN | SC_PKCS15_PIN_FLAG_SO_PIN }, { 6, 1, 0, 6, 0x00, "4100", "globale PIN", SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED }, {0, 0, 0, 0, 0, NULL, NULL, 0} }; sc_card_t *card = p15card->card; sc_context_t *ctx = p15card->card->ctx; sc_path_t path; sc_file_t *file; sc_serial_number_t serialnr; char serial[30]; int i, j, found, r, usage, cardtype; /* check if we have the correct card OS unless SC_PKCS15EMU_FLAGS_NO_CHECK */ i=(opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK); if (!i && strcmp(card->name, "TCOS")) return SC_ERROR_WRONG_CARD; /* get the card serial number */ r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serialnr); if (r < 0) { sc_debug(ctx, "unable to get ICCSN\n"); r = SC_ERROR_WRONG_CARD; goto failed; } sc_bin_to_hex(serialnr.value, serialnr.len , serial, sizeof(serial), 0); serial[19] = '\0'; set_string(&p15card->serial_number, serial); /* detect cardtype and certificates */ cardtype=0; for(i=0; certlist[i].id; ++i) { if(cardtype && certlist[i].type!=cardtype) continue; if(!cardtype && (certlist[i].flags&1)) continue; if(!cardtype && ctx->debug>=2) sc_debug(ctx, "Testing %s\n",cardlist[certlist[i].type-1].card); if(ctx->debug>=2) sc_debug(ctx, "Testing Cert %s, %s\n", certlist[i].path, certlist[i].label); sc_format_path(certlist[i].path, &path); sc_ctx_suppress_errors_on(ctx); r = sc_select_file(card, &path, NULL); sc_ctx_suppress_errors_off(ctx); if(r<0) continue; cardtype=certlist[i].type; certlist[i].flags |= 4; } if(ctx->debug >= 1) sc_debug(ctx, "Cardtype=%d, %s\n", cardtype, cardlist[cardtype-1].card); if(cardtype<1 || cardtype>(int)(sizeof(cardlist)/sizeof(cardlist[0]))) { r = SC_ERROR_WRONG_CARD; goto failed; } set_string(&p15card->label, cardlist[cardtype-1].card); set_string(&p15card->manufacturer_id, cardlist[cardtype-1].manufacturer); /* insert certificates */ for(found=1; found;) { for(i=found=0; certlist[i].id && !found; ++i) if(certlist[i].flags&4) found=certlist[i].id; for(j=0; j<2; ++j) for(i=0; certlist[i].id; ++i) { struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_object cert_obj; unsigned char cert[20]; if(certlist[i].id!=found) continue; if((certlist[i].flags&2) == 2*j) continue; if(!(certlist[i].flags&4)) continue; certlist[i].flags-=4; sc_format_path(certlist[i].path, &path); if(sc_select_file(card, &path, NULL)<0) continue; /* read first 20 bytes of certificate, first two bytes * must be 0x30 0x82, otherwise this is an empty cert-file */ r = sc_read_binary(card, 0, cert, sizeof(cert), 0); if(r<0 || cert[0]!=0x30 || cert[1]!=0x82) continue; if(ctx->debug>=1) { sc_debug(ctx,"Cert %02X %s, %s\n",certlist[i].id,certlist[i].path,certlist[i].label); } /* Telesec-Certificates are prefixed by an OID, * for example 06:03:55:04:24. so use appropriate offset */ if(cert[4]==0x06 && cert[5]<10 && cert[6+cert[5]]==0x30 && cert[7+cert[5]]==0x82) { path.index=6+cert[5]; path.count=(cert[8+cert[5]]<<8) + cert[9+cert[5]] + 4; } else { path.index=0; path.count=(cert[2]<<8) + cert[3] + 4; } memset(&cert_info, 0, sizeof(cert_info)); cert_info.id.len = 1; cert_info.id.value[0] = certlist[i].id; cert_info.authority = 0; cert_info.path = path; memset(&cert_obj, 0, sizeof(cert_obj)); strlcpy(cert_obj.label, certlist[i].label, sizeof(cert_obj.label)); cert_obj.flags = certlist[i].writable ? SC_PKCS15_CO_FLAG_MODIFIABLE : 0; r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) { sc_debug(ctx, "sc_pkcs15emu_add_x509_cert(%s) failed\n", certlist[i].path); r = SC_ERROR_INTERNAL; goto failed; } } } for(i=0; keylist[i].id; ++i) { struct sc_pkcs15_prkey_info prkey_info; struct sc_pkcs15_object prkey_obj; if(keylist[i].type!=cardtype) continue; sc_format_path(keylist[i].path, &path); sc_ctx_suppress_errors_on(ctx); r = sc_select_file(card, &path, &file); sc_ctx_suppress_errors_off(ctx); if (r < 0) continue; if(ctx->debug >= 1) sc_debug(ctx,"Key %02X %s, %s\n",keylist[i].id,keylist[i].path,keylist[i].label); usage = SC_PKCS15_PRKEY_USAGE_SIGN; if (file->prop_attr[1] & 0x04) usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT; if (file->prop_attr[1] & 0x08) usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION; memset(&prkey_info, 0, sizeof(prkey_info)); prkey_info.id.len = 1; prkey_info.id.value[0] = keylist[i].id; prkey_info.usage = usage; prkey_info.native = 1; prkey_info.key_reference = keylist[i].key_reference; prkey_info.modulus_length = 1024; sc_format_path(keylist[i].path, &prkey_info.path); memset(&prkey_obj, 0, sizeof(prkey_obj)); strlcpy(prkey_obj.label, keylist[i].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] = keylist[i].auth_id; r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); sc_file_free(file); if (r < 0) { sc_debug(ctx, "sc_pkcs15emu_add_rsa_prkey(%s) failed\n", keylist[i].path); r = SC_ERROR_INTERNAL; goto failed; } } for(i=0; pinlist[i].id; ++i) { struct sc_pkcs15_pin_info pin_info; struct sc_pkcs15_object pin_obj; if(pinlist[i].type && pinlist[i].type!=cardtype) continue; sc_format_path(pinlist[i].path, &path); sc_ctx_suppress_errors_on(ctx); r = sc_select_file(card, &path, &file); sc_ctx_suppress_errors_off(ctx); if (r < 0) continue; if(ctx->debug >= 1) sc_debug(ctx, "PIN %02X %s, %s\n", pinlist[i].id,pinlist[i].path,pinlist[i].label); memset(&pin_info, 0, sizeof(pin_info)); pin_info.auth_id.len = 1; pin_info.auth_id.value[0] = pinlist[i].id; pin_info.reference = pinlist[i].reference; pin_info.flags = pinlist[i].flags; pin_info.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; pin_info.min_length = pinlist[i].min_length; pin_info.stored_length = 16; pin_info.max_length = 16; pin_info.pad_char = '\0'; pin_info.tries_left = file->prop_attr[3]; sc_format_path(pinlist[i].path, &pin_info.path); memset(&pin_obj, 0, sizeof(pin_obj)); strlcpy(pin_obj.label, pinlist[i].label, sizeof(pin_obj.label)); pin_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE; pin_obj.auth_id.len = pinlist[i].auth_id ? 0 : 1; pin_obj.auth_id.value[0] = pinlist[i].auth_id; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); sc_file_free(file); if (r < 0) { sc_debug(ctx, "sc_pkcs15emu_add_pin_obj(%s) failed\n", pinlist[i].path); r = SC_ERROR_INTERNAL; goto failed; } } /* return to MF */ sc_format_path("3F00", &path); r = sc_select_file(card, &path, NULL); failed: if (r < 0) sc_debug(ctx, "PKCS15-emulation for TCOS based preformatted failed: %s\n", sc_strerror(r)); return r; }
static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) { /* The cert objects will return all the data */ const objdata objects[] = { {"1", "Card Capability Container", "2.16.840.1.101.3.7.1.219.0", NULL, "DB00", 0}, {"2", "Card Holder Unique Identifier", "2.16.840.1.101.3.7.2.48.0", NULL, "3000", 0}, {"3", "Unsigned Card Holder Unique Identifier", "2.16.840.1.101.3.7.2.48.2", NULL, "3010", 0}, {"4", "X.509 Certificate for PIV Authentication", "2.16.840.1.101.3.7.2.1.1", NULL, "0101", 0}, {"5", "Card Holder Fingerprints", "2.16.840.1.101.3.7.2.96.16", "1", "6010", SC_PKCS15_CO_FLAG_PRIVATE}, {"6", "Printed Information", "2.16.840.1.101.3.7.2.48.1", "1", "3001", SC_PKCS15_CO_FLAG_PRIVATE}, {"7", "Card Holder Facial Image", "2.16.840.1.101.3.7.2.96.48", "1", "6030", SC_PKCS15_CO_FLAG_PRIVATE}, {"8", "X.509 Certificate for Digital Signature", "2.16.840.1.101.3.7.2.1.0", NULL, "0100", 0}, {"9", "X.509 Certificate for Key Management", "2.16.840.1.101.3.7.2.1.2", NULL, "0102", 0}, {"10","X.509 Certificate for Card Authentication", "2.16.840.1.101.3.7.2.5.0", NULL, "0500", 0}, {"11", "Security Object", "2.16.840.1.101.3.7.2.144.0", NULL, "9000", 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; /* * NIST 800-73-1 is proposing to lift the restriction on * requering pin protected certs. Thus the default will be to * not require this. But there are a number of test cards * that do enforce it. Code later on will allow SC_PKCS15_CO_FLAG_PRIVATE * to be set. */ /* certs will be pulled out from the cert objects */ cdata certs[] = { {"1", "Certificate for PIV Authentication", 0, "0101cece", 0, 0}, {"2", "Certificate for Digital Signature", 0, "0100cece", 0, 0}, {"3", "Certificate for Key Management", 0, "0102cece", 0, 0}, {"4", "Certificate for Card Authentication", 0, "0500cece", 0, 0}, {NULL, NULL, 0, NULL, 0, 0} }; const pindata pins[] = { { "1", "PIV Card Holder pin", "", 0x80, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 8, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL, -1, 0xFF, SC_PKCS15_CO_FLAG_PRIVATE }, { "2", "PIV PUK", "", 0x81, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 8, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_SO_PIN | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN, -1, 0xFF, SC_PKCS15_CO_FLAG_PRIVATE }, /* there are some more key, but dont need for now */ /* The admin 9b might fall in here */ { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; /* * The size of the key or the algid is not really known * but can be derived from the certificates. * the cert, pubkey and privkey are a set. * Key usages bits taken from pkcs15v1_1 Table 2 */ pubdata pubkeys[] = { { "1", "PIV AUTH pubkey", 0000, SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP | SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER, "9A06", 0x9A, "1", 0, 0}, { "2", "SIGN pubkey", 0000, SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, "9C06", 0x9C, "1", 0, 0}, { "3", "KEY MAN pubkey", 0000, SC_PKCS15_PRKEY_USAGE_WRAP, "9D06", 0x9D, "1", 0, 0}, { "4", "CARD AUTH pubkey", 0000, SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER, "9E06", 0x9E, "0", 0, 0}, /* no pin, and avail in contactless */ { NULL, NULL, 0, 0, NULL, 0, NULL, 0, 0} }; prdata prkeys[] = { { "1", "PIV AUTH key", 0000, SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP | SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER, "", 0x9A, "1", 0}, { "2", "SIGN key", 0000, SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, "", 0x9C, "1", 0}, { "3", "KEY MAN key", 0000, SC_PKCS15_PRKEY_USAGE_UNWRAP, "", 0x9D, "1", 0}, { "4", "CARD AUTH key", 0000, SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER, "", 0x9E, NULL, 0}, /* no PIN needed, works with wireless */ { NULL, NULL, 0, 0, NULL, 0, NULL, 0} }; int r, i; sc_card_t *card = p15card->card; sc_file_t *file_out = NULL; int exposed_cert[4] = {1, 0, 0, 0}; sc_serial_number_t serial; char buf[SC_MAX_SERIALNR * 2 + 1]; SC_FUNC_CALLED(card->ctx, 1); /* could read this off card if needed */ /* CSP does not like a - in the name */ p15card->label = strdup("PIV_II"); p15card->manufacturer_id = strdup(MANU_ID); /* * get serial number * We will use the FASC-N from the CHUID * Note we are not verifying CHUID, belongs to this card * but need serial number for Mac tokend */ sc_ctx_suppress_errors_on(card->ctx); r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial); sc_ctx_suppress_errors_off(card->ctx); if (r < 0) { sc_debug(card->ctx,"sc_card_ctl rc=%d",r); p15card->serial_number = strdup("00000000"); } else { sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0); p15card->serial_number = strdup(buf); } sc_debug(card->ctx, "PIV-II adding objects..."); /* set other objects */ for (i = 0; objects[i].label; i++) { 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(objects[i].id, &obj_info.id); sc_format_path(objects[i].path, &obj_info.path); /* We could make sure the object is on the card */ /* But really don't need to do this now */ // sc_ctx_suppress_errors_on(card->ctx); // r = sc_select_file(card, &obj_info.path, NULL); // sc_ctx_suppress_errors_off(card->ctx); // if (r == SC_ERROR_FILE_NOT_FOUND) // continue; strncpy(obj_info.app_label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); r = sc_format_oid(&obj_info.app_oid, objects[i].aoid); if (r != SC_SUCCESS) return r; if (objects[i].auth_id) sc_pkcs15_format_id(objects[i].auth_id, &obj_obj.auth_id); strncpy(obj_obj.label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); obj_obj.flags = objects[i].obj_flags; r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info); if (r < 0) SC_FUNC_RETURN(card->ctx, 1, r); } /* * certs, pubkeys and priv keys are related and we assume * they are in order * We need to read the cert, get modulus and keylen * We use those for the pubkey, and priv key objects. * If no cert, then see if pubkey (i.e. we are initilizing, * and the pubkey is in a file,) then add pubkey and privkey * If no cert and no pubkey, skip adding them. */ /* set certs */ sc_debug(card->ctx, "PIV-II adding certs..."); for (i = 0; certs[i].label; i++) { struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_object cert_obj; sc_pkcs15_der_t cert_der; sc_pkcs15_cert_t *cert_out; if ((card->flags & 0x20) && (exposed_cert[i] == 0)) continue; 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); strncpy(cert_obj.label, certs[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); cert_obj.flags = certs[i].obj_flags; /* see if we have a cert */ /* use a &file_out so card-piv will read cert if present */ sc_ctx_suppress_errors_on(card->ctx); r = sc_pkcs15_read_file(p15card, &cert_info.path, &cert_der.value, &cert_der.len, &file_out); sc_ctx_suppress_errors_off(card->ctx); if (file_out) { sc_file_free(file_out); file_out = NULL; } if (r) { sc_debug(card->ctx, "No cert found,i=%d", i); continue; } certs[i].found = 1; /* cache it using the PKCS15 emulation objects */ /* as it does not change */ if (cert_der.value) { cert_info.value.value = cert_der.value; cert_info.value.len = cert_der.len; cert_info.path.len = 0; /* use in mem cert from now on */ } /* following will find the cached cert in cert_info */ r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out); if (r < 0) { sc_debug(card->ctx, "Failed to read/parse the certificate r=%d",r); continue; } /* TODO support DSA keys */ if (cert_out->key.algorithm == SC_ALGORITHM_RSA) { /* save modulus_len in pub and priv */ pubkeys[i].modulus_len = cert_out->key.u.rsa.modulus.len * 8; prkeys[i].modulus_len = cert_out->key.u.rsa.modulus.len * 8; } sc_pkcs15_free_certificate(cert_out); r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) { sc_error(card->ctx, " Failed to add cert obj r=%d",r); continue; } } /* set pins */ sc_debug(card->ctx, "PIV-II adding pins..."); for (i = 0; pins[i].label; i++) { struct sc_pkcs15_pin_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.reference = pins[i].ref; pin_info.flags = pins[i].flags; pin_info.type = pins[i].type; pin_info.min_length = pins[i].minlen; pin_info.stored_length = pins[i].storedlen; pin_info.max_length = pins[i].maxlen; pin_info.pad_char = pins[i].pad_char; sc_format_path(pins[i].path, &pin_info.path); pin_info.tries_left = -1; strncpy(pin_obj.label, pins[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); pin_obj.flags = pins[i].obj_flags; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) SC_FUNC_RETURN(card->ctx, 1, r); } /* set public keys */ /* We may only need this during initialzation when genkey * gets the pubkey, but it can not be read from the card * at a later time. The piv-tool can stach in file */ sc_debug(card->ctx, "PIV-II adding pub keys..."); for (i = 0; pubkeys[i].label; i++) { struct sc_pkcs15_pubkey_info pubkey_info; struct sc_pkcs15_object pubkey_obj; struct sc_pkcs15_pubkey *p15_key; if ((card->flags & 0x20) && (exposed_cert[i] == 0)) continue; memset(&pubkey_info, 0, sizeof(pubkey_info)); memset(&pubkey_obj, 0, sizeof(pubkey_obj)); sc_pkcs15_format_id(pubkeys[i].id, &pubkey_info.id); pubkey_info.usage = pubkeys[i].usage; pubkey_info.native = 1; pubkey_info.key_reference = pubkeys[i].ref; sc_format_path(pubkeys[i].path, &pubkey_info.path); strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); pubkey_obj.flags = pubkeys[i].obj_flags; if (pubkeys[i].auth_id) sc_pkcs15_format_id(pubkeys[i].auth_id, &pubkey_obj.auth_id); if (certs[i].found == 0) { /* no cert found */ sc_debug(card->ctx,"No cert for this pub key i=%d",i); /* TODO DSA */ pubkey_obj.type = SC_PKCS15_TYPE_PUBKEY_RSA; pubkey_obj.data = &pubkey_info; sc_ctx_suppress_errors_on(card->ctx); r = sc_pkcs15_read_pubkey(p15card, &pubkey_obj, &p15_key); sc_ctx_suppress_errors_off(card->ctx); pubkey_obj.data = NULL; sc_debug(card->ctx," READING PUB KEY r=%d",r); if (r < 0 ) { continue; } /* Only get here if no cert, and the card-piv.c found * there is a pub key file. This only happens when trying * initializing a card and have set env to point at file */ if (p15_key->algorithm == SC_ALGORITHM_RSA) { /* save modulus_len in pub and priv */ pubkeys[i].modulus_len = p15_key->u.rsa.modulus.len * 8; prkeys[i].modulus_len = p15_key->u.rsa.modulus.len * 8; pubkeys[i].found = 1; } } pubkey_info.modulus_length = pubkeys[i].modulus_len; strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); /* TODO DSA keys */ r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); if (r < 0) SC_FUNC_RETURN(card->ctx, 1, r); /* should not fail */ pubkeys[i].found = 1; } /* set private keys */ sc_debug(card->ctx, "PIV-II adding private keys..."); for (i = 0; prkeys[i].label; i++) { struct sc_pkcs15_prkey_info prkey_info; struct sc_pkcs15_object prkey_obj; if ((card->flags & 0x20) && (exposed_cert[i] == 0)) continue; memset(&prkey_info, 0, sizeof(prkey_info)); memset(&prkey_obj, 0, sizeof(prkey_obj)); if (certs[i].found == 0 && pubkeys[i].found == 0) continue; /* i.e. no cert or pubkey */ 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; /* The cert or pubkey should have filled modulus_len */ /* TODO DSA keys */ sc_format_path(prkeys[i].path, &prkey_info.path); strncpy(prkey_obj.label, prkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); 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) SC_FUNC_RETURN(card->ctx, 1, r); } SC_FUNC_RETURN(card->ctx, 1, SC_SUCCESS); }
int sc_test_init(int *argc, char *argv[]) { char *opt_driver = NULL, *app_name; int opt_debug = 0, opt_reader = -1; int i, c, rc; sc_context_param_t ctx_param; if ((app_name = strrchr(argv[0], '/')) != NULL) app_name++; else app_name = argv[0]; while ((c = getopt_long(*argc, argv, "r:c:d", options, NULL)) != -1) { switch (c) { case 'r': opt_reader = atoi(optarg); break; case 'c': opt_driver = optarg; break; case 'd': opt_debug++; break; default: fprintf(stderr, "usage: %s [-r reader] [-c driver] [-d]\n", app_name); exit(1); } } *argc = optind; printf("Using libopensc version %s.\n", sc_get_version()); memset(&ctx_param, 0, sizeof(ctx_param)); ctx_param.ver = 0; ctx_param.app_name = app_name; i = sc_context_create(&ctx, &ctx_param); if (i != SC_SUCCESS) { printf("Failed to establish context: %s\n", sc_strerror(i)); return i; } ctx->debug = opt_debug; if (opt_reader >= sc_ctx_get_reader_count(ctx)) { fprintf(stderr, "Illegal reader number.\n" "Only %d reader(s) configured.\n", sc_ctx_get_reader_count(ctx)); exit(1); } while (1) { if (opt_reader >= 0) { rc = sc_detect_card_presence(sc_ctx_get_reader(ctx, opt_reader)); printf("Card %s.\n", rc == 1 ? "present" : "absent"); if (rc < 0) return rc; } else { for (i = rc = 0; rc != 1 && i < sc_ctx_get_reader_count(ctx); i++) rc = sc_detect_card_presence(sc_ctx_get_reader(ctx, opt_reader)); if (rc == 1) opt_reader = i - 1; } if (rc > 0) { printf("Card detected in reader '%s'\n",sc_ctx_get_reader(ctx, opt_reader)->name); break; } if (rc < 0) return rc; printf("Please insert a smart card. Press return to continue"); fflush(stdout); while (getc(stdin) != '\n') ; } printf("Connecting... "); fflush(stdout); i = sc_connect_card(sc_ctx_get_reader(ctx, opt_reader), &card); if (i != SC_SUCCESS) { printf("Connecting to card failed: %s\n", sc_strerror(i)); return i; } printf("connected.\n"); { char tmp[SC_MAX_ATR_SIZE*3]; sc_bin_to_hex(card->atr, card->atr_len, tmp, sizeof(tmp) - 1, ':'); printf("ATR = %s\n",tmp); } if (opt_driver != NULL) { rc = sc_set_card_driver(ctx, opt_driver); if (rc != 0) { fprintf(stderr, "Driver '%s' not found!\n", opt_driver); return rc; } } return 0; }
static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int password_shares_threshold, int password_shares_total) { int r, i; BIGNUM prime; BIGNUM secret; char buf[64]; char hex[64]; int l; secret_share_t *shares = NULL; secret_share_t *sp; u8 rngseed[16]; printf( "\nThe DKEK will be enciphered using a randomly generated 64 bit password.\n"); printf( "This password is split using a (%i-of-%i) threshold scheme.\n\n", password_shares_threshold, password_shares_total); printf( "Please keep the generated and encrypted DKEK file in a safe location. We also recommend \n"); printf( "to keep a paper printout, in case the electronic version becomes unavailable. A printable version\n"); printf( "of the file can be generated using \"openssl base64 -in <filename>\".\n"); printf("\n\nPress <enter> to continue"); waitForEnterKeyPressed(); *pwd = calloc(1, 8); *pwdlen = 8; r = sc_get_challenge(card, *pwd, 8); if (r < 0) { printf("Error generating random key failed with ", sc_strerror(r)); OPENSSL_cleanse(pwd, *pwdlen); free(pwd); return r; } **pwd |= 0x80; /* * Initialize prime and secret */ BN_init(&prime); BN_init(&secret); /* * Encode the secret value */ BN_bin2bn(*pwd, *pwdlen, &secret); /* * Generate seed and calculate a prime depending on the size of the secret */ r = sc_get_challenge(card, rngseed, 16); if (r < 0) { printf("Error generating random seed failed with ", sc_strerror(r)); OPENSSL_cleanse(pwd, *pwdlen); free(pwd); return r; } generatePrime(&prime, &secret, password_shares_total, rngseed); // Allocate data buffer for the generated shares shares = malloc(password_shares_total * sizeof(secret_share_t)); createShares(&secret, password_shares_threshold, password_shares_total, prime, shares); sp = shares; for (i = 0; i < password_shares_total; i++) { clearScreen(); printf("Press <enter> to display key share %i of %i\n\n", i + 1, password_shares_total); waitForEnterKeyPressed(); clearScreen(); printf("Share %i of %i\n\n", i + 1, password_shares_total); l = BN_bn2bin(&prime, buf); sc_bin_to_hex(buf, l, hex, 64, ':'); printf("\nPrime : %s\n", hex); printf("Share ID : %s\n", BN_bn2dec(&(sp->x))); l = BN_bn2bin(&(sp->y), buf); sc_bin_to_hex(buf, l, hex, 64, ':'); printf("Share value : %s\n", hex); printf("\n\nPlease note ALL values above and press <enter> when finished"); waitForEnterKeyPressed(); sp++; } clearScreen(); cleanUpShares(shares, password_shares_total); BN_clear_free(&prime); BN_clear_free(&secret); return 0; }
static int sc_pkcs15emu_piv_init(sc_pkcs15_card_t *p15card) { /* The cert objects will return all the data */ /* Note: pkcs11 objects do not have CK_ID values */ static const objdata objects[] = { {"1", "Card Capability Container", "2.16.840.1.101.3.7.1.219.0", NULL, "DB00", 0}, {"2", "Card Holder Unique Identifier", "2.16.840.1.101.3.7.2.48.0", NULL, "3000", 0}, {"3", "Unsigned Card Holder Unique Identifier", "2.16.840.1.101.3.7.2.48.2", NULL, "3010", 0}, {"4", "X.509 Certificate for PIV Authentication", "2.16.840.1.101.3.7.2.1.1", NULL, "0101", 0}, {"5", "Cardholder Fingerprints", "2.16.840.1.101.3.7.2.96.16", "1", "6010", SC_PKCS15_CO_FLAG_PRIVATE}, {"6", "Printed Information", "2.16.840.1.101.3.7.2.48.1", "1", "3001", SC_PKCS15_CO_FLAG_PRIVATE}, {"7", "Cardholder Facial Image", "2.16.840.1.101.3.7.2.96.48", "1", "6030", SC_PKCS15_CO_FLAG_PRIVATE}, {"8", "X.509 Certificate for Digital Signature", "2.16.840.1.101.3.7.2.1.0", NULL, "0100", 0}, {"9", "X.509 Certificate for Key Management", "2.16.840.1.101.3.7.2.1.2", NULL, "0102", 0}, {"10","X.509 Certificate for Card Authentication", "2.16.840.1.101.3.7.2.5.0", NULL, "0500", 0}, {"11", "Security Object", "2.16.840.1.101.3.7.2.144.0", NULL, "9000", 0}, {"12", "Discovery Object", "2.16.840.1.101.3.7.2.96.80", NULL, "6050", 0}, {"13", "Key History Object", "2.16.840.1.101.3.7.2.96.96", NULL, "6060", 0}, {"14", "Cardholder Iris Image", "2.16.840.1.101.3.7.2.16.21", NULL, "1015", SC_PKCS15_CO_FLAG_PRIVATE}, {"15", "Retired X.509 Certificate for Key Management 1", "2.16.840.1.101.3.7.2.16.1", NULL, "1001", 0}, {"16", "Retired X.509 Certificate for Key Management 2", "2.16.840.1.101.3.7.2.16.2", NULL, "1002", 0}, {"17", "Retired X.509 Certificate for Key Management 3", "2.16.840.1.101.3.7.2.16.3", NULL, "1003", 0}, {"18", "Retired X.509 Certificate for Key Management 4", "2.16.840.1.101.3.7.2.16.4", NULL, "1004", 0}, {"19", "Retired X.509 Certificate for Key Management 5", "2.16.840.1.101.3.7.2.16.5", NULL, "1005", 0}, {"20", "Retired X.509 Certificate for Key Management 6", "2.16.840.1.101.3.7.2.16.6", NULL, "1006", 0}, {"21", "Retired X.509 Certificate for Key Management 7", "2.16.840.1.101.3.7.2.16.7", NULL, "1007", 0}, {"22", "Retired X.509 Certificate for Key Management 8", "2.16.840.1.101.3.7.2.16.8", NULL, "1008", 0}, {"23", "Retired X.509 Certificate for Key Management 9", "2.16.840.1.101.3.7.2.16.9", NULL, "1009", 0}, {"24", "Retired X.509 Certificate for Key Management 10", "2.16.840.1.101.3.7.2.16.10", NULL, "100A", 0}, {"25", "Retired X.509 Certificate for Key Management 11", "2.16.840.1.101.3.7.2.16.11", NULL, "100B", 0}, {"26", "Retired X.509 Certificate for Key Management 12", "2.16.840.1.101.3.7.2.16.12", NULL, "100C", 0}, {"27", "Retired X.509 Certificate for Key Management 13", "2.16.840.1.101.3.7.2.16.13", NULL, "100D", 0}, {"28", "Retired X.509 Certificate for Key Management 14", "2.16.840.1.101.3.7.2.16.14", NULL, "100E", 0}, {"29", "Retired X.509 Certificate for Key Management 15", "2.16.840.1.101.3.7.2.16.15", NULL, "100F", 0}, {"30", "Retired X.509 Certificate for Key Management 16", "2.16.840.1.101.3.7.2.16.16", NULL, "1010", 0}, {"31", "Retired X.509 Certificate for Key Management 17", "2.16.840.1.101.3.7.2.16.17", NULL, "1011", 0}, {"32", "Retired X.509 Certificate for Key Management 18", "2.16.840.1.101.3.7.2.16.18", NULL, "1012", 0}, {"33", "Retired X.509 Certificate for Key Management 19", "2.16.840.1.101.3.7.2.16.19", NULL, "1013", 0}, {"34", "Retired X.509 Certificate for Key Management 20", "2.16.840.1.101.3.7.2.16.20", NULL, "1014", 0}, {NULL, NULL, NULL, NULL, NULL, 0} }; /* * NIST 800-73-1 lifted the restriction on * requering pin protected certs. Thus the default is to * not require this. */ /* certs will be pulled out from the cert objects */ /* the number of cert, pubkey and prkey triplets */ #define PIV_NUM_CERTS_AND_KEYS 24 static const cdata certs[PIV_NUM_CERTS_AND_KEYS] = { {"1", "Certificate for PIV Authentication", 0, "0101cece", 0}, {"2", "Certificate for Digital Signature", 0, "0100cece", 0}, {"3", "Certificate for Key Management", 0, "0102cece", 0}, {"4", "Certificate for Card Authentication", 0, "0500cece", 0}, {"5", "Retired Certificate for Key Management 1", 0, "1001cece", 0}, {"6", "Retired Certificate for Key Management 2", 0, "1002cece", 0}, {"7", "Retired Certificate for Key Management 3", 0, "1003cece", 0}, {"8", "Retired Certificate for Key Management 4", 0, "1004cece", 0}, {"9", "Retired Certificate for Key Management 5", 0, "1005cece", 0}, {"10", "Retired Certificate for Key Management 6", 0, "1006cece", 0}, {"11", "Retired Certificate for Key Management 7", 0, "1007cece", 0}, {"12", "Retired Certificate for Key Management 8", 0, "1008cece", 0}, {"13", "Retired Certificate for Key Management 9", 0, "1009cece", 0}, {"14", "Retired Certificate for Key Management 10", 0, "100Acece", 0}, {"15", "Retired Certificate for Key Management 11", 0, "100Bcece", 0}, {"16", "Retired Certificate for Key Management 12", 0, "100Ccece", 0}, {"17", "Retired Certificate for Key Management 13", 0, "100Dcece", 0}, {"18", "Retired Certificate for Key Management 14", 0, "100Ecece", 0}, {"19", "Retired Certificate for Key Management 15", 0, "100Fcece", 0}, {"20", "Retired Certificate for Key Management 16", 0, "1010cece", 0}, {"21", "Retired Certificate for Key Management 17", 0, "1011cece", 0}, {"22", "Retired Certificate for Key Management 18", 0, "1012cece", 0}, {"23", "Retired Certificate for Key Management 19", 0, "1013cece", 0}, {"24", "Retired Certificate for Key Management 20", 0, "1014cece", 0} }; static const pindata pins[] = { { "1", "PIV Card Holder pin", "", 0x80, /* label and ref will change if using global pin */ SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 8, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL, -1, 0xFF, SC_PKCS15_CO_FLAG_PRIVATE }, { "2", "PIV PUK", "", 0x81, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 8, 4, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL | SC_PKCS15_PIN_FLAG_SO_PIN | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN, -1, 0xFF, SC_PKCS15_CO_FLAG_PRIVATE }, { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; /* * The size of the key or the algid is not really known * but can be derived from the certificates. * the cert, pubkey and privkey are a set. * Key usages bits taken from pkcs15v1_1 Table 2 * RSA and EC hav differents set of usage */ static const pubdata pubkeys[PIV_NUM_CERTS_AND_KEYS] = { { "1", "PIV AUTH pubkey", /*RSA*/SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP | SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER, /*EC*/SC_PKCS15_PRKEY_USAGE_VERIFY, "9A06", 0x9A, "1", 0, "PIV_9A_KEY"}, { "2", "SIGN pubkey", /*RSA*/SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, /*EC*/SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, "9C06", 0x9C, "1", 0, "PIV_9C_KEY"}, { "3", "KEY MAN pubkey", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "9D06", 0x9D, "1", 0, "PIV_9D_KEY"}, { "4", "CARD AUTH pubkey", /*RSA*/SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER, /*EC*/SC_PKCS15_PRKEY_USAGE_VERIFY, "9E06", 0x9E, "0", 0, "PIV_9E_KEY"}, /* no pin, and avail in contactless */ { "5", "Retired KEY MAN 1", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8206", 0x82, "1", 0, NULL}, { "6", "Retired KEY MAN 2", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8306", 0x83, "1", 0, NULL}, { "7", "Retired KEY MAN 3", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8406", 0x84, "1", 0, NULL}, { "8", "Retired KEY MAN 4", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8506", 0x85, "1", 0, NULL}, { "9", "Retired KEY MAN 5", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8606", 0x86, "1", 0, NULL}, { "10", "Retired KEY MAN 6", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8706", 0x87, "1", 0, NULL}, { "11", "Retired KEY MAN 7", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8806", 0x88, "1", 0, NULL}, { "12", "Retired KEY MAN 8", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8906", 0x89, "1", 0, NULL}, { "13", "Retired KEY MAN 9", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8A06", 0x8A, "1", 0, NULL}, { "14", "Retired KEY MAN 10", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8B06", 0x8B, "1", 0, NULL}, { "15", "Retired KEY MAN 11", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8C06", 0x8C, "1", 0, NULL}, { "16", "Retired KEY MAN 12", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8D06", 0x8D, "1", 0, NULL}, { "17", "Retired KEY MAN 13", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8E06", 0x8E, "1", 0, NULL}, { "18", "Retired KEY MAN 14", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "8F06", 0x8F, "1", 0, NULL}, { "19", "Retired KEY MAN 15", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "9006", 0x90, "1", 0, NULL}, { "20", "Retired KEY MAN 16", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "9106", 0x91, "1", 0, NULL}, { "21", "Retired KEY MAN 17", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "9206", 0x92, "1", 0, NULL}, { "22", "Retired KEY MAN 18", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "9306", 0x93, "1", 0, NULL}, { "23", "Retired KEY MAN 19", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "9406", 0x94, "1", 0, NULL}, { "24", "Retired KEY MAN 20", /*RSA*/SC_PKCS15_PRKEY_USAGE_WRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "9506", 0x95, "1", 0, NULL} }; /* * note some of the SC_PKCS15_PRKEY values are dependent * on the key algorithm, and will be reset. */ static const prdata prkeys[PIV_NUM_CERTS_AND_KEYS] = { { "1", "PIV AUTH key", /*RSA*/SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP | SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER, /*EC*/SC_PKCS15_PRKEY_USAGE_SIGN, "", 0x9A, "1", SC_PKCS15_CO_FLAG_PRIVATE, 0}, { "2", "SIGN key", /*RSA*/SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, /*EC*/SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, "", 0x9C, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "3", "KEY MAN key", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x9D, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "4", "CARD AUTH key", /*RSA*/SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER, /*EC*/SC_PKCS15_PRKEY_USAGE_SIGN, "", 0x9E, NULL, 0, 0}, /* no PIN needed, works with wireless */ { "5", "Retired KEY MAN 1", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x82, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "6", "Retired KEY MAN 2", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x83, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "7", "Retired KEY MAN 3", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x84, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "8", "Retired KEY MAN 4", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x85, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "9", "Retired KEY MAN 5", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x86, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "10", "Retired KEY MAN 6", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x87, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "11", "Retired KEY MAN 7", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x88, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "12", "Retired KEY MAN 8", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x89, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "13", "Retired KEY MAN 9", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x8A, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "14", "Retired KEY MAN 10", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x8B, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "15", "Retired KEY MAN 11", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x8C, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "16", "Retired KEY MAN 12", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x8D, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "17", "Retired KEY MAN 13", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x8E, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "18", "Retired KEY MAN 14", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x8F, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "19", "Retired KEY MAN 15", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x90, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "20", "Retired KEY MAN 16", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x91, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "21", "Retired KEY MAN 17", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x92, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "22", "Retired KEY MAN 18", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x93, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "23", "Retired KEY MAN 19", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x94, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1}, { "24", "Retired KEY MAN 20", /*RSA*/SC_PKCS15_PRKEY_USAGE_UNWRAP, /*EC*/SC_PKCS15_PRKEY_USAGE_DERIVE, "", 0x95, "1", SC_PKCS15_CO_FLAG_PRIVATE, 1} }; int r, i; sc_card_t *card = p15card->card; sc_file_t *file_out = NULL; int exposed_cert[PIV_NUM_CERTS_AND_KEYS] = {1, 0, 0, 0}; sc_serial_number_t serial; char buf[SC_MAX_SERIALNR * 2 + 1]; common_key_info ckis[PIV_NUM_CERTS_AND_KEYS]; SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE); /* could read this off card if needed */ /* CSP does not like a - in the name */ p15card->tokeninfo->label = strdup("PIV_II"); p15card->tokeninfo->manufacturer_id = strdup(MANU_ID); /* * get serial number * We will use the FASC-N from the CHUID * Note we are not verifying CHUID, belongs to this card * but need serial number for Mac tokend */ r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"sc_card_ctl rc=%d",r); p15card->tokeninfo->serial_number = strdup("00000000"); } else { sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0); p15card->tokeninfo->serial_number = strdup(buf); } sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "PIV-II adding objects..."); /* set other objects */ for (i = 0; objects[i].label; i++) { 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(objects[i].id, &obj_info.id); sc_format_path(objects[i].path, &obj_info.path); /* See if the object can not be present on the card */ r = (card->ops->card_ctl)(card, SC_CARDCTL_PIV_OBJECT_PRESENT, &obj_info.path); if (r == 1) continue; /* Not on card, do not define the object */ strncpy(obj_info.app_label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); r = sc_format_oid(&obj_info.app_oid, objects[i].aoid); if (r != SC_SUCCESS) return r; if (objects[i].auth_id) sc_pkcs15_format_id(objects[i].auth_id, &obj_obj.auth_id); strncpy(obj_obj.label, objects[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); obj_obj.flags = objects[i].obj_flags; r = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info); if (r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); /* TODO * PIV keys 9C and 9D require the pin verify be done just befor any * crypto operation using these keys. * * Nss 3.12.7 does not check the CKA_ALWAYS_AUTHENTICATE attribute of a key * and will do a C_FindObjects with only CKA_VALUE looking for a certificate * it had found earlier after c_Login. The template does not add CKA_TYPE=cert. * This will cause the card-piv to read all the objects and will reset * the security status for the 9C and 9D keys. * Mozilla Bug 457025 * * We can not read all the objects, as some need the PIN! */ } /* * certs, pubkeys and priv keys are related and we assume * they are in order * We need to read the cert, get modulus and keylen * We use those for the pubkey, and priv key objects. * If no cert, then see if pubkey (i.e. we are initilizing, * and the pubkey is in a file,) then add pubkey and privkey * If no cert and no pubkey, skip adding them. */ /* set certs */ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "PIV-II adding certs..."); for (i = 0; i < PIV_NUM_CERTS_AND_KEYS; i++) { struct sc_pkcs15_cert_info cert_info; struct sc_pkcs15_object cert_obj; sc_pkcs15_der_t cert_der; sc_pkcs15_cert_t *cert_out; ckis[i].cert_found = 0; ckis[i].key_alg = -1; ckis[i].pubkey_found = 0; ckis[i].pubkey_len = 0; if ((card->flags & 0x20) && (exposed_cert[i] == 0)) continue; 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); strncpy(cert_obj.label, certs[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); cert_obj.flags = certs[i].obj_flags; /* See if the cert might be present or not. */ r = (card->ops->card_ctl)(card, SC_CARDCTL_PIV_OBJECT_PRESENT, &cert_info.path); if (r == 1) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Cert can not be present,i=%d", i); continue; } /* use a &file_out so card-piv.c will read cert if present */ r = sc_pkcs15_read_file(p15card, &cert_info.path, &cert_der.value, &cert_der.len, &file_out); if (file_out) { sc_file_free(file_out); file_out = NULL; } if (r) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "No cert found,i=%d", i); continue; } ckis[i].cert_found = 1; /* cache it using the PKCS15 emulation objects */ /* as it does not change */ if (cert_der.value) { cert_info.value.value = cert_der.value; cert_info.value.len = cert_der.len; cert_info.path.len = 0; /* use in mem cert from now on */ } /* following will find the cached cert in cert_info */ r = sc_pkcs15_read_certificate(p15card, &cert_info, &cert_out); if (r < 0 || cert_out->key == NULL) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Failed to read/parse the certificate r=%d",r); continue; } ckis[i].key_alg = cert_out->key->algorithm; switch (cert_out->key->algorithm) { case SC_ALGORITHM_RSA: /* save pubkey_len for pub and priv */ ckis[i].pubkey_len = cert_out->key->u.rsa.modulus.len * 8; break; case SC_ALGORITHM_EC: ckis[i].pubkey_len = cert_out->key->u.ec.field_length; break; default: sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unsuported key.algorithm %d", cert_out->key->algorithm); ckis[i].pubkey_len = 0; /* set some value for now */ } sc_pkcs15_free_certificate(cert_out); r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, " Failed to add cert obj r=%d",r); continue; } } /* set pins */ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "PIV-II adding pins..."); for (i = 0; pins[i].label; i++) { struct sc_pkcs15_pin_info pin_info; struct sc_pkcs15_object pin_obj; const char * label; int pin_ref; 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.reference = pins[i].ref; pin_info.flags = pins[i].flags; pin_info.type = pins[i].type; pin_info.min_length = pins[i].minlen; pin_info.stored_length = pins[i].storedlen; pin_info.max_length = pins[i].maxlen; pin_info.pad_char = pins[i].pad_char; sc_format_path(pins[i].path, &pin_info.path); pin_info.tries_left = -1; label = pins[i].label; if (i == 0 && (card->ops->card_ctl)(card, SC_CARDCTL_PIV_PIN_PREFERENCE, &pin_ref) == 0 && pin_ref == 0x00) { /* must be 80 for PIV pin, or 00 for Global PIN */ pin_info.reference = pin_ref; label = "Global PIN"; } sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "DEE Adding pin %d label=%s",i, label); strncpy(pin_obj.label, label, SC_PKCS15_MAX_LABEL_SIZE - 1); pin_obj.flags = pins[i].obj_flags; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); } /* set public keys */ /* We may only need this during initialzation when genkey * gets the pubkey, but it can not be read from the card * at a later time. The piv-tool can stach pubkey in file */ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "PIV-II adding pub keys..."); for (i = 0; i < PIV_NUM_CERTS_AND_KEYS; i++) { struct sc_pkcs15_pubkey_info pubkey_info; struct sc_pkcs15_object pubkey_obj; struct sc_pkcs15_pubkey *p15_key; if ((card->flags & 0x20) && (exposed_cert[i] == 0)) continue; memset(&pubkey_info, 0, sizeof(pubkey_info)); memset(&pubkey_obj, 0, sizeof(pubkey_obj)); sc_pkcs15_format_id(pubkeys[i].id, &pubkey_info.id); pubkey_info.native = 1; pubkey_info.key_reference = pubkeys[i].ref; // sc_format_path(pubkeys[i].path, &pubkey_info.path); strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); pubkey_obj.flags = pubkeys[i].obj_flags; if (pubkeys[i].auth_id) sc_pkcs15_format_id(pubkeys[i].auth_id, &pubkey_obj.auth_id); /* If no cert found, piv-tool may have stached the pubkey * so we can use it when generating a certificate request * The file is a OpenSSL DER EVP_KEY, which looks like * a certificate subjectPublicKeyInfo. * */ if (ckis[i].cert_found == 0 ) { /* no cert found */ char * filename = NULL; sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"No cert for this pub key i=%d",i); /* * If we used the piv-tool to generate a key, * we would have saved the public key as a file. * This code is only used while signing a request * After the certificate is loaded on the card, * the public key is extracted from the certificate. */ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"DEE look for env %s", pubkeys[i].getenvname?pubkeys[i].getenvname:"NULL"); if (pubkeys[i].getenvname == NULL) continue; filename = getenv(pubkeys[i].getenvname); sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"DEE look for file %s", filename?filename:"NULL"); if (filename == NULL) continue; sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"Adding pubkey from file %s",filename); r = sc_pkcs15_pubkey_from_spki_filename(card->ctx, filename, &p15_key); if (r < 0) continue; /* Only get here if no cert, and the the above found the * pub key file (actually the SPKI version). This only * happens when trying initializing a card and have set * env PIV_9A_KEY or 9C, 9D, 9E to point at the file. * * We will cache it using the PKCS15 emulation objects */ pubkey_info.path.len = 0; ckis[i].key_alg = p15_key->algorithm; switch (p15_key->algorithm) { case SC_ALGORITHM_RSA: /* save pubkey_len in pub and priv */ ckis[i].pubkey_len = p15_key->u.rsa.modulus.len * 8; ckis[i].pubkey_found = 1; break; case SC_ALGORITHM_EC: ckis[i].key_alg = SC_ALGORITHM_EC; ckis[i].pubkey_len = p15_key->u.ec.field_length; ckis[i].pubkey_found = 1; break; default: sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"Unsupported key_alg %d",p15_key->algorithm); continue; } pubkey_obj.emulated = p15_key; p15_key = NULL; } sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"adding pubkey for %d keyalg=%d",i, ckis[i].key_alg); switch (ckis[i].key_alg) { case SC_ALGORITHM_RSA: pubkey_info.usage = pubkeys[i].usage_rsa; pubkey_info.modulus_length = ckis[i].pubkey_len; strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); if (r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); /* should not fail */ ckis[i].pubkey_found = 1; break; case SC_ALGORITHM_EC: pubkey_info.usage = pubkeys[i].usage_ec; pubkey_info.field_length = ckis[i].pubkey_len; strncpy(pubkey_obj.label, pubkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); r = sc_pkcs15emu_add_ec_pubkey(p15card, &pubkey_obj, &pubkey_info); if (r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); /* should not fail */ ckis[i].pubkey_found = 1; break; default: sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"key_alg %d not supported", ckis[i].key_alg); continue; } } /* set private keys */ sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "PIV-II adding private keys..."); for (i = 0; i < PIV_NUM_CERTS_AND_KEYS; i++) { struct sc_pkcs15_prkey_info prkey_info; struct sc_pkcs15_object prkey_obj; if ((card->flags & 0x20) && (exposed_cert[i] == 0)) continue; memset(&prkey_info, 0, sizeof(prkey_info)); memset(&prkey_obj, 0, sizeof(prkey_obj)); if (ckis[i].cert_found == 0 && ckis[i].pubkey_found == 0) continue; /* i.e. no cert or pubkey */ sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id); prkey_info.native = 1; prkey_info.key_reference = prkeys[i].ref; sc_format_path(prkeys[i].path, &prkey_info.path); strncpy(prkey_obj.label, prkeys[i].label, SC_PKCS15_MAX_LABEL_SIZE - 1); prkey_obj.flags = prkeys[i].obj_flags; prkey_obj.user_consent = prkeys[i].user_consent; if (prkeys[i].auth_id) sc_pkcs15_format_id(prkeys[i].auth_id, &prkey_obj.auth_id); switch (ckis[i].key_alg) { case SC_ALGORITHM_RSA: prkey_info.usage = prkeys[i].usage_rsa; prkey_info.modulus_length= ckis[i].pubkey_len; r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); break; case SC_ALGORITHM_EC: prkey_info.usage = prkeys[i].usage_ec; prkey_info.field_length = ckis[i].pubkey_len; sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "DEE added key_alg %2.2x prkey_obj.flags %8.8x", ckis[i].key_alg, prkey_obj.flags); r = sc_pkcs15emu_add_ec_prkey(p15card, &prkey_obj, &prkey_info); break; default: sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unsupported key_alg %d", ckis[i].key_alg); r = 0; /* we just skip this one */ } if (r < 0) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r); } SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_SUCCESS); }
static int sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *p15card) { sc_card_t *card = p15card->card; sc_context_t *ctx = card->ctx; char string[256]; u8 buffer[256]; size_t length; int r, i; set_string(&p15card->label, "OpenPGP Card"); set_string(&p15card->manufacturer_id, "OpenPGP project"); if ((r = read_file(card, "004f", buffer, sizeof(buffer))) < 0) goto failed; sc_bin_to_hex(buffer, (size_t)r, string, sizeof(string), 0); set_string(&p15card->serial_number, string); p15card->version = (buffer[6] << 8) | buffer[7]; p15card->flags = SC_PKCS15_CARD_FLAG_LOGIN_REQUIRED | SC_PKCS15_CARD_FLAG_PRN_GENERATION | SC_PKCS15_CARD_FLAG_EID_COMPLIANT; /* Extract preferred language */ r = read_file(card, "00655f2d", string, sizeof(string)-1); if (r < 0) goto failed; string[r] = '\0'; set_string(&p15card->preferred_language, string); /* Get Application Related Data (006E) */ if ((r = sc_get_data(card, 0x006E, buffer, sizeof(buffer))) < 0) goto failed; length = r; /* TBD: extract algorithm info */ /* Get CHV status bytes: * 00: ?? * 01-03: max length of pins 1-3 * 04-07: tries left for pins 1-3 */ if ((r = read_file(card, "006E007300C4", buffer, sizeof(buffer))) < 0) goto failed; if (r != 7) { sc_error(ctx, "CHV status bytes have unexpected length " "(expected 7, got %d)\n", r); return SC_ERROR_OBJECT_NOT_VALID; } for (i = 0; i < 3; i++) { unsigned int flags; struct sc_pkcs15_pin_info pin_info; struct sc_pkcs15_object pin_obj; memset(&pin_info, 0, sizeof(pin_info)); memset(&pin_obj, 0, sizeof(pin_obj)); flags = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE | SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_LOCAL; if (i == 2) { flags |= SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED | SC_PKCS15_PIN_FLAG_SO_PIN; } pin_info.auth_id.len = 1; pin_info.auth_id.value[0] = i + 1; pin_info.reference = i + 1; pin_info.flags = flags; pin_info.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; pin_info.min_length = 0; pin_info.stored_length = buffer[1+i]; pin_info.max_length = buffer[1+i]; pin_info.pad_char = '\0'; sc_format_path("3F00", &pin_info.path); pin_info.tries_left = buffer[4+i]; strlcpy(pin_obj.label, pgp_pin_name[i], sizeof(pin_obj.label)); pin_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE; r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); if (r < 0) return SC_ERROR_INTERNAL; } for (i = 0; i < 3; i++) { static int prkey_pin[3] = { 1, 2, 2 }; static int prkey_usage[3] = { SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP, SC_PKCS15_PRKEY_USAGE_NONREPUDIATION }; 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] = i + 1; prkey_info.usage = prkey_usage[i]; prkey_info.native = 1; prkey_info.key_reference = i; prkey_info.modulus_length= 1024; strlcpy(prkey_obj.label, pgp_key_name[i], sizeof(prkey_obj.label)); prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE | SC_PKCS15_CO_FLAG_MODIFIABLE; prkey_obj.auth_id.len = 1; prkey_obj.auth_id.value[0] = prkey_pin[i]; r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info); if (r < 0) return SC_ERROR_INTERNAL; } for (i = 0; i < 3; i++) { static int pubkey_usage[3] = { SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER, SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP, SC_PKCS15_PRKEY_USAGE_VERIFY }; struct sc_pkcs15_pubkey_info pubkey_info; struct sc_pkcs15_object pubkey_obj; memset(&pubkey_info, 0, sizeof(pubkey_info)); memset(&pubkey_obj, 0, sizeof(pubkey_obj)); pubkey_info.id.len = 1; pubkey_info.id.value[0] = i +1; pubkey_info.modulus_length = 1024; pubkey_info.usage = pubkey_usage[i]; sc_format_path(pgp_pubkey_path[i], &pubkey_info.path); strlcpy(pubkey_obj.label, pgp_key_name[i], sizeof(pubkey_obj.label)); pubkey_obj.auth_id.len = 1; pubkey_obj.auth_id.value[0] = 3; pubkey_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE; r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); if (r < 0) return SC_ERROR_INTERNAL; } return 0; failed: sc_error(card->ctx, "Failed to initialize OpenPGP emulation: %s\n", sc_strerror(r)); return r; }
int main(int argc, char * const argv[]) { int err = 0, r, c, long_optind = 0; int do_list_readers = 0; int do_list_drivers = 0; int do_list_rdrivers = 0; int do_list_files = 0; int do_send_apdu = 0; int do_print_atr = 0; int do_print_serial = 0; int do_print_name = 0; int action_count = 0; const char *opt_driver = NULL; sc_context_param_t ctx_param; setbuf(stderr, NULL); setbuf(stdout, NULL); while (1) { c = getopt_long(argc, argv, "nlfr:vs:DRc:aw", options, &long_optind); if (c == -1) break; if (c == '?') print_usage_and_die(app_name, options, option_help); switch (c) { case 'l': do_list_readers = 1; action_count++; break; case 'D': do_list_drivers = 1; action_count++; break; case 'R': do_list_rdrivers = 1; action_count++; break; case 'f': do_list_files = 1; action_count++; break; case 's': opt_apdus = (char **) realloc(opt_apdus, (opt_apdu_count + 1) * sizeof(char *)); opt_apdus[opt_apdu_count] = optarg; do_send_apdu++; if (opt_apdu_count == 0) action_count++; opt_apdu_count++; break; case 'a': do_print_atr = 1; action_count++; break; case 'n': do_print_name = 1; action_count++; break; case 'r': opt_reader = atoi(optarg); break; case 'v': verbose++; break; case 'c': opt_driver = optarg; break; case 'w': opt_wait = 1; break; case OPT_SERIAL: do_print_serial = 1; action_count++; break; } } if (action_count == 0) print_usage_and_die(app_name, options, option_help); memset(&ctx_param, 0, sizeof(ctx_param)); ctx_param.ver = 0; ctx_param.app_name = app_name; r = sc_context_create(&ctx, &ctx_param); if (r) { fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r)); return 1; } if (verbose > 1) ctx->debug = verbose-1; if (do_list_rdrivers) { if ((err = list_reader_drivers())) goto end; action_count--; } if (do_list_readers) { if ((err = list_readers())) goto end; action_count--; } if (do_list_drivers) { if ((err = list_drivers())) goto end; action_count--; } if (action_count <= 0) goto end; if (opt_driver != NULL) { err = sc_set_card_driver(ctx, opt_driver); if (err) { fprintf(stderr, "Driver '%s' not found!\n", opt_driver); err = 1; goto end; } } err = connect_card(ctx, &card, opt_reader, 0, opt_wait, verbose); if (err) goto end; if (do_print_atr) { if (verbose) { printf("Card ATR:\n"); hex_dump_asc(stdout, card->atr, card->atr_len, -1); } else { char tmp[SC_MAX_ATR_SIZE*3]; sc_bin_to_hex(card->atr, card->atr_len, tmp, sizeof(tmp) - 1, ':'); fprintf(stdout,"%s\n",tmp); } action_count--; } if (do_print_serial) { if (verbose) printf("Card serial number:"); print_serial(card); action_count--; } if (do_print_name) { if (verbose) printf("Card name: "); printf("%s\n", card->name); action_count--; } if (do_send_apdu) { if ((err = send_apdu())) goto end; action_count--; } if (do_list_files) { if ((err = list_files())) goto end; action_count--; } end: if (card) { sc_unlock(card); sc_disconnect_card(card, 0); } if (ctx) sc_release_context(ctx); return err; }
static int parse_dir_record(sc_card_t *card, u8 ** buf, size_t *buflen, int rec_nr) { struct sc_context *ctx = card->ctx; struct sc_asn1_entry asn1_dirrecord[5], asn1_dir[2]; scconf_block *conf_block = NULL; sc_app_info_t *app = NULL; struct sc_aid aid; u8 label[128], path[128], ddo[128]; size_t label_len = sizeof(label) - 1, path_len = sizeof(path), ddo_len = sizeof(ddo); int r; LOG_FUNC_CALLED(ctx); aid.len = sizeof(aid.value); memset(label, 0, sizeof(label)); sc_copy_asn1_entry(c_asn1_dirrecord, asn1_dirrecord); sc_copy_asn1_entry(c_asn1_dir, asn1_dir); sc_format_asn1_entry(asn1_dir + 0, asn1_dirrecord, NULL, 0); sc_format_asn1_entry(asn1_dirrecord + 0, aid.value, &aid.len, 0); sc_format_asn1_entry(asn1_dirrecord + 1, label, &label_len, 0); sc_format_asn1_entry(asn1_dirrecord + 2, path, &path_len, 0); sc_format_asn1_entry(asn1_dirrecord + 3, ddo, &ddo_len, 0); r = sc_asn1_decode(ctx, asn1_dir, *buf, *buflen, (const u8 **) buf, buflen); if (r == SC_ERROR_ASN1_END_OF_CONTENTS) LOG_FUNC_RETURN(ctx, r); LOG_TEST_RET(ctx, r, "EF(DIR) parsing failed"); conf_block = sc_get_conf_block(ctx, "framework", "pkcs15", 1); if (conf_block) { scconf_block **blocks = NULL; char aid_str[SC_MAX_AID_STRING_SIZE]; int ignore_app = 0; sc_bin_to_hex(aid.value, aid.len, aid_str, sizeof(aid_str), 0); blocks = scconf_find_blocks(card->ctx->conf, conf_block, "application", aid_str); if (blocks) { ignore_app = (blocks[0] && scconf_get_str(blocks[0], "disable", 0)); free(blocks); } if (ignore_app) { sc_log(ctx, "Application '%s' ignored", aid_str); LOG_FUNC_RETURN(ctx, SC_SUCCESS); } } app = calloc(1, sizeof(struct sc_app_info)); if (app == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); memcpy(&app->aid, &aid, sizeof(struct sc_aid)); if (asn1_dirrecord[1].flags & SC_ASN1_PRESENT) app->label = strdup((char *) label); else app->label = NULL; if (asn1_dirrecord[2].flags & SC_ASN1_PRESENT && path_len > 0) { /* application path present: ignore AID */ if (path_len > SC_MAX_PATH_SIZE) { free(app); LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "Application path is too long."); } memcpy(app->path.value, path, path_len); app->path.len = path_len; app->path.type = SC_PATH_TYPE_PATH; } else { /* application path not present: use AID as application path */ memcpy(app->path.value, aid.value, aid.len); app->path.len = aid.len; app->path.type = SC_PATH_TYPE_DF_NAME; } if (asn1_dirrecord[3].flags & SC_ASN1_PRESENT) { app->ddo.value = malloc(ddo_len); if (app->ddo.value == NULL) { free(app); LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate DDO value"); } memcpy(app->ddo.value, ddo, ddo_len); app->ddo.len = ddo_len; } else { app->ddo.value = NULL; app->ddo.len = 0; } app->rec_nr = rec_nr; card->app[card->app_count] = app; card->app_count++; LOG_FUNC_RETURN(ctx, 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 generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int password_shares_threshold, int password_shares_total) { int r, i; BIGNUM *prime; BIGNUM *secret; unsigned char buf[64]; char hex[64]; int l; secret_share_t *shares = NULL; secret_share_t *sp; u8 rngseed[16]; if ((password_shares_threshold == -1) || (password_shares_total == -1)) { fprintf(stderr, "Must specify both, --pwd-shares-total and --pwd-shares-threshold\n"); return -1; } if (password_shares_total < 3) { fprintf(stderr, "--pwd-shares-total must be 3 or larger\n"); return -1; } if (password_shares_threshold < 2) { fprintf(stderr, "--pwd-shares-threshold must 2 or larger\n"); return -1; } if (password_shares_threshold > password_shares_total) { fprintf(stderr, "--pwd-shares-threshold must be smaller or equal to --pwd-shares-total\n"); return -1; } printf( "\nThe DKEK will be enciphered using a randomly generated 64 bit password.\n"); printf( "This password is split using a (%i-of-%i) threshold scheme.\n\n", password_shares_threshold, password_shares_total); printf( "Please keep the generated and encrypted DKEK file in a safe location. We also recommend \n"); printf( "to keep a paper printout, in case the electronic version becomes unavailable. A printable version\n"); printf( "of the file can be generated using \"openssl base64 -in <filename>\".\n"); printf("\n\nPress <enter> to continue"); waitForEnterKeyPressed(); *pwd = calloc(1, 8); *pwdlen = 8; r = sc_get_challenge(card, (unsigned char *)*pwd, 8); if (r < 0) { printf("Error generating random key failed with %s", sc_strerror(r)); OPENSSL_cleanse(*pwd, *pwdlen); free(*pwd); return r; } **pwd &= 0x7F; // Make sure the bit size of the secret is not bigger than 63 bits /* * Initialize prime and secret */ prime = BN_new(); secret = BN_new(); /* * Encode the secret value */ BN_bin2bn((unsigned char *)*pwd, *pwdlen, secret); /* * Generate seed and calculate a prime depending on the size of the secret */ r = sc_get_challenge(card, rngseed, SEED_LENGTH); if (r < 0) { printf("Error generating random seed failed with %s", sc_strerror(r)); OPENSSL_cleanse(*pwd, *pwdlen); free(*pwd); return r; } r = generatePrime(prime, secret, 64, rngseed, SEED_LENGTH); if (r < 0) { printf("Error generating valid prime number. Please try again."); OPENSSL_cleanse(*pwd, *pwdlen); free(*pwd); return r; } // Allocate data buffer for the generated shares shares = malloc(password_shares_total * sizeof(secret_share_t)); createShares(secret, password_shares_threshold, password_shares_total, prime, shares); sp = shares; for (i = 0; i < password_shares_total; i++) { clearScreen(); printf("Press <enter> to display key share %i of %i\n\n", i + 1, password_shares_total); waitForEnterKeyPressed(); clearScreen(); printf("Share %i of %i\n\n", i + 1, password_shares_total); l = BN_bn2bin(prime, buf); sc_bin_to_hex(buf, l, hex, 64, ':'); printf("\nPrime : %s\n", hex); printf("Share ID : %s\n", BN_bn2dec((sp->x))); l = BN_bn2bin((sp->y), buf); sc_bin_to_hex(buf, l, hex, 64, ':'); printf("Share value : %s\n", hex); printf("\n\nPlease note ALL values above and press <enter> when finished"); waitForEnterKeyPressed(); sp++; } clearScreen(); cleanUpShares(shares, password_shares_total); BN_clear_free(prime); BN_clear_free(secret); return 0; }
static int match_atr_table(sc_context_t *ctx, const struct sc_atr_table *table, struct sc_atr *atr) { u8 *card_atr_bin; size_t card_atr_bin_len; char card_atr_hex[3 * SC_MAX_ATR_SIZE]; size_t card_atr_hex_len; unsigned int i = 0; if (ctx == NULL || table == NULL || atr == NULL) return -1; card_atr_bin = atr->value; card_atr_bin_len = atr->len; sc_bin_to_hex(card_atr_bin, card_atr_bin_len, card_atr_hex, sizeof(card_atr_hex), ':'); card_atr_hex_len = strlen(card_atr_hex); sc_debug(ctx, SC_LOG_DEBUG_MATCH, "ATR : %s", card_atr_hex); for (i = 0; table[i].atr != NULL; i++) { const char *tatr = table[i].atr; const char *matr = table[i].atrmask; size_t tatr_len = strlen(tatr); u8 mbin[SC_MAX_ATR_SIZE], tbin[SC_MAX_ATR_SIZE]; size_t mbin_len, tbin_len, s, matr_len; size_t fix_hex_len = card_atr_hex_len; size_t fix_bin_len = card_atr_bin_len; sc_debug(ctx, SC_LOG_DEBUG_MATCH, "ATR try : %s", tatr); if (tatr_len != fix_hex_len) { sc_debug(ctx, SC_LOG_DEBUG_MATCH, "ignored - wrong length"); continue; } if (matr != NULL) { sc_debug(ctx, SC_LOG_DEBUG_MATCH, "ATR mask: %s", matr); matr_len = strlen(matr); if (tatr_len != matr_len) continue; tbin_len = sizeof(tbin); sc_hex_to_bin(tatr, tbin, &tbin_len); mbin_len = sizeof(mbin); sc_hex_to_bin(matr, mbin, &mbin_len); if (mbin_len != fix_bin_len) { sc_debug(ctx, SC_LOG_DEBUG_MATCH, "length of atr and atr mask do not match - ignored: %s - %s", tatr, matr); continue; } for (s = 0; s < tbin_len; s++) { /* reduce tatr with mask */ tbin[s] = (tbin[s] & mbin[s]); /* create copy of card_atr_bin masked) */ mbin[s] = (card_atr_bin[s] & mbin[s]); } if (memcmp(tbin, mbin, tbin_len) != 0) continue; } else { if (strncasecmp(tatr, card_atr_hex, tatr_len) != 0) continue; } return i; } return -1; }
static int sc_pkcs15emu_starcert_init(sc_pkcs15_card_t *p15card) { const cdata certs[] = { {"DS certificate", 0, "3F00DF01C000","1", SC_PKCS15_CO_FLAG_MODIFIABLE}, {"CA certificate", 1, "3F00DF01C008","2", SC_PKCS15_CO_FLAG_MODIFIABLE}, {"KE certificate", 0, "3F00DF01C200","3", SC_PKCS15_CO_FLAG_MODIFIABLE}, {"AUT certificate",0, "3F00DF01C500","4", SC_PKCS15_CO_FLAG_MODIFIABLE}, {NULL, 0, NULL, NULL, 0} }; const pindata pins[] = { { "99", "DS pin", "3F00DF01", 0x99, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC, 8, 8, 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[] = { { "1", "DS key", 1024, USAGE_NONREP, "3F00DF01", 0x84, "99", SC_PKCS15_CO_FLAG_PRIVATE}, { "3", "KE key", 1024, USAGE_KE, "3F00DF01", 0x85, NULL, SC_PKCS15_CO_FLAG_PRIVATE}, { "4", "AUT key", 1024, USAGE_AUT, "3F00DF01", 0x82, NULL, SC_PKCS15_CO_FLAG_PRIVATE}, { NULL, NULL, 0, 0, NULL, 0, NULL, 0} }; int r, i; char buf[256]; sc_path_t path; sc_file_t *file = NULL; sc_card_t *card = p15card->card; sc_serial_number_t serial; /* get serial number */ r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial); r = sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0); if (r != SC_SUCCESS) return SC_ERROR_INTERNAL; if (p15card->serial_number) free(p15card->serial_number); p15card->serial_number = (char *) malloc(strlen(buf) + 1); if (!p15card->serial_number) return SC_ERROR_INTERNAL; strcpy(p15card->serial_number, buf); /* the TokenInfo version number */ p15card->version = 0; /* the manufacturer ID, in this case Giesecke & Devrient GmbH */ if (p15card->manufacturer_id) free(p15card->manufacturer_id); p15card->manufacturer_id = (char *) malloc(strlen(MANU_ID) + 1); if (!p15card->manufacturer_id) return SC_ERROR_INTERNAL; strcpy(p15card->manufacturer_id, MANU_ID); /* 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_pin_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.reference = pins[i].ref; pin_info.flags = pins[i].flags; pin_info.type = pins[i].type; pin_info.min_length = pins[i].minlen; pin_info.stored_length = pins[i].storedlen; pin_info.max_length = pins[i].maxlen; pin_info.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("3F00DF01", &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 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; }
static int cardos_info(void) { sc_apdu_t apdu; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; int is_cardos5 = 0; int r; if (verbose) { printf("Card ATR:\n"); util_hex_dump_asc(stdout, card->atr.value, card->atr.len, -1); } else { char tmp[SC_MAX_ATR_SIZE*3]; sc_bin_to_hex(card->atr.value, card->atr.len, tmp, sizeof(tmp) - 1, ':'); fprintf(stdout,"%s\n",tmp); } memset(&apdu, 0, sizeof(apdu)); apdu.cla = 0x00; apdu.ins = 0xca; apdu.p1 = 0x01; apdu.p2 = 0x80; apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); apdu.lc = 0; apdu.le = 256; apdu.cse = SC_APDU_CASE_2_SHORT; r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (check_apdu(&apdu)) return 1; printf("Info : %s\n", apdu.resp); apdu.p2 = 0x82; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (check_apdu(&apdu)) return 1; if (apdu.resp[0] == 0xc9) is_cardos5 = 1; apdu.p2 = 0x81; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (check_apdu(&apdu)) return 1; if (is_cardos5) { printf("Serial number: %02x %02x %02x %02x %02x %02x %02x %02x\n", apdu.resp[0], apdu.resp[1], apdu.resp[2], apdu.resp[3], apdu.resp[4], apdu.resp[5], apdu.resp[6], apdu.resp[7]); } else { printf("Chip type: %d\n", apdu.resp[8]); printf("Serial number: %02x %02x %02x %02x %02x %02x\n", apdu.resp[10], apdu.resp[11], apdu.resp[12], apdu.resp[13], apdu.resp[14], apdu.resp[15]); printf("Full prom dump:\n"); if (apdu.resplen) util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); } apdu.p2 = 0x82; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (check_apdu(&apdu)) return 1; printf("OS Version: %d.%d", apdu.resp[0], apdu.resp[1]); if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x02) { printf(" (that's CardOS M4.0)\n"); } else if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x03) { printf(" (that's CardOS M4.01)\n"); } else if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x04) { printf(" (that's CardOS M4.01a)\n"); } else if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x06) { printf(" (that's CardOS M4.2)\n"); } else if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x07) { printf(" (that's CardOS M4.3)\n"); } else if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x08) { printf(" (that's CardOS M4.3B)\n"); } else if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x09) { printf(" (that's CardOS M4.2B)\n"); } else if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x0B) { printf(" (that's CardOS M4.2C)\n"); } else if (apdu.resp[0] == 0xc8 && apdu.resp[1] == 0x0D) { printf(" (that's CardOS M4.4)\n"); } else if (apdu.resp[0] == 0xc9 && apdu.resp[1] == 0x01) { printf(" (that's CardOS V5.0)\n"); } else { printf(" (unknown Version)\n"); } apdu.p2 = 0x83; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (check_apdu(&apdu)) return 1; printf("Current life cycle: "); if (rbuf[0] == 0x34) { printf("%d (manufacturing)\n", rbuf[0]); } else if (rbuf[0] == 0x26) { if (is_cardos5) printf("%d (physinit)\n", rbuf[0]); else printf("%d (initialization)\n", rbuf[0]); } else if (rbuf[0] == 0x23) { printf("%d (physpers)\n", rbuf[0]); } else if (rbuf[0] == 0x24) { printf("%d (personalization)\n", rbuf[0]); } else if (rbuf[0] == 0x20) { printf("%d (administration)\n", rbuf[0]); } else if (rbuf[0] == 0x10) { printf("%d (operational)\n", rbuf[0]); } else if (rbuf[0] == 0x29) { printf("%d (erase in progress)\n", rbuf[0]); } else if (rbuf[0] == 0x3F) { printf("%d (death)\n", rbuf[0]); } else { printf("%d (unknown)\n", rbuf[0]); } apdu.p2 = 0x84; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (check_apdu(&apdu)) return 1; printf("Security Status of current DF:\n"); util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); apdu.p2 = 0x85; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (check_apdu(&apdu)) return 1; printf("Free memory : %d\n", rbuf[0]<<8|rbuf[1]); apdu.p2 = 0x86; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (check_apdu(&apdu)) return 1; if (rbuf[0] == 0x00) { printf("ATR Status: 0x%d ROM-ATR\n",rbuf[0]); } else if (rbuf[0] == 0x80) { printf("ATR Status: 0x%d EEPROM-ATR\n",rbuf[0]); } else { printf("ATR Status: 0x%d unknown\n",rbuf[0]); } apdu.p2 = 0x88; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (check_apdu(&apdu)) return 1; printf("Packages installed:\n"); util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); apdu.p2 = 0x89; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (check_apdu(&apdu)) return 1; if (is_cardos5) printf("Ram size: %d, Eeprom size: %d, cpu type: %x, chip config: %d, chip manufacturer: %d\n", rbuf[0]<<8|rbuf[1], rbuf[2]<<8|rbuf[3], rbuf[4], rbuf[6], rbuf[7]); else printf("Ram size: %d, Eeprom size: %d, cpu type: %x, chip config: %d\n", rbuf[0]<<8|rbuf[1], rbuf[2]<<8|rbuf[3], rbuf[4], rbuf[5]); apdu.p2 = 0x8a; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (check_apdu(&apdu)) return 1; if (is_cardos5) printf("Free eeprom memory: %d\n", rbuf[0]<<24|rbuf[1]<<16|rbuf[2]<<8|rbuf[3]); else printf("Free eeprom memory: %d\n", rbuf[0]<<8|rbuf[1]); apdu.p2 = 0x8d; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (check_apdu(&apdu)) return 1; printf("Current Maximum Data Field Length: %d\n", rbuf[0]<<8|rbuf[1]); if (is_cardos5) { apdu.p2 = 0x8B; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (check_apdu(&apdu)) return 1; printf("Complete chip production data:\n"); util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); } apdu.p2 = 0x96; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (check_apdu(&apdu)) return 1; printf("System keys: PackageLoadKey (version 0x%02x, retries %d)\n", rbuf[0], rbuf[1]); printf("System keys: StartKey (version 0x%02x, retries %d)\n", rbuf[2], rbuf[3]); apdu.p2 = 0x87; apdu.resplen = sizeof(rbuf); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } if (check_apdu(&apdu)) return 1; printf("Path to current DF:\n"); util_hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); return 0; }