static int do_change(int argc, char **argv) { int ref, r, tries_left = -1; u8 oldpin[64]; u8 newpin[64]; size_t oldpinlen = 0; size_t newpinlen = 0; struct sc_pin_cmd_data data; memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_CHANGE; if (argc < 1 || argc > 3) return usage(do_change); if (strncasecmp(argv[0], "CHV", 3)) { printf("Invalid type.\n"); return usage(do_change); } if (sscanf(argv[0] + 3, "%d", &ref) != 1) { printf("Invalid key reference.\n"); return usage(do_change); } if (argc == 3) { oldpinlen = sizeof(oldpin); if (parse_string_or_hexdata(argv[1], oldpin, &oldpinlen) != 0) { printf("Invalid key value.\n"); return usage(do_change); } } if (argc >= 2) { newpinlen = sizeof(newpin); if (parse_string_or_hexdata(argv[argc-1], newpin, &newpinlen) != 0) { printf("Invalid key value.\n"); return usage(do_change); } } data.pin_type = SC_AC_CHV; data.pin_reference = ref; data.pin1.data = oldpinlen ? oldpin : NULL; data.pin1.len = oldpinlen; data.pin2.data = newpinlen ? newpin : NULL; data.pin2.len = newpinlen; r = sc_pin_cmd(card, &data, &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; }
static int do_unblock(int argc, char **argv) { int ref, r; u8 puk[30]; u8 newpin[30]; size_t puklen = 0; size_t newpinlen = 0; 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; } if (argc > 1) { puklen = sizeof(puk); if (parse_string_or_hexdata(argv[1], puk, &puklen) != 0) { printf("Invalid key value.\n"); goto usage; } } if (argc > 2) { newpinlen = sizeof(newpin); if (parse_string_or_hexdata(argv[2], newpin, &newpinlen) != 0) { printf("Invalid key value.\n"); goto usage; } } r = sc_reset_retry_counter (card, SC_AC_CHV, ref, puklen ? puk : NULL, puklen, newpinlen ? newpin : NULL, 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 do_change(int argc, char **argv) { int ref, r, tries_left = -1; u8 oldpin[30]; u8 newpin[30]; size_t oldpinlen = 0; size_t newpinlen = 0; 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; } if (argc == 3) { oldpinlen = sizeof(oldpin); if (parse_string_or_hexdata(argv[1], oldpin, &oldpinlen) != 0) { printf("Invalid key value.\n"); goto usage; } } if (argc >= 2) { newpinlen = sizeof(newpin); if (parse_string_or_hexdata(argv[argc-1], 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; }
static int do_unblock(int argc, char **argv) { int ref, r; u8 puk[64]; u8 newpin[64]; size_t puklen = 0; size_t newpinlen = 0; struct sc_pin_cmd_data data; memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_UNBLOCK; if (argc < 1 || argc > 3) return usage(do_unblock); if (strncasecmp(argv[0], "CHV", 3)) { printf("Invalid type.\n"); return usage(do_unblock); } if (sscanf(argv[0] + 3, "%d", &ref) != 1) { printf("Invalid key reference.\n"); return usage(do_unblock); } if (argc > 1) { puklen = sizeof(puk); if (parse_string_or_hexdata(argv[1], puk, &puklen) != 0) { printf("Invalid key value.\n"); return usage(do_unblock); } } if (argc > 2) { newpinlen = sizeof(newpin); if (parse_string_or_hexdata(argv[2], newpin, &newpinlen) != 0) { printf("Invalid key value.\n"); return usage(do_unblock); } } data.pin_type = SC_AC_CHV; data.pin_reference = ref; data.pin1.data = puklen ? puk : NULL; data.pin1.len = puklen; data.pin2.data = newpinlen ? newpin : NULL; data.pin2.len = newpinlen; r = sc_pin_cmd(card, &data, NULL); 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; }
static int do_update_record(int argc, char **argv) { u8 buf[240]; size_t buflen; int r, i, err = 1; int rec, offs; sc_path_t path; sc_file_t *file; if (argc != 4) return usage(do_update_record); if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_update_record); rec = strtol(argv[1],NULL,10); offs = strtol(argv[2],NULL,10); printf("in: %i; %i; %s\n", rec, offs, argv[3]); r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); return -1; } if (file->ef_structure != SC_FILE_EF_LINEAR_VARIABLE) { printf("EF structure should be SC_FILE_EF_LINEAR_VARIABLE\n"); goto err; } else if (rec < 1 || rec > file->record_count) { printf("Invalid record number %i\n", rec); goto err; } r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR); if (r<0) { printf("Cannot read record %i; return %i\n", rec, r); goto err;; } buflen = sizeof(buf) - offs; i = parse_string_or_hexdata(argv[3], buf + offs, &buflen); if (!i) { printf("unable to parse data\n"); goto err; } r = sc_update_record(card, rec, buf, r, SC_RECORD_BY_REC_NR); if (r<0) { printf("Cannot update record %i; return %i\n", rec, r); goto err; } printf("Total of %d bytes written to record %i at %i offset.\n", i, rec, offs); err = 0; err: sc_file_free(file); select_current_path_or_die(); return -err; }
/** * Use PUT DATA command to write to Data Object. **/ static int do_put_data(int argc, char **argv) { unsigned int tag; u8 buf[8192]; size_t buflen = sizeof(buf); int r; if (argc != 2) return usage(do_put_data); /* Extract DO's tag */ tag = strtoul(argv[0], NULL, 16); /* Extract the new content */ /* buflen is the max length of reception buffer */ r = parse_string_or_hexdata(argv[1], buf, &buflen); if (r < 0) { printf("unable to parse data\n"); return -1; } /* Call OpenSC to do put data */ r = sc_put_data(card, tag, buf, buflen); if (r < 0) { printf("Cannot put data to %04X; return %i\n", tag, r); return -1; } printf("Total of %d bytes written.\n", r); return 0; }
static int do_apdu(int argc, char **argv) { sc_apdu_t apdu; u8 buf[SC_MAX_APDU_BUFFER_SIZE * 2]; u8 rbuf[SC_MAX_APDU_BUFFER_SIZE * 2]; size_t len, i; int r; if (argc < 1) return usage(do_apdu); for (i = 0, len = 0; i < (unsigned) argc; i++) { size_t len0 = strlen(argv[i]); if ((r = parse_string_or_hexdata(argv[i], buf + len, &len0)) < 0) { fprintf(stderr, "error parsing %s: %s\n", argv[i], sc_strerror(r)); return r; }; 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: "); util_hex_dump(stdout, buf, len, " "); 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); r = sc_check_sw(card, apdu.sw1, apdu.sw2); if (r) printf("Failure: %s\n", sc_strerror(r)); else printf("Success!\n"); return 0; }
static int do_update_binary(int argc, char **argv) { u8 buf[240]; size_t buflen = sizeof(buf); int r, err = 1; int offs; sc_path_t path; sc_file_t *file; if (argc != 3) return usage(do_update_binary); if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_update_binary); offs = strtol(argv[1],NULL,10); printf("in: %i; %s\n", offs, argv[2]); r = parse_string_or_hexdata(argv[2], buf, &buflen); if (r < 0) { printf("unable to parse data\n"); return -1; } r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); return -1; } if (file->ef_structure != SC_FILE_EF_TRANSPARENT) { printf("EF structure should be SC_FILE_EF_TRANSPARENT\n"); goto err; } r = sc_update_binary(card, offs, buf, buflen, 0); if (r < 0) { printf("Cannot update %04X; return %i\n", file->id, r); goto err; } printf("Total of %d bytes written to %04X at %i offset.\n", r, file->id, offs); err = 0; err: sc_file_free(file); select_current_path_or_die(); return -err; }
static int do_verify(int argc, char **argv) { const id2str_t typeNames[] = { { SC_AC_CHV, "CHV" }, { SC_AC_AUT, "KEY" }, { SC_AC_AUT, "AUT" }, { SC_AC_PRO, "PRO" }, { SC_AC_NONE, NULL, } }; int r, tries_left = -1; u8 buf[64]; size_t buflen = sizeof(buf), i; struct sc_pin_cmd_data data; if (argc < 1 || argc > 2) goto usage; memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_VERIFY; data.pin_type = SC_AC_NONE; for (i = 0; typeNames[i].str; i++) { if (strncasecmp(argv[0], typeNames[i].str, 3) == 0) { data.pin_type = typeNames[i].id; break; } } if (data.pin_type == SC_AC_NONE) { printf("Invalid type.\n"); goto usage; } if (sscanf(argv[0] + 3, "%d", &data.pin_reference) != 1) { printf("Invalid key reference.\n"); goto usage; } if (argc < 2) { if (!(card->reader->capabilities & SC_READER_CAP_PIN_PAD)) { printf("Card reader or driver doesn't support PIN PAD\n"); return -1; } printf("Please enter PIN on the reader's pin pad.\n"); data.pin1.prompt = "Please enter PIN"; data.flags |= SC_PIN_CMD_USE_PINPAD; } else { r = parse_string_or_hexdata(argv[1], buf, &buflen); if (0 != r) { printf("Invalid key value.\n"); goto usage; } data.pin1.data = buf; data.pin1.len = buflen; } r = sc_pin_cmd(card, &data, &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"); } else printf("Unable to verify PIN code: %s\n", sc_strerror(r)); return -1; } printf("Code correct.\n"); return 0; usage: printf("Usage: verify <key type><key ref> [<pin>]\n"); printf("Possible values of <key type>:\n"); for (i = 0; typeNames[i].str; i++) printf("\t%s\n", typeNames[i].str); printf("Example: verify CHV2 31:32:33:34:00:00:00:00\n"); printf("If key is omitted, card reader's keypad will be used to collect PIN.\n"); return -1; }
static int do_verify(int argc, char **argv) { const id2str_t typeNames[] = { { SC_AC_CHV, "CHV" }, { SC_AC_AUT, "KEY" }, { SC_AC_AUT, "AUT" }, { SC_AC_PRO, "PRO" }, { SC_AC_NONE, NULL, } }; int r, tries_left = -1; u8 buf[64]; size_t buflen = sizeof(buf), i; struct sc_pin_cmd_data data; int prefix_len = 0; if (argc < 1 || argc > 2) return usage(do_verify); memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_VERIFY; data.pin_type = SC_AC_NONE; for (i = 0; typeNames[i].str; i++) { prefix_len = strlen(typeNames[i].str); if (strncasecmp(argv[0], typeNames[i].str, prefix_len) == 0) { data.pin_type = typeNames[i].id; break; } } if (data.pin_type == SC_AC_NONE) { printf("Invalid type.\n"); return usage(do_verify); } if (sscanf(argv[0] + prefix_len, "%d", &data.pin_reference) != 1) { printf("Invalid key reference.\n"); return usage(do_verify); } if (argc < 2) { if (card->reader->capabilities & SC_READER_CAP_PIN_PAD) { printf("Please enter PIN on the reader's pin pad.\n"); data.pin1.prompt = "Please enter PIN"; data.flags |= SC_PIN_CMD_USE_PINPAD; } else { char *pin = NULL; size_t len = 0; printf("Please enter PIN: "); r = util_getpass(&pin, &len, stdin); if (r < 0) { printf("No PIN entered - aborting VERIFY.\n"); return -1; } if (strlcpy((char *)buf, pin, sizeof(buf)) >= sizeof(buf)) { free(pin); printf("PIN too long - aborting VERIFY.\n"); return -1; } free(pin); data.pin1.data = buf; data.pin1.len = strlen((char *)buf); } } else { r = parse_string_or_hexdata(argv[1], buf, &buflen); if (0 != r) { printf("Invalid key value.\n"); return usage(do_verify); } data.pin1.data = buf; data.pin1.len = buflen; } r = sc_pin_cmd(card, &data, &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"); } else printf("Unable to verify PIN code: %s\n", sc_strerror(r)); return -1; } printf("Code correct.\n"); return 0; }