int sc_update_binary(sc_card_t *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) { size_t max_lc = sc_get_max_send_size(card); int r; if (card == NULL || card->ops == NULL || buf == NULL) { return SC_ERROR_INVALID_ARGUMENTS; } sc_log(card->ctx, "called; %"SC_FORMAT_LEN_SIZE_T"u bytes at index %d", count, idx); if (count == 0) return 0; #ifdef ENABLE_SM if (card->sm_ctx.ops.update_binary) { r = card->sm_ctx.ops.update_binary(card, idx, buf, count); if (r) LOG_FUNC_RETURN(card->ctx, r); } #endif if (card->ops->update_binary == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); if (count > max_lc) { int bytes_written = 0; const u8 *p = buf; r = sc_lock(card); LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); while (count > 0) { size_t n = count > max_lc? max_lc : count; r = sc_update_binary(card, idx, p, n, flags); if (r < 0) { sc_unlock(card); LOG_TEST_RET(card->ctx, r, "sc_update_binary() failed"); } p += r; idx += r; bytes_written += r; count -= r; if (r == 0) { sc_unlock(card); LOG_FUNC_RETURN(card->ctx, bytes_written); } } sc_unlock(card); LOG_FUNC_RETURN(card->ctx, bytes_written); } r = card->ops->update_binary(card, idx, buf, count, flags); LOG_FUNC_RETURN(card->ctx, r); }
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); }
int sc_update_binary(sc_card_t *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) { size_t max_lc = card->max_send_size; int r; assert(card != NULL && card->ops != NULL && buf != NULL); sc_log(card->ctx, "called; %d bytes at index %d", count, idx); if (count == 0) return 0; #ifdef ENABLE_SM if (card->sm_ctx.ops.update_binary) { r = card->sm_ctx.ops.update_binary(card, idx, buf, count); if (r) LOG_FUNC_RETURN(card->ctx, r); } #endif if (card->ops->update_binary == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); if (count > max_lc) { int bytes_written = 0; const u8 *p = buf; r = sc_lock(card); LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); while (count > 0) { size_t n = count > max_lc? max_lc : count; r = sc_update_binary(card, idx, p, n, flags); if (r < 0) { sc_unlock(card); LOG_TEST_RET(card->ctx, r, "sc_update_binary() failed"); } p += r; idx += r; bytes_written += r; count -= r; if (r == 0) { sc_unlock(card); LOG_FUNC_RETURN(card->ctx, bytes_written); } } sc_unlock(card); LOG_FUNC_RETURN(card->ctx, bytes_written); } r = card->ops->update_binary(card, idx, buf, count, flags); LOG_FUNC_RETURN(card->ctx, r); }
int sc_read_binary(sc_card_t *card, unsigned int idx, unsigned char *buf, size_t count, unsigned long flags) { size_t max_le = sc_get_max_recv_size(card); int r; assert(card != NULL && card->ops != NULL && buf != NULL); sc_log(card->ctx, "called; %d bytes at index %d", count, idx); if (count == 0) return 0; #ifdef ENABLE_SM if (card->sm_ctx.ops.read_binary) { r = card->sm_ctx.ops.read_binary(card, idx, buf, count); if (r) LOG_FUNC_RETURN(card->ctx, r); } #endif if (card->ops->read_binary == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); if (count > max_le) { int bytes_read = 0; unsigned char *p = buf; r = sc_lock(card); LOG_TEST_RET(card->ctx, r, "sc_lock() failed"); while (count > 0) { size_t n = count > max_le ? max_le : count; r = sc_read_binary(card, idx, p, n, flags); if (r < 0) { sc_unlock(card); LOG_TEST_RET(card->ctx, r, "sc_read_binary() failed"); } p += r; idx += r; bytes_read += r; count -= r; if (r == 0) { sc_unlock(card); LOG_FUNC_RETURN(card->ctx, bytes_read); } } sc_unlock(card); LOG_FUNC_RETURN(card->ctx, bytes_read); } r = card->ops->read_binary(card, idx, buf, count, flags); LOG_FUNC_RETURN(card->ctx, r); }
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; }
/* Close a card and release all resources */ void card_close (CARD card) { if (card) { #ifdef HAVE_OPENSC if (card->p15card) { sc_pkcs15_unbind (card->p15card); card->p15card = NULL; } if (card->p15priv) p15_release_private_data (card); if (card->scard) { sc_unlock (card->scard); sc_disconnect_card (card->scard, 0); card->scard = NULL; } if (card->ctx) { sc_release_context (card->ctx); card->ctx = NULL; } #endif xfree (card); } }
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; }
void *thread_pop(void * camera){ camera_t *cam=(camera_t *)camera; sc_frame_t *f; int count=0; zbfp=fopen("zbzb.yuv","wb"); slogi("pop "); while(!cam->stopflag){ if(count==0){ sc_lock(&cam->q->mutex); slogi("wait for signal"); pthread_cond_wait(&cam->q->cond,&cam->q->mutex);/*等待*/ slogi("wake up"); sc_unlock(&cam->q->mutex); } count++; int ret=queue_popfront(cam->q,&f); if(ret==0 && f!=NULL){ // slogi("pop ok delete it"); if(zbfp) { yuv_write(f->data, f->len, zbfp); // sc_write_onebyone(f->data, f->len, count); }else{ slogi("#####zbzb.yuv open fail#####"); } delete_frame(f);} if(ret==QEMPTY_POPFAIL || ret==QGNEL_FAIL ){//宁愿popfail,也不能让push数据放不进去而丢帧 usleep(300); } } }
static void die(int ret) { if (card) { sc_unlock(card); sc_disconnect_card(card, 0); } if (ctx) sc_release_context(ctx); exit(ret); }
static void die(int ret) { sc_file_free(current_file); if (card) { sc_unlock(card); sc_disconnect_card(card); } if (ctx) sc_release_context(ctx); exit(ret); }
int sc_update_binary(sc_card_t *card, unsigned int idx, const u8 *buf, size_t count, unsigned long flags) { size_t max_lc = card->max_send_size > 0 ? card->max_send_size : 255; int r; assert(card != NULL && card->ops != NULL && buf != NULL); sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "called; %d bytes at index %d\n", count, idx); if (count == 0) return 0; if (card->ops->update_binary == NULL) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED); if (count > max_lc) { int bytes_written = 0; const u8 *p = buf; r = sc_lock(card); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed"); while (count > 0) { size_t n = count > max_lc? max_lc : count; r = sc_update_binary(card, idx, p, n, flags); if (r < 0) { sc_unlock(card); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_update_binary() failed"); } p += r; idx += r; bytes_written += r; count -= r; if (r == 0) { sc_unlock(card); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, bytes_written); } } sc_unlock(card); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, bytes_written); } r = card->ops->update_binary(card, idx, buf, count, flags); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); }
int main(int argc, char *argv[]) { struct sc_pkcs15_object **objs = NULL; int i, count; i = sc_test_init(&argc, argv); if (i < 0) return 1; if (card->reader->capabilities & SC_READER_CAP_PIN_PAD) printf("Slot is capable of doing pinpad operations!\n"); printf("Looking for a PKCS#15 compatible Smart Card... "); fflush(stdout); if (SC_SUCCESS != sc_lock(card)) return 1; i = sc_pkcs15_bind(card, NULL, &p15card); if (SC_SUCCESS != sc_unlock(card)) return 1; if (i) { fprintf(stderr, "failed: %s\n", sc_strerror(i)); sc_test_cleanup(); return 1; } printf("found.\n"); printf("Enumerating PIN codes...\n"); if (SC_SUCCESS != sc_lock(card)) return 1; count = enum_pins(&objs); if (SC_SUCCESS != sc_unlock(card)) return 1; if (count < 0) { sc_pkcs15_unbind(p15card); sc_test_cleanup(); return 1; } for (i = 0; i < count; i++) { ask_and_verify_pin(objs[i]); } sc_pkcs15_unbind(p15card); sc_test_cleanup(); return 0; }
int sc_get_challenge(sc_card_t *card, u8 *rnd, size_t len) { int r; size_t retry = 10; if (len == 0) return SC_SUCCESS; if (card == NULL || rnd == NULL) { return SC_ERROR_INVALID_ARGUMENTS; } LOG_FUNC_CALLED(card->ctx); if (card->ops == NULL || card->ops->get_challenge == NULL) LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); r = sc_lock(card); if (r != SC_SUCCESS) LOG_FUNC_RETURN(card->ctx, r); while (len > 0 && retry > 0) { r = card->ops->get_challenge(card, rnd, len); if (r < 0) { sc_unlock(card); LOG_FUNC_RETURN(card->ctx, r); } if (r > 0) { rnd += (size_t) r; len -= (size_t) r; } else { retry--; } } sc_unlock(card); LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); }
int sc_read_binary(sc_card_t *card, unsigned int idx, unsigned char *buf, size_t count, unsigned long flags) { size_t max_le = card->max_recv_size > 0 ? card->max_recv_size : 256; int r; assert(card != NULL && card->ops != NULL && buf != NULL); sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "called; %d bytes at index %d", count, idx); if (count == 0) return 0; if (card->ops->read_binary == NULL) SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED); if (count > max_le) { int bytes_read = 0; unsigned char *p = buf; r = sc_lock(card); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed"); while (count > 0) { size_t n = count > max_le ? max_le : count; r = sc_read_binary(card, idx, p, n, flags); if (r < 0) { sc_unlock(card); SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_read_binary() failed"); } p += r; idx += r; bytes_read += r; count -= r; if (r == 0) { sc_unlock(card); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, bytes_read); } } sc_unlock(card); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, bytes_read); } r = card->ops->read_binary(card, idx, buf, count, flags); SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r); }
static int dump_objects(const char *what, int type) { struct sc_pkcs15_object **objs; int count, i; printf("\nEnumerating %s... ", what); fflush(stdout); sc_lock(card); count = sc_pkcs15_get_objects(p15card, type, NULL, 0); if (count < 0) { printf("failed.\n"); fprintf(stderr, "Error enumerating %s: %s\n", what, sc_strerror(count)); sc_unlock(card); return 1; } if (count == 0) { printf("none found.\n"); sc_unlock(card); return 0; } printf("%u found.\n", count); objs = (struct sc_pkcs15_object **) calloc(count, sizeof(*objs)); if ((count = sc_pkcs15_get_objects(p15card, type, objs, count)) < 0) { fprintf(stderr, "Error enumerating %s: %s\n", what, sc_strerror(count)); } else { for (i = 0; i < count; i++) sc_test_print_object(objs[i]); } free(objs); sc_unlock(card); return (count < 0) ? 1 : 0; }
void sc_process_image(const void *buf, int size,int cmd,camera_t *camera) { switch(cmd){ case CMD_OUT_FILE: { frame_number++; sc_write_onebyone(buf,size,frame_number); } break; case CMD_OUT_BUF: { sc_frame_t *f=new_frame(size); /* The memcpy() function returns a pointer to dest.*/ memcpy(f->data,buf,size); f->len=size; sc_queue_t *q=camera->q; int ret=queue_pushback(q, f); if(ret==QGNEL_FAIL || ret==QFULL_PUSHFAIL){ sleep(1);slogi("sleep for full"); // usleep(500); } #if 1 if(count==0){ sc_lock(&q->mutex); count=count+1; slogi("signal"); pthread_cond_signal(&q->cond);/*条件改变,发送信号,通知t_b进程*/ sc_unlock(&q->mutex); } #endif break; } default: printf("process image"); } }
static int sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding) { struct sc_pkcs15_object *key_obj; int r; if (padding != RSA_PKCS1_PADDING) return -1; r = sc_prkey_op_init(rsa, &key_obj, SC_USAGE_DECRYPT); if (r) return -1; r = sc_pkcs15_decipher(p15card, key_obj, SC_ALGORITHM_RSA_PAD_PKCS1, from, flen, to, flen); sc_unlock(card); if (r < 0) { error("sc_pkcs15_decipher() failed: %s", sc_strerror(r)); goto err; } return r; err: sc_close(); return -1; }
static int sc_sign(int type, u_char *m, unsigned int m_len, unsigned char *sigret, unsigned int *siglen, RSA *rsa) { struct sc_pkcs15_object *key_obj; int r; unsigned long flags = 0; /* XXX: sc_prkey_op_init will search for a pkcs15 private * key object with the sign or signrecover usage flag set. * If the signing key has only the non-repudiation flag set * the key will be rejected as using a non-repudiation key * for authentication is not recommended. Note: This does not * prevent the use of a non-repudiation key for authentication * if the sign or signrecover flag is set as well. */ r = sc_prkey_op_init(rsa, &key_obj, SC_USAGE_SIGN); if (r) return -1; /* FIXME: length of sigret correct? */ /* FIXME: check 'type' and modify flags accordingly */ flags = SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_SHA1; r = sc_pkcs15_compute_signature(p15card, key_obj, flags, m, m_len, sigret, RSA_size(rsa)); sc_unlock(card); if (r < 0) { error("sc_pkcs15_compute_signature() failed: %s", sc_strerror(r)); goto err; } *siglen = r; return 1; err: sc_close(); return 0; }
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; }
/* * 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_pin_info *pin_info = (struct sc_pkcs15_pin_info *)pin_obj->data; /* make sure the pins are in valid range */ if ((r = _validate_pin(p15card, pin_info, oldpinlen)) != SC_SUCCESS) return r; if ((r = _validate_pin(p15card, pin_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 (pin_info->path.len > 0) { r = sc_select_file(card, &pin_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 = pin_info->reference; data.pin1.data = oldpin; data.pin1.len = oldpinlen; data.pin1.pad_char = pin_info->pad_char; data.pin1.min_length = pin_info->min_length; data.pin1.max_length = pin_info->max_length; data.pin1.pad_length = pin_info->stored_length; data.pin2.data = newpin; data.pin2.len = newpinlen; data.pin2.pad_char = pin_info->pad_char; data.pin2.min_length = pin_info->min_length; data.pin2.max_length = pin_info->max_length; data.pin2.pad_length = pin_info->stored_length; if (pin_info->flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING) data.flags |= SC_PIN_CMD_NEED_PADDING; switch (pin_info->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 (pin_info->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, &pin_info->tries_left); if (r == SC_SUCCESS) sc_pkcs15_pincache_add(p15card, pin_obj, newpin, newpinlen); out: sc_unlock(card); return r; }
int main(int argc, char * const argv[]) { int err = 0, r, c, long_optind = 0; int action_count = 0; int do_initialize = 0; int do_import_dkek_share = 0; int do_create_dkek_share = 0; int do_wrap_key = 0; int do_unwrap_key = 0; sc_path_t path; sc_file_t *file = NULL; const char *opt_so_pin = NULL; const char *opt_pin = NULL; const char *opt_filename = NULL; char *opt_password = NULL; int opt_retry_counter = 3; int opt_dkek_shares = -1; int opt_key_reference = -1; int opt_password_shares_threshold = -1; int opt_password_shares_total = -1; int opt_force = 0; int opt_iter = 10000000; sc_context_param_t ctx_param; setbuf(stderr, NULL); setbuf(stdout, NULL); while (1) { c = getopt_long(argc, argv, "XC:I:W:U:s:i:fr:wv", options, &long_optind); if (c == -1) break; if (c == '?') util_print_usage_and_die(app_name, options, option_help, NULL); switch (c) { case 'X': do_initialize = 1; action_count++; break; case 'C': do_create_dkek_share = 1; opt_filename = optarg; action_count++; break; case 'I': do_import_dkek_share = 1; opt_filename = optarg; action_count++; break; case 'W': do_wrap_key = 1; opt_filename = optarg; action_count++; break; case 'U': do_unwrap_key = 1; opt_filename = optarg; action_count++; break; case OPT_PASSWORD: opt_password = optarg; break; case OPT_SO_PIN: opt_so_pin = optarg; break; case OPT_PIN: opt_pin = optarg; break; case OPT_RETRY: opt_retry_counter = atol(optarg); break; case OPT_PASSWORD_SHARES_THRESHOLD: opt_password_shares_threshold = atol(optarg); break; case OPT_PASSWORD_SHARES_TOTAL: opt_password_shares_total = atol(optarg); break; case 's': opt_dkek_shares = atol(optarg); break; case 'f': opt_force = 1; break; case 'i': opt_key_reference = atol(optarg); break; case 'r': opt_reader = optarg; break; case 'v': verbose++; break; case 'w': opt_wait = 1; break; } } CRYPTO_malloc_init(); ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); 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"); } err = util_connect_card(ctx, &card, opt_reader, opt_wait, verbose); if (r != SC_SUCCESS) { fprintf(stderr, "Failed to connect to card: %s\n", sc_strerror(r)); goto end; } sc_path_set(&path, SC_PATH_TYPE_DF_NAME, sc_hsm_aid.value, sc_hsm_aid.len, 0, 0); r = sc_select_file(card, &path, &file); if (r != SC_SUCCESS) { fprintf(stderr, "Failed to select application: %s\n", sc_strerror(r)); goto end; } if (do_initialize) { initialize(card, opt_so_pin, opt_pin, opt_retry_counter, opt_dkek_shares); } if (do_create_dkek_share) { create_dkek_share(card, opt_filename, opt_iter, opt_password, opt_password_shares_threshold, opt_password_shares_total); } if (do_import_dkek_share) { import_dkek_share(card, opt_filename, opt_iter, opt_password, opt_password_shares_total); } if (do_wrap_key) { wrap_key(card, opt_key_reference, opt_filename, opt_pin); } if (do_unwrap_key) { unwrap_key(card, opt_key_reference, opt_filename, opt_pin, opt_force); } if (action_count == 0) { print_info(card, file); } end: if (card) { sc_unlock(card); sc_disconnect_card(card); } if (ctx) sc_release_context(ctx); ERR_print_errors_fp(stderr); return err; }
int main(int argc, char * const argv[]) { int err = 0, r, c, long_optind = 0; int do_list_readers = 0; int do_list_drivers = 0; int do_list_rdrivers = 0; int do_list_files = 0; int do_send_apdu = 0; int do_print_atr = 0; int do_print_serial = 0; int do_print_name = 0; int action_count = 0; const char *opt_driver = NULL; sc_context_param_t ctx_param; setbuf(stderr, NULL); setbuf(stdout, NULL); while (1) { c = getopt_long(argc, argv, "nlfr:vs:DRc:aw", options, &long_optind); if (c == -1) break; if (c == '?') print_usage_and_die(app_name, options, option_help); switch (c) { case 'l': do_list_readers = 1; action_count++; break; case 'D': do_list_drivers = 1; action_count++; break; case 'R': do_list_rdrivers = 1; action_count++; break; case 'f': do_list_files = 1; action_count++; break; case 's': opt_apdus = (char **) realloc(opt_apdus, (opt_apdu_count + 1) * sizeof(char *)); opt_apdus[opt_apdu_count] = optarg; do_send_apdu++; if (opt_apdu_count == 0) action_count++; opt_apdu_count++; break; case 'a': do_print_atr = 1; action_count++; break; case 'n': do_print_name = 1; action_count++; break; case 'r': opt_reader = atoi(optarg); break; case 'v': verbose++; break; case 'c': opt_driver = optarg; break; case 'w': opt_wait = 1; break; case OPT_SERIAL: do_print_serial = 1; action_count++; break; } } if (action_count == 0) print_usage_and_die(app_name, options, option_help); 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-1; if (do_list_rdrivers) { if ((err = list_reader_drivers())) goto end; action_count--; } if (do_list_readers) { if ((err = list_readers())) goto end; action_count--; } if (do_list_drivers) { if ((err = list_drivers())) goto end; action_count--; } if (action_count <= 0) goto end; if (opt_driver != NULL) { err = sc_set_card_driver(ctx, opt_driver); if (err) { fprintf(stderr, "Driver '%s' not found!\n", opt_driver); err = 1; goto end; } } err = connect_card(ctx, &card, opt_reader, 0, opt_wait, verbose); if (err) goto end; if (do_print_atr) { if (verbose) { printf("Card ATR:\n"); hex_dump_asc(stdout, card->atr, card->atr_len, -1); } else { char tmp[SC_MAX_ATR_SIZE*3]; sc_bin_to_hex(card->atr, card->atr_len, tmp, sizeof(tmp) - 1, ':'); fprintf(stdout,"%s\n",tmp); } action_count--; } if (do_print_serial) { if (verbose) printf("Card serial number:"); print_serial(card); action_count--; } if (do_print_name) { if (verbose) printf("Card name: "); printf("%s\n", card->name); action_count--; } if (do_send_apdu) { if ((err = send_apdu())) goto end; action_count--; } if (do_list_files) { if ((err = list_files())) goto end; action_count--; } end: if (card) { sc_unlock(card); sc_disconnect_card(card, 0); } if (ctx) sc_release_context(ctx); return err; }
int main(int argc, char *argv[]) { int i, c, r, cnt = 3, freq[39]; struct timeval tv1, tv2; u8 buf[14]; i = sc_test_init(&argc, argv); for (i = 0; i < 39; i++) freq[i] = 0; c = 0; while (cnt) { u8 nbuf[39]; for (i = 0; i < 39; i++) { nbuf[i] = i + 1; } if (c == 0) gettimeofday(&tv1, NULL); sc_lock(card); r = sc_get_challenge(card, buf, 14); sc_unlock(card); if (r == 0) { int left = 39; printf("Lottery: "); for (i = 0; i < 7; i++) { unsigned short s = buf[2 * i] + (buf[2 * i + 1] << 8); int lot = s % (left + 1); int num = nbuf[lot]; nbuf[lot] = nbuf[left - 1]; left--; freq[num - 1]++; printf("%3d ", num); } printf("\n"); } else { fprintf(stderr, "sc_get_challenge() failed: %s\n", sc_strerror(r)); sc_test_cleanup(); return 1; } c++; if (c == 50) { unsigned long long foo, foo2; gettimeofday(&tv2, NULL); foo = tv2.tv_sec * 1000 + tv2.tv_usec / 1000; foo2 = tv1.tv_sec * 1000 + tv1.tv_usec / 1000; printf("Time per one: %lld ms\n", (foo - foo2) / 50); printf("Frequencies:\n"); for (i = 0; i < 39; i++) { printf("%3d: %-5d", i + 1, freq[i]); if (((i + 1) % 10) == 0) printf("\n"); } printf("\n"); c = 0; cnt--; } } sc_test_cleanup(); return 0; }
LIBOPENSC_API int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_object *obj, unsigned long flags, const u8 * in, size_t inlen, u8 *out, size_t outlen) { sc_context_t *ctx = p15card->card->ctx; int r; sc_algorithm_info_t *alg_info; sc_security_env_t senv; const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data; unsigned long pad_flags = 0, sec_flags = 0; LOG_FUNC_CALLED(ctx); memset(&senv, 0, sizeof(senv)); /* Card driver should have the access to supported algorithms from 'tokenInfo'. So that * it can get value of card specific 'AlgorithmInfo::algRef'. */ memcpy(&senv.supported_algos, &p15card->tokeninfo->supported_algos, sizeof(senv.supported_algos)); /* If the key is not native, we can't operate with it. */ if (!prkey->native) LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "This key is not native, cannot operate with it"); if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_DECRYPT|SC_PKCS15_PRKEY_USAGE_UNWRAP))) LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for decryption"); switch (obj->type) { case SC_PKCS15_TYPE_PRKEY_RSA: alg_info = sc_card_find_rsa_alg(p15card->card, prkey->modulus_length); if (alg_info == NULL) { sc_log(ctx, "Card does not support RSA with key length %d", prkey->modulus_length); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } senv.algorithm = SC_ALGORITHM_RSA; break; case SC_PKCS15_TYPE_PRKEY_GOSTR3410: alg_info = sc_card_find_gostr3410_alg(p15card->card, prkey->modulus_length); if (alg_info == NULL) { sc_log(ctx, "Card does not support GOSTR3410 with key length %d", prkey->modulus_length); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } senv.algorithm = SC_ALGORITHM_GOSTR3410; break; default: LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED,"Key type not supported"); } r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags); LOG_TEST_RET(ctx, r, "cannot encode security operation flags"); senv.algorithm_flags = sec_flags; senv.operation = SC_SEC_OPERATION_DECIPHER; senv.flags = 0; /* optional keyReference attribute (the default value is -1) */ if (prkey->key_reference >= 0) { senv.key_ref_len = 1; senv.key_ref[0] = prkey->key_reference & 0xFF; senv.flags |= SC_SEC_ENV_KEY_REF_PRESENT; } senv.flags |= SC_SEC_ENV_ALG_PRESENT; r = sc_lock(p15card->card); LOG_TEST_RET(ctx, r, "sc_lock() failed"); if (prkey->path.len != 0 || prkey->path.aid.len != 0) { r = select_key_file(p15card, prkey, &senv); if (r < 0) { sc_unlock(p15card->card); LOG_TEST_RET(ctx, r,"Unable to select private key file"); } } r = sc_set_security_env(p15card->card, &senv, 0); if (r < 0) { sc_unlock(p15card->card); LOG_TEST_RET(ctx, r, "sc_set_security_env() failed"); } r = sc_decipher(p15card->card, in, inlen, out, outlen); if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) { if (sc_pkcs15_pincache_revalidate(p15card, obj) == SC_SUCCESS) r = sc_decipher(p15card->card, in, inlen, out, outlen); } sc_unlock(p15card->card); LOG_TEST_RET(ctx, r, "sc_decipher() failed"); /* Strip any padding */ if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { size_t s = r; r = sc_pkcs1_strip_02_padding(out, s, out, &s); LOG_TEST_RET(ctx, r, "Invalid PKCS#1 padding"); } LOG_FUNC_RETURN(ctx, r); }
LIBOPENSC_API int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_object *obj, unsigned long flags, const u8 *in, size_t inlen, u8 *out, size_t outlen) { sc_context_t *ctx = p15card->card->ctx; int r; sc_security_env_t senv; sc_algorithm_info_t *alg_info; const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data; u8 buf[1024], *tmp; size_t modlen; unsigned long pad_flags = 0, sec_flags = 0; LOG_FUNC_CALLED(ctx); sc_log(ctx, "security operation flags 0x%X", flags); memset(&senv, 0, sizeof(senv)); /* Card driver should have the access to supported algorithms from 'tokenInfo'. So that * it can get value of card specific 'AlgorithmInfo::algRef'. */ memcpy(&senv.supported_algos, &p15card->tokeninfo->supported_algos, sizeof(senv.supported_algos)); if ((obj->type & SC_PKCS15_TYPE_CLASS_MASK) != SC_PKCS15_TYPE_PRKEY) LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This is not a private key"); /* If the key is not native, we can't operate with it. */ if (!prkey->native) LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "This key is not native, cannot operate with it"); if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER| SC_PKCS15_PRKEY_USAGE_NONREPUDIATION))) LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for signing"); switch (obj->type) { case SC_PKCS15_TYPE_PRKEY_RSA: modlen = prkey->modulus_length / 8; alg_info = sc_card_find_rsa_alg(p15card->card, prkey->modulus_length); if (alg_info == NULL) { sc_log(ctx, "Card does not support RSA with key length %d", prkey->modulus_length); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } senv.flags |= SC_SEC_ENV_ALG_PRESENT; senv.algorithm = SC_ALGORITHM_RSA; break; case SC_PKCS15_TYPE_PRKEY_GOSTR3410: modlen = (prkey->modulus_length + 7) / 8 * 2; alg_info = sc_card_find_gostr3410_alg(p15card->card, prkey->modulus_length); if (alg_info == NULL) { sc_log(ctx, "Card does not support GOSTR3410 with key length %d", prkey->modulus_length); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } senv.flags |= SC_SEC_ENV_ALG_PRESENT; senv.algorithm = SC_ALGORITHM_GOSTR3410; break; case SC_PKCS15_TYPE_PRKEY_EC: modlen = ((prkey->field_length +7) / 8) * 2; /* 2*nLen */ alg_info = sc_card_find_ec_alg(p15card->card, prkey->field_length); if (alg_info == NULL) { sc_log(ctx, "Card does not support EC with field_size %d", prkey->field_length); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } senv.algorithm = SC_ALGORITHM_EC; senv.flags |= SC_SEC_ENV_ALG_PRESENT; senv.flags |= SC_SEC_ENV_ALG_REF_PRESENT; senv.algorithm_ref = prkey->field_length; break; /* add other crypto types here */ default: LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Key type not supported"); } /* Probably never happens, but better make sure */ if (inlen > sizeof(buf) || outlen < modlen) LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL); memcpy(buf, in, inlen); /* revert data to sign when signing with the GOST key. * TODO: can it be confirmed by the GOST standard? * TODO: tested with RuTokenECP, has to be validated for RuToken. */ if (obj->type == SC_PKCS15_TYPE_PRKEY_GOSTR3410) sc_mem_reverse(buf, inlen); tmp = buf; /* flags: the requested algo * algo_info->flags: what is supported by the card * senv.algorithm_flags: what the card will have to do */ /* if the card has SC_ALGORITHM_NEED_USAGE set, and the key is for signing and decryption, we need to emulate signing */ /* TODO: -DEE assume only RSA keys will ever use _NEED_USAGE */ sc_log(ctx, "supported algorithm flags 0x%X, private key usage 0x%X", alg_info->flags, prkey->usage); if ((alg_info->flags & SC_ALGORITHM_NEED_USAGE) && ((prkey->usage & USAGE_ANY_SIGN) && (prkey->usage & USAGE_ANY_DECIPHER)) ) { size_t tmplen = sizeof(buf); if (flags & SC_ALGORITHM_RSA_RAW) { r = sc_pkcs15_decipher(p15card, obj,flags, in, inlen, out, outlen); LOG_FUNC_RETURN(ctx, r); } if (modlen > tmplen) LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "Buffer too small, needs recompile!"); r = sc_pkcs1_encode(ctx, flags, in, inlen, buf, &tmplen, modlen); /* no padding needed - already done */ flags &= ~SC_ALGORITHM_RSA_PADS; /* instead use raw rsa */ flags |= SC_ALGORITHM_RSA_RAW; LOG_TEST_RET(ctx, r, "Unable to add padding"); r = sc_pkcs15_decipher(p15card, obj,flags, buf, modlen, out, outlen); LOG_FUNC_RETURN(ctx, r); } /* If the card doesn't support the requested algorithm, see if we * can strip the input so a more restrictive algo can be used */ if ((flags == (SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE)) && !(alg_info->flags & (SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_NONE))) { unsigned int algo; size_t tmplen = sizeof(buf); r = sc_pkcs1_strip_digest_info_prefix(&algo, tmp, inlen, tmp, &tmplen); if (r != SC_SUCCESS || algo == SC_ALGORITHM_RSA_HASH_NONE) { sc_mem_clear(buf, sizeof(buf)); LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); } flags &= ~SC_ALGORITHM_RSA_HASH_NONE; flags |= algo; inlen = tmplen; } r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags); if (r != SC_SUCCESS) { sc_mem_clear(buf, sizeof(buf)); LOG_FUNC_RETURN(ctx, r); } senv.algorithm_flags = sec_flags; sc_log(ctx, "DEE flags:0x%8.8x alg_info->flags:0x%8.8x pad:0x%8.8x sec:0x%8.8x", flags, alg_info->flags, pad_flags, sec_flags); /* add the padding bytes (if necessary) */ if (pad_flags != 0) { size_t tmplen = sizeof(buf); r = sc_pkcs1_encode(ctx, pad_flags, tmp, inlen, tmp, &tmplen, modlen); SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Unable to add padding"); inlen = tmplen; } else if ( senv.algorithm == SC_ALGORITHM_RSA && (flags & SC_ALGORITHM_RSA_PADS) == SC_ALGORITHM_RSA_PAD_NONE) { /* Add zero-padding if input is shorter than the modulus */ if (inlen < modlen) { if (modlen > sizeof(buf)) return SC_ERROR_BUFFER_TOO_SMALL; memmove(tmp+modlen-inlen, tmp, inlen); memset(tmp, 0, modlen-inlen); } inlen = modlen; } senv.operation = SC_SEC_OPERATION_SIGN; /* optional keyReference attribute (the default value is -1) */ if (prkey->key_reference >= 0) { senv.key_ref_len = 1; senv.key_ref[0] = prkey->key_reference & 0xFF; senv.flags |= SC_SEC_ENV_KEY_REF_PRESENT; } r = sc_lock(p15card->card); LOG_TEST_RET(ctx, r, "sc_lock() failed"); sc_log(ctx, "Private key path '%s'", sc_print_path(&prkey->path)); if (prkey->path.len != 0 || prkey->path.aid.len != 0) { r = select_key_file(p15card, prkey, &senv); if (r < 0) { sc_unlock(p15card->card); LOG_TEST_RET(ctx, r,"Unable to select private key file"); } } r = sc_set_security_env(p15card->card, &senv, 0); if (r < 0) { sc_unlock(p15card->card); LOG_TEST_RET(ctx, r, "sc_set_security_env() failed"); } r = sc_compute_signature(p15card->card, tmp, inlen, out, outlen); if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) if (sc_pkcs15_pincache_revalidate(p15card, obj) == SC_SUCCESS) r = sc_compute_signature(p15card->card, tmp, inlen, out, outlen); sc_mem_clear(buf, sizeof(buf)); sc_unlock(p15card->card); LOG_TEST_RET(ctx, r, "sc_compute_signature() failed"); LOG_FUNC_RETURN(ctx, r); }
/* derive one key from another. RSA can use decipher, so this is for only ECDH * Since the value may be returned, and the call is expected to provide * the buffer, we used the PKCS#11 convention of outlen == 0 and out == NULL * to indicate that this is a request for the size. * In that case r = 0, and *poutlen = expected size */ LIBOPENSC_API int sc_pkcs15_derive(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_object *obj, unsigned long flags, const u8 * in, size_t inlen, u8 *out, unsigned long *poutlen) { sc_context_t *ctx = p15card->card->ctx; int r; sc_algorithm_info_t *alg_info; sc_security_env_t senv; const struct sc_pkcs15_prkey_info *prkey = (const struct sc_pkcs15_prkey_info *) obj->data; unsigned long pad_flags = 0, sec_flags = 0; LOG_FUNC_CALLED(ctx); memset(&senv, 0, sizeof(senv)); /* Card driver should have the access to supported algorithms from 'tokenInfo'. So that * it can get value of card specific 'AlgorithmInfo::algRef'. */ memcpy(&senv.supported_algos, &p15card->tokeninfo->supported_algos, sizeof(senv.supported_algos)); /* If the key is not native, we can't operate with it. */ if (!prkey->native) LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "This key is not native, cannot operate with it"); if (!(prkey->usage & (SC_PKCS15_PRKEY_USAGE_DERIVE))) LOG_TEST_RET(ctx, SC_ERROR_NOT_ALLOWED, "This key cannot be used for derivation"); switch (obj->type) { case SC_PKCS15_TYPE_PRKEY_EC: alg_info = sc_card_find_ec_alg(p15card->card, prkey->field_length); if (alg_info == NULL) { sc_log(ctx, "Card does not support EC with field_size %d", prkey->field_length); LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); } if (out == NULL || *poutlen < (prkey->field_length +7) / 8) { *poutlen = (prkey->field_length +7) / 8; r = 0; /* say no data to return */ goto out; } senv.algorithm = SC_ALGORITHM_EC; senv.flags |= SC_SEC_ENV_ALG_PRESENT; senv.flags |= SC_SEC_ENV_ALG_REF_PRESENT; senv.algorithm_ref = prkey->field_length; break; default: LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED,"Key type not supported"); } r = sc_get_encoding_flags(ctx, flags, alg_info->flags, &pad_flags, &sec_flags); LOG_TEST_RET(ctx, r, "cannot encode security operation flags"); senv.algorithm_flags = sec_flags; senv.operation = SC_SEC_OPERATION_DERIVE; /* optional keyReference attribute (the default value is -1) */ if (prkey->key_reference >= 0) { senv.key_ref_len = 1; senv.key_ref[0] = prkey->key_reference & 0xFF; senv.flags |= SC_SEC_ENV_KEY_REF_PRESENT; } r = sc_lock(p15card->card); LOG_TEST_RET(ctx, r, "sc_lock() failed"); if (prkey->path.len != 0 || prkey->path.aid.len != 0) { r = select_key_file(p15card, prkey, &senv); if (r < 0) { sc_unlock(p15card->card); LOG_TEST_RET(ctx, r,"Unable to select private key file"); } } r = sc_set_security_env(p15card->card, &senv, 0); if (r < 0) { sc_unlock(p15card->card); LOG_TEST_RET(ctx, r, "sc_set_security_env() failed"); } /* TODO Do we need a sc_derive? PIV at least can use the decipher, * senv.operation = SC_SEC_OPERATION_DERIVE; */ r = sc_decipher(p15card->card, in, inlen, out, *poutlen); if (r == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED) { if (sc_pkcs15_pincache_revalidate(p15card, obj) == SC_SUCCESS) r = sc_decipher(p15card->card, in, inlen, out, *poutlen); } sc_unlock(p15card->card); LOG_TEST_RET(ctx, r, "sc_decipher/derive() failed"); /* Strip any padding */ if (pad_flags & SC_ALGORITHM_RSA_PAD_PKCS1) { size_t s = r; r = sc_pkcs1_strip_02_padding(out, s, out, &s); LOG_TEST_RET(ctx, r, "Invalid PKCS#1 padding"); } /* If card stores derived key on card, then no data is returned * and the key must be used on the card. */ *poutlen = r; out: LOG_FUNC_RETURN(ctx, r); }
int main(int argc, char *const argv[]) { int err = 0, r, c, long_optind = 0; int do_info = 0; int do_format = 0; int do_change_startkey = 0; int action_count = 0; const char *opt_driver = NULL; const char *opt_startkey = NULL; const char *opt_change_startkey = NULL; sc_context_param_t ctx_param; while (1) { c = getopt_long(argc, argv, "hifs:r:vdc:wS:", options, &long_optind); if (c == -1) break; switch (c) { case 'h': printf("NB! This tool is only for Siemens CardOS based cards!\n\n"); util_print_usage_and_die(app_name, options, option_help); case 'i': do_info = 1; action_count++; break; case 'f': do_format = 1; action_count++; break; case 's': opt_startkey = optarg; break; case 'S': do_change_startkey = 1; opt_change_startkey = optarg; action_count++; break; case 'r': opt_reader = optarg; break; case 'v': verbose++; break; case 'c': opt_driver = optarg; break; case 'w': opt_wait = 1; break; } } /* create sc_context_t object */ 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; ctx->debug_file = stderr; } if (opt_driver != NULL) { err = sc_set_card_driver(ctx, opt_driver); if (err) { fprintf(stderr, "Driver '%s' not found!\n", opt_driver); err = 1; goto end; } } err = util_connect_card(ctx, &card, opt_reader, opt_wait, verbose); if (err) goto end; if (do_info) { if ((err = cardos_info())) { goto end; } action_count--; } if (do_change_startkey) { if ((err = cardos_change_startkey(opt_change_startkey))) { goto end; } action_count--; } if (do_format) { if ((err = cardos_format(opt_startkey))) { goto end; } action_count--; } end: if (card) { sc_unlock(card); sc_disconnect_card(card); } if (ctx) sc_release_context(ctx); return err; }
/* * 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_pin_info *pin_info = (struct sc_pkcs15_pin_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); r = _validate_pin(p15card, pin_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 (pin_info->path.len > 0) { r = sc_select_file(card, &pin_info->path, NULL); if (r) goto out; } /* Initialize arguments */ memset(&data, 0, sizeof(data)); data.cmd = SC_PIN_CMD_VERIFY; data.pin_type = pin_info->auth_method; data.pin_reference = pin_info->reference; data.pin1.min_length = pin_info->min_length; data.pin1.max_length = pin_info->max_length; data.pin1.pad_length = pin_info->stored_length; data.pin1.pad_char = pin_info->pad_char; data.pin1.data = pincode; data.pin1.len = pinlen; if (pin_info->flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING) data.flags |= SC_PIN_CMD_NEED_PADDING; switch (pin_info->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 (pin_info->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, &pin_info->tries_left); if (r == SC_SUCCESS) sc_pkcs15_pincache_add(p15card, pin_obj, pincode, pinlen); out: sc_unlock(card); return r; }
int sc_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu) { int r = SC_SUCCESS; if (card == NULL || apdu == NULL) return SC_ERROR_INVALID_ARGUMENTS; LOG_FUNC_CALLED(card->ctx); /* determine the APDU type if necessary, i.e. to use * short or extended APDUs */ sc_detect_apdu_cse(card, apdu); /* basic APDU consistency check */ r = sc_check_apdu(card, apdu); if (r != SC_SUCCESS) return SC_ERROR_INVALID_ARGUMENTS; r = sc_lock(card); /* acquire card lock*/ if (r != SC_SUCCESS) { sc_log(card->ctx, "unable to acquire lock"); return r; } if ((apdu->flags & SC_APDU_FLAGS_CHAINING) != 0) { /* divide et impera: transmit APDU in chunks with Lc <= max_send_size * bytes using command chaining */ size_t len = apdu->datalen; const u8 *buf = apdu->data; size_t max_send_size = card->max_send_size; while (len != 0) { size_t plen; sc_apdu_t tapdu; int last = 0; tapdu = *apdu; /* clear chaining flag */ tapdu.flags &= ~SC_APDU_FLAGS_CHAINING; if (len > max_send_size) { /* adjust APDU case: in case of CASE 4 APDU * the intermediate APDU are of CASE 3 */ if ((tapdu.cse & SC_APDU_SHORT_MASK) == SC_APDU_CASE_4_SHORT) tapdu.cse--; /* XXX: the chunk size must be adjusted when * secure messaging is used */ plen = max_send_size; tapdu.cla |= 0x10; tapdu.le = 0; /* the intermediate APDU don't expect data */ tapdu.lc = 0; tapdu.resplen = 0; tapdu.resp = NULL; } else { plen = len; last = 1; } tapdu.data = buf; tapdu.datalen = tapdu.lc = plen; r = sc_check_apdu(card, &tapdu); if (r != SC_SUCCESS) { sc_log(card->ctx, "inconsistent APDU while chaining"); break; } r = sc_transmit(card, &tapdu); if (r != SC_SUCCESS) break; if (last != 0) { /* in case of the last APDU set the SW1 * and SW2 bytes in the original APDU */ apdu->sw1 = tapdu.sw1; apdu->sw2 = tapdu.sw2; apdu->resplen = tapdu.resplen; } else { /* otherwise check the status bytes */ r = sc_check_sw(card, tapdu.sw1, tapdu.sw2); if (r != SC_SUCCESS) break; } len -= plen; buf += plen; } } else /* transmit single APDU */ r = sc_transmit(card, apdu); /* all done => release lock */ if (sc_unlock(card) != SC_SUCCESS) sc_log(card->ctx, "sc_unlock failed"); return r; }
/* * Unblock a PIN. */ int sc_pkcs15_unblock_pin(struct sc_pkcs15_card *p15card, 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_pin_info *puk_info = NULL; struct sc_pkcs15_pin_info *pin_info = (struct sc_pkcs15_pin_info *)pin_obj->data; /* make sure the pins are in valid range */ if ((r = _validate_pin(p15card, pin_info, newpinlen)) != SC_SUCCESS) return r; card = p15card->card; /* 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_pin_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 = pin_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 (pin_info->path.len > 0) { r = sc_select_file(card, &pin_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 = pin_info->reference; data.pin1.data = puk; data.pin1.len = puklen; data.pin1.pad_char = pin_info->pad_char; data.pin1.min_length = pin_info->min_length; data.pin1.max_length = pin_info->max_length; data.pin1.pad_length = pin_info->stored_length; data.pin2.data = newpin; data.pin2.len = newpinlen; data.pin2.pad_char = puk_info->pad_char; data.pin2.min_length = puk_info->min_length; data.pin2.max_length = puk_info->max_length; data.pin2.pad_length = puk_info->stored_length; if (pin_info->flags & SC_PKCS15_PIN_FLAG_NEEDS_PADDING) data.flags |= SC_PIN_CMD_NEED_PADDING; switch (pin_info->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->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 (pin_info->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, &pin_info->tries_left); if (r == SC_SUCCESS) sc_pkcs15_pincache_add(p15card, pin_obj, newpin, newpinlen); out: sc_unlock(card); return r; }