void sc_pkcs15_format_id(const char *str, struct sc_pkcs15_id *id) { size_t len = sizeof(id->value); if (sc_hex_to_bin(str, id->value, &len) >= 0) id->len = len; }
static int atrust_acos_match_card(struct sc_card *card) { int i, match = 0; for (i = 0; atrust_acos_atrs[i] != NULL; i++) { u8 defatr[SC_MAX_ATR_SIZE]; size_t len = sizeof(defatr); const char *atrp = atrust_acos_atrs[i]; if (sc_hex_to_bin(atrp, defatr, &len)) continue; /* we may only verify part of ATR since */ /* part of the hist chars is variable */ if (len > card->atr_len) continue; if (memcmp(card->atr, defatr, len) != 0) continue; match = 1; card->name = atrust_acos_names[i]; break; } return match; }
static int get_conf_aid(sc_card_t *card, u8 *aid, size_t *len) { sc_context_t *ctx = card->ctx; scconf_block *conf_block, **blocks; int i; const char *str_aid; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); conf_block = NULL; for (i = 0; ctx->conf_blocks[i] != NULL; i++) { blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i], "card", "gemsafeV1"); if (blocks[0] != NULL) conf_block = blocks[0]; free(blocks); } if (!conf_block) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "no card specific options configured, trying default AID\n"); return SC_ERROR_INTERNAL; } str_aid = scconf_get_str(conf_block, "aid", NULL); if (!str_aid) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "no aid configured, trying default AID\n"); return SC_ERROR_INTERNAL; } return sc_hex_to_bin(str_aid, aid, len); }
int sc_pkcs15_encode_tokeninfo(sc_context_t *ctx, sc_pkcs15_tokeninfo_t *ti, u8 **buf, size_t *buflen) { int r; int version = ti->version; size_t serial_len, mnfid_len, label_len, flags_len, last_upd_len; struct sc_asn1_entry asn1_toki[14], asn1_tokeninfo[2]; sc_copy_asn1_entry(c_asn1_toki, asn1_toki); sc_copy_asn1_entry(c_asn1_tokeninfo, asn1_tokeninfo); version--; sc_format_asn1_entry(asn1_toki + 0, &version, NULL, 1); if (ti->serial_number != NULL) { u8 serial[128]; serial_len = 0; if (strlen(ti->serial_number)/2 > sizeof(serial)) return SC_ERROR_BUFFER_TOO_SMALL; serial_len = sizeof(serial); if (sc_hex_to_bin(ti->serial_number, serial, &serial_len) < 0) return SC_ERROR_INVALID_ARGUMENTS; sc_format_asn1_entry(asn1_toki + 1, serial, &serial_len, 1); } else sc_format_asn1_entry(asn1_toki + 1, NULL, NULL, 0); if (ti->manufacturer_id != NULL) { mnfid_len = strlen(ti->manufacturer_id); sc_format_asn1_entry(asn1_toki + 2, ti->manufacturer_id, &mnfid_len, 1); } else sc_format_asn1_entry(asn1_toki + 2, NULL, NULL, 0); if (ti->label != NULL) { label_len = strlen(ti->label); sc_format_asn1_entry(asn1_toki + 3, ti->label, &label_len, 1); } else sc_format_asn1_entry(asn1_toki + 3, NULL, NULL, 0); if (ti->flags) { flags_len = sizeof(ti->flags); sc_format_asn1_entry(asn1_toki + 5, &ti->flags, &flags_len, 1); } else sc_format_asn1_entry(asn1_toki + 5, NULL, NULL, 0); sc_format_asn1_entry(asn1_toki + 6, NULL, NULL, 0); sc_format_asn1_entry(asn1_toki + 7, NULL, NULL, 0); sc_format_asn1_entry(asn1_toki + 8, NULL, NULL, 0); sc_format_asn1_entry(asn1_toki + 9, NULL, NULL, 0); sc_format_asn1_entry(asn1_toki + 10, NULL, NULL, 0); if (ti->last_update != NULL) { last_upd_len = strlen(ti->last_update); sc_format_asn1_entry(asn1_toki + 11, ti->last_update, &last_upd_len, 1); } else sc_format_asn1_entry(asn1_toki + 11, NULL, NULL, 0); sc_format_asn1_entry(asn1_toki + 12, NULL, NULL, 0); sc_format_asn1_entry(asn1_tokeninfo, asn1_toki, NULL, 1); r = sc_asn1_encode(ctx, asn1_tokeninfo, buf, buflen); if (r) { sc_error(ctx, "sc_asn1_encode() failed: %s\n", sc_strerror(r)); return r; } return 0; }
static int arg_to_path(const char *arg, sc_path_t *path, int is_id) { memset(path, 0, sizeof(sc_path_t)); if (strncasecmp(arg, "aid:", strlen("aid:")) == 0) { /* DF aid */ const char *p = arg + strlen("aid:"); int r; path->type = SC_PATH_TYPE_DF_NAME; path->len = sizeof(path->value); if ((r = sc_hex_to_bin(p, path->value, &path->len)) < 0) { printf("Error parsing AID: %s\n", p); return r; } } else { /* file id */ unsigned int buf[2]; u8 cbuf[2]; if (strlen(arg) != 4) { printf("Wrong ID length.\n"); return -1; } if (sscanf(arg, "%02X%02X", &buf[0], &buf[1]) != 2) { printf("Invalid ID.\n"); return -1; } cbuf[0] = buf[0]; cbuf[1] = buf[1]; if ((cbuf[0] == 0x3F && cbuf[1] == 0x00) || is_id) { path->len = 2; memcpy(path->value, cbuf, 2); path->type = (is_id) ? SC_PATH_TYPE_FILE_ID : SC_PATH_TYPE_PATH; } else { *path = current_path; if (path->type == SC_PATH_TYPE_DF_NAME) { if (path->len > sizeof(path->aid.value)) { printf("Invalid length of DF_NAME path\n"); return -1; } memcpy(path->aid.value, path->value, path->len); path->aid.len = path->len; path->type = SC_PATH_TYPE_FILE_ID; path->len = 0; } sc_append_path_id(path, cbuf, 2); } } return 0; }
/** * Delete key, for OpenPGP card. * This function is not complete and is reserved for future version (> 2) of OpenPGP card. **/ int delete_key_openpgp(sc_card_t *card, u8 in_key_id) { char *del_fingerprint = "00:DA:00:C6:14:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00"; char *del_creationtime = "00:DA:00:CD:04:00:00:00:00"; /* We need to replace the 4th byte later */ char *apdustring = NULL; u8 buf[SC_MAX_APDU_BUFFER_SIZE]; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; sc_apdu_t apdu; size_t len0; int i; int r = SC_SUCCESS; for (i = 0; i < 2; i++) { if (i == 0) /* Reset fingerprint */ apdustring = del_fingerprint; else /* Reset creation time */ apdustring = del_creationtime; /* Convert the string to binary array */ len0 = sizeof(buf); sc_hex_to_bin(apdustring, buf, &len0); /* Replace DO tag, subject to key ID */ buf[3] = buf[3] + in_key_id; /* Build APDU from binary array */ r = sc_bytes2apdu(card->ctx, buf, len0, &apdu); if (r) { util_error("failed to build APDU: %s", sc_strerror(r)); return r; } apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); /* Send APDU to card */ r = sc_transmit_apdu(card, &apdu); if (r) { util_error("transmitting APDU failed: %s", sc_strerror(r)); return r; } } /* TODO: Rewrite Extended Header List. * Not support by OpenGPG v2 yet */ return r; }
static int do_apdu(int argc, char **argv) { sc_apdu_t apdu; u8 buf[SC_MAX_APDU_BUFFER_SIZE]; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; size_t len, len0, r, ii; if (argc < 1) { puts("Usage: apdu [apdu:hex:codes:...]"); return -1; } for (ii = 0, len = 0; ii < (unsigned) argc; ii++) { len0 = strlen(argv[ii]); sc_hex_to_bin(argv[ii], buf + len, &len0); len += len0; } r = sc_bytes2apdu(card->ctx, buf, len, &apdu); if (r) { fprintf(stderr, "Invalid APDU: %s\n", sc_strerror(r)); return 2; } apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); printf("Sending: "); for (r = 0; r < len0; r++) printf("%02X ", buf[r]); printf("\n"); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } printf("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 0; }
static int sm_gp_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info) { scconf_block *sm_conf_block = NULL, **blocks; struct sm_gp_keyset *gp_keyset = &sm_info->session.gp.gp_keyset; const char *kmc = NULL; unsigned char hex[48]; size_t hex_len = sizeof(hex); int rv, ii; sc_log(ctx, "SM get KMC from config section '%s'", sm_info->config_section); for (ii = 0; ctx->conf_blocks[ii]; ii++) { blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[ii], "secure_messaging", sm_info->config_section); if (blocks) { sm_conf_block = blocks[0]; free(blocks); } if (sm_conf_block) break; } kmc = scconf_get_str(sm_conf_block, "kmc", NULL); if (!kmc) return SC_ERROR_SM_KEYSET_NOT_FOUND; rv = sc_hex_to_bin(kmc, hex, &hex_len); if (rv) { sc_log(ctx, "SM get KMC: hex to bin failed for '%s'; error %i", kmc, rv); return SC_ERROR_UNKNOWN_DATA_RECEIVED; } sc_log(ctx, "SM type:%X, KMC(%i) %s", sm_info->sm_type, hex_len, sc_dump_hex(hex, hex_len)); if (hex_len != 16 && hex_len != 48 ) return SC_ERROR_INVALID_DATA; memcpy(gp_keyset->kmc, hex, hex_len); gp_keyset->kmc_len = hex_len; return SC_SUCCESS; }
static void write_dg(sc_card_t *card, unsigned char sfid, const char *dg_str, const char *dg_hex) { unsigned char dg[0xff]; size_t dg_len = sizeof dg; int r; r = sc_hex_to_bin(dg_hex, dg, &dg_len); if (r < 0) { fprintf(stderr, "Could not parse DG %02u %s (%s)\n", sfid, dg_str, sc_strerror(r)); } else { r = write_binary_rec(card, sfid, dg, dg_len); if (r < 0) fprintf(stderr, "Could not write DG %02u %s (%s)\n", sfid, dg_str, sc_strerror(r)); else printf("Wrote DG %02u %s\n", sfid, dg_str); } }
static int do_aid(struct state *cur, int argc, char **argv) { struct sc_file *file = cur->file->file; const char *name = argv[0]; unsigned int len; int res = 0; if (*name == '=') { len = strlen(++name); if (len > sizeof(file->name)) { parse_error(cur, "AID \"%s\" too long\n", name); return 1; } memcpy(file->name, name, len); file->namelen = len; } else { file->namelen = sizeof(file->name); res = sc_hex_to_bin(name, file->name, &file->namelen); } return res; }
static int parse_string_or_hexdata(const char *in, u8 *out, size_t *outlen) { if (in == NULL) return SC_ERROR_INVALID_ARGUMENTS; if (*in == '"') { u8 quote = *in++; size_t count = 0; while (*in != quote && *in != '\0' && count < *outlen) out[count++] = *in++; if (*in == '\0') return SC_ERROR_INVALID_ARGUMENTS; if (count >= *outlen) return SC_ERROR_BUFFER_TOO_SMALL; *outlen = count; return 0; } else return sc_hex_to_bin(in, out, outlen); }
static int do_key_value(struct state *cur, int argc, char **argv) { struct auth_info *ai = cur->key; const char *key = argv[0]; size_t key_len; unsigned char keybuf[32]; if (key[0] == '=') { ++key; key_len = strlen(key); memcpy(keybuf, key, key_len); } else { key_len = sizeof(keybuf); if (sc_hex_to_bin(key, keybuf, &key_len)) { parse_error(cur, "Error parsing PIN/key \"%s\"\n", key); return 1; } } memcpy(ai->key, keybuf, key_len); ai->key_len = key_len; return 0; }
static void initialize(sc_card_t *card, const char *so_pin, const char *user_pin, int retry_counter, int dkek_shares) { sc_cardctl_sc_hsm_init_param_t param; size_t len; char *_so_pin = NULL, *_user_pin = NULL; int r; if (so_pin == NULL) { printf("Enter SO-PIN (16 hexadecimal characters) : "); util_getpass(&_so_pin, NULL, stdin); printf("\n"); } else { _so_pin = (char *)so_pin; } len = sizeof(param.init_code); r = sc_hex_to_bin(_so_pin, param.init_code, &len); if (r < 0) { fprintf(stderr, "Error decoding initialization code (%s)\n", sc_strerror(r)); return; } if (len != 8) { fprintf(stderr, "SO-PIN must be a hexadecimal string of 16 characters\n"); return; } if (user_pin == NULL) { printf("Enter initial User-PIN (6 - 16 characters) : "); util_getpass(&_user_pin, NULL, stdin); printf("\n"); } else { _user_pin = (char *)user_pin; } param.user_pin_len = strlen(_user_pin); if (param.user_pin_len < 6) { fprintf(stderr, "PIN must be at least 6 characters long\n"); return; } if (param.user_pin_len > 16) { fprintf(stderr, "PIN must not be longer than 16 characters\n"); return; } if ((param.user_pin_len == 6) && (retry_counter > 3)) { fprintf(stderr, "Retry counter must not exceed 3 for a 6 digit PIN. Use a longer PIN for a higher retry counter.\n"); return; } if ((param.user_pin_len == 7) && (retry_counter > 5)) { fprintf(stderr, "Retry counter must not exceed 5 for a 7 digit PIN. Use a longer PIN for a higher retry counter.\n"); return; } if (retry_counter > 10) { fprintf(stderr, "Retry counter must not exceed 10\n"); return; } param.user_pin = (u8 *)_user_pin; param.user_pin_retry_counter = (u8)retry_counter; param.options[0] = 0x00; param.options[1] = 0x01; param.dkek_shares = (char)dkek_shares; r = sc_card_ctl(card, SC_CARDCTL_SC_HSM_INITIALIZE, (void *)¶m); if (r < 0) { fprintf(stderr, "sc_card_ctl(*, SC_CARDCTL_SC_HSM_INITIALIZE, *) failed with %s\n", sc_strerror(r)); } }
static int send_apdu(void) { sc_apdu_t apdu; u8 buf[SC_MAX_APDU_BUFFER_SIZE], sbuf[SC_MAX_APDU_BUFFER_SIZE], rbuf[SC_MAX_APDU_BUFFER_SIZE], *p; size_t len, len0, r; int c; for (c = 0; c < opt_apdu_count; c++) { len0 = sizeof(buf); sc_hex_to_bin(opt_apdus[c], buf, &len0); if (len0 < 4) { fprintf(stderr, "APDU too short (must be at least 4 bytes).\n"); return 2; } len = len0; p = buf; memset(&apdu, 0, sizeof(apdu)); apdu.cla = *p++; apdu.ins = *p++; apdu.p1 = *p++; apdu.p2 = *p++; apdu.resp = rbuf; apdu.resplen = sizeof(rbuf); len -= 4; if (len > 1) { apdu.lc = *p++; len--; memcpy(sbuf, p, apdu.lc); apdu.data = sbuf; apdu.datalen = apdu.lc; if (len < apdu.lc) { fprintf(stderr, "APDU too short (need %lu bytes).\n", (unsigned long) apdu.lc-len); return 2; } len -= apdu.lc; p += apdu.lc; if (len) { apdu.le = *p++; if (apdu.le == 0) apdu.le = 256; len--; apdu.cse = SC_APDU_CASE_4_SHORT; } else apdu.cse = SC_APDU_CASE_3_SHORT; if (len) { fprintf(stderr, "APDU too long (%lu bytes extra).\n", (unsigned long) len); return 2; } } else if (len == 1) { apdu.le = *p++; if (apdu.le == 0) apdu.le = 256; len--; apdu.cse = SC_APDU_CASE_2_SHORT; } else apdu.cse = SC_APDU_CASE_1; printf("Sending: "); for (r = 0; r < len0; r++) printf("%02X ", buf[r]); printf("\n"); r = sc_transmit_apdu(card, &apdu); if (r) { fprintf(stderr, "APDU transmit failed: %s\n", sc_strerror(r)); return 1; } printf("Received (SW1=0x%02X, SW2=0x%02X)%s\n", apdu.sw1, apdu.sw2, apdu.resplen ? ":" : ""); if (apdu.resplen) hex_dump_asc(stdout, apdu.resp, apdu.resplen, -1); } return 0; }
static int cardos_change_startkey(const char *change_startkey_apdu) { #define MAX_APDU 60 unsigned char cardos_version[2]; unsigned char apdu_bin[MAX_APDU]; size_t apdu_len=MAX_APDU; unsigned char checksum[SHA_DIGEST_LENGTH]; static const unsigned char cardos_43b_checksum[SHA_DIGEST_LENGTH] = { 0x5C, 0xD6, 0x8C, 0x2C, 0x24, 0x77, 0x3C, 0xDC, 0x93, 0x73, 0xD8, 0x4B, 0x47, 0x29, 0x19, 0x70, 0x9F, 0xA2, 0x42, 0xB4 }; sc_apdu_t apdu; u8 rbuf[256]; int r; if (verbose) { printf ("Change StartKey APDU:\n"); util_hex_dump_asc(stdout, (unsigned char *)change_startkey_apdu, strlen(change_startkey_apdu), -1); } /* use GET DATA for version - 00 ca 01 82 * returns e.g. c8 09 for 4.2B */ memset(&apdu, 0, sizeof(apdu)); apdu.cla = 0x00; apdu.ins = 0xca; apdu.p1 = 0x01; apdu.p2 = 0x82; 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; } if (apdu.resplen != 0x02) { printf("did not receive version info, aborting\n"); return 1; } /* check all supported versions here. need a checksum check for each of them below */ if ( (rbuf[0] != 0xc8 || rbuf[1] != 0x08) ) { /* M4.3B */ printf("currently only CardOS M4.01, M4.2B, M4.2C and M4.3B are supported, aborting\n"); return 1; } cardos_version[0] = rbuf[0]; cardos_version[1] = rbuf[1]; /* GET DATA for startkey index - 00 ca 01 96 * returns 6 bytes PackageLoadKey.Version, PackageLoadKey.Retry * Startkey.Version, Startkey.Retry, 2 internal data byes */ memset(&apdu, 0, sizeof(apdu)); apdu.cla = 0x00; apdu.ins = 0xca; apdu.p1 = 0x01; apdu.p2 = 0x96; 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; } if (apdu.resplen < 0x04) { printf("expected 4-6 bytes form GET DATA for startkey data, but got only %ld\n", apdu.resplen); printf("aborting\n"); return 1; } if (apdu.resp[2] != 0x00) { printf("startkey version is 0x%02x, currently we support only 0x00\n", (int) apdu.resp[3]); printf("aborting\n"); return 1; } if (apdu.resp[3] < 5) { printf("startkey has only %d tries left. to be safe: aborting\n", apdu.resp[3]); return 1; } /* now check if the correct APDU was passed */ if (sc_hex_to_bin(change_startkey_apdu, apdu_bin, &apdu_len) != 0) { printf("can't convert startkey apdu to binary format: aborting\n"); return 1; } SHA1(apdu_bin, apdu_len, checksum); if (cardos_version[0] == 0xc8 && cardos_version[1] == 0x08) { if (memcmp(checksum, cardos_43b_checksum, SHA_DIGEST_LENGTH) != 0) { printf("change startkey apdu is wrong, checksum doesn't match\n"); util_hex_dump_asc(stdout, checksum, SHA_DIGEST_LENGTH, -1); util_hex_dump_asc(stdout, cardos_43b_checksum, SHA_DIGEST_LENGTH, -1); printf("aborting\n"); return 1; } goto change_startkey; } printf("checksum for your card not yet implemented, aborting\n"); return 1; change_startkey: /* run change startkey apdu */ memset(&apdu, 0, sizeof(apdu)); apdu.cla = apdu_bin[0]; apdu.ins = apdu_bin[1]; apdu.p1 = apdu_bin[2]; apdu.p2 = apdu_bin[3]; apdu.lc = apdu_bin[4]; apdu.data = &apdu_bin[5]; apdu.datalen = apdu.lc; apdu.resp = 00; apdu.le = 00; apdu.cse = SC_APDU_CASE_3_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("change startkey command issued with success\n"); /* GET DATA for startkey index - 00 ca 01 96 * returns 6 bytes PackageLoadKey.Version, PackageLoadKey.Retry * Startkey.Version, Startkey.Retry, 2 internal data byes */ memset(&apdu, 0, sizeof(apdu)); apdu.cla = 0x00; apdu.ins = 0xca; apdu.p1 = 0x01; apdu.p2 = 0x96; 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; } if (apdu.resplen < 0x04) { printf("expected 4-6 bytes form GET DATA for startkey data, but got only %ld\n", apdu.resplen); printf("aborting\n"); return 1; } if (apdu.resp[2] != 0xff) { printf("startkey version is 0x%02x, should have been changed to 0xff.\n", apdu.resp[2]); printf("aborting\n"); return 1; } printf("startkey is now 0xff, success!\n"); return 0; }
int npa_translate_apdus(sc_card_t *card, FILE *input) { u8 buf[4 + 3 + 0xffff + 3]; char *read = NULL; size_t readlen = 0, apdulen; sc_apdu_t apdu; ssize_t linelen; int r; memset(&apdu, 0, sizeof apdu); while (1) { if (input == stdin) printf("Enter unencrypted C-APDU (empty line to exit)\n"); linelen = getline(&read, &readlen, input); if (linelen <= 1) { if (linelen < 0) { r = SC_ERROR_INTERNAL; sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE_TOOL, "Could not read line"); } else { r = SC_SUCCESS; printf("Thanks for flying with ccid\n"); } break; } read[linelen - 1] = 0; apdulen = sizeof buf; if (sc_hex_to_bin(read, buf, &apdulen) < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE_TOOL, "Could not format binary string"); continue; } if (input != stdin) bin_print(stdout, "Unencrypted C-APDU", buf, apdulen); r = sc_bytes2apdu(card->ctx, buf, apdulen, &apdu); if (r < 0) { bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Invalid C-APDU", buf, apdulen); continue; } apdu.resp = buf; apdu.resplen = sizeof buf; r = sc_transmit_apdu(card, &apdu); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE_TOOL, "Could not send C-APDU: %s", sc_strerror(r)); continue; } printf("Decrypted R-APDU sw1=%02x sw2=%02x\n", apdu.sw1, apdu.sw2); bin_print(stdout, "Decrypted R-APDU response data", apdu.resp, apdu.resplen); printf("======================================================================\n"); } if (read) free(read); return r; }
int main(int argc, char * const argv[]) { int err = 0, r, c, long_optind = 0; int do_decipher = 0; int do_sign = 0; int action_count = 0; struct sc_pkcs15_object *key; sc_context_param_t ctx_param; while (1) { c = getopt_long(argc, argv, "sck:r:i:o:f:Rp:vw", options, &long_optind); if (c == -1) break; if (c == '?') util_print_usage_and_die(app_name, options, option_help, NULL); switch (c) { case 's': do_sign++; action_count++; break; case 'c': do_decipher++; action_count++; break; case 'k': opt_key_id = optarg; action_count++; break; case 'r': opt_reader = optarg; break; case 'i': opt_input = optarg; break; case 'o': opt_output = optarg; break; case 'f': opt_sig_format = optarg; break; case 'R': opt_raw = 1; break; case OPT_SHA1: opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA1; break; case OPT_SHA256: opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA256; break; case OPT_SHA384: opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA384; break; case OPT_SHA512: opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA512; break; case OPT_SHA224: opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_SHA224; break; case OPT_MD5: opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_MD5; break; case OPT_PKCS1: opt_crypt_flags |= SC_ALGORITHM_RSA_PAD_PKCS1; break; case 'v': verbose++; break; case 'p': opt_pincode = optarg; break; case OPT_BIND_TO_AID: opt_bind_to_aid = optarg; break; case 'w': opt_wait = 1; break; } } if (action_count == 0) util_print_usage_and_die(app_name, options, option_help, NULL); if (!(opt_crypt_flags & SC_ALGORITHM_RSA_HASHES)) opt_crypt_flags |= SC_ALGORITHM_RSA_HASH_NONE; 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; sc_ctx_log_to_file(ctx, "stderr"); } err = util_connect_card(ctx, &card, opt_reader, opt_wait, verbose); if (err) goto end; if (verbose) fprintf(stderr, "Trying to find a PKCS #15 compatible card...\n"); if (opt_bind_to_aid) { struct sc_aid aid; aid.len = sizeof(aid.value); if (sc_hex_to_bin(opt_bind_to_aid, aid.value, &aid.len)) { fprintf(stderr, "Invalid AID value: '%s'\n", opt_bind_to_aid); return 1; } r = sc_pkcs15_bind(card, &aid, &p15card); } else { r = sc_pkcs15_bind(card, NULL, &p15card); } if (r) { fprintf(stderr, "PKCS #15 binding failed: %s\n", sc_strerror(r)); err = 1; goto end; } if (verbose) fprintf(stderr, "Found %s!\n", p15card->tokeninfo->label); if (do_decipher) { if ((err = get_key(SC_PKCS15_PRKEY_USAGE_DECRYPT, &key)) || (err = decipher(key))) goto end; action_count--; } if (do_sign) { if ((err = get_key(SC_PKCS15_PRKEY_USAGE_SIGN| SC_PKCS15_PRKEY_USAGE_SIGNRECOVER| SC_PKCS15_PRKEY_USAGE_NONREPUDIATION, &key)) || (err = sign(key))) goto end; action_count--; } end: if (p15card) sc_pkcs15_unbind(p15card); if (card) { sc_unlock(card); sc_disconnect_card(card); } if (ctx) sc_release_context(ctx); return err; }
int main(int argc, char * const argv[]) { int err = 0, r, c, long_optind = 0; int do_list_sdos = 0; int do_list_apps = 0; int action_count = 0; sc_context_param_t ctx_param; setbuf(stderr, NULL); setbuf(stdout, NULL); while (1) { c = getopt_long(argc, argv, "v", options, &long_optind); if (c == -1) break; if (c == '?') util_print_usage_and_die(app_name, options, option_help, NULL); switch (c) { case OPT_LIST_SDOS: do_list_sdos = 1; opt_sdo_tag = optarg; action_count++; break; case OPT_LIST_APPLICATIONS: do_list_apps = 1; action_count++; break; case OPT_BIND_TO_AID: opt_bind_to_aid = optarg; break; case OPT_READER: opt_reader = optarg; break; case 'v': verbose++; break; } } if (action_count == 0) util_print_usage_and_die(app_name, options, option_help, NULL); memset(&ctx_param, 0, sizeof(sc_context_param_t)); ctx_param.app_name = app_name; r = sc_context_create(&ctx, &ctx_param); if (r != SC_SUCCESS) { fprintf(stderr, "Failed to establish context: %s\n", sc_strerror(r)); return 1; } /* Only change if not in opensc.conf */ if (verbose > 1 && ctx->debug == 0) { ctx->debug = verbose; sc_ctx_log_to_file(ctx, "stderr"); } if (action_count <= 0) goto end; err = util_connect_card(ctx, &card, opt_reader, opt_wait, verbose); if (err) goto end; if (opt_bind_to_aid) { struct sc_aid aid; aid.len = sizeof(aid.value); if (sc_hex_to_bin(opt_bind_to_aid, aid.value, &aid.len)) { fprintf(stderr, "Invalid AID value: '%s'\n", opt_bind_to_aid); return 1; } r = sc_pkcs15_bind(card, &aid, &p15card); } else if (!do_list_sdos) { r = sc_pkcs15_bind(card, NULL, &p15card); } if (do_list_sdos) { if ((err = list_sdos(opt_sdo_tag))) goto end; action_count--; } if (do_list_apps) { if ((err = list_apps(stdout))) goto end; action_count--; } end: if (p15card) sc_pkcs15_unbind(p15card); if (card) { sc_unlock(card); sc_disconnect_card(card); } if (ctx) sc_release_context(ctx); return err; }
static int do_unblock(int argc, char **argv) { int ref, r; u8 puk_buf[30], *puk = NULL; u8 newpin_buf[30], *newpin = NULL; const char *s; size_t puklen = sizeof(puk_buf), i; size_t newpinlen = sizeof(newpin_buf); if (argc < 1 || argc > 3) goto usage; if (strncasecmp(argv[0], "CHV", 3)) { printf("Invalid type.\n"); goto usage; } if (sscanf(argv[0] + 3, "%d", &ref) != 1) { printf("Invalid key reference.\n"); goto usage; } argc--; argv++; if (argc == 0) { puklen = 0; puk = NULL; } else { if (argv[0][0] == '"') { for (s = argv[0] + 1, i = 0; i < sizeof(puk_buf) && *s && *s != '"'; i++) puk_buf[i] = *s++; puklen = i; } else if (sc_hex_to_bin(argv[0], puk_buf, &puklen) != 0) { printf("Invalid key value.\n"); goto usage; } puk = &puk_buf[0]; argc--; argv++; } if (argc) { if (argv[0][0] == '"') { for (s = argv[0] + 1, i = 0; i < sizeof(newpin_buf) && *s && *s != '"'; i++) newpin_buf[i] = *s++; newpinlen = i; } else if (sc_hex_to_bin(argv[0], newpin_buf, &newpinlen) != 0) { printf("Invalid key value.\n"); goto usage; } newpin = &newpin_buf[0]; } else { newpinlen = 0; newpin = NULL; } r = sc_reset_retry_counter (card, SC_AC_CHV, ref, puk, puklen, newpin, newpinlen); if (r) { if (r == SC_ERROR_PIN_CODE_INCORRECT) printf("Incorrect code.\n"); printf("Unable to unblock PIN code: %s\n", sc_strerror(r)); return -1; } printf("PIN unblocked.\n"); return 0; usage: printf("Usage: unblock CHV<pin ref> [<puk>] [<new pin>]\n"); printf("PUK and PIN values can be hexadecimal, ASCII, empty (\"\") or absent\n"); printf("Examples:\n"); printf("\tUnblock PIN and set a new value: unblock CHV2 00:00:00:00:00:00 \"foobar\"\n"); printf("\tUnblock PIN keeping the old value: unblock CHV2 00:00:00:00:00:00 \"\"\n"); printf("\tSet new PIN value: unblock CHV2 \"\" \"foobar\"\n"); printf("Examples with pinpad:\n"); printf("\tUnblock PIN: new PIN value is prompted by pinpad: unblock CHV2 00:00:00:00:00:00\n"); printf("\tSet PIN: new PIN value is prompted by pinpad: unblock CHV2 \"\"\n"); printf("\tUnblock PIN: unblock code and new PIN value are prompted by pinpad: unblock CHV2\n"); return -1; }
static int recreate_password_from_shares(char **pwd, int *pwdlen, int num_of_password_shares) { int r, i; BIGNUM prime; BIGNUM secret; BIGNUM *p; char inbuf[64]; char bin[64]; int binlen = 0; char *ip; secret_share_t *shares = NULL; secret_share_t *sp; /* * Initialize prime and secret */ BN_init(&prime); BN_init(&secret); // Allocate data buffer for the shares shares = malloc(num_of_password_shares * sizeof(secret_share_t)); printf("\nDeciphering the DKEK for import into the SmartCard-HSM requires %i key custodians", num_of_password_shares); printf("\nto present their share. Only the first key custodian needs to enter the public prime."); printf("\nPlease remember to present the share id as well as the share value."); printf("\n\nPlease enter prime: "); memset(inbuf, 0, sizeof(inbuf)); fgets(inbuf, sizeof(inbuf), stdin); binlen = 64; sc_hex_to_bin(inbuf, bin, &binlen); BN_bin2bn(bin, binlen, &prime); sp = shares; for (i = 0; i < num_of_password_shares; i++) { clearScreen(); printf("Press <enter> to enter share %i of %i\n\n", i + 1, num_of_password_shares); waitForEnterKeyPressed(); clearScreen(); BN_init(&(sp->x)); BN_init(&(sp->y)); printf("Share %i of %i\n\n", i + 1, num_of_password_shares); printf("Please enter share ID: "); memset(inbuf, 0, sizeof(inbuf)); fgets(inbuf, sizeof(inbuf), stdin); p = &(sp->x); BN_hex2bn(&p, inbuf); printf("Please enter share value: "); memset(inbuf, 0, sizeof(inbuf)); fgets(inbuf, sizeof(inbuf), stdin); binlen = 64; sc_hex_to_bin(inbuf, bin, &binlen); BN_bin2bn(bin, binlen, &(sp->y)); sp++; } clearScreen(); r = reconstructSecret(shares, num_of_password_shares, prime, &secret); if (r < 0) { printf("\nError during reconstruction of secret. Wrong shares?\n"); return r; } /* * Encode the secret value */ ip = inbuf; *pwdlen = BN_bn2bin(&secret, ip); *pwd = calloc(1, *pwdlen); memcpy(*pwd, ip, *pwdlen); cleanUpShares(shares, num_of_password_shares); BN_clear_free(&prime); BN_clear_free(&secret); return 0; }
static int sm_cwa_config_get_keyset(struct sc_context *ctx, struct sm_info *sm_info) { struct sm_cwa_session *cwa_session = &sm_info->session.cwa; struct sm_cwa_keyset *cwa_keyset = &sm_info->session.cwa.cwa_keyset; scconf_block *sm_conf_block = NULL, **blocks; struct sc_crt *crt_at = &sm_info->session.cwa.params.crt_at; const char *value = NULL; char name[128]; unsigned char hex[48]; size_t hex_len = sizeof(hex); int rv, ii, ref = crt_at->refs[0] & IASECC_OBJECT_REF_MAX; for (ii = 0; ctx->conf_blocks[ii]; ii++) { blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[ii], "secure_messaging", sm_info->config_section); if (blocks) { sm_conf_block = blocks[0]; free(blocks); } if (sm_conf_block) break; } sc_log(ctx, "CRT(algo:%X,ref:%X)", crt_at->algo, crt_at->refs[0]); /* Keyset ENC */ if (sm_info->current_aid.len && (crt_at->refs[0] & IASECC_OBJECT_REF_LOCAL)) snprintf(name, sizeof(name), "keyset_%s_%02i_enc", sc_dump_hex(sm_info->current_aid.value, sm_info->current_aid.len), ref); else snprintf(name, sizeof(name), "keyset_%02i_enc", ref); value = scconf_get_str(sm_conf_block, name, NULL); if (!value) { sc_log(ctx, "No %s value in OpenSC config", name); return SC_ERROR_SM_KEYSET_NOT_FOUND; } sc_log(ctx, "keyset::enc(%i) %s", strlen(value), value); if (strlen(value) == 16) { memcpy(cwa_keyset->enc, value, 16); } else { hex_len = sizeof(hex); rv = sc_hex_to_bin(value, hex, &hex_len); if (rv) { sc_log(ctx, "SM get %s: hex to bin failed for '%s'; error %i", name, value, rv); return SC_ERROR_UNKNOWN_DATA_RECEIVED; } sc_log(ctx, "ENC(%i) %s", hex_len, sc_dump_hex(hex, hex_len)); if (hex_len != 16) return SC_ERROR_INVALID_DATA; memcpy(cwa_keyset->enc, hex, hex_len); } sc_log(ctx, "%s %s", name, sc_dump_hex(cwa_keyset->enc, 16)); /* Keyset MAC */ if (sm_info->current_aid.len && (crt_at->refs[0] & IASECC_OBJECT_REF_LOCAL)) snprintf(name, sizeof(name), "keyset_%s_%02i_mac", sc_dump_hex(sm_info->current_aid.value, sm_info->current_aid.len), ref); else snprintf(name, sizeof(name), "keyset_%02i_mac", ref); value = scconf_get_str(sm_conf_block, name, NULL); if (!value) { sc_log(ctx, "No %s value in OpenSC config", name); return SC_ERROR_SM_KEYSET_NOT_FOUND; } sc_log(ctx, "keyset::mac(%i) %s", strlen(value), value); if (strlen(value) == 16) { memcpy(cwa_keyset->mac, value, 16); } else { hex_len = sizeof(hex); rv = sc_hex_to_bin(value, hex, &hex_len); if (rv) { sc_log(ctx, "SM get '%s': hex to bin failed for '%s'; error %i", name, value, rv); return SC_ERROR_UNKNOWN_DATA_RECEIVED; } sc_log(ctx, "MAC(%i) %s", hex_len, sc_dump_hex(hex, hex_len)); if (hex_len != 16) return SC_ERROR_INVALID_DATA; memcpy(cwa_keyset->mac, hex, hex_len); } sc_log(ctx, "%s %s", name, sc_dump_hex(cwa_keyset->mac, 16)); cwa_keyset->sdo_reference = crt_at->refs[0]; /* IFD parameters */ //memset(cwa_session, 0, sizeof(struct sm_cwa_session)); value = scconf_get_str(sm_conf_block, "ifd_serial", NULL); if (!value) return SC_ERROR_SM_IFD_DATA_MISSING; hex_len = sizeof(hex); rv = sc_hex_to_bin(value, hex, &hex_len); if (rv) { sc_log(ctx, "SM get 'ifd_serial': hex to bin failed for '%s'; error %i", value, rv); return SC_ERROR_UNKNOWN_DATA_RECEIVED; } if (hex_len != sizeof(cwa_session->ifd.sn)) { sc_log(ctx, "SM get 'ifd_serial': invalid IFD serial length: %i", hex_len); return SC_ERROR_UNKNOWN_DATA_RECEIVED; } memcpy(cwa_session->ifd.sn, hex, hex_len); rv = RAND_bytes(cwa_session->ifd.rnd, 8); if (!rv) { sc_log(ctx, "Generate random error: %i", rv); return SC_ERROR_SM_RAND_FAILED; } rv = RAND_bytes(cwa_session->ifd.k, 32); if (!rv) { sc_log(ctx, "Generate random error: %i", rv); return SC_ERROR_SM_RAND_FAILED; } sc_log(ctx, "IFD.Serial: %s", sc_dump_hex(cwa_session->ifd.sn, sizeof(cwa_session->ifd.sn))); sc_log(ctx, "IFD.Rnd: %s", sc_dump_hex(cwa_session->ifd.rnd, sizeof(cwa_session->ifd.rnd))); sc_log(ctx, "IFD.K: %s", sc_dump_hex(cwa_session->ifd.k, sizeof(cwa_session->ifd.k))); return SC_SUCCESS; }
static int changeAdminKey(sc_card_t* card, const char *so_pin, const char* new_key) { char *_so_pin = NULL, *_new_key = NULL; size_t len; u8 key[24]; int r; if (so_pin == NULL) { printf("============================================================\n"); printf("WARNING\n"); printf("Entering an incorrect admin key can break your card\n"); printf("WARNING\n"); printf("============================================================\n"); printf("Enter admin key (48 hexadecimal characters) : "); util_getpass(&_so_pin, NULL, stdin); printf("\n"); } else { _so_pin = (char *)so_pin; } len = sizeof(key); r = sc_hex_to_bin(_so_pin, key, &len); if (r < 0) { fprintf(stderr, "Error decoding initialization code (%s)\n", sc_strerror(r)); return -1; } if (len != 24) { fprintf(stderr, "admin key must be a hexadecimal string of 48 characters\n"); return -1; } r = sc_card_ctl(card, SC_CARDCTL_GIDS_AUTHENTICATE_ADMIN, (void *)key); if (r < 0) { fprintf(stderr, "sc_card_ctl(*, SC_CARDCTL_GIDS_AUTHENTICATE_ADMIN, *) failed with %s\n", sc_strerror(r)); return -1; } if (new_key == NULL) { printf("Enter new admin key (48 hexadecimal characters) : "); util_getpass(&_so_pin, NULL, stdin); printf("\n"); } else { _new_key = (char *)new_key; } len = sizeof(key); r = sc_hex_to_bin(_new_key, key, &len); if (r < 0) { fprintf(stderr, "Error decoding initialization code (%s)\n", sc_strerror(r)); return -1; } if (len != 24) { fprintf(stderr, "admin key must be a hexadecimal string of 48 characters\n"); return -1; } r = sc_card_ctl(card, SC_CARDCTL_GIDS_SET_ADMIN_KEY, (void *)key); sc_logout(card); if (r < 0) { fprintf(stderr, "sc_card_ctl(*, SC_CARDCTL_GIDS_SET_ADMIN_KEY, *) failed with %s\n", sc_strerror(r)); return -1; } return 0; }
int sm_gp_decode_card_answer(struct sc_context *ctx, struct sc_remote_data *rdata, unsigned char *out, size_t out_len) { #if 0 struct sc_asn1_entry asn1_authentic_card_response[4], asn1_card_response[2]; struct sc_hash *hash = NULL; unsigned char *hex = NULL; size_t hex_len; int rv, offs; unsigned char card_data[SC_MAX_APDU_BUFFER_SIZE]; size_t card_data_len = sizeof(card_data), len_left = 0; LOG_FUNC_CALLED(ctx); if (!out || !out_len) LOG_FUNC_RETURN(ctx, 0); if (strstr(str_data, "DATA=")) { rv = sc_hash_parse(ctx, str_data, strlen(str_data), &hash); LOG_TEST_RET(ctx, rv, "SM GP decode card answer: parse input data error"); str_data = sc_hash_get(hash, "DATA"); } if (!strlen(str_data)) LOG_FUNC_RETURN(ctx, 0); hex_len = strlen(str_data) / 2; hex = calloc(1, hex_len); if (!hex) LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "SM GP decode card answer: hex allocate error"); sc_log(ctx, "SM GP decode card answer: hex length %i", hex_len); rv = sc_hex_to_bin(str_data, hex, &hex_len); LOG_TEST_RET(ctx, rv, "SM GP decode card answer: data 'HEX to BIN' conversion error"); sc_log(ctx, "SM GP decode card answer: hex length %i", hex_len); if (hash) sc_hash_free(hash); for (offs = 0, len_left = hex_len; len_left; ) { int num, status; sc_copy_asn1_entry(c_asn1_authentic_card_response, asn1_authentic_card_response); sc_copy_asn1_entry(c_asn1_card_response, asn1_card_response); sc_format_asn1_entry(asn1_authentic_card_response + 0, &num, NULL, 0); sc_format_asn1_entry(asn1_authentic_card_response + 1, &status, NULL, 0); card_data_len = sizeof(card_data); sc_format_asn1_entry(asn1_authentic_card_response + 2, &card_data, &card_data_len, 0); sc_format_asn1_entry(asn1_card_response + 0, asn1_authentic_card_response, NULL, 0); rv = sc_asn1_decode(ctx, asn1_card_response, hex + hex_len - len_left, len_left, NULL, &len_left); if (rv) { sc_log(ctx, "SM GP decode card answer: ASN.1 parse error: %s", sc_strerror(rv)); return rv; } if (status != 0x9000) continue; if (asn1_authentic_card_response[2].flags & SC_ASN1_PRESENT) { sc_log(ctx, "SM GP decode card answer: card_data_len %i", card_data_len); if (out_len < offs + card_data_len) LOG_TEST_RET(ctx, SC_ERROR_BUFFER_TOO_SMALL, "SM GP decode card answer: buffer too small"); memcpy(out + offs, card_data, card_data_len); offs += card_data_len; } sc_log(ctx, "SM GP decode card answer: offs:%i,left:%i", offs, len_left); } free(hex); LOG_FUNC_RETURN(ctx, offs); #else LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); #endif }
static int recreate_password_from_shares(char **pwd, int *pwdlen, int num_of_password_shares) { int r, i; BIGNUM *prime; BIGNUM *secret; BIGNUM *p; char inbuf[64]; unsigned char bin[64]; size_t binlen = 0; unsigned char *ip; secret_share_t *shares = NULL; secret_share_t *sp; if (num_of_password_shares < 2) { fprintf(stderr, "--pwd-shares-total must 2 or larger\n"); return -1; } // Allocate data buffer for the shares shares = malloc(num_of_password_shares * sizeof(secret_share_t)); if (!shares) return -1; /* * Initialize prime and secret */ prime = BN_new(); secret = BN_new(); printf("\nDeciphering the DKEK for import into the SmartCard-HSM requires %i key custodians", num_of_password_shares); printf("\nto present their share. Only the first key custodian needs to enter the public prime."); printf("\nPlease remember to present the share id as well as the share value."); printf("\n\nPlease enter prime: "); memset(inbuf, 0, sizeof(inbuf)); if (fgets(inbuf, sizeof(inbuf), stdin) == NULL) { fprintf(stderr, "Input aborted\n"); free(shares); return -1; } binlen = 64; sc_hex_to_bin(inbuf, bin, &binlen); BN_bin2bn(bin, binlen, prime); sp = shares; for (i = 0; i < num_of_password_shares; i++) { clearScreen(); printf("Press <enter> to enter share %i of %i\n\n", i + 1, num_of_password_shares); waitForEnterKeyPressed(); clearScreen(); sp->x = BN_new(); sp->y = BN_new(); printf("Share %i of %i\n\n", i + 1, num_of_password_shares); printf("Please enter share ID: "); memset(inbuf, 0, sizeof(inbuf)); if (fgets(inbuf, sizeof(inbuf), stdin) == NULL) { fprintf(stderr, "Input aborted\n"); free(shares); return -1; } p = (sp->x); BN_hex2bn(&p, inbuf); printf("Please enter share value: "); memset(inbuf, 0, sizeof(inbuf)); if (fgets(inbuf, sizeof(inbuf), stdin) == NULL) { fprintf(stderr, "Input aborted\n"); free(shares); return -1; } binlen = 64; sc_hex_to_bin(inbuf, bin, &binlen); BN_bin2bn(bin, binlen, (sp->y)); sp++; } clearScreen(); r = reconstructSecret(shares, num_of_password_shares, prime, secret); if (r < 0) { printf("\nError during reconstruction of secret. Wrong shares?\n"); cleanUpShares(shares, num_of_password_shares); return r; } /* * Encode the secret value */ ip = (unsigned char *) inbuf; *pwdlen = BN_bn2bin(secret, ip); *pwd = calloc(1, *pwdlen); if (*pwd) { memcpy(*pwd, ip, *pwdlen); } cleanUpShares(shares, num_of_password_shares); BN_clear_free(prime); BN_clear_free(secret); return *pwd ? 0 : -1; }
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 do_change(int argc, char **argv) { int ref, r, tries_left = -1; u8 oldpin[30]; u8 newpin[30]; const char *s; size_t oldpinlen = sizeof(oldpin), i; size_t newpinlen = sizeof(newpin); if (argc < 1 || argc > 3) goto usage; if (strncasecmp(argv[0], "CHV", 3)) { printf("Invalid type.\n"); goto usage; } if (sscanf(argv[0] + 3, "%d", &ref) != 1) { printf("Invalid key reference.\n"); goto usage; } argc--; argv++; if (argc == 0) { /* set without verification */ oldpinlen = 0; newpinlen = 0; } else if (argc == 1) { /* set without verification */ oldpinlen = 0; } else { if (argv[0][0] == '"') { for (s = argv[0] + 1, i = 0; i < sizeof(oldpin) && *s && *s != '"'; i++) oldpin[i] = *s++; oldpinlen = i; } else if (sc_hex_to_bin(argv[0], oldpin, &oldpinlen) != 0) { printf("Invalid key value.\n"); goto usage; } argc--; argv++; } if (argc) { if (argv[0][0] == '"') { for (s = argv[0] + 1, i = 0; i < sizeof(newpin) && *s && *s != '"'; i++) newpin[i] = *s++; newpinlen = i; } else if (sc_hex_to_bin(argv[0], newpin, &newpinlen) != 0) { printf("Invalid key value.\n"); goto usage; } } r = sc_change_reference_data (card, SC_AC_CHV, ref, oldpinlen ? oldpin : NULL, oldpinlen, newpinlen ? newpin : NULL, newpinlen, &tries_left); if (r) { if (r == SC_ERROR_PIN_CODE_INCORRECT) { if (tries_left >= 0) printf("Incorrect code, %d tries left.\n", tries_left); else printf("Incorrect code.\n"); } printf("Unable to change PIN code: %s\n", sc_strerror(r)); return -1; } printf("PIN changed.\n"); return 0; usage: printf("Usage: change CHV<pin ref> [[<old pin>] <new pin>]\n"); printf("Examples: \n"); printf("\tChange PIN: change CHV2 00:00:00:00:00:00 \"foobar\"\n"); printf("\tSet PIN: change CHV2 \"foobar\"\n"); printf("\tChange PIN with pinpad': change CHV2\n"); return -1; }
int main(/*@unused@*/ int argc, /*@unused@*/ char **argv) { SCARDHANDLE hCard; SCARDCONTEXT hContext; SCARD_READERSTATE_A rgReaderStates[1]; DWORD dwReaderLen, dwState, dwProt, dwAtrLen; DWORD dwPref, dwReaders = 0; char *pcReaders = NULL, *mszReaders; #ifdef USE_AUTOALLOCATE unsigned char *pbAtr = NULL; #else unsigned char pbAtr[MAX_ATR_SIZE]; #endif union { unsigned char as_char[100]; DWORD as_DWORD; uint32_t as_uint32_t; } buf; DWORD dwBufLen; unsigned char *pbAttr = NULL; DWORD pcbAttrLen; char *mszGroups; DWORD dwGroups = 0; long rv; DWORD i; int p, iReader; int iList[16]; SCARD_IO_REQUEST pioRecvPci; SCARD_IO_REQUEST pioSendPci; unsigned char bSendBuffer[MAX_BUFFER_SIZE]; unsigned char bRecvBuffer[MAX_BUFFER_SIZE]; DWORD send_length, length; (void)argc; (void)argv; printf("\nMUSCLE PC/SC Lite unitary test Program\n\n"); printf(MAGENTA "THIS PROGRAM IS NOT DESIGNED AS A TESTING TOOL FOR END USERS!\n"); printf("Do NOT use it unless you really know what you do.\n\n" NORMAL); printf("Testing SCardEstablishContext\t: "); rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); test_rv(rv, hContext, PANIC); printf("Testing SCardIsValidContext\t: "); rv = SCardIsValidContext(hContext); test_rv(rv, hContext, PANIC); printf("Testing SCardIsValidContext\t: "); rv = SCardIsValidContext(hContext+1); test_rv(rv, hContext, DONT_PANIC); printf("Testing SCardListReaderGroups\t: "); #ifdef USE_AUTOALLOCATE dwGroups = SCARD_AUTOALLOCATE; rv = SCardListReaderGroups(hContext, (LPSTR)&mszGroups, &dwGroups); #else rv = SCardListReaderGroups(hContext, NULL, &dwGroups); test_rv(rv, hContext, PANIC); printf("Testing SCardListReaderGroups\t: "); mszGroups = calloc(dwGroups, sizeof(char)); rv = SCardListReaderGroups(hContext, mszGroups, &dwGroups); #endif test_rv(rv, hContext, PANIC); /* * Have to understand the multi-string here */ p = 0; for (i = 0; i+1 < dwGroups; i++) { ++p; printf(GREEN "Group %02d: %s\n" NORMAL, p, &mszGroups[i]); while (mszGroups[++i] != 0) ; } #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, mszGroups); test_rv(rv, hContext, PANIC); #else free(mszGroups); #endif wait_for_card_again: mszGroups = NULL; printf("Testing SCardListReaders\t: "); rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders); test_rv(rv, hContext, DONT_PANIC); if (SCARD_E_NO_READERS_AVAILABLE == rv) { printf("Testing SCardGetStatusChange \n"); printf("Please insert a working reader\t: "); (void)fflush(stdout); rgReaderStates[0].szReader = "\\\\?PnP?\\Notification"; rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY; rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1); test_rv(rv, hContext, PANIC); } printf("Testing SCardListReaders\t: "); #ifdef USE_AUTOALLOCATE dwReaders = SCARD_AUTOALLOCATE; rv = SCardListReaders(hContext, mszGroups, (LPSTR)&mszReaders, &dwReaders); #else rv = SCardListReaders(hContext, mszGroups, NULL, &dwReaders); test_rv(rv, hContext, PANIC); printf("Testing SCardListReaders\t: "); mszReaders = calloc(dwReaders, sizeof(char)); rv = SCardListReaders(hContext, mszGroups, mszReaders, &dwReaders); #endif test_rv(rv, hContext, DONT_PANIC); /* * Have to understand the multi-string here */ p = 0; for (i = 0; i+1 < dwReaders; i++) { ++p; printf(GREEN "Reader %02d: %s\n" NORMAL, p, &mszReaders[i]); iList[p] = i; while (mszReaders[++i] != 0) ; } if (p > 1) do { char input[80]; printf("Enter the reader number\t\t: "); (void)fgets(input, sizeof(input), stdin); (void)sscanf(input, "%d", &iReader); if (iReader > p || iReader <= 0) printf("Invalid Value - try again\n"); } while (iReader > p || iReader <= 0); else iReader = 1; rgReaderStates[0].szReader = &mszReaders[iList[iReader]]; rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY; printf("Waiting for card insertion\t: "); (void)fflush(stdout); rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1); test_rv(rv, hContext, PANIC); if (rgReaderStates[0].dwEventState & SCARD_STATE_UNKNOWN) { printf("\nA reader has been connected/disconnected\n"); goto wait_for_card_again; } printf("Testing SCardConnect\t\t: "); rv = SCardConnect(hContext, &mszReaders[iList[iReader]], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwPref); test_rv(rv, hContext, PANIC); switch(dwPref) { case SCARD_PROTOCOL_T0: pioSendPci = *SCARD_PCI_T0; break; case SCARD_PROTOCOL_T1: pioSendPci = *SCARD_PCI_T1; break; case SCARD_PROTOCOL_RAW: pioSendPci = *SCARD_PCI_RAW; break; default: printf("Unknown protocol\n"); return -1; } int bBreak = 0; while (1) { char inputCommand[1024]; char inputAPDU[1024]; int inputAPDULen = sizeof(inputAPDU); printf("Enter APDU to send, (e.g. 00:A4:04:00:00)\n"); printf("Command APDU: "); (void)fgets(inputCommand, sizeof(inputCommand), stdin); int stringlen = strlen(inputCommand); if( inputCommand[stringlen-1] == '\n' ) { inputCommand[stringlen-1] = 0; } //remove newline int bError = sc_hex_to_bin(inputCommand, inputAPDU, &inputAPDULen); //printf("debug - value bError: %i\n",bError); if (bError) { printf("Error parsing input\n\n"); continue; } send_length = inputAPDULen; if (inputAPDULen == 0) { break; } printf("debug inputAPDULen: %i\n",inputAPDULen); memcpy(bSendBuffer, inputAPDU, send_length); length = sizeof(bRecvBuffer); printf("Testing SCardTransmit:\n "); printf("-> "); for (i=0; i<send_length; i++) { printf(" %02X", bSendBuffer[i]); } printf("\n"); rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length, &pioRecvPci, bRecvBuffer, &length); test_rv(rv, hContext, PANIC); printf("<- " GREEN); for (i=0; i<length; i++) printf(" %02X", bRecvBuffer[i]); printf("\n" NORMAL); } testrun(&hCard, &hContext, &pioSendPci, 0); testrun(&hCard, &hContext, &pioSendPci, 1); testrun(&hCard, &hContext, &pioSendPci, 2); testrun(&hCard, &hContext, &pioSendPci, 3); printf("Testing SCardControl\t\t: "); #ifdef PCSC_PRE_120 { char buffer[1024] = "Foobar"; DWORD cbRecvLength = sizeof(buffer); rv = SCardControl(hCard, buffer, 7, buffer, &cbRecvLength); } #else { char buffer[1024] = { 0x02 }; DWORD cbRecvLength = sizeof(buffer); rv = SCardControl(hCard, SCARD_CTL_CODE(1), buffer, 1, buffer, sizeof(buffer), &cbRecvLength); if (cbRecvLength && (SCARD_S_SUCCESS == rv)) { for (i=0; i<cbRecvLength; i++) printf("%c", buffer[i]); printf(" "); } } #endif test_rv(rv, hContext, DONT_PANIC); printf("Testing SCardGetAttrib\t\t: "); #ifdef USE_AUTOALLOCATE pcbAttrLen = SCARD_AUTOALLOCATE; rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, (unsigned char *)&pbAttr, &pcbAttrLen); #else rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, NULL, &pcbAttrLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) { printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME length: " GREEN "%ld\n" NORMAL, pcbAttrLen); pbAttr = malloc(pcbAttrLen); } printf("Testing SCardGetAttrib\t\t: "); rv = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME, pbAttr, &pcbAttrLen); #endif test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) printf("SCARD_ATTR_DEVICE_FRIENDLY_NAME: " GREEN "%s\n" NORMAL, pbAttr); #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, pbAttr); test_rv(rv, hContext, PANIC); #else if (pbAttr) free(pbAttr); #endif printf("Testing SCardGetAttrib\t\t: "); #ifdef USE_AUTOALLOCATE pcbAttrLen = SCARD_AUTOALLOCATE; rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (unsigned char *)&pbAttr, &pcbAttrLen); #else rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &pcbAttrLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) { printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen); pbAttr = malloc(pcbAttrLen); } printf("Testing SCardGetAttrib\t\t: "); rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAttr, &pcbAttrLen); #endif test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) { printf("SCARD_ATTR_ATR_STRING length: " GREEN "%ld\n" NORMAL, pcbAttrLen); printf("SCARD_ATTR_ATR_STRING: " GREEN); for (i = 0; i < pcbAttrLen; i++) printf("%02X ", pbAttr[i]); printf("\n" NORMAL); } #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, pbAttr); test_rv(rv, hContext, PANIC); #else if (pbAttr) free(pbAttr); #endif printf("Testing SCardGetAttrib\t\t: "); dwBufLen = sizeof(buf); rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_IFD_VERSION, buf.as_char, &dwBufLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) printf("Vendor IFD version\t\t: " GREEN "0x%08lX\n" NORMAL, buf.as_DWORD); printf("Testing SCardGetAttrib\t\t: "); dwBufLen = sizeof(buf); rv = SCardGetAttrib(hCard, SCARD_ATTR_MAXINPUT, buf.as_char, &dwBufLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) { if (dwBufLen == sizeof(uint32_t)) printf("Max message length\t\t: " GREEN "%d\n" NORMAL, buf.as_uint32_t); else printf(RED "Wrong size" NORMAL); } printf("Testing SCardGetAttrib\t\t: "); dwBufLen = sizeof(buf); rv = SCardGetAttrib(hCard, SCARD_ATTR_VENDOR_NAME, buf.as_char, &dwBufLen); test_rv(rv, hContext, DONT_PANIC); if (rv == SCARD_S_SUCCESS) printf("Vendor name\t\t\t: " GREEN "%s\n" NORMAL, buf.as_char); printf("Testing SCardSetAttrib\t\t: "); rv = SCardSetAttrib(hCard, SCARD_ATTR_ATR_STRING, (LPCBYTE)"", 1); test_rv(rv, hContext, DONT_PANIC); printf("Testing SCardStatus\t\t: "); #ifdef USE_AUTOALLOCATE dwReaderLen = SCARD_AUTOALLOCATE; dwAtrLen = SCARD_AUTOALLOCATE; rv = SCardStatus(hCard, (LPSTR)&pcReaders, &dwReaderLen, &dwState, &dwProt, (LPBYTE)&pbAtr, &dwAtrLen); #else dwReaderLen = 100; pcReaders = malloc(sizeof(char) * 100); dwAtrLen = MAX_ATR_SIZE; rv = SCardStatus(hCard, pcReaders, &dwReaderLen, &dwState, &dwProt, pbAtr, &dwAtrLen); #endif test_rv(rv, hContext, PANIC); printf("Current Reader Name\t\t: " GREEN "%s\n" NORMAL, pcReaders); printf("Current Reader State\t\t: " GREEN "0x%.4lx\n" NORMAL, dwState); printf("Current Reader Protocol\t\t: T=" GREEN "%ld\n" NORMAL, dwProt - 1); printf("Current Reader ATR Size\t\t: " GREEN "%ld" NORMAL " bytes\n", dwAtrLen); printf("Current Reader ATR Value\t: " GREEN); for (i = 0; i < dwAtrLen; i++) { printf("%02X ", pbAtr[i]); } printf(NORMAL "\n"); #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, pcReaders); test_rv(rv, hContext, PANIC); printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, pbAtr); test_rv(rv, hContext, PANIC); #else if (pcReaders) free(pcReaders); #endif if (rv != SCARD_S_SUCCESS) { (void)SCardDisconnect(hCard, SCARD_RESET_CARD); (void)SCardReleaseContext(hContext); } printf("Press enter: "); (void)getchar(); printf("Testing SCardReconnect\t\t: "); rv = SCardReconnect(hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_UNPOWER_CARD, &dwPref); test_rv(rv, hContext, PANIC); printf("Testing SCardDisconnect\t\t: "); rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD); test_rv(rv, hContext, PANIC); #ifdef USE_AUTOALLOCATE printf("Testing SCardFreeMemory\t\t: "); rv = SCardFreeMemory(hContext, mszReaders); test_rv(rv, hContext, PANIC); #else free(mszReaders); #endif printf("Testing SCardReleaseContext\t: "); rv = SCardReleaseContext(hContext); test_rv(rv, hContext, PANIC); printf("\n"); printf("PC/SC Test Completed Successfully !\n"); return 0; }
static int unblock(sc_card_t* card, const char *so_pin, const char *user_pin) { int r; char *_so_pin = NULL, *_user_pin = NULL; size_t len; u8 key[24]; struct sc_pin_cmd_data data; memset(&data, 0, sizeof(struct sc_pin_cmd_data)); if (so_pin == NULL) { printf("============================================================\n"); printf("WARNING\n"); printf("Entering an incorrect admin key can break your card\n"); printf("WARNING\n"); printf("============================================================\n"); printf("Enter admin key (48 hexadecimal characters) : "); util_getpass(&_so_pin, NULL, stdin); printf("\n"); } else { _so_pin = (char *)so_pin; } len = sizeof(key); r = sc_hex_to_bin(_so_pin, key, &len); if (r < 0) { fprintf(stderr, "Error decoding initialization code (%s)\n", sc_strerror(r)); return -1; } if (len != 24) { fprintf(stderr, "admin key must be a hexadecimal string of 48 characters\n"); return -1; } r = sc_card_ctl(card, SC_CARDCTL_GIDS_AUTHENTICATE_ADMIN, (void *)key); if (r < 0) { fprintf(stderr, "sc_card_ctl(*, SC_CARDCTL_GIDS_AUTHENTICATE_ADMIN, *) failed with %s\n", sc_strerror(r)); return -1; } printf("Administrator authentication successful\n"); printf("Setting the new PIN\n"); if (user_pin == NULL) { printf("Enter User-PIN (4 - 16 characters) : "); util_getpass(&_user_pin, NULL, stdin); printf("\n"); } else { _user_pin = (char *)user_pin; } data.pin_type = SC_AC_CHV; data.cmd = SC_PIN_CMD_UNBLOCK; data.pin2.len = strlen(_user_pin); data.pin2.data = (unsigned char*) _user_pin; data.pin_reference = 0x80; r = sc_pin_cmd(card, &data, NULL); if (r < 0) { fprintf(stderr, "reset pin failed with %s\n", sc_strerror(r)); return -1; } printf("Unblock PIN done successfuly\n"); // the card should have deauthenticated the admin, but to be sure: sc_logout(card); return 0; }
int sc_pkcs15_hex_string_to_id(const char *in, struct sc_pkcs15_id *out) { out->len = sizeof(out->value); return sc_hex_to_bin(in, out->value, &out->len); }
static int initialize(sc_card_t *card, const char *so_pin, const char *user_pin, const char* serial) { sc_cardctl_gids_init_param_t param; size_t len; char *_so_pin = NULL, *_user_pin = NULL, *_serial = NULL; int r; memset(¶m, 0, sizeof(sc_cardctl_gids_init_param_t)); if (so_pin == NULL) { printf("Enter admin key (48 hexadecimal characters) : \n"); printf("Press Enter to set the admin key to 00...00\n"); util_getpass(&_so_pin, NULL, stdin); printf("\n"); } else { _so_pin = (char *)so_pin; } len = sizeof(param.init_code); r = sc_hex_to_bin(_so_pin, param.init_code, &len); if (r < 0) { fprintf(stderr, "Error decoding initialization code (%s)\n", sc_strerror(r)); return -1; } if (len == 0) { } else if (len != 24) { fprintf(stderr, "The admin key must be a hexadecimal string of 48 characters\n"); return -1; } if (user_pin == NULL) { printf("Enter initial User-PIN (4 - 16 characters) : "); util_getpass(&_user_pin, NULL, stdin); printf("\n"); } else { _user_pin = (char *)user_pin; } if (serial == NULL) { printf("Enter serial number (32 hexadecimal characters): \n"); printf("Press Enter to set a random serial number\n"); util_getpass(&_serial, NULL, stdin); printf("\n"); } else { _serial = (char *)serial; } if (_serial[0] == '\0') { memset(param.cardid, 0, sizeof(param.cardid)); } else if (strlen(_serial) != 32) { fprintf(stderr, "the serial number must be a hexadecimal string of 32 characters\n"); return -1; } else { len = sizeof(param.cardid); r = sc_hex_to_bin(_serial, param.cardid, &len); if (r < 0) { fprintf(stderr, "Error decoding serial number (%s)\n", sc_strerror(r)); return -1; } } param.user_pin_len = strlen(_user_pin); if (param.user_pin_len < 4) { fprintf(stderr, "PIN must be at least 4 characters long\n"); return -1; } if (param.user_pin_len > 16) { fprintf(stderr, "PIN must not be longer than 16 characters\n"); return -1; } param.user_pin = (u8 *)_user_pin; r = sc_card_ctl(card, SC_CARDCTL_GIDS_INITIALIZE, (void *)¶m); if (r < 0) { fprintf(stderr, "sc_card_ctl(*, SC_CARDCTL_GIDS_INITIALIZE, *) failed with %s\n", sc_strerror(r)); } return 0; }