📄 pkcs15-init.c
字号:
/* * Initialize Cards according to PKCS#15. * * This is a fill in the blanks sort of exercise. You need a * profile that describes characteristics of your card, and the * application specific layout on the card. This program will * set up the card according to this specification (including * PIN initialization etc) and create the corresponding PKCS15 * structure. * * There are a very few tasks that are too card specific to have * a generic implementation; that is how PINs and keys are stored * on the card. These should be implemented in pkcs15-<cardname>.c * * Copyright (C) 2002, Olaf Kirch <okir@lst.de> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <ctype.h>#include <stdarg.h>#include <assert.h>#include <openssl/evp.h>#include <openssl/pem.h>#include <openssl/err.h>#include <openssl/rand.h>#include <openssl/rsa.h>#include <openssl/dsa.h>#include <openssl/bn.h>#include <openssl/pkcs12.h>#include <opensc/cardctl.h>#include <opensc/pkcs15.h>#include <opensc/pkcs15-init.h>#include "util.h"#undef GET_KEY_ECHO_OFFconst char *app_name = "pkcs15-init";/* Handle encoding of PKCS15 on the card */typedef int (*pkcs15_encoder)(struct sc_context *, struct sc_pkcs15_card *, u8 **, size_t *);/* Local functions */static int open_reader_and_card(int);static int do_assert_pristine(struct sc_card *);static int do_erase(struct sc_card *, struct sc_profile *);static int do_init_app(struct sc_profile *);static int do_store_pin(struct sc_profile *);static int do_generate_key(struct sc_profile *, const char *);static int do_store_private_key(struct sc_profile *);static int do_store_public_key(struct sc_profile *, EVP_PKEY *);static int do_store_certificate(struct sc_profile *);static int do_convert_private_key(struct sc_pkcs15_prkey *, EVP_PKEY *);static int do_convert_public_key(struct sc_pkcs15_pubkey *, EVP_PKEY *);static int do_convert_cert(sc_pkcs15_der_t *, X509 *);static int do_read_data_object(const char *name, u8 **out, size_t *outlen);static int do_store_data_object(struct sc_profile *profile);static void set_secrets(struct sc_profile *);static int init_keyargs(struct sc_pkcs15init_prkeyargs *);static int read_one_pin(struct sc_profile *, const char *, const struct sc_pkcs15_pin_info *, int, char **);static int get_pin_callback(struct sc_profile *profile, int id, const struct sc_pkcs15_pin_info *info, const char *label, u8 *pinbuf, size_t *pinsize);static int get_key_callback(struct sc_profile *, int method, int reference, const u8 *, size_t, u8 *, size_t *);static int do_generate_key_soft(int, unsigned int, EVP_PKEY **);static int do_read_private_key(const char *, const char *, EVP_PKEY **, X509 **, unsigned int);static int do_read_public_key(const char *, const char *, EVP_PKEY **);static int do_read_certificate(const char *, const char *, X509 **);static void parse_commandline(int argc, char **argv);static void read_options_file(const char *);static void ossl_print_errors(void);enum { OPT_OPTIONS = 0x100, OPT_PASSPHRASE, OPT_PUBKEY, OPT_EXTRACTABLE, OPT_UNPROTECTED, OPT_AUTHORITY, OPT_SOFT_KEYGEN, OPT_SPLIT_KEY, OPT_ASSERT_PRISTINE, OPT_SECRET, OPT_PIN1 = 0x10000, /* don't touch these values */ OPT_PUK1 = 0x10001, OPT_PIN2 = 0x10002, OPT_PUK2 = 0x10003, OPT_SERIAL = 0x10004, OPT_NO_SOPIN = 0x10005, OPT_NO_PROMPT= 0x10006,};const struct option options[] = { { "erase-card", no_argument, 0, 'E' }, { "create-pkcs15", no_argument, 0, 'C' }, { "store-pin", no_argument, 0, 'P' }, { "generate-key", required_argument, 0, 'G' }, { "store-private-key", required_argument, 0, 'S' }, { "store-public-key", required_argument, 0, OPT_PUBKEY }, { "store-certificate", required_argument, 0, 'X' }, { "store-data", required_argument, 0, 'W' }, { "reader", required_argument, 0, 'r' }, { "pin", required_argument, 0, OPT_PIN1 }, { "puk", required_argument, 0, OPT_PUK1 }, { "so-pin", required_argument, 0, OPT_PIN2 }, { "so-puk", required_argument, 0, OPT_PUK2 }, { "no-so-pin", no_argument, 0, OPT_NO_SOPIN }, { "serial", required_argument, 0, OPT_SERIAL }, { "auth-id", required_argument, 0, 'a' }, { "id", required_argument, 0, 'i' }, { "label", required_argument, 0, 'l' }, { "output-file", required_argument, 0, 'o' }, { "format", required_argument, 0, 'f' }, { "passphrase", required_argument, 0, OPT_PASSPHRASE }, { "authority", no_argument, 0, OPT_AUTHORITY }, { "key-usage", required_argument, 0, 'u' }, { "split-key", no_argument, 0, OPT_SPLIT_KEY }, { "extractable", no_argument, 0, OPT_EXTRACTABLE }, { "insecure", no_argument, 0, OPT_UNPROTECTED }, { "soft", no_argument, 0, OPT_SOFT_KEYGEN }, { "use-default-transport-keys", no_argument, 0, 'T' }, { "no-prompt", no_argument, 0, OPT_NO_PROMPT }, { "profile", required_argument, 0, 'p' }, { "card-profile", required_argument, 0, 'c' }, { "options-file", required_argument, 0, OPT_OPTIONS }, { "wait", no_argument, 0, 'w' }, { "debug", no_argument, 0, 'd' }, { "quiet", no_argument, 0, 'q' }, { "help", no_argument, 0, 'h' }, /* Hidden options for testing */ { "assert-pristine", no_argument, 0, OPT_ASSERT_PRISTINE }, { "secret", required_argument, 0, OPT_SECRET }, { 0, 0, 0, 0 }};const char * option_help[] = { "Erase the smart card (can be used with --create-pkcs15)", "Creates a new PKCS #15 structure", "Store a new PIN/PUK on the card", "Generate a new key and store it on the card", "Store private key", "Store public key", "Store an X.509 certificate", "Store a data object", "Specify which reader to use", "Specify PIN", "Specify unblock PIN", "Specify security officer (SO) PIN", "Specify unblock PIN for SO PIN", "Do not install a SO PIN, and dont prompt for it", "Specify the serial number of the card", "Specify ID of PIN to use/create", "Specify ID of key/certificate", "Specify label of PIN/key", "Output public portion of generated key to file", "Specify key file format (default PEM)", "Specify passphrase for unlocking secret key", "Mark certificate as a CA certificate", "Specify X.509 key usage (use \"--key-usage help\" for more information)", "Automatically create two keys with same ID and different usage (sign vs decipher)", "Private key stored as an extractable key", "Insecure mode: do not require PIN/passphrase for private key", "Use software key generation, even if the card supports on-board key generation", "Always ask for transport keys etc, even if the driver thinks it knows the key", "Do not prompt the user, except for PINs", "Specify the general profile to use", "Specify the card profile option to use", "Read additional command line options from file", "Wait for card insertion", "Enable debugging output", "Be less verbose", "Display this message", NULL, NULL,};enum { ACTION_NONE = 0, ACTION_ASSERT_PRISTINE, ACTION_ERASE, ACTION_INIT, ACTION_STORE_PIN, ACTION_GENERATE_KEY, ACTION_STORE_PRIVKEY, ACTION_STORE_PUBKEY, ACTION_STORE_CERT, ACTION_STORE_DATA, ACTION_MAX};static char * action_names[] = { "do nothing", "verify that card is pristine", "erase card", "create PKCS #15 meta structure", "store PIN", "generate key", "store private key", "store public key", "store certificate", "store data object"};/* Flags for read_one_pin */#define READ_PIN_OPTIONAL 0x01#define READ_PIN_RETYPE 0x02#define MAX_CERTS 4#define MAX_SECRETS 16struct secret { int type; int reference; sc_pkcs15_id_t id; unsigned char key[64]; size_t len;};static struct sc_context * ctx = NULL;static struct sc_card * card = NULL;static struct sc_pkcs15_card * p15card = NULL;static unsigned int opt_actions;static int opt_reader = -1, opt_debug = 0, opt_quiet = 0, opt_extractable = 0, opt_unprotected = 0, opt_authority = 0, opt_softkeygen = 0, opt_no_prompt = 0, opt_no_sopin = 0, opt_use_defkeys = 0, opt_split_key = 0, opt_wait = 0;static char * opt_profile = "pkcs15";static char * opt_card_profile = NULL;static char * opt_infile = 0;static char * opt_format = 0;static char * opt_authid = 0;static char * opt_objectid = 0;static char * opt_label = 0;static char * opt_pins[4];static char * opt_serial = 0;static char * opt_passphrase = 0;static char * opt_newkey = 0;static char * opt_outkey = 0;static unsigned int opt_x509_usage = 0;static int ignore_cmdline_pins = 0;static struct secret opt_secrets[MAX_SECRETS];static unsigned int opt_secret_count;static struct sc_pkcs15init_callbacks callbacks = { error, /* error() */ NULL, /* debug() */ get_pin_callback, /* get_pin() */ get_key_callback, /* get_key() */};intmain(int argc, char **argv){ struct sc_profile *profile; unsigned int n; int r = 0; /* OpenSSL magic */ SSLeay_add_all_algorithms(); CRYPTO_malloc_init();#ifdef RANDOM_POOL if (!RAND_load_file(RANDOM_POOL, 32)) fatal("Unable to seed random number pool for key generation");#endif parse_commandline(argc, argv); if (optind != argc) print_usage_and_die(); if (opt_actions == 0) { fprintf(stderr, "No action specified.\n"); print_usage_and_die(); } if (!opt_profile) { fprintf(stderr, "No profile specified.\n"); print_usage_and_die(); } /* Connect to the card */ if (!open_reader_and_card(opt_reader)) return 1; sc_pkcs15init_set_callbacks(&callbacks); /* Bind the card-specific operations and load the profile */ if ((r = sc_pkcs15init_bind(card, opt_profile, opt_card_profile, &profile)) < 0) return 1; set_secrets(profile); for (n = 0; n < ACTION_MAX; n++) { unsigned int action = n; if (!(opt_actions & (1 << action))) continue; if (action != ACTION_ERASE && action != ACTION_INIT && action != ACTION_ASSERT_PRISTINE && p15card == NULL) { /* Read the PKCS15 structure from the card */ r = sc_pkcs15_bind(card, &p15card); if (r) { fprintf(stderr, "PKCS#15 initialization failed: %s\n", sc_strerror(r)); break; } /* XXX: should compare card to profile here to make * sure we're not messing things up */ if (!opt_quiet) printf("Found %s\n", p15card->label); } if (!opt_quiet && action != ACTION_ASSERT_PRISTINE) printf("About to %s.\n", action_names[action]); switch (action) { case ACTION_ASSERT_PRISTINE: /* skip printing error message */ if ((r = do_assert_pristine(card)) < 0) goto out; continue; case ACTION_ERASE: r = do_erase(card, profile); break; case ACTION_INIT: r = do_init_app(profile); break; case ACTION_STORE_PIN: r = do_store_pin(profile); break; case ACTION_STORE_PRIVKEY: r = do_store_private_key(profile); break; case ACTION_STORE_PUBKEY: r = do_store_public_key(profile, NULL); break; case ACTION_STORE_CERT: r = do_store_certificate(profile); break; case ACTION_STORE_DATA: r = do_store_data_object(profile); break; case ACTION_GENERATE_KEY: r = do_generate_key(profile, opt_newkey); break; default: fatal("Action not yet implemented\n"); } if (r < 0) { fprintf(stderr, "Failed to %s: %s\n", action_names[action], sc_strerror(r)); break; } }out: if (card) { sc_unlock(card); sc_disconnect_card(card, 0); } sc_release_context(ctx); return r < 0? 1 : 0;}static intopen_reader_and_card(int reader){ int r; r = sc_establish_context(&ctx, app_name); if (r) { error("Failed to establish context: %s\n", sc_strerror(r)); return 0; } if (opt_debug) { ctx->debug = opt_debug; ctx->debug_file = stderr; } if (connect_card(ctx, &card, reader, 0, opt_wait, opt_quiet)) return 0; if (!opt_quiet) printf("Using card driver: %s\n", card->driver->name); r = sc_lock(card); if (r) { error("Unable to lock card: %s\n", sc_strerror(r)); return 0; } return 1;}/* * Make sure there's no pkcs15 structure on the card */static intdo_assert_pristine(struct sc_card *card){ sc_path_t path; int r, res = 0; card->ctx->log_errors = 0; sc_format_path("2F00", &path); if ((r = sc_select_file(card, &path, NULL)) >= 0 || r != SC_ERROR_FILE_NOT_FOUND) res = -1; sc_format_path("5015", &path); if ((r = sc_select_file(card, &path, NULL)) >= 0 || r != SC_ERROR_FILE_NOT_FOUND) res = -1; card->ctx->log_errors = 1; if (res < 0) { fprintf(stderr, "Card not pristine; detected (possibly incomplete) " "PKCS#15 structure\n"); } else if (!opt_quiet) { printf("Pristine card.\n"); } return res;}/* * Erase card */static intdo_erase(struct sc_card *card, struct sc_profile *profile){ int r; ignore_cmdline_pins++; r = sc_pkcs15init_erase_card(card, profile); ignore_cmdline_pins--; return r;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -