static int rutoken_cipher(sc_card_t *card, u8 keyid, const u8 *in, size_t inlen, u8 *out, size_t outlen, int oper) { int r; struct sc_rutoken_decipherinfo inf = { in, inlen, out, outlen }; sc_security_env_t env; int cmd = (oper == OP_ENCRYPT) ? SC_CARDCTL_RUTOKEN_GOST_ENCIPHER : SC_CARDCTL_RUTOKEN_GOST_DECIPHER; memset(&env, 0, sizeof(env)); env.key_ref[0] = keyid; env.key_ref_len = 1; env.algorithm = SC_ALGORITHM_GOST; env.operation = SC_SEC_OPERATION_DECIPHER; /* set security env */ r = sc_set_security_env(card, &env, 0); if (r) { fprintf(stderr, "Error: Cipher failed (set security environment): %s\n", sc_strerror(r)); return -1; } /* cipher */ r = sc_card_ctl(card, cmd, &inf); if (r) { fprintf(stderr, "Error: Cipher failed: %s\n", sc_strerror(r)); return -1; } return 0; }
int do_genkey(sc_card_t *card, u8 key_id, unsigned int key_len) { int r; sc_cardctl_openpgp_keygen_info_t key_info; u8 fingerprints[60]; sc_path_t path; sc_file_t *file; if (key_id < 1 || key_id > 3) { printf("Unknown key ID %d.\n", key_id); return 1; } memset(&key_info, 0, sizeof(sc_cardctl_openpgp_keygen_info_t)); key_info.keytype = key_id; key_info.modulus_len = key_len; key_info.modulus = malloc(key_len/8); r = sc_card_ctl(card, SC_CARDCTL_OPENPGP_GENERATE_KEY, &key_info); free(key_info.modulus); if (r < 0) { printf("Failed to generate key. Error %s.\n", sc_strerror(r)); return 1; } sc_format_path("006E007300C5", &path); r = sc_select_file(card, &path, &file); r = sc_read_binary(card, 0, fingerprints, 60, 0); if (r < 0) { printf("Failed to retrieve fingerprints. Error %s.\n", sc_strerror(r)); return 1; } printf("Fingerprint:\n%s\n", (char *)sc_dump_hex(fingerprints + 20*(key_id - 1), 20)); return 0; }
static void handle_change( sc_card_t *card, int pin1, int pin2, int do_change, u8 *newpin, int newlen) { sc_path_t p; sc_file_t *f; struct sc_apdu a; u8 ref; int i; printf("\n%s %s with %s: ", do_change ? "Changing" : "Unblocking", pinlist[pin1].label, pinlist[pin2].label); sc_format_path(pinlist[pin1].path,&p); if((i=sc_select_file(card,&p,&f))<0){ printf("\nCannot select %s, %s\n", pinlist[pin1].label, sc_strerror(i)); return; } ref=f->prop_attr[2] | (strlen(pinlist[pin1].path)>8 ? 0x80 : 0x00); if(do_change){ sc_format_apdu(card, &a, SC_APDU_CASE_3_SHORT, 0x24, 0x01, ref); a.data=newpin, a.lc=a.datalen=newlen; } else { sc_format_apdu(card, &a, SC_APDU_CASE_1, 0x2C, 0x03, ref); } if((i=sc_transmit_apdu(card, &a))<0){ printf("\nsc_transmit_apdu() failed, %s\n", sc_strerror(i)); return; } if(a.sw1!=0x90 && a.sw2!=0x00){ printf("%02X%02X\n", a.sw1, a.sw2); return; } printf("OK\n"); }
int sc_disconnect_card(sc_card_t *card) { sc_context_t *ctx; if (!card) return SC_ERROR_INVALID_ARGUMENTS; ctx = card->ctx; LOG_FUNC_CALLED(ctx); if (card->lock_count != 0) return SC_ERROR_NOT_ALLOWED; if (card->ops->finish) { int r = card->ops->finish(card); if (r) sc_log(ctx, "card driver finish() failed: %s", sc_strerror(r)); } if (card->reader->ops->disconnect) { int r = card->reader->ops->disconnect(card->reader); if (r) sc_log(ctx, "disconnect() failed: %s", sc_strerror(r)); } #ifdef ENABLE_SM /* release SM related resources */ sc_card_sm_unload(card); #endif sc_card_free(card); LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
static int rutoken_info(sc_card_t *card) { u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; sc_serial_number_t serial; int r; r = sc_card_ctl(card, SC_CARDCTL_RUTOKEN_GET_INFO, rbuf); if (r) { fprintf(stderr, "Error: Get info failed: %s\n", sc_strerror(r)); return -1; } printf("Type: %d\n", rbuf[0]); printf("Version: %d.%d\n", rbuf[1]>>4, rbuf[1] & 0x0F); printf("Memory: %d Kb\n", rbuf[2]*8); printf("Protocol version: %d\n", rbuf[3]); printf("Software version: %d\n", rbuf[4]); printf("Order: %d\n", rbuf[5]); r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial); if (r) { fprintf(stderr, "Error: Get serial failed: %s\n", sc_strerror(r)); return -1; } printf("Serial number: "); util_hex_dump(stdout, serial.value, serial.len, NULL); putchar('\n'); return 0; }
static int rutoken_mac(sc_card_t *card, u8 keyid, const u8 *in, size_t inlen, u8 *out, size_t outlen) { int r; sc_security_env_t env; memset(&env, 0, sizeof(env)); env.key_ref[0] = keyid; env.key_ref_len = 1; env.algorithm = SC_ALGORITHM_GOST; env.operation = SC_SEC_OPERATION_SIGN; /* set security env */ r = sc_set_security_env(card, &env, 0); if (r) { fprintf(stderr, "Error: Computation signature (MAC) failed" " (set security environment): %s\n", sc_strerror(r)); return -1; } /* calculate hash */ r = sc_compute_signature(card, in, inlen, out, outlen); if (r) { fprintf(stderr, "Error: Computation signature (MAC) failed: %s\n", sc_strerror(r)); return -1; } return 0; }
int main(int argc, char **argv) { sc_context_t *ctx = NULL; sc_context_param_t ctx_param; sc_card_t *card = NULL; int r; /* get options */ decode_options(argc, argv); /* connect to the card */ 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; } r = util_connect_card(ctx, &card, opt_reader, opt_wait, 0); if (r) { fprintf(stderr, "Failed to connect to card: %s\n", sc_strerror(r)); return 1; } /* Check card type */ if (card->type == SC_CARD_TYPE_MCRD_ESTEID_V10 || card->type == SC_CARD_TYPE_MCRD_ESTEID_V11 || card->type == SC_CARD_TYPE_MCRD_ESTEID_V30) do_esteid(card); else if (card->type == SC_CARD_TYPE_BELPIC_EID) do_belpic(card); else { fprintf(stderr, "Not an EstEID or Belpic card!\n"); goto out; } if (exec_program) { char *const largv[] = {exec_program, NULL}; sc_unlock(card); sc_disconnect_card(card); sc_release_context(ctx); execv(exec_program, largv); /* we should not get here */ perror("execv()"); exit(1); } out: sc_unlock(card); sc_disconnect_card(card); sc_release_context(ctx); exit(exit_status); }
static int read_data_object(void) { int r, i, count, oid_len = 0; struct sc_pkcs15_object *objs[32]; struct sc_object_id oid; r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_DATA_OBJECT, objs, 32); if (r < 0) { fprintf(stderr, "Data object enumeration failed: %s\n", sc_strerror(r)); return 1; } count = r; r = sc_format_oid(&oid, opt_data); if (r == SC_SUCCESS) { while (oid.value[oid_len] >= 0) oid_len++; } for (i = 0; i < count; i++) { struct sc_pkcs15_data_info *cinfo = (struct sc_pkcs15_data_info *) objs[i]->data; struct sc_pkcs15_data *data_object; if (oid_len) { if (memcmp(oid.value, cinfo->app_oid.value, sizeof(int) * oid_len)) continue; } else { if (strcmp(opt_data, cinfo->app_label) && strcmp(opt_data, objs[i]->label)) continue; } if (verbose) printf("Reading data object with label '%s'\n", opt_data); r = authenticate(objs[i]); if (r >= 0) { r = sc_pkcs15_read_data_object(p15card, cinfo, &data_object); if (r) { fprintf(stderr, "Data object read failed: %s\n", sc_strerror(r)); if (r == SC_ERROR_FILE_NOT_FOUND) continue; /* DEE emulation may say there is a file */ return 1; } r = print_data_object("Data Object", data_object->data, data_object->data_len); sc_pkcs15_free_data_object(data_object); return r; } else { fprintf(stderr, "Authentication error: %s\n", sc_strerror(r)); return 1; } } fprintf(stderr, "Data object with label '%s' not found.\n", opt_data); return 2; }
static int do_cd(int argc, char **argv) { sc_path_t path; sc_file_t *file; int r; if (argc != 1) goto usage; if (strcmp(argv[0], "..") == 0) { if (current_path.len < 4) { printf("unable to go up, already in MF.\n"); return -1; } path = current_path; path.len -= 2; r = sc_select_file(card, &path, &file); if (r) { printf("unable to go up: %s\n", sc_strerror(r)); return -1; } sc_file_free(current_file); current_file = file; current_path = path; return 0; } if (arg_to_path(argv[0], &path, 0) != 0) goto usage; r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select DF", current_file); return -1; } if ((file->type != SC_FILE_TYPE_DF) && !(card->caps & SC_CARD_CAP_NO_FCI)) { printf("Error: file is not a DF.\n"); sc_file_free(file); r = sc_select_file(card, ¤t_path, NULL); if (r) { printf("unable to select parent file: %s\n", sc_strerror(r)); die(1); } return -1; } current_path = path; sc_file_free(current_file); current_file = file; return 0; usage: puts("Usage: cd <file_id>|aid:<DF name>"); return -1; }
static int format_data(sc_card_t *card, const struct iso_sm_ctx *ctx, const u8 *data, size_t datalen, struct sc_asn1_entry *formatted_encrypted_data_entry, u8 **formatted_data, size_t *formatted_data_len) { int r; u8 *pad_data = NULL; size_t pad_data_len = 0; if (!ctx || !formatted_data || !formatted_data_len) { r = SC_ERROR_INVALID_ARGUMENTS; goto err; } r = add_padding(ctx, data, datalen, &pad_data); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not add padding to data: %s", sc_strerror(r)); goto err; } pad_data_len = r; bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Data to encrypt", pad_data, pad_data_len); r = ctx->encrypt(card, ctx, pad_data, pad_data_len, formatted_data); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not encrypt the data"); goto err; } bin_log(card->ctx, SC_LOG_DEBUG_NORMAL, "Cryptogram", *formatted_data, r); r = prefix_buf(ctx->padding_indicator, *formatted_data, r, formatted_data); if (r < 0) { sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not prepend padding indicator to formatted " "data: %s", sc_strerror(r)); goto err; } *formatted_data_len = r; sc_format_asn1_entry(formatted_encrypted_data_entry, *formatted_data, formatted_data_len, SC_ASN1_PRESENT); r = SC_SUCCESS; err: if (pad_data) { sc_mem_clear(pad_data, pad_data_len); free(pad_data); } return r; }
static int dump_unusedspace(void) { u8 *buf = NULL; size_t buf_len; sc_path_t path; sc_pkcs15_unusedspace_t *us; int r; if (p15card->file_unusedspace != NULL) path = p15card->file_unusedspace->path; else { path = p15card->file_app->path; sc_append_path_id(&path, (const u8 *) "\x50\x33", 2); } path.count = -1; sc_ctx_suppress_errors_on(p15card->card->ctx); r = sc_pkcs15_read_file(p15card, &path, &buf, &buf_len, NULL); sc_ctx_suppress_errors_off(p15card->card->ctx); if (r < 0) { if (r == SC_ERROR_FILE_NOT_FOUND) { printf("\nNo EF(UnusedSpace) file\n"); r = 0; } else printf("\nError reading file \"%s\": %s\n", sc_print_path(&path), sc_strerror(r)); goto err; } r = sc_pkcs15_parse_unusedspace(buf, buf_len, p15card); if (r != 0) { printf("\nError parsing EF(UnusedSpace): %s\n", sc_strerror(r)); goto err; } if (p15card->unusedspace_list == NULL) printf("\nEF(UnusedSpace) file is empty\n"); else { printf("\nContents of EF(UnusedSpace):\n"); for (us = p15card->unusedspace_list; us != NULL; us = us->next) printf(" - path=%s, index=%d, length=%d -- auth_id = %s\n", sc_print_path(&us->path), us->path.index, us->path.count, us->auth_id.len == 0 ? "<empty>" : sc_pkcs15_print_id(&us->auth_id)); } err: if (buf != NULL) free(buf); return r; }
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_info(sc_card_t *card, const struct ef_name_map *map) { int i; u8 buf[2048]; for (i = 0; map[i].ef != NULL; i++) { sc_path_t path; sc_file_t *file; size_t count; int r; sc_format_path(map[i].ef, &path); r = sc_select_file(card, &path, &file); if (r) { util_error("failed to select EF %s: %s", map[i].ef, sc_strerror(r)); return EXIT_FAILURE; } count = file->size; if (!count) continue; if (count > sizeof(buf) - 1) { util_error("too small buffer to read the OpenPGP map"); return EXIT_FAILURE; } r = sc_read_binary(card, 0, buf, count, 0); if (r < 0) { util_error("failed to read %s: %s", map[i].ef, sc_strerror(r)); return EXIT_FAILURE; } if (r != (signed) count || (size_t) r < map[i].offset + map[i].length) { util_error("%s: expecting %"SC_FORMAT_LEN_SIZE_T"d bytes, got only %d", map[i].ef, count, r); return EXIT_FAILURE; } if (map[i].offset > 0) { memmove(buf, buf + map[i].offset, map[i].length); count -= map[i].offset; } if (map[i].length > 0 && count > map[i].length) count = map[i].length; if (map[i].type == TYPE_STRING) buf[count] = '\0'; display_data(&map[i], buf, count); } return EXIT_SUCCESS; }
static void show_initial_puk(sc_card_t *card) { sc_path_t p; sc_file_t *f; struct sc_apdu a; u8 buf1[128], buf2[128]; int i; printf("\nReading crypted Initial-PUK-file: "); sc_format_path("3F004350",&p); if((i=sc_select_file(card,&p,&f))<0){ printf("Cannot select crypted Initial-PUK-file, %s\n", sc_strerror(i)); return; } if((i=sc_read_binary(card,0,buf1,128,0))!=128){ printf("Cannot read crypted Initial-PUK-file, %s\n", sc_strerror(i)); return; } printf("OK\nDecrypting crypted Initial-PUK-file: "); sc_format_path("3F00DF01",&p); if((i=sc_select_file(card,&p,&f))<0){ printf("Cannot select DF01, %s\n", sc_strerror(i)); return; } sc_format_apdu(card, &a, SC_APDU_CASE_3_SHORT, 0x22, 0xC1, 0xB8); buf2[0]=0x80, buf2[1]=0x01, buf2[2]=0x10, buf2[3]=0x84, buf2[4]=0x01, buf2[5]=0x81; a.data=buf2, a.lc=a.datalen=6; if((i=sc_transmit_apdu(card, &a))<0){ printf("sc_transmit_apdu(MSE) failed, %s\n", sc_strerror(i)); return; } if(a.sw1!=0x90 && a.sw2!=0x00){ printf("MSE=%02X%02X\n", a.sw1, a.sw2); return; } sc_format_apdu(card, &a, SC_APDU_CASE_4_SHORT, 0x2A, 0x84, 0x80); a.data=buf1, a.lc=a.datalen=128; a.resp=buf2, a.le=a.resplen=128; if((i=sc_transmit_apdu(card, &a))<0){ printf("sc_transmit_apdu(PSO) failed, %s\n", sc_strerror(i)); return; } if(a.sw1!=0x90 && a.sw2!=0x00){ printf("PSO=%02X%02X\n", a.sw1, a.sw2); return; } printf("OK ==> Initial-PUK:"); for(i=120;i<128;++i) printf("%c",buf2[i]); printf("\n"); }
static int list_data_objects(void) { int r, i, count; struct sc_pkcs15_object *objs[32]; r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_DATA_OBJECT, objs, 32); if (r < 0) { fprintf(stderr, "Data object enumeration failed: %s\n", sc_strerror(r)); return 1; } count = r; for (i = 0; i < count; i++) { int idx; struct sc_pkcs15_data_info *cinfo = (struct sc_pkcs15_data_info *) objs[i]->data; printf("Reading data object <%i>\n", i); printf("applicationName: %s\n", cinfo->app_label); printf("Label: %s\n", objs[i]->label); printf("applicationOID: "); if (cinfo->app_oid.value[0] >= 0) { printf("%i", cinfo->app_oid.value[0]); idx = 1; while (idx < SC_MAX_OBJECT_ID_OCTETS) { if (cinfo->app_oid.value[idx] < 0) break; printf(".%i", cinfo->app_oid.value[idx++]); } printf("\n"); } else printf("NONE\n"); printf("Path: %s\n", sc_print_path(&cinfo->path)); if (objs[i]->auth_id.len == 0) { struct sc_pkcs15_data *data_object; r = sc_pkcs15_read_data_object(p15card, cinfo, &data_object); if (r) { fprintf(stderr, "Data object read failed: %s\n", sc_strerror(r)); if (r == SC_ERROR_FILE_NOT_FOUND) continue; /* DEE emulation may say there is a file */ return 1; } r = list_data_object("Data Object", data_object->data, data_object->data_len); sc_pkcs15_free_data_object(data_object); } else { printf("Auth ID: %s\n", sc_pkcs15_print_id(&objs[i]->auth_id)); } } return 0; }
static int create_sysdf(sc_profile_t *profile, sc_card_t *card, const char *name) { sc_file_t *file; sc_path_t path; int r; assert(profile && card && card->ctx && name); r = sc_profile_get_file(profile, name, &file); if (r == SC_SUCCESS) { assert(file); path = file->path; assert(path.len > 2); if (path.len > 2) path.len -= 2; r = sc_select_file(card, &path, NULL); if (r == SC_SUCCESS) r = sc_file_add_acl_entry(file, SC_AC_OP_CREATE, SC_AC_CHV, RTECP_USER_PIN_REF); if (r == SC_SUCCESS) r = sc_file_add_acl_entry(file, SC_AC_OP_DELETE, SC_AC_NEVER, SC_AC_KEY_REF_NONE); if (r == SC_SUCCESS) r = sc_create_file(card, file); assert(file); sc_file_free(file); } sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Create %s failed: %s\n", name, sc_strerror(r)); return r; }
static void do_random() { unsigned char buffer[128]; int r, count = 128; int n = 128; int n_bits = 1024; struct rand_pool_info *output; int fd = open(DEV_RANDOM, O_WRONLY); if (fd == -1) { syslog(LOG_ERR,"Failed to open %s", DEV_RANDOM); } while (1) { r = sc_get_challenge(card, buffer, count); if (r < 0) { syslog(LOG_ERR,"Failed to get random bytes: %s\n", sc_strerror(r)); } output = (struct rand_pool_info *)malloc(sizeof(struct rand_pool_info) + n); output -> entropy_count = n_bits; output -> buf_size = n; memcpy(&(output -> buf[0]), buffer, n); if (ioctl(fd, RNDADDENTROPY, output) == -1) { syslog(LOG_ERR,"ioctl(RNDADDENTROPY) failed!"); } free(output); sleep(1); } close(fd); }
static int generate_gostkey(sc_card_t *card, u8 keyid, u8 keyoptions) { const sc_SecAttrV2_t gk_sec_attr = {0x44, 0, 0, 1, 0, 0, 0, 1, 0, 0, 2, 0, 0, 0, 2}; sc_DOHdrV2_t paramkey; int r; memset(¶mkey, 0, sizeof(paramkey)); paramkey.wDOBodyLen = SC_RUTOKEN_DEF_LEN_DO_GOST; paramkey.OTID.byObjectType = SC_RUTOKEN_TYPE_KEY; paramkey.OTID.byObjectID = keyid; paramkey.OP.byObjectOptions = keyoptions; /* assert(sizeof(*gk_sec_attr)); */ /* assert(sizeof(*paramkey.SA_V2)); */ /* assert(sizeof(paramkey.SA_V2) == sizeof(gk_sec_attr)); */ memcpy(paramkey.SA_V2, gk_sec_attr, sizeof(gk_sec_attr)); r = sc_card_ctl(card, SC_CARDCTL_RUTOKEN_GENERATE_KEY_DO, ¶mkey); if (r) { fprintf(stderr, "Error: Generate GOST key failed: %s\n", sc_strerror(r)); return -1; } return 0; }
static int do_random(int argc, char **argv) { unsigned char buffer[128]; int r, count; if (argc != 1) goto usage; count = atoi(argv[0]); if (count < 0 || count > 128) { printf("Number must be in range 0..128\n"); return -1; } r = sc_get_challenge(card, buffer, count); if (r < 0) { printf("Failed to get random bytes: %s\n", sc_strerror(r)); return -1; } util_hex_dump_asc(stdout, buffer, count, 0); return 0; usage: printf("Usage: random count\n"); return -1; }
static int enum_pins(struct sc_pkcs15_object ***ret) { struct sc_pkcs15_object **objs; int i, n; n = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, NULL, 0); if (n < 0) { fprintf(stderr, "Error enumerating PIN codes: %s\n", sc_strerror(n)); return 1; } if (n == 0) { fprintf(stderr, "No PIN codes found!\n"); return 0; } objs = calloc(n, sizeof(*objs)); if (!objs) { fprintf(stderr, "Not enough memory!\n"); return 1; } if (0 > sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, n)) { fprintf(stderr, "Error enumerating PIN codes\n"); free(objs); return 1; } for (i = 0; i < n; i++) { sc_test_print_object(objs[i]); } *ret = objs; return n; }
static int ask_and_verify_pin(struct sc_pkcs15_object *obj) { struct sc_pkcs15_pin_info *pin; int i = 0; char prompt[80]; u8 *pass; pin = (struct sc_pkcs15_pin_info *) obj->data; if (pin->flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN) { printf("Skipping unblocking pin [%s]\n", obj->label); return 0; } sprintf(prompt, "Please enter PIN code [%s]: ", obj->label); pass = (u8 *) getpass(prompt); sc_lock(card); i = sc_pkcs15_verify_pin(p15card, pin, pass, strlen((char *) pass)); sc_unlock(card); if (i) { if (i == SC_ERROR_PIN_CODE_INCORRECT) fprintf(stderr, "Incorrect PIN code (%d tries left)\n", pin->tries_left); else fprintf(stderr, "PIN verifying failed: %s\n", sc_strerror(i)); return 1; } else printf("PIN code correct.\n"); return 0; }
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 void check_ret(int r, int op, const char *err, const sc_file_t *file) { fprintf(stderr, "%s: %s\n", err, sc_strerror(r)); if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) fprintf(stderr, "ACL for operation: %s\n", util_acl_to_str(sc_file_get_acl_entry(file, op))); }
static int do_sm(int argc, char **argv) { int r = SC_ERROR_NOT_SUPPORTED, ret = -1; if (argc != 1) return usage(do_sm); #ifdef ENABLE_SM if (!strcmp(argv[0],"open")) { if (!card->sm_ctx.ops.open) { printf("Not supported\n"); return -1; } r = card->sm_ctx.ops.open(card); } else if (!strcmp(argv[0],"close")) { if (!card->sm_ctx.ops.close) { printf("Not supported\n"); return -1; } r = card->sm_ctx.ops.close(card); } #endif if (r == SC_SUCCESS) { ret = 0; printf("Success!\n"); } else { printf("Failure: %s\n", sc_strerror(r)); } return ret; }
char * sc_get_key_label(Key *key) { int r; const struct sc_priv_data *priv; struct sc_pkcs15_object *key_obj; priv = (const struct sc_priv_data *) RSA_get_app_data(key->rsa); if (priv == NULL || p15card == NULL) { logit("SmartCard key not loaded"); /* internal error => return default label */ return xstrdup("smartcard key"); } r = sc_pkcs15_find_prkey_by_id(p15card, &priv->cert_id, &key_obj); if (r) { logit("Unable to find private key from SmartCard: %s", sc_strerror(r)); return xstrdup("smartcard key"); } if (key_obj == NULL || key_obj->label == NULL) /* the optional PKCS#15 label does not exists * => return the default label */ return xstrdup("smartcard key"); return xstrdup(key_obj->label); }
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_get_data(int argc, char **argv) { unsigned char buffer[256]; unsigned int tag; FILE *fp; int r; if (argc != 1 && argc != 2) return usage(do_get_data); tag = strtoul(argv[0], NULL, 16); r = sc_get_data(card, tag, buffer, sizeof(buffer)); if (r < 0) { printf("Failed to get data object: %s\n", sc_strerror(r)); return -1; } if (argc == 2) { const char *filename = argv[1]; if (!(fp = fopen(filename, "w"))) { perror(filename); return -1; } fwrite(buffer, r, 1, fp); fclose(fp); } else { printf("Object %04x:\n", tag & 0xFFFF); util_hex_dump_asc(stdout, buffer, r, 0); } return 0; }
static int decipher(struct sc_pkcs15_object *obj) { u8 buf[1024], out[1024]; int r, c, len; if (opt_input == NULL) { fprintf(stderr, "No input file specified.\n"); return 2; } c = read_input(buf, sizeof(buf)); if (c < 0) return 2; len = sizeof(out); if (!((struct sc_pkcs15_prkey_info *) obj->data)->native) { fprintf(stderr, "Deprecated non-native key detected! Upgrade your smart cards.\n"); return SC_ERROR_NOT_SUPPORTED; } r = sc_pkcs15_decipher(p15card, obj, opt_crypt_flags & SC_ALGORITHM_RSA_PAD_PKCS1, buf, c, out, len); if (r < 0) { fprintf(stderr, "Decrypt failed: %s\n", sc_strerror(r)); return 1; } r = write_output(out, r); return 0; }
int main(int argc, char *argv[]) { int i; i = sc_test_init(&argc, argv); if (i < 0) return 1; printf("Looking for a PKCS#15 compatible Smart Card... "); fflush(stdout); sc_lock(card); i = sc_pkcs15_bind(card, &p15card); /* Keep card locked to prevent useless calls to sc_logout */ if (i) { fprintf(stderr, "failed: %s\n", sc_strerror(i)); return 1; } printf("found.\n"); sc_test_print_card(p15card); dump_objects("PIN codes", SC_PKCS15_TYPE_AUTH_PIN); dump_objects("Private keys", SC_PKCS15_TYPE_PRKEY); dump_objects("Public keys", SC_PKCS15_TYPE_PUBKEY); dump_objects("X.509 certificates", SC_PKCS15_TYPE_CERT_X509); dump_objects("data objects", SC_PKCS15_TYPE_DATA_OBJECT); dump_unusedspace(); sc_pkcs15_unbind(p15card); sc_unlock(card); sc_test_cleanup(); 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; }