/* * Unblock a PIN. */ int sc_pkcs15_unblock_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *so_pin_obj, struct sc_pkcs15_object *pin_obj, const u8 *puk, size_t puklen, const u8 *newpin, size_t newpinlen) { int r; sc_card_t *card; struct sc_pin_cmd_data data; struct sc_pkcs15_object *puk_obj; struct sc_pkcs15_auth_info *puk_info = NULL; struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data; if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) return SC_ERROR_NOT_SUPPORTED; /* make sure the pins are in valid range */ if ((r = _validate_pin(p15card, auth_info, newpinlen)) != SC_SUCCESS) return r; card = p15card->card; if (so_pin_obj) { puk_info = (struct sc_pkcs15_auth_info *)so_pin_obj->data; } else { /* get pin_info object of the puk (this is a little bit complicated * as we don't have the id of the puk (at least now)) * note: for compatibility reasons we give no error if no puk object * is found */ /* first step: try to get the pkcs15 object of the puk */ r = sc_pkcs15_find_pin_by_auth_id(p15card, &pin_obj->auth_id, &puk_obj); if (r >= 0 && puk_obj) { /* second step: get the pkcs15 info object of the puk */ puk_info = (struct sc_pkcs15_auth_info *)puk_obj->data; } if (!puk_info) { sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unable to get puk object, using pin object instead!"); puk_info = auth_info; } } /* make sure the puk is in valid range */ if ((r = _validate_pin(p15card, puk_info, puklen)) != SC_SUCCESS) return r; r = sc_lock(card); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed"); /* the path in the pin object is optional */ if (auth_info->path.len > 0) { r = sc_select_file(card, &auth_info->path, NULL); if (r) goto out; } /* set pin_cmd data */ memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_UNBLOCK; data.pin_type = SC_AC_CHV; data.pin_reference = auth_info->attrs.pin.reference; data.so_pin_reference= puk_info->attrs.pin.reference; data.pin1.data = puk; data.pin1.len = puklen; data.pin1.pad_char = auth_info->attrs.pin.pad_char; data.pin1.min_length = auth_info->attrs.pin.min_length; data.pin1.max_length = auth_info->attrs.pin.max_length; data.pin1.pad_length = auth_info->attrs.pin.stored_length; data.pin2.data = newpin; data.pin2.len = newpinlen; data.pin2.pad_char = puk_info->attrs.pin.pad_char; data.pin2.min_length = puk_info->attrs.pin.min_length; data.pin2.max_length = puk_info->attrs.pin.max_length; data.pin2.pad_length = puk_info->attrs.pin.stored_length; if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING) data.flags |= SC_PIN_CMD_NEED_PADDING; switch (auth_info->attrs.pin.type) { case SC_PKCS15_PIN_TYPE_BCD: data.pin1.encoding = SC_PIN_ENCODING_BCD; break; case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: data.pin1.encoding = SC_PIN_ENCODING_ASCII; break; } switch (puk_info->attrs.pin.type) { case SC_PKCS15_PIN_TYPE_BCD: data.pin2.encoding = SC_PIN_ENCODING_BCD; break; case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: data.pin2.encoding = SC_PIN_ENCODING_ASCII; break; } if(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) { data.flags |= SC_PIN_CMD_USE_PINPAD; if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) { data.pin1.prompt = "Please enter PUK"; data.pin2.prompt = "Please enter new SO PIN"; } else { data.pin1.prompt = "Please enter PUK"; data.pin2.prompt = "Please enter new PIN"; } } r = sc_pin_cmd(card, &data, &auth_info->tries_left); if (r == SC_SUCCESS) sc_pkcs15_pincache_add(p15card, pin_obj, newpin, newpinlen); out: sc_unlock(card); return r; }
/* * Verify a PIN. * * If the code given to us has zero length, this means we * should ask the card reader to obtain the PIN from the * reader's PIN pad */ int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pin_obj, const unsigned char *pincode, size_t pinlen) { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data; int r; sc_card_t *card; struct sc_pin_cmd_data data; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "PIN(%p;len:%i)", pincode, pinlen); /* TODO: verify other authentication objects */ if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) return SC_ERROR_NOT_SUPPORTED; r = _validate_pin(p15card, auth_info, pinlen); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "PIN value do not conforms the PIN policy"); card = p15card->card; r = sc_lock(card); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed"); /* the path in the pin object is optional */ if (auth_info->path.len > 0) { r = sc_select_file(card, &auth_info->path, NULL); if (r) goto out; } /* Initialize arguments */ memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_VERIFY; data.pin_type = auth_info->auth_method; data.pin_reference = auth_info->attrs.pin.reference; data.pin1.min_length = auth_info->attrs.pin.min_length; data.pin1.max_length = auth_info->attrs.pin.max_length; data.pin1.pad_length = auth_info->attrs.pin.stored_length; data.pin1.pad_char = auth_info->attrs.pin.pad_char; data.pin1.data = pincode; data.pin1.len = pinlen; if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING) data.flags |= SC_PIN_CMD_NEED_PADDING; switch (auth_info->attrs.pin.type) { case SC_PKCS15_PIN_TYPE_BCD: data.pin1.encoding = SC_PIN_ENCODING_BCD; break; case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: data.pin1.encoding = SC_PIN_ENCODING_ASCII; break; default: /* assume/hope the card driver knows how to encode the pin */ data.pin1.encoding = 0; } if(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) { if (!pincode && !pinlen) data.flags |= SC_PIN_CMD_USE_PINPAD; if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) data.pin1.prompt = "Please enter SO PIN"; else data.pin1.prompt = "Please enter PIN"; } r = sc_pin_cmd(card, &data, &auth_info->tries_left); if (r == SC_SUCCESS) sc_pkcs15_pincache_add(p15card, pin_obj, pincode, pinlen); out: sc_unlock(card); SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, r); }
/* * Change a PIN. */ int sc_pkcs15_change_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pin_obj, const u8 *oldpin, size_t oldpinlen, const u8 *newpin, size_t newpinlen) { int r; sc_card_t *card; struct sc_pin_cmd_data data; struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data; if (auth_info->auth_type != SC_PKCS15_PIN_AUTH_TYPE_PIN) return SC_ERROR_NOT_SUPPORTED; /* make sure the pins are in valid range */ if ((r = _validate_pin(p15card, auth_info, oldpinlen)) != SC_SUCCESS) return r; if ((r = _validate_pin(p15card, auth_info, newpinlen)) != SC_SUCCESS) return r; card = p15card->card; r = sc_lock(card); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed"); /* the path in the pin object is optional */ if (auth_info->path.len > 0) { r = sc_select_file(card, &auth_info->path, NULL); if (r) goto out; } /* set pin_cmd data */ memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_CHANGE; data.pin_type = SC_AC_CHV; data.pin_reference = auth_info->attrs.pin.reference; data.pin1.data = oldpin; data.pin1.len = oldpinlen; data.pin1.pad_char = auth_info->attrs.pin.pad_char; data.pin1.min_length = auth_info->attrs.pin.min_length; data.pin1.max_length = auth_info->attrs.pin.max_length; data.pin1.pad_length = auth_info->attrs.pin.stored_length; data.pin2.data = newpin; data.pin2.len = newpinlen; data.pin2.pad_char = auth_info->attrs.pin.pad_char; data.pin2.min_length = auth_info->attrs.pin.min_length; data.pin2.max_length = auth_info->attrs.pin.max_length; data.pin2.pad_length = auth_info->attrs.pin.stored_length; if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING) data.flags |= SC_PIN_CMD_NEED_PADDING; switch (auth_info->attrs.pin.type) { case SC_PKCS15_PIN_TYPE_BCD: data.pin1.encoding = SC_PIN_ENCODING_BCD; data.pin2.encoding = SC_PIN_ENCODING_BCD; break; case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: data.pin1.encoding = SC_PIN_ENCODING_ASCII; data.pin2.encoding = SC_PIN_ENCODING_ASCII; break; } if((!oldpin || !newpin) && p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) { data.flags |= SC_PIN_CMD_USE_PINPAD; if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) { data.pin1.prompt = "Please enter SO PIN"; data.pin2.prompt = "Please enter new SO PIN"; } else { data.pin1.prompt = "Please enter PIN"; data.pin2.prompt = "Please enter new PIN"; } } r = sc_pin_cmd(card, &data, &auth_info->tries_left); if (r == SC_SUCCESS) sc_pkcs15_pincache_add(p15card, pin_obj, newpin, newpinlen); out: sc_unlock(card); return r; }
static void print_info(sc_card_t *card, sc_file_t *file) { int r, tries_left; struct sc_pin_cmd_data data; sc_cardctl_sc_hsm_dkek_t dkekinfo; u8 major, minor, opt; major = file->prop_attr[file->prop_attr_len - 2]; minor = file->prop_attr[file->prop_attr_len - 1]; printf("Version : %d.%d\n", (int)major, (int)minor); if (file->prop_attr_len > 2) { /* Version >= 2.0 */ opt = file->prop_attr[file->prop_attr_len - 4]; if (opt != 0) { printf("Config options :\n"); if (opt & INIT_RRC_ENABLED) { printf(" User PIN reset with SO-PIN enabled\n"); } if (opt & INIT_TRANSPORT_PIN) { printf(" Transport-PIN mode enabled\n"); } } /* Try to update SO-PIN info from card */ memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_GET_INFO; data.pin_type = SC_AC_CHV; data.pin_reference = ID_SO_PIN; r = sc_pin_cmd(card, &data, &tries_left); if (r == SC_ERROR_DATA_OBJECT_NOT_FOUND) { printf("SmartCard-HSM has never been initialized. Please use --initialize to set SO-PIN and user PIN.\n"); } else { if (tries_left == 0) { printf("SO-PIN locked\n"); } else { printf("SO-PIN tries left : %d\n", tries_left); } /* Try to update PIN info from card */ memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_GET_INFO; data.pin_type = SC_AC_CHV; data.pin_reference = ID_USER_PIN; r = sc_pin_cmd(card, &data, &tries_left); if (r == SC_ERROR_CARD_CMD_FAILED) { printf("Public key authentication active.\n"); } else if (r == SC_ERROR_REF_DATA_NOT_USABLE) { printf("Transport-PIN active. Please change to user selected PIN first.\n"); } else { if (tries_left == 0) { printf("User PIN locked\n"); } else { printf("User PIN tries left : %d\n", tries_left); } } } } else { /* Version < 2.0 */ /* Try to update PIN info from card */ memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_GET_INFO; data.pin_type = SC_AC_CHV; data.pin_reference = ID_USER_PIN; r = sc_pin_cmd(card, &data, &tries_left); if (r == SC_ERROR_REF_DATA_NOT_USABLE) { printf("SmartCard-HSM has never been initialized. Please use --initialize to set SO-PIN and user PIN.\n"); } else { if (tries_left == 0) { printf("User PIN locked\n"); } else { printf("User PIN tries left : %d\n", tries_left); } } } memset(&dkekinfo, 0, sizeof(dkekinfo)); r = sc_card_ctl(card, SC_CARDCTL_SC_HSM_IMPORT_DKEK_SHARE, (void *)&dkekinfo); if (r == SC_ERROR_INS_NOT_SUPPORTED) { // Not supported or not initialized for key shares return; } if (r < 0) { fprintf(stderr, "sc_card_ctl(*, SC_CARDCTL_SC_HSM_IMPORT_DKEK_SHARE, *) failed with %s\n", sc_strerror(r)); } print_dkek_info(&dkekinfo); }
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; }
/* * Verify a PIN. * * If the code given to us has zero length, this means we * should ask the card reader to obtain the PIN from the * reader's PIN pad */ int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pin_obj, const unsigned char *pincode, size_t pinlen) { struct sc_context *ctx = p15card->card->ctx; struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *)pin_obj->data; int r; sc_card_t *card; struct sc_pin_cmd_data data; LOG_FUNC_CALLED(ctx); sc_log(ctx, "PIN(type:%X;method:%X;len:)", auth_info->auth_type, auth_info->auth_method, pinlen); if (pinlen > SC_MAX_PIN_SIZE) LOG_TEST_RET(ctx, SC_ERROR_INVALID_PIN_LENGTH, "Invalid PIN size"); card = p15card->card; /* Initialize arguments */ memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_VERIFY; data.pin_type = auth_info->auth_method; if (auth_info->auth_type == SC_PKCS15_PIN_AUTH_TYPE_PIN) { data.pin_reference = auth_info->attrs.pin.reference; data.pin1.min_length = auth_info->attrs.pin.min_length; data.pin1.max_length = auth_info->attrs.pin.max_length; data.pin1.pad_length = auth_info->attrs.pin.stored_length; data.pin1.pad_char = auth_info->attrs.pin.pad_char; data.pin1.data = pincode; data.pin1.len = pinlen; if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING) data.flags |= SC_PIN_CMD_NEED_PADDING; switch (auth_info->attrs.pin.type) { case SC_PKCS15_PIN_TYPE_BCD: data.pin1.encoding = SC_PIN_ENCODING_BCD; break; case SC_PKCS15_PIN_TYPE_ASCII_NUMERIC: data.pin1.encoding = SC_PIN_ENCODING_ASCII; break; default: /* assume/hope the card driver knows how to encode the pin */ data.pin1.encoding = 0; } } else if (auth_info->auth_type == SC_PKCS15_PIN_AUTH_TYPE_AUTH_KEY) { struct sc_pkcs15_object *skey_obj = NULL; struct sc_pkcs15_id *skey_id = &auth_info->attrs.authkey.skey_id; struct sc_pkcs15_skey_info *skey_info = NULL; r = sc_pkcs15_find_skey_by_id(p15card, skey_id, &skey_obj); if (r) { sc_log(ctx, "cannot find secret key with id:%s", sc_pkcs15_print_id(skey_id)); LOG_FUNC_RETURN(ctx, r); } skey_info = (struct sc_pkcs15_skey_info *)skey_obj->data; sc_log(ctx, "found secret key '%s'", skey_obj->label); data.pin_reference = skey_info->key_reference; } if(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) { if (!pincode && !pinlen) data.flags |= SC_PIN_CMD_USE_PINPAD; if (auth_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN) data.pin1.prompt = "Please enter SO PIN"; else data.pin1.prompt = "Please enter PIN"; } r = sc_lock(card); LOG_TEST_RET(ctx, r, "sc_lock() failed"); /* the path in the pin object is optional */ if ((auth_info->path.len > 0) || ((auth_info->path.aid.len > 0))) { r = sc_select_file(card, &auth_info->path, NULL); if (r) goto out; } r = sc_pin_cmd(card, &data, &auth_info->tries_left); sc_log(ctx, "PIN cmd result %i", r); if (r == SC_SUCCESS) sc_pkcs15_pincache_add(p15card, pin_obj, pincode, pinlen); out: sc_unlock(card); LOG_FUNC_RETURN(ctx, r); }
static int sc_pkcs15emu_pteid_init(sc_pkcs15_card_t * p15card) { u8 buf[1024]; sc_pkcs15_df_t *df; sc_pkcs15_object_t *p15_obj; sc_path_t path; struct sc_file *file = NULL; size_t len; int rv; int i; sc_context_t *ctx = p15card->card->ctx; LOG_FUNC_CALLED(ctx); /* Check for correct card atr */ if (pteid_detect_card(p15card->card) != SC_SUCCESS) return SC_ERROR_WRONG_CARD; sc_log(p15card->card->ctx, "Selecting application DF"); sc_format_path("4F00", &path); rv = sc_select_file(p15card->card, &path, &file); if (rv != SC_SUCCESS || !file) return SC_ERROR_INTERNAL; /* set the application DF */ if (p15card->file_app) free(p15card->file_app); p15card->file_app = file; /* Load TokenInfo */ len = sizeof(buf); rv = dump_ef(p15card->card, "4F005032", buf, &len); if (rv != SC_SUCCESS) { sc_log(ctx, "Reading of EF.TOKENINFO failed: %d", rv); LOG_FUNC_RETURN(ctx, rv); } memset(p15card->tokeninfo, 0, sizeof(*p15card->tokeninfo)); rv = sc_pkcs15_parse_tokeninfo(p15card->card->ctx, p15card->tokeninfo, buf, len); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.TOKENINFO failed: %d", rv); LOG_FUNC_RETURN(ctx, rv); } p15card->tokeninfo->flags |= SC_PKCS15_TOKEN_PRN_GENERATION | SC_PKCS15_TOKEN_EID_COMPLIANT | SC_PKCS15_TOKEN_READONLY; /* Load ODF */ len = sizeof(buf); rv = dump_ef(p15card->card, "4F005031", buf, &len); if (rv != SC_SUCCESS) { sc_log(ctx, "Reading of ODF failed: %d", rv); LOG_FUNC_RETURN(ctx, rv); } rv = parse_odf(buf, len, p15card); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of ODF failed: %d", rv); LOG_FUNC_RETURN(ctx, rv); } /* Decode EF.PrKDF, EF.PuKDF, EF.CDF and EF.AODF */ for (df = p15card->df_list; df != NULL; df = df->next) { if (df->type == SC_PKCS15_PRKDF) { rv = sc_pkcs15_parse_df(p15card, df); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.PrKDF (%s) failed: %d", sc_print_path(&df->path), rv); } } if (df->type == SC_PKCS15_PUKDF) { rv = sc_pkcs15_parse_df(p15card, df); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.PuKDF (%s) failed: %d", sc_print_path(&df->path), rv); } } if (df->type == SC_PKCS15_CDF) { rv = sc_pkcs15_parse_df(p15card, df); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.CDF (%s) failed: %d", sc_print_path(&df->path), rv); } } if (df->type == SC_PKCS15_AODF) { rv = sc_pkcs15_parse_df(p15card, df); if (rv != SC_SUCCESS) { sc_log(ctx, "Decoding of EF.AODF (%s) failed: %d", sc_print_path(&df->path), rv); } } } p15_obj = p15card->obj_list; while (p15_obj != NULL) { if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_PRKDF) ) { struct sc_pkcs15_prkey_info *prkey_info = (sc_pkcs15_prkey_info_t *) p15_obj->data; prkey_info->access_flags = SC_PKCS15_PRKEY_ACCESS_SENSITIVE | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE | SC_PKCS15_PRKEY_ACCESS_LOCAL; p15_obj->flags = SC_PKCS15_CO_FLAG_PRIVATE; } if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_AODF) ) { static const char *pteid_pin_names[3] = { "Auth PIN", "Sign PIN", "Address PIN" }; struct sc_pin_cmd_data pin_cmd_data; struct sc_pkcs15_auth_info *pin_info = (sc_pkcs15_auth_info_t *) p15_obj->data; strlcpy(p15_obj->label, pteid_pin_names[pin_info->auth_id.value[0]-1], sizeof(p15_obj->label)); pin_info->attrs.pin.flags |= SC_PKCS15_PIN_FLAG_NEEDS_PADDING; pin_info->tries_left = -1; pin_info->max_tries = 3; pin_info->auth_method = SC_AC_CHV; memset(&pin_cmd_data, 0, sizeof(pin_cmd_data)); pin_cmd_data.cmd = SC_PIN_CMD_GET_INFO; pin_cmd_data.pin_type = pin_info->attrs.pin.type; pin_cmd_data.pin_reference = pin_info->attrs.pin.reference; rv = sc_pin_cmd(p15card->card, &pin_cmd_data, NULL); if (rv == SC_SUCCESS) { pin_info->tries_left = pin_cmd_data.pin1.tries_left; } } /* Remove found public keys as cannot be read_binary()'d */ if ( p15_obj->df && (p15_obj->df->type == SC_PKCS15_PUKDF) ) { sc_pkcs15_object_t *puk = p15_obj; p15_obj = p15_obj->next; sc_pkcs15_remove_object(p15card, puk); sc_pkcs15_free_object(puk); } else { p15_obj = p15_obj->next; } } /* Add data objects */ for (i = 0; i < 5; i++) { static const char *object_ids[5] = {"1", "2", "3", "4", "5"}; static const char *object_labels[5] = { "Citizen Data", "Citizen Address Data", "Citizen Notepad", "SOD", "TRACE", }; static const char *object_authids[5] = {NULL, "3", NULL, NULL, NULL}; static const char *object_paths[5] = { "3f005f00ef02", "3f005f00ef05", "3f005f00ef07", "3f005f00ef06", "3F000003", }; static const int object_flags[5] = { 0, SC_PKCS15_CO_FLAG_PRIVATE, 0, 0, 0, }; struct sc_pkcs15_data_info obj_info; struct sc_pkcs15_object obj_obj; memset(&obj_info, 0, sizeof(obj_info)); memset(&obj_obj, 0, sizeof(obj_obj)); sc_pkcs15_format_id(object_ids[i], &obj_info.id); sc_format_path(object_paths[i], &obj_info.path); strlcpy(obj_info.app_label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE); if (object_authids[i] != NULL) sc_pkcs15_format_id(object_authids[i], &obj_obj.auth_id); strlcpy(obj_obj.label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE); obj_obj.flags = object_flags[i]; rv = sc_pkcs15emu_object_add(p15card, SC_PKCS15_TYPE_DATA_OBJECT, &obj_obj, &obj_info); if (rv != SC_SUCCESS){ sc_log(ctx, "Object add failed: %d", rv); break; } } LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
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 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; }
static int do_verify(int argc, char **argv) { struct { const char * name; int type; } typeNames[] = { { "CHV", SC_AC_CHV }, { "KEY", SC_AC_AUT }, { "AUT", SC_AC_AUT }, { "PRO", SC_AC_PRO }, { NULL, SC_AC_NONE } }; int r, tries_left = -1; u8 buf[64]; const char *s; 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].name; i++) { if (strncasecmp(argv[0], typeNames[i].name, 3) == 0) { data.pin_type = typeNames[i].type; 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->slot[0].capabilities & SC_SLOT_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 if (argv[1][0] == '"') { for (s=argv[1]+1, i=0; i < sizeof(buf) && *s && *s != '"';i++) buf[i] = *s++; data.pin1.data = buf; data.pin1.len = i; } else { r = sc_hex_to_bin(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> [<key in hex>]\n"); printf("Possible values of <key type>:\n"); for (i = 0; typeNames[i].name; i++) printf("\t%s\n", typeNames[i].name); 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; }