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; }
/* Validate the PIN code associated with an object */ int sc_pkcs15_pincache_revalidate(struct sc_pkcs15_card *p15card, const sc_pkcs15_object_t *obj) { struct sc_context *ctx = p15card->card->ctx; sc_pkcs15_object_t *pin_obj; int r; LOG_FUNC_CALLED(ctx); if (!p15card->opts.use_pin_cache) return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; /* Apps that do not support CK_ALWAYS_AUTHENTICATE * may need pin_cache_ignore_user_consent = 1 */ if (!p15card->opts.pin_cache_ignore_user_consent) { if (obj->user_consent) return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; } if (p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; r = sc_pkcs15_find_pin_by_auth_id(p15card, &obj->auth_id, &pin_obj); if (r != SC_SUCCESS) { sc_log(ctx, "Could not find pin object for auth_id %s", sc_pkcs15_print_id(&obj->auth_id)); return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; } if (pin_obj->usage_counter >= p15card->opts.pin_cache_counter) { sc_pkcs15_free_object_content(pin_obj); return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; } if (!pin_obj->content.value || !pin_obj->content.len) return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; pin_obj->usage_counter++; r = sc_pkcs15_verify_pin(p15card, pin_obj, pin_obj->content.value, pin_obj->content.len); if (r != SC_SUCCESS) { /* Ensure that wrong PIN isn't used again */ sc_pkcs15_free_object_content(pin_obj); sc_log(ctx, "Verify PIN error %i", r); return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; } LOG_FUNC_RETURN(ctx, SC_SUCCESS); }
/* Validate the PIN code associated with an object */ int sc_pkcs15_pincache_revalidate(struct sc_pkcs15_card *p15card, const sc_pkcs15_object_t *obj) { struct sc_context *ctx = p15card->card->ctx; sc_pkcs15_object_t *pin_obj; int r; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL); if (!p15card->opts.use_pin_cache) return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; if (obj->user_consent) return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; if (p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; r = sc_pkcs15_find_pin_by_auth_id(p15card, &obj->auth_id, &pin_obj); if (r != SC_SUCCESS) { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Could not find pin object for auth_id %s", sc_pkcs15_print_id(&obj->auth_id)); return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; } if (pin_obj->usage_counter >= p15card->opts.pin_cache_counter) { sc_pkcs15_free_object_content(pin_obj); return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; } if (!pin_obj->content.value || !pin_obj->content.len) return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; pin_obj->usage_counter++; r = sc_pkcs15_verify_pin(p15card, pin_obj, pin_obj->content.value, pin_obj->content.len); if (r != SC_SUCCESS) { /* Ensure that wrong PIN isn't used again */ sc_pkcs15_free_object_content(pin_obj); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Verify PIN error %i", r); return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; } SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS); }
static int ask_and_verify_pin(struct sc_pkcs15_object *pin_obj) { struct sc_pkcs15_auth_info *pin_info = (struct sc_pkcs15_auth_info *) pin_obj->data; int i = 0; char prompt[(sizeof pin_obj->label) + 30]; u8 *pass; if (pin_info->attrs.pin.flags & SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN) { printf("Skipping unblocking pin [%.*s]\n", (int) sizeof pin_obj->label, pin_obj->label); return 0; } snprintf(prompt, sizeof(prompt), "Please enter PIN code [%.*s]: ", (int) sizeof pin_obj->label, pin_obj->label); pass = (u8 *) getpass(prompt); if (SC_SUCCESS != sc_lock(card)) return 1; i = sc_pkcs15_verify_pin(p15card, pin_obj, pass, strlen((char *) pass)); if (SC_SUCCESS != sc_unlock(card)) return 1; if (i) { if (i == SC_ERROR_PIN_CODE_INCORRECT) fprintf(stderr, "Incorrect PIN code (%d tries left)\n", pin_info->tries_left); else fprintf(stderr, "PIN verifying failed: %s\n", sc_strerror(i)); return 1; } else printf("PIN code correct.\n"); return 0; }
int ask_and_verify_pin_code(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *pin) { int r; size_t len; const char *argv[3]; const char *pgmname = PIN_ENTRY; ASSUAN_CONTEXT ctx; char buf[500]; char errtext[100]; struct entry_parm_s parm; struct sc_pkcs15_pin_info *pinfo = (struct sc_pkcs15_pin_info *) pin->data; argv[0] = pgmname; argv[1] = NULL; r = assuan_pipe_connect(&ctx, pgmname, (char **) argv, NULL); if (r) { printf("Can't connect to the PIN entry module: %s\n", assuan_strerror((AssuanError) r)); goto err; } sprintf(buf, "SETDESC Enter PIN [%s] for digital signing ", pin->label); r = assuan_transact(ctx, buf, NULL, NULL, NULL, NULL, NULL, NULL); if (r) { printf("SETDESC: %s\n", assuan_strerror((AssuanError) r)); goto err; } errtext[0] = 0; while (1) { if (errtext[0]) { sprintf(buf, "SETERROR %s", errtext); r = assuan_transact(ctx, buf, NULL, NULL, NULL, NULL, NULL, NULL); errtext[0] = 0; } parm.lines = 0; parm.size = sizeof(buf); parm.buffer = buf; r = assuan_transact(ctx, "GETPIN", getpin_cb, &parm, NULL, NULL, NULL, NULL); if (r == ASSUAN_Canceled) { assuan_disconnect(ctx); return -2; } if (r) { printf("GETPIN: %s\n", assuan_strerror((AssuanError) r)); goto err; } len = strlen(buf); if (len < pinfo->min_length) { sprintf(errtext, "PIN code too short, min. %lu digits", (unsigned long) pinfo->min_length); continue; } if (len > pinfo->max_length) { sprintf(errtext, "PIN code too long, max. %lu digits", (unsigned long) pinfo->max_length); continue; } r = sc_pkcs15_verify_pin(p15card, pinfo, (const u8 *) buf, strlen(buf)); switch (r) { case SC_ERROR_PIN_CODE_INCORRECT: sprintf(errtext, "PIN code incorrect (%d %s left)", pinfo->tries_left, pinfo->tries_left == 1 ? "try" : "tries"); break; case 0: break; default: goto err; } if (r == 0) break; } assuan_disconnect(ctx); return 0; err: assuan_disconnect(ctx); return -1; }
static int sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path, unsigned char **out, size_t *out_len, int verify_pin) { struct sc_context *ctx = p15card->card->ctx; struct sc_card *card = p15card->card; struct sc_file *file = NULL; struct sc_path path; size_t sz; int rv; SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE); if (!in_path || !out || !out_len) SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS, "Cannot read oberthur file"); sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "read file '%s'; verify_pin:%i", in_path, verify_pin); *out = NULL; *out_len = 0; sc_format_path(in_path, &path); rv = sc_select_file(card, &path, &file); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "Cannot select oberthur file to read"); if (file->ef_structure == SC_FILE_EF_TRANSPARENT) sz = file->size; else sz = (file->record_length + 2) * file->record_count; *out = calloc(sz, 1); if (*out == NULL) SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_MEMORY_FAILURE, "Cannot read oberthur file"); if (file->ef_structure == SC_FILE_EF_TRANSPARENT) { rv = sc_read_binary(card, 0, *out, sz, 0); } else { int rec; int offs = 0; int rec_len = file->record_length; for (rec = 1; ; rec++) { rv = sc_read_record(card, rec, *out + offs + 2, rec_len, SC_RECORD_BY_REC_NR); if (rv == SC_ERROR_RECORD_NOT_FOUND) { rv = 0; break; } else if (rv < 0) { break; } rec_len = rv; *(*out + offs) = 'R'; *(*out + offs + 1) = rv; offs += rv + 2; } sz = offs; } sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "read oberthur file result %i", rv); if (verify_pin && rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) { struct sc_pkcs15_object *objs[0x10], *pin_obj = NULL; const struct sc_acl_entry *acl = sc_file_get_acl_entry(file, SC_AC_OP_READ); int ii; rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 0x10); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, rv, "Cannot read oberthur file: get AUTH objects error"); for (ii=0; ii<rv; ii++) { struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *) objs[ii]->data; sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "compare PIN/ACL refs:%i/%i, method:%i/%i", auth_info->attrs.pin.reference, acl->key_ref, auth_info->auth_method, acl->method); if (auth_info->attrs.pin.reference == (int)acl->key_ref && auth_info->auth_method == (unsigned)acl->method) { pin_obj = objs[ii]; break; } } if (!pin_obj || !pin_obj->content.value) { rv = SC_ERROR_SECURITY_STATUS_NOT_SATISFIED; } else { rv = sc_pkcs15_verify_pin(p15card, pin_obj, pin_obj->content.value, pin_obj->content.len); if (!rv) rv = sc_oberthur_read_file(p15card, in_path, out, out_len, 0); } }; sc_file_free(file); if (rv < 0) { free(*out); *out = NULL; *out_len = 0; } *out_len = sz; SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, rv); }
static int get_key(unsigned int usage, sc_pkcs15_object_t **result) { sc_pkcs15_object_t *key, *pin; const char *usage_name; sc_pkcs15_id_t id; int r; usage_name = (usage & SC_PKCS15_PRKEY_USAGE_SIGN)? "signature" : "decryption"; if (opt_key_id != NULL) { sc_pkcs15_hex_string_to_id(opt_key_id, &id); r = sc_pkcs15_find_prkey_by_id_usage(p15card, &id, usage, &key); if (r < 0) { fprintf(stderr, "Unable to find private %s key '%s': %s\n", usage_name, opt_key_id, sc_strerror(r)); return 2; } } else { r = sc_pkcs15_find_prkey_by_id_usage(p15card, NULL, usage, &key); if (r < 0) { fprintf(stderr, "Unable to find any private %s key: %s\n", usage_name, sc_strerror(r)); return 2; } } *result = key; if (key->auth_id.len) { static sc_pkcs15_object_t *prev_pin = NULL; char *pincode; r = sc_pkcs15_find_pin_by_auth_id(p15card, &key->auth_id, &pin); if (r) { fprintf(stderr, "Unable to find PIN code for private key: %s\n", sc_strerror(r)); return 1; } /* Pin already verified previously */ if (pin == prev_pin) return 0; pincode = get_pin(pin); if (((pincode == NULL || *pincode == '\0')) && !(p15card->card->reader->capabilities & SC_READER_CAP_PIN_PAD)) return 5; r = sc_pkcs15_verify_pin(p15card, pin, (const u8 *)pincode, pincode ? strlen(pincode) : 0); if (r) { fprintf(stderr, "PIN code verification failed: %s\n", sc_strerror(r)); return 5; } free(pincode); if (verbose) fprintf(stderr, "PIN code correct.\n"); prev_pin = pin; } return 0; }
static int sc_prkey_op_init(RSA *rsa, struct sc_pkcs15_object **key_obj_out, unsigned int usage) { int r; struct sc_priv_data *priv; struct sc_pkcs15_object *key_obj; struct sc_pkcs15_prkey_info *key; struct sc_pkcs15_object *pin_obj; struct sc_pkcs15_pin_info *pin; priv = (struct sc_priv_data *) RSA_get_app_data(rsa); if (priv == NULL) return -1; if (p15card == NULL) { sc_close(); r = sc_init(); if (r) { error("SmartCard init failed: %s", sc_strerror(r)); goto err; } } r = sc_pkcs15_find_prkey_by_id_usage(p15card, &priv->cert_id, usage, &key_obj); if (r) { error("Unable to find private key from SmartCard: %s", sc_strerror(r)); goto err; } key = key_obj->data; r = sc_pkcs15_find_pin_by_auth_id(p15card, &key_obj->auth_id, &pin_obj); if (r == SC_ERROR_OBJECT_NOT_FOUND) { /* no pin required */ r = sc_lock(card); if (r) { error("Unable to lock smartcard: %s", sc_strerror(r)); goto err; } *key_obj_out = key_obj; return 0; } else if (r) { error("Unable to find PIN object from SmartCard: %s", sc_strerror(r)); goto err; } pin = pin_obj->data; r = sc_lock(card); if (r) { error("Unable to lock smartcard: %s", sc_strerror(r)); goto err; } if (sc_pin != NULL) { r = sc_pkcs15_verify_pin(p15card, pin, sc_pin, strlen(sc_pin)); if (r) { sc_unlock(card); error("PIN code verification failed: %s", sc_strerror(r)); goto err; } } *key_obj_out = key_obj; return 0; err: sc_close(); return -1; }