📄 pkcs11-tool.c
字号:
/* * pkcs11-tool.c: Tool for poking around pkcs11 modules/tokens * * 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 <getopt.h>#include <opensc/pkcs11.h>#include "util.h"#ifdef HAVE_OPENSSL#include "openssl/evp.h"#include "openssl/x509.h"#include "openssl/err.h"#endif#define NEED_SESSION_RO 0x01#define NEED_SESSION_RW 0x02#define NO_SLOT ((CK_SLOT_ID) -1)#define NO_MECHANISM ((CK_MECHANISM_TYPE) -1)enum { OPT_MODULE = 0x100, OPT_SLOT, OPT_SLOT_LABEL,};const struct option options[] = { { "show-info", 0, 0, 'I' }, { "list-slots", 0, 0, 'L' }, { "list-mechanisms", 0, 0, 'M' }, { "list-objects", 0, 0, 'O' }, { "sign", 0, 0, 's' }, { "hash", 0, 0, 'h' }, { "mechanism", 1, 0, 'm' }, { "login", 0, 0, 'l' }, { "pin", 1, 0, 'p' }, { "change-pin", 0, 0, 'c' }, { "keypairgen", 0, 0, 'k' }, { "write-object", 1, 0, 'w' }, { "type", 1, 0, 'y' }, { "id", 1, 0, 'd' }, { "label", 1, 0, 'a' }, { "set-id", 1, 0, 'e' }, { "slot", 1, 0, OPT_SLOT }, { "slot-label", 1, 0, OPT_SLOT_LABEL }, { "input-file", 1, 0, 'i' }, { "output-file", 1, 0, 'o' }, { "module", 1, 0, OPT_MODULE }, { "quiet", 0, 0, 'q' }, { "test", 0, 0, 't' }, { "moz-cert", 1, 0, 'z' }, { 0, 0, 0, 0 }};const char *option_help[] = { "Show global token information", "List slots available on the token", "Show slot information", "List mechanisms supported by the token", "Sign some data", "Hash some data", "Specify mechanism (use -M for a list of supported mechanisms)", "Log into the token first (not needed when using --pin)", "Supply PIN on the command line (if used in scripts: careful!)", "Change your (user) PIN", "Key pair generation", "Write an object (key, cert) to the card", "Specify the type of object (e.g. cert, privkey, pubkey)", "Specify the id of the object", "Specify the label of the object", "Specify number of the slot to use", "Specify label of the slot to use", "Set the CKA_ID of an object, >args>= the (new) CKA_ID", "Specify the input file", "Specify the output file", "Specify the module to load", "Quiet operation", "Test (best used with the --login or --pin option)", "Test Mozilla-like keypair gen and cert req, <arg>=certfile"};const char * app_name = "pkcs11-tool"; /* for utils.c */static int opt_quiet = 0;static const char * opt_input = NULL;static const char * opt_output = NULL;static const char * opt_module = NULL;static CK_SLOT_ID opt_slot = NO_SLOT;static const char * opt_slot_label = NULL;static CK_MECHANISM_TYPE opt_mechanism = NO_MECHANISM;static const char * opt_file_to_write = NULL;static const char * opt_object_class_str = NULL;static CK_OBJECT_CLASS opt_object_class = -1;static CK_BYTE opt_object_id[100], new_object_id[100];static size_t opt_object_id_len = 0, new_object_id_len = 0;static char * opt_object_label = NULL;static void *module = NULL;static CK_FUNCTION_LIST_PTR p11 = NULL;static CK_SLOT_ID_PTR p11_slots = NULL;static CK_ULONG p11_num_slots = 0;struct flag_info { CK_FLAGS value; const char * name;};struct mech_info { CK_MECHANISM_TYPE mech; const char * name; const char * short_name;};static void show_cryptoki_info(void);static void list_slots(void);static void show_token(CK_SLOT_ID);static void list_mechs(CK_SLOT_ID);static void list_objects(CK_SESSION_HANDLE);static int change_pin(CK_SLOT_ID, CK_SESSION_HANDLE);static void show_object(CK_SESSION_HANDLE, CK_OBJECT_HANDLE);static void show_key(CK_SESSION_HANDLE, CK_OBJECT_HANDLE, int);static void show_cert(CK_SESSION_HANDLE, CK_OBJECT_HANDLE);static void sign_data(CK_SLOT_ID, CK_SESSION_HANDLE, CK_OBJECT_HANDLE);static void hash_data(CK_SLOT_ID, CK_SESSION_HANDLE);static int gen_keypair(CK_SLOT_ID, CK_SESSION_HANDLE, CK_OBJECT_HANDLE *, CK_OBJECT_HANDLE *);static int write_object(CK_SLOT_ID slot, CK_SESSION_HANDLE session);static void set_id_attr(CK_SLOT_ID slot, CK_SESSION_HANDLE session);static int find_object(CK_SESSION_HANDLE, CK_OBJECT_CLASS, CK_OBJECT_HANDLE_PTR, const unsigned char *, size_t id_len, int obj_index);static CK_MECHANISM_TYPE find_mechanism(CK_SLOT_ID, CK_FLAGS, int stop_if_not_found);static CK_SLOT_ID find_slot_by_label(const char *);static void get_token_info(CK_SLOT_ID, CK_TOKEN_INFO_PTR);static void get_mechanisms(CK_SLOT_ID, CK_MECHANISM_TYPE_PTR *, CK_ULONG_PTR);static void p11_fatal(const char *, CK_RV);static const char * p11_slot_info_flags(CK_FLAGS);static const char * p11_token_info_flags(CK_FLAGS);static const char * p11_utf8_to_local(CK_UTF8CHAR *, size_t);static const char * p11_flag_names(struct flag_info *, CK_FLAGS);static const char * p11_mechanism_to_name(CK_MECHANISM_TYPE);static CK_MECHANISM_TYPE p11_name_to_mechanism(const char *);static void p11_perror(const char *, CK_RV);static const char * CKR2Str(CK_ULONG res);static int p11_test(CK_SLOT_ID slot, CK_SESSION_HANDLE session);static int hex_to_bin(const char *in, CK_BYTE *out, size_t *outlen);static void test_kpgen_certwrite(CK_SLOT_ID slot, CK_SESSION_HANDLE session);/* win32 needs this in open(2) */#ifndef O_BINARY# define O_BINARY 0#endifintmain(int argc, char * const argv[]){ CK_SESSION_HANDLE session = CK_INVALID_HANDLE; CK_OBJECT_HANDLE object = CK_INVALID_HANDLE; char *opt_pin = NULL; int err = 0, c, long_optind = 0; int do_show_info = 0; int do_list_slots = 0; int do_list_mechs = 0; int do_list_objects = 0; int do_sign = 0; int do_hash = 0; int do_gen_keypair = 0; int do_write_object = 0; int do_set_id = 0; int do_test = 0; int do_test_kpgen_certwrite = 0; int need_session = 0; int opt_login = 0; int do_change_pin = 0; int action_count = 0; CK_RV rv; while (1) { c = getopt_long(argc, argv, "ILMOa:d:e:hi:klm:o:p:scqty:w:z:", options, &long_optind); if (c == -1) break; switch (c) { case 'I': do_show_info = 1; action_count++; break; case 'L': do_list_slots = 1; action_count++; break; case 'M': do_list_mechs = 1; action_count++; break; case 'O': need_session |= NEED_SESSION_RO; do_list_objects = 1; action_count++; break; case 'h': need_session |= NEED_SESSION_RO; do_hash = 1; action_count++; break; case 'k': need_session |= NEED_SESSION_RW; do_gen_keypair = 1; action_count++; break; case 'w': need_session |= NEED_SESSION_RW; do_write_object = 1; opt_file_to_write = optarg; action_count++; break; case 'e': need_session |= NEED_SESSION_RW; do_set_id = 1; new_object_id_len = sizeof(new_object_id); if (!hex_to_bin(optarg, new_object_id, &new_object_id_len)) { printf("Invalid ID \"%s\"\n", optarg); print_usage_and_die(); } action_count++; break; case 'y': opt_object_class_str = optarg; if (strcmp(optarg, "cert") == 0) opt_object_class = CKO_CERTIFICATE; else if (strcmp(optarg, "privkey") == 0) opt_object_class = CKO_PRIVATE_KEY; else if (strcmp(optarg, "pubkey") == 0) opt_object_class = CKO_PUBLIC_KEY; else { printf("Unsupported object type \"%s\"\n", optarg); print_usage_and_die(); } break; case 'd': opt_object_id_len = sizeof(opt_object_id); if (!hex_to_bin(optarg, opt_object_id, &opt_object_id_len)) { printf("Invalid ID \"%s\"\n", optarg); print_usage_and_die(); } break; case 'a': opt_object_label = optarg; break; case 'i': opt_input = optarg; break; case 'l': need_session |= NEED_SESSION_RW; opt_login = 1; break; case 'm': opt_mechanism = p11_name_to_mechanism(optarg); break; case 'o': opt_output = optarg; break; case 'p': need_session |= NEED_SESSION_RW; opt_login = 1; opt_pin = optarg; break; case 'c': do_change_pin = 1; need_session |= CKF_SERIAL_SESSION; /* no need for a R/W session */ action_count++; break; case 's': need_session |= NEED_SESSION_RW; do_sign = 1; action_count++; break; case 't': do_test = 1; action_count++; break; case 'z': do_test_kpgen_certwrite = 1; opt_file_to_write = optarg; action_count++; break; case 'q': opt_quiet++; break; case OPT_SLOT: opt_slot = (CK_SLOT_ID) atoi(optarg); break; case OPT_SLOT_LABEL: opt_slot_label = optarg; break; case OPT_MODULE: opt_module = optarg; break; default: print_usage_and_die(); } } if (action_count == 0) print_usage_and_die(); module = C_LoadModule(opt_module, &p11); if (module == NULL) fatal("Failed to load pkcs11 module"); rv = p11->C_Initialize(NULL); if (rv != CKR_OK) p11_fatal("C_Initialize", rv); if (do_show_info) show_cryptoki_info(); /* Get the list of slots */ rv = p11->C_GetSlotList(FALSE, p11_slots, &p11_num_slots); if (rv != CKR_OK && rv != CKR_BUFFER_TOO_SMALL) p11_fatal("C_GetSlotList", rv); p11_slots = (CK_SLOT_ID *) calloc(p11_num_slots, sizeof(CK_SLOT_ID)); if (p11_slots == NULL) { perror("calloc failed"); err = 1; goto end; } rv = p11->C_GetSlotList(FALSE, p11_slots, &p11_num_slots); if (rv != CKR_OK) p11_fatal("C_GetSlotList", rv); if (do_list_slots) list_slots(); if (p11_num_slots == 0) { fprintf(stderr, "No slots...\n"); err = 1; goto end; } if (opt_slot_label) { CK_SLOT_ID slot; slot = find_slot_by_label(opt_slot_label); if (slot == NO_SLOT) { fprintf(stderr, "No slot named \"%s\"\n", opt_slot_label); err = 1; goto end; } if (opt_slot != NO_SLOT && opt_slot != slot) { fprintf(stderr, "Conflicting slots specified\n"); err = 1; goto end; } opt_slot = slot; } if (opt_slot == NO_SLOT) opt_slot = p11_slots[0]; /* XXX: add wait for slot event */ if (do_list_mechs) list_mechs(opt_slot); if (do_sign) { CK_TOKEN_INFO info; get_token_info(opt_slot, &info); if (!(info.flags & CKF_TOKEN_INITIALIZED)) fatal("Token not initialized\n"); if (info.flags & CKF_LOGIN_REQUIRED) opt_login++; } if (need_session) { int flags = CKF_SERIAL_SESSION; if (need_session & NEED_SESSION_RW) flags |= CKF_RW_SESSION; rv = p11->C_OpenSession(opt_slot, flags, NULL, NULL, &session); if (rv != CKR_OK) p11_fatal("C_OpenSession", rv); } if (do_change_pin) /* To be sure we won't mix things up with the -l or -p options, * we safely stop here. */ return change_pin(opt_slot, session); if (opt_login) { char *pin; CK_TOKEN_INFO info; get_token_info(opt_slot, &info); /* Identify which pin to enter */ if (info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) { pin = NULL; } else if (info.flags & CKF_LOGIN_REQUIRED) { if (opt_pin == NULL) pin = getpass("Please enter PIN: "); else pin = opt_pin; if (!pin || !*pin) return 1; } else { goto skip_login; } rv = p11->C_Login(session, CKU_USER, (CK_UTF8CHAR *) pin, pin == NULL ? 0 : strlen(pin)); if (rv != CKR_OK) p11_fatal("C_Login", rv); }skip_login: if (do_sign) { if (!find_object(session, CKO_PRIVATE_KEY, &object, NULL, 0, 0)) fatal("Private key not found"); } if (do_list_objects) list_objects(session); if (do_sign) sign_data(opt_slot, session, object); if (do_hash) hash_data(opt_slot, session); if (do_gen_keypair) { CK_OBJECT_HANDLE hPublicKey, hPrivateKey; gen_keypair(opt_slot, session, &hPublicKey, &hPrivateKey); } if (do_write_object) { if (opt_object_class_str == NULL) fatal("You should specify the object type with the -y option\n"); write_object(opt_slot, session); } if (do_set_id) { if (opt_object_class_str == NULL) fatal("You should specify the object type with the -y option\n"); if (opt_object_id_len == 0) fatal("You should specify the current ID with the -d option\n"); set_id_attr(opt_slot, session); } if (do_test) p11_test(opt_slot, session); if (do_test_kpgen_certwrite) test_kpgen_certwrite(opt_slot, session);end: if (session) p11->C_CloseSession(session); if (p11) p11->C_Finalize(NULL_PTR); if (module) C_UnloadModule(module); return err;}voidshow_cryptoki_info(void){ CK_INFO info; CK_RV rv; rv = p11->C_GetInfo(&info); if (rv != CKR_OK) p11_fatal("C_GetInfo", rv); printf("Cryptoki version %u.%u\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -