summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 9248031)
raw | patch | inline | side by side (parent: 9248031)
author | Sajesh Kumar Saran <sajesh@ti.com> | |
Sat, 5 Jan 2013 00:00:33 +0000 (19:00 -0500) | ||
committer | Sajesh Kumar Saran <sajesh@ti.com> | |
Sat, 5 Jan 2013 00:00:33 +0000 (19:00 -0500) |
src/engine_pkcs11.c | patch | blob | history | |
src/engine_pkcs11.h | patch | blob | history | |
src/hw_pkcs11.c | patch | blob | history |
diff --git a/src/engine_pkcs11.c b/src/engine_pkcs11.c
index c1b8fbbe65b4fbff0d04c65bfce2129cca7818b7..c97d08bbc9abbb91e75c98495e5370c77349b12c 100644 (file)
--- a/src/engine_pkcs11.c
+++ b/src/engine_pkcs11.c
/*
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
* Copyright (c) 2002 Juha Yrjölä. All rights reserved.
* Copyright (c) 2001 Markus Friedl.
* Copyright (c) 2002 Olaf Kirch
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/*****************************************************************************
+ ChangeLog (01/04/2013):
+ Added following new functionalities
+ - API to list objects on the token
+ - API to store certificate to token
+ - API to generate & store RSA key pair to token
+ - API to get RSA public key from token
+ - API to Delete object from token
+ *****************************************************************************/
+
#include <config.h>
#include <stdio.h>
#include <string.h>
/** The maximum length of an internally-allocated PIN */
#define MAX_PIN_LENGTH 32
-static PKCS11_CTX *ctx;
+/* Maximum size of a token object */
+#define MAX_OBJECT_SIZE 5000
+
+static int do_login(PKCS11_SLOT *slot);
+static int pkcs11_store_cert
+(
+ ENGINE * e,
+ int slot_nr,
+ unsigned char *cert_id,
+ size_t cert_id_len,
+ char *cert_label,
+ X509 *x
+);
+static int parse_cert_store_string
+(
+ const char *cert_store_str,
+ int *slot,
+ unsigned char *id,
+ size_t * id_len,
+ char **label,
+ char **cert_file
+);
+static int parse_key_gen_string
+(
+ const char *key_gen_str,
+ int *slot,
+ int *key_size,
+ unsigned char *id,
+ size_t * id_len,
+ char **label
+);
+static int pkcs11_gen_key
+(
+ ENGINE * e,
+ int slot_nr,
+ unsigned int key_size,
+ unsigned char *key_id,
+ size_t key_id_len,
+ char *key_label
+);
+static int pkcs11_del_obj
+(
+ ENGINE * e,
+ int slot_nr,
+ char *type_str,
+ unsigned char *id,
+ size_t id_len,
+ char *label
+);
+static int parse_del_obj_string
+(
+ const char *del_obj_str,
+ int *slot,
+ char **type,
+ unsigned char *id,
+ size_t * id_len,
+ char **label
+);
+static int parse_key_string
+(
+ const char *pubkey_get_str,
+ int *slot,
+ unsigned char *id,
+ size_t * id_len,
+ char **label,
+ char **key_file
+);
+
+static PKCS11_CTX *ctx = NULL;
/**
* The PIN used for login. Cache for the get_pin function.
int pkcs11_finish(ENGINE * engine)
{
+ if (verbose) {
+ fprintf(stderr, "engine finish\n");
+ }
if (ctx) {
PKCS11_CTX_unload(ctx);
PKCS11_CTX_free(ctx);
return 1;
}
-static EVP_PKEY *pkcs11_load_key(ENGINE * e, const char *s_slot_key_id,
- UI_METHOD * ui_method, void *callback_data,
- int isPrivate)
+static EVP_PKEY *pkcs11_load_key
+(
+ ENGINE * e,
+ int slot_nr,
+ unsigned char *key_id,
+ size_t key_id_len,
+ char *key_label,
+ UI_METHOD * ui_method,
+ void *callback_data,
+ int isPrivate
+)
{
PKCS11_SLOT *slot_list, *slot;
PKCS11_SLOT *found_slot = NULL;
PKCS11_CERT *certs;
EVP_PKEY *pk;
unsigned int slot_count, cert_count, key_count, n, m;
- unsigned char key_id[MAX_VALUE_LEN / 2];
- size_t key_id_len = sizeof(key_id);
- char *key_label = NULL;
- int slot_nr = -1;
char flags[64];
- if (s_slot_key_id && *s_slot_key_id) {
- n = parse_slot_id_string(s_slot_key_id, &slot_nr,
- key_id, &key_id_len, &key_label);
-
- if (!n) {
- fprintf(stderr,
- "supported formats: <id>, <slot>:<id>, id_<id>, slot_<slot>-id_<id>, label_<label>, slot_<slot>-label_<label>\n");
- fprintf(stderr,
- "where <slot> is the slot number as normal integer,\n");
- fprintf(stderr,
- "and <id> is the id number as hex string.\n");
- fprintf(stderr,
- "and <label> is the textual key label string.\n");
- return NULL;
- }
- if (verbose) {
- fprintf(stderr, "Looking in slot %d for key: ",
- slot_nr);
- if (key_label == NULL) {
- for (n = 0; n < key_id_len; n++)
- fprintf(stderr, "%02x", key_id[n]);
- fprintf(stderr, "\n");
- } else
- fprintf(stderr, "label: %s\n", key_label);
- }
+ if (ctx == NULL) {
+ pkcs11_init(e);
}
if (PKCS11_enumerate_slots(ctx, &slot_list, &slot_count) < 0)
fprintf(stderr, "Found %u slot%s\n", slot_count,
(slot_count <= 1) ? "" : "s");
}
+
for (n = 0; n < slot_count; n++) {
slot = slot_list + n;
flags[0] = '\0';
PKCS11_release_all_slots(ctx, slot_list, slot_count);
return NULL;
}
-/* Removed for interop with some other pkcs11 libs. */
-#if 0
- if (!tok->initialized) {
- fprintf(stderr, "Found uninitialized token; \n");
- return NULL;
- }
-#endif
+
if (isPrivate && !tok->userPinSet && !tok->readOnly) {
fprintf(stderr, "Found slot without user PIN\n");
PKCS11_release_all_slots(ctx, slot_list, slot_count);
fprintf(stderr, "Found token: %s\n", slot->token->label);
}
+#ifdef DEBUG
if (PKCS11_enumerate_certs(tok, &certs, &cert_count))
fail("unable to enumerate certificates\n");
fprintf(stderr, "\n");
}
}
+#endif
/* Perform login to the token if required */
if (tok->loginRequired) {
fprintf(stderr, "Found %u key%s:\n", key_count,
(key_count <= 1) ? "" : "s");
}
- if (s_slot_key_id && *s_slot_key_id && (key_id_len != 0 || key_label != NULL)) {
+ if ((key_id_len != 0) || (key_label != NULL)) {
for (n = 0; n < key_count; n++) {
PKCS11_KEY *k = keys + n;
if (isPrivate) {
pk = PKCS11_get_private_key(selected_key);
} else {
- /*pk = PKCS11_get_public_key(&keys[0]);
- need a get_public_key? */
- pk = PKCS11_get_private_key(selected_key);
+ pk = PKCS11_get_public_key(selected_key);
}
- if (key_label != NULL)
- free(key_label);
return pk;
}
EVP_PKEY *pkcs11_load_public_key(ENGINE * e, const char *s_key_id,
UI_METHOD * ui_method, void *callback_data)
{
+ int n;
+ unsigned char key_id[MAX_VALUE_LEN / 2];
+ size_t key_id_len = sizeof(key_id);
+ char *key_label = NULL;
+ int slot_nr = -1;
EVP_PKEY *pk;
- pk = pkcs11_load_key(e, s_key_id, ui_method, callback_data, 0);
+ n = parse_key_string(s_key_id, &slot_nr, key_id, &key_id_len,
+ &key_label, NULL);
+ if (n) {
+ fprintf(stderr,
+ "supported format: slot_<slot>:id_<id>:label_<label>\n");
+ fprintf(stderr,
+ "where <slot> is the slot number as normal integer,\n");
+ fprintf(stderr,
+ "and <id> is the id number as hex string.\n");
+ fprintf(stderr,
+ "and <label> is the textual key label string.\n");
+ return NULL;
+ }
+
+ pk = pkcs11_load_key(e, slot_nr, key_id, key_id_len, key_label,
+ ui_method, callback_data, 0);
if (pk == NULL)
fail("PKCS11_load_public_key returned NULL\n");
+
return pk;
}
EVP_PKEY *pkcs11_load_private_key(ENGINE * e, const char *s_key_id,
UI_METHOD * ui_method, void *callback_data)
{
+ int n;
+ unsigned char key_id[MAX_VALUE_LEN / 2];
+ size_t key_id_len = sizeof(key_id);
+ char *key_label = NULL;
+ int slot_nr = -1;
EVP_PKEY *pk;
- pk = pkcs11_load_key(e, s_key_id, ui_method, callback_data, 1);
+ n = parse_key_string(s_key_id, &slot_nr, key_id, &key_id_len,
+ &key_label, NULL);
+ if (n) {
+ fprintf(stderr,
+ "supported format: slot_<slot>:id_<id>:label_<label>\n");
+ fprintf(stderr,
+ "where <slot> is the slot number as normal integer,\n");
+ fprintf(stderr,
+ "and <id> is the id number as hex string.\n");
+ fprintf(stderr,
+ "and <label> is the textual key label string.\n");
+ return NULL;
+ }
+
+ pk = pkcs11_load_key(e, slot_nr, key_id, key_id_len, key_label,
+ ui_method, callback_data, 1);
if (pk == NULL)
fail("PKCS11_get_private_key returned NULL\n");
+
return pk;
}
+
+int list_token_objects
+(
+ ENGINE * e,
+ long slot_nr /* slot number */
+)
+{
+ PKCS11_SLOT *slot_list, *slot, *found_slot = NULL;
+ PKCS11_TOKEN *tok;
+ PKCS11_CERT *certs;
+ PKCS11_KEY *keys;
+ unsigned int slot_count, cert_count, key_count, m, n, i;
+ char flags[64];
+
+ if (verbose) {
+ fprintf(stderr, "Displaying token objects from slot %d\n", (int)slot_nr);
+ }
+
+ if (ctx == NULL) {
+ pkcs11_init(e);
+ }
+ if (PKCS11_enumerate_slots(ctx, &slot_list, &slot_count)) {
+ fprintf(stderr, "failed to enumerate slots\n");
+ return 0;
+ }
+
+ if (verbose) {
+ fprintf(stderr, "Found %u slots\n", slot_count);
+ }
+
+ for (n = 0; n < slot_count; n++) {
+ slot = slot_list + n;
+ flags[0] = '\0';
+ if (slot->token) {
+ if (!slot->token->initialized)
+ strcat(flags, "uninitialized, ");
+ else if (!slot->token->userPinSet)
+ strcat(flags, "no pin, ");
+ if (slot->token->loginRequired)
+ strcat(flags, "login, ");
+ if (slot->token->readOnly)
+ strcat(flags, "ro, ");
+ } else {
+ strcpy(flags, "no token");
+ }
+ if ((m = strlen(flags)) != 0) {
+ flags[m - 2] = '\0';
+ }
+
+ if (slot_nr != -1 &&
+ slot_nr == PKCS11_get_slotid_from_slot(slot)) {
+ found_slot = slot;
+ }
+
+ if (verbose) {
+ fprintf(stderr, "[%lu] %-25.25s %-16s",
+ PKCS11_get_slotid_from_slot(slot),
+ slot->description, flags);
+ if (slot->token) {
+ fprintf(stderr, " (%s)",
+ slot->token->label[0] ?
+ slot->token->label : "no label");
+ }
+ fprintf(stderr, "\n");
+ }
+ }
+
+ if (found_slot) {
+ slot = found_slot;
+ } else {
+ fprintf(stderr, "Invalid slot number: %d\n", (int)slot_nr);
+ PKCS11_release_all_slots(ctx, slot_list, slot_count);
+ return 0;
+ }
+
+ tok = slot->token;
+
+ if (tok == NULL) {
+ fprintf(stderr, "Found empty token; \n");
+ PKCS11_release_all_slots(ctx, slot_list, slot_count);
+ return 0;
+ }
+
+ if (verbose) {
+ fprintf(stderr, "Found slot: %s\n", slot->description);
+ fprintf(stderr, "Found token: %s\n", slot->token->label);
+ }
+
+ if ((tok->loginRequired) && (do_login(slot))) {
+ fprintf(stderr, "failed to login\n");
+ PKCS11_release_all_slots(ctx, slot_list, slot_count);
+ return 0;
+ }
+
+ if (PKCS11_enumerate_certs(tok, &certs, &cert_count)) {
+ fprintf(stderr, "unable to enumerate certificates\n");
+ PKCS11_release_all_slots(ctx, slot_list, slot_count);
+ return 0;
+ }
+
+ for (n=0; n<cert_count; n++) {
+ PKCS11_CERT *c = certs + n;
+ char *dn = NULL;
+
+ fprintf(stderr, "Certificate Object:\n");
+ fprintf(stderr, "\ttype: X.509 cert\n");
+ fprintf(stderr, "\tlabel: %s\n", c->label);
+ fprintf(stderr, "\tID: ", c->id);
+ for (i = 0; i < c->id_len; i++)
+ printf("%02x", c->id[i]);
+ printf("\n");
+
+ if (c->x509)
+ dn = X509_NAME_oneline(X509_get_subject_name(c->x509),
+ NULL, 0);
+ if (dn) {
+ fprintf(stderr, "\tname: %s\n", dn);
+ OPENSSL_free(dn);
+ }
+ }
+
+ if (PKCS11_enumerate_keys(tok, &keys, &key_count)) {
+ fprintf(stderr, "unable to enumerate keys\n");
+ PKCS11_release_all_slots(ctx, slot_list, slot_count);
+ return 0;
+ }
+
+ for (n=0; n<key_count; n++) {
+ PKCS11_KEY *k = keys + n;
+
+ if (k->isPrivate) {
+ fprintf(stderr, "Private Key Object:\n");
+ fprintf(stderr, "\ttype: RSA\n");
+ } else {
+ fprintf(stderr, "Public Key Object:\n");
+ fprintf(stderr, "\ttype: RSA %d bits\n",
+ (PKCS11_get_key_size(k)*8));
+ }
+ fprintf(stderr, "\tlabel: %s\n", k->label);
+ fprintf(stderr, "\tID: ");
+ for (i = 0; i < k->id_len; i++)
+ printf("%02x", k->id[i]);
+ printf("\n");
+ }
+
+ return 1;
+}
+
+static int do_login(PKCS11_SLOT *slot)
+{
+ PKCS11_TOKEN *tok = slot->token;
+
+ if (pin == NULL) {
+ fprintf(stderr, "PIN not set\n");
+ return -1;
+ }
+
+ /* Now login in with the (possibly NULL) pin */
+ if (PKCS11_login(slot, 0, pin)) {
+ /* Login failed, so free the PIN if present */
+ if (pin != NULL) {
+ OPENSSL_cleanse(pin, pin_length);
+ free(pin);
+ pin = NULL;
+ pin_length = 0;
+ }
+ fprintf(stderr, "Login failed\n");
+ return -1;
+ }
+ return 0;
+}
+
+int store_cert_ctrl(ENGINE * e, void *p)
+{
+ struct {
+ int slot_nr;
+ unsigned char *cert_id;
+ size_t cert_id_len;
+ char *cert_label;
+ X509 *cert;
+ } *parms = p;
+
+ if (parms->cert == NULL)
+ return 0;
+
+ if (pkcs11_store_cert(e, parms->slot_nr, parms->cert_id,
+ parms->cert_id_len, parms->cert_label, parms->cert))
+ return 0;
+
+ return 1;
+}
+
+int store_cert_cmd(ENGINE * e, const char *p)
+{
+ int n, rv=0;
+ unsigned char cert_id[MAX_VALUE_LEN / 2];
+ size_t cert_id_len = sizeof(cert_id);
+ char *cert_label = NULL;
+ char *cert_file = NULL;
+ int slot_nr = -1;
+ unsigned char data[MAX_OBJECT_SIZE];
+ const unsigned char *pp = data;
+ int data_len = 0;
+ FILE *f;
+ X509 *x;
+
+ if (!p || !*p) {
+ fprintf(stderr, "no parameter\n");
+ return 0;
+ }
+
+ n = parse_cert_store_string(p, &slot_nr, cert_id, &cert_id_len,
+ &cert_label, &cert_file);
+ if (n) {
+ fprintf(stderr,
+ "supported format: slot_<slot>:id_<id>:label_<label>:cert_<filename>\n");
+ fprintf(stderr,
+ "where <slot> is the slot number as normal integer,\n");
+ fprintf(stderr,
+ "and <id> is the id number as hex string.\n");
+ fprintf(stderr,
+ "and <label> is the textual cert label string.\n");
+ fprintf(stderr,
+ "and <filename> is the cert filename with full path.\n");
+ goto store_cert_err_out;
+ }
+
+ f = fopen(cert_file, "rb");
+ if (f == NULL) {
+ fprintf(stderr, "Couldn't open cert file \"%s\"\n", cert_file);
+ goto store_cert_err_out;
+ }
+
+ data_len = fread(data, 1, sizeof(data), f);
+
+ if (data_len < 0) {
+ fprintf(stderr, "Couldn't read from file \"%s\"\n", cert_file);
+ goto store_cert_err_out;
+ }
+
+ x = d2i_X509(NULL, &pp, data_len);
+ if (!x) {
+ fprintf(stderr, "OpenSSL cert parse error\n");
+ goto store_cert_err_out;
+ }
+
+ /* No ID specified */
+ if (cert_id_len == sizeof(cert_id))
+ cert_id_len = 0;
+
+ if (verbose) {
+ fprintf(stderr, "Storing cert(%s) in slot(%d) with label(%s) and id(",
+ cert_file, slot_nr, cert_label);
+ for (n = 0; n < cert_id_len; n++)
+ fprintf(stderr, "%02x", cert_id[n]);
+ fprintf(stderr, ")\n");
+ }
+
+ if (pkcs11_store_cert(e, slot_nr, cert_id, cert_id_len, cert_label, x))
+ goto store_cert_err_out;
+
+ rv = 1;
+
+store_cert_err_out:
+ if (f) fclose(f);
+ return rv;
+}
+
+static int pkcs11_store_cert
+(
+ ENGINE * e,
+ int slot_nr,
+ unsigned char *cert_id,
+ size_t cert_id_len,
+ char *cert_label,
+ X509 *x
+)
+{
+ PKCS11_SLOT *slot_list, *slot;
+ PKCS11_SLOT *found_slot = NULL;
+ PKCS11_TOKEN *tok;
+ PKCS11_CERT *certs, *ret_cert = NULL;
+ unsigned int slot_count, cert_count;
+ char flags[64];
+ int n,m;
+
+ if (ctx == NULL) {
+ pkcs11_init(e);
+ }
+
+ if (PKCS11_enumerate_slots(ctx, &slot_list, &slot_count)) {
+ fprintf(stderr, "failed to enumerate slots\n");
+ return -1;
+ }
+
+ if (verbose) {
+ fprintf(stderr, "Found %u slots\n", slot_count);
+ }
+
+ for (n = 0; n < slot_count; n++) {
+ slot = slot_list + n;
+ flags[0] = '\0';
+ if (slot->token) {
+ if (!slot->token->initialized)
+ strcat(flags, "uninitialized, ");
+ else if (!slot->token->userPinSet)
+ strcat(flags, "no pin, ");
+ if (slot->token->loginRequired)
+ strcat(flags, "login, ");
+ if (slot->token->readOnly)
+ strcat(flags, "ro, ");
+ } else {
+ strcpy(flags, "no token");
+ }
+ if ((m = strlen(flags)) != 0) {
+ flags[m - 2] = '\0';
+ }
+
+ if (slot_nr != -1 &&
+ slot_nr == PKCS11_get_slotid_from_slot(slot)) {
+ found_slot = slot;
+ }
+
+ if (verbose) {
+ fprintf(stderr, "[%lu] %-25.25s %-16s",
+ PKCS11_get_slotid_from_slot(slot),
+ slot->description, flags);
+ if (slot->token) {
+ fprintf(stderr, " (%s)",
+ slot->token->label[0] ?
+ slot->token->label : "no label");
+ }
+ fprintf(stderr, "\n");
+ }
+ }
+
+ if (found_slot) {
+ slot = found_slot;
+ } else {
+ fprintf(stderr, "Invalid slot number: %d\n", (int)slot_nr);
+ goto err_out;
+ }
+
+ tok = slot->token;
+
+ if (tok == NULL) {
+ fprintf(stderr, "Found empty token; \n");
+ goto err_out;
+ }
+
+ if (verbose) {
+ fprintf(stderr, "Found slot: %s\n", slot->description);
+ fprintf(stderr, "Found token: %s\n", slot->token->label);
+ }
+
+ if ((tok->loginRequired) && (do_login(slot))) {
+ fprintf(stderr, "failed to login\n");
+ goto err_out;
+ }
+
+ /* Enumerate certs to initialize libp11 cert count */
+ if (PKCS11_enumerate_certs(tok, &certs, &cert_count)) {
+ fprintf(stderr, "unable to enumerate certificates\n");
+ goto err_out;
+ }
+
+ if (PKCS11_store_certificate(tok, x, cert_label, cert_id,
+ cert_id_len, &ret_cert)) {
+ fprintf(stderr, "failed to store cert\n");
+ goto err_out;
+ }
+
+ return 0;
+
+err_out:
+ PKCS11_release_all_slots(ctx, slot_list, slot_count);
+ return -1;
+}
+
+static int parse_cert_store_string
+(
+ const char *cert_store_str,
+ int *slot,
+ unsigned char *id,
+ size_t * id_len,
+ char **label,
+ char **cert_file
+)
+{
+ char *token;
+ const char *sep = ":";
+ char *str = (char *)cert_store_str;
+
+ if (!cert_store_str)
+ return -1;
+
+ /* Default values */
+ *slot = 0;
+ *label = NULL;
+ *cert_file = NULL;
+
+ token = strtok(str, sep);
+
+ while (token) {
+
+ /* slot identifier */
+ if (!strncmp(token, "slot_", 5)) {
+ /* slot is a decimal number */
+ if (sscanf(token + 5, "%d", slot) != 1) {
+ fprintf(stderr, "slot number not deciphered!\n");
+ return -1;
+ }
+ } else if (!strncmp(token, "id_", 3)) {
+ /* certificate ID */
+ /* id is hexadecimal number */
+ if (!hex_to_bin(token + 3, id, id_len)) {
+ fprintf(stderr, "id not deciphered!\n");
+ return -1;
+ }
+ } else if (!strncmp(token, "label_", 6)) {
+ /* label */
+ /* label is string */
+ *label = strdup(token + 6);
+ if (*label == NULL) {
+ fprintf(stderr, "label not deciphered!\n");
+ return -1;
+ }
+ } else if (!strncmp(token, "cert_", 5)) {
+ /* cert file name */
+ *cert_file = strdup(token + 5);
+ if (*cert_file == NULL) {
+ fprintf(stderr, "cert file not deciphered!\n");
+ return -1;
+ }
+ }
+ token = strtok(NULL, sep);
+ } /* end while(token) */
+
+ if (*cert_file == NULL) {
+ fprintf(stderr, "cert file name not present!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int gen_key_cmd(ENGINE * e, const char *p)
+{
+ int key_size, n;
+ unsigned char key_id[MAX_VALUE_LEN / 2];
+ size_t key_id_len = sizeof(key_id);
+ char *key_label = NULL;
+ int slot_nr = -1;
+
+ if (!p || !*p) {
+ fprintf(stderr, "no parameter\n");
+ return 0;
+ }
+
+ n = parse_key_gen_string(p, &slot_nr, &key_size, key_id, &key_id_len,
+ &key_label);
+ if (n) {
+ fprintf(stderr,
+ "supported format: slot_<slot>:size_<size>:id_<id>:label_<label>\n");
+ fprintf(stderr,
+ "where <slot> is the slot number as normal integer,\n");
+ fprintf(stderr,
+ "and <size> is the RSA key size in bits.\n");
+ fprintf(stderr,
+ "and <id> is the id number as hex string.\n");
+ fprintf(stderr,
+ "and <label> is the textual cert label string.\n");
+ goto gen_key_err_out;
+ }
+
+ if (verbose) {
+ fprintf(stderr, "Generating %dbits RSA key in slot(%d) with label(%s) and id(",
+ key_size, slot_nr, key_label);
+ for (n = 0; n < key_id_len; n++)
+ fprintf(stderr, "%02x", key_id[n]);
+ fprintf(stderr, ")\n");
+ }
+
+ if (pkcs11_gen_key(e, slot_nr, (unsigned int)key_size, key_id, key_id_len, key_label))
+ goto gen_key_err_out;
+
+ return 1;
+
+gen_key_err_out:
+ return 0;
+
+}
+
+static int parse_key_gen_string
+(
+ const char *key_gen_str,
+ int *slot,
+ int *key_size,
+ unsigned char *id,
+ size_t * id_len,
+ char **label
+)
+{
+ char *token;
+ const char *sep = ":";
+ char *str = (char *)key_gen_str;
+
+ if (!key_gen_str)
+ return -1;
+
+ /* Default values */
+ *slot = 0;
+ *label = NULL;
+ *key_size = -1;
+
+ token = strtok(str, sep);
+
+ while (token) {
+
+ /* slot identifier */
+ if (!strncmp(token, "slot_", 5)) {
+ /* slot is a decimal number */
+ if (sscanf(token + 5, "%d", slot) != 1) {
+ fprintf(stderr, "slot number not deciphered!\n");
+ return -1;
+ }
+ } else if (!strncmp(token, "id_", 3)) {
+ /* certificate ID */
+ /* id is hexadecimal number */
+ if (!hex_to_bin(token + 3, id, id_len)) {
+ fprintf(stderr, "id not deciphered!\n");
+ return -1;
+ }
+ } else if (!strncmp(token, "label_", 6)) {
+ /* label */
+ /* label is string */
+ *label = strdup(token + 6);
+ if (*label == NULL) {
+ fprintf(stderr, "label not deciphered!\n");
+ return -1;
+ }
+ } else if (!strncmp(token, "size_", 5)) {
+ /* key size in bits */
+ if (sscanf(token + 5, "%d", key_size) != 1) {
+ fprintf(stderr, "key size not deciphered!\n");
+ return -1;
+ }
+ }
+ token = strtok(NULL, sep);
+ } /* end while(token) */
+
+ if (*key_size == -1) {
+ fprintf(stderr, "key size not present!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int pkcs11_gen_key
+(
+ ENGINE * e,
+ int slot_nr,
+ unsigned int key_size,
+ unsigned char *key_id,
+ size_t key_id_len,
+ char *key_label
+)
+{
+ PKCS11_SLOT *slot_list, *slot;
+ PKCS11_SLOT *found_slot = NULL;
+ PKCS11_TOKEN *tok;
+ PKCS11_KEY *keys, *ret_key = NULL;
+ unsigned int slot_count, key_count;
+ char flags[64];
+ int n,m;
+
+ if (ctx == NULL) {
+ pkcs11_init(e);
+ }
+
+ if (PKCS11_enumerate_slots(ctx, &slot_list, &slot_count)) {
+ fprintf(stderr, "failed to enumerate slots\n");
+ return -1;
+ }
+
+ if (verbose) {
+ fprintf(stderr, "Found %u slots\n", slot_count);
+ }
+
+ for (n = 0; n < slot_count; n++) {
+ slot = slot_list + n;
+ flags[0] = '\0';
+ if (slot->token) {
+ if (!slot->token->initialized)
+ strcat(flags, "uninitialized, ");
+ else if (!slot->token->userPinSet)
+ strcat(flags, "no pin, ");
+ if (slot->token->loginRequired)
+ strcat(flags, "login, ");
+ if (slot->token->readOnly)
+ strcat(flags, "ro, ");
+ } else {
+ strcpy(flags, "no token");
+ }
+ if ((m = strlen(flags)) != 0) {
+ flags[m - 2] = '\0';
+ }
+
+ if (slot_nr != -1 &&
+ slot_nr == PKCS11_get_slotid_from_slot(slot)) {
+ found_slot = slot;
+ }
+
+ if (verbose) {
+ fprintf(stderr, "[%lu] %-25.25s %-16s",
+ PKCS11_get_slotid_from_slot(slot),
+ slot->description, flags);
+ if (slot->token) {
+ fprintf(stderr, " (%s)",
+ slot->token->label[0] ?
+ slot->token->label : "no label");
+ }
+ fprintf(stderr, "\n");
+ }
+ }
+
+ if (found_slot) {
+ slot = found_slot;
+ } else {
+ fprintf(stderr, "Invalid slot number: %d\n", (int)slot_nr);
+ goto err_out;
+ }
+
+ tok = slot->token;
+
+ if (tok == NULL) {
+ fprintf(stderr, "Found empty token; \n");
+ goto err_out;
+ }
+
+ if (verbose) {
+ fprintf(stderr, "Found slot: %s\n", slot->description);
+ fprintf(stderr, "Found token: %s\n", slot->token->label);
+ }
+
+ if ((tok->loginRequired) && (do_login(slot))) {
+ fprintf(stderr, "failed to login\n");
+ goto err_out;
+ }
+
+ /* Enumerate keys to initialize libp11 key count */
+ if (PKCS11_enumerate_keys(tok, &keys, &key_count)) {
+ fprintf(stderr, "unable to enumerate keys\n");
+ goto err_out;
+ }
+
+ if (PKCS11_generate_key(tok, EVP_PKEY_RSA, key_size, key_label,
+ key_id, key_id_len)) {
+ fprintf(stderr, "failed to generate RSA key pair\n");
+ goto err_out;
+ }
+
+ return 0;
+
+err_out:
+ PKCS11_release_all_slots(ctx, slot_list, slot_count);
+ return -1;
+}
+
+int del_obj_cmd(ENGINE * e, const char *p)
+{
+ int n;
+ unsigned char id[MAX_VALUE_LEN / 2];
+ size_t id_len = sizeof(id);
+ char *label = NULL, *type = NULL;
+ int slot_nr = -1;
+
+ if (!p || !*p) {
+ fprintf(stderr, "no parameter\n");
+ return 0;
+ }
+
+ n = parse_del_obj_string(p, &slot_nr, &type, id, &id_len, &label);
+ if (n) {
+ fprintf(stderr,
+ "supported format: slot_<slot>:type_<type>:id_<id>:label_<label>:\n");
+ fprintf(stderr,
+ "where <slot> is the slot number as normal integer,\n");
+ fprintf(stderr,
+ "and <type> is the object type (privkey/pubkey/cert)\n");
+ fprintf(stderr,
+ "and <id> is the id number as hex string.\n");
+ fprintf(stderr,
+ "and <label> is the textual label string.\n");
+ return 0;
+ }
+
+ /* No ID specified */
+ if (id_len == sizeof(id))
+ id_len = 0;
+
+ if (verbose) {
+ fprintf(stderr, "Deleting object type(%s) from slot(%d) with label(%s) and id(",
+ type, slot_nr, label);
+ for (n = 0; n < id_len; n++)
+ fprintf(stderr, "%02x", id[n]);
+ fprintf(stderr, ")\n");
+ }
+
+ if (pkcs11_del_obj(e, slot_nr, type, id, id_len, label))
+ return 0;
+
+ return 1;
+}
+
+static int parse_del_obj_string
+(
+ const char *del_obj_str,
+ int *slot,
+ char **type,
+ unsigned char *id,
+ size_t * id_len,
+ char **label
+)
+{
+ char *token;
+ const char *sep = ":";
+ char *str = (char *)del_obj_str;
+
+ if (!del_obj_str)
+ return -1;
+
+ /* Default values */
+ *slot = 0;
+ *label = NULL;
+ *type = NULL;
+
+ token = strtok(str, sep);
+
+ while (token) {
+
+ /* slot identifier */
+ if (!strncmp(token, "slot_", 5)) {
+ /* slot is a decimal number */
+ if (sscanf(token + 5, "%d", slot) != 1) {
+ fprintf(stderr, "slot number not deciphered!\n");
+ return -1;
+ }
+ } else if (!strncmp(token, "id_", 3)) {
+ /* certificate ID */
+ /* id is hexadecimal number */
+ if (!hex_to_bin(token + 3, id, id_len)) {
+ fprintf(stderr, "id not deciphered!\n");
+ return -1;
+ }
+ } else if (!strncmp(token, "label_", 6)) {
+ /* label */
+ /* label is string */
+ *label = strdup(token + 6);
+ if (*label == NULL) {
+ fprintf(stderr, "label not deciphered!\n");
+ return -1;
+ }
+ } else if (!strncmp(token, "type_", 5)) {
+ /* Object type */
+ *type = strdup(token + 5);
+ if (*type == NULL) {
+ fprintf(stderr, "type not deciphered!\n");
+ return -1;
+ }
+ }
+ token = strtok(NULL, sep);
+ } /* end while(token) */
+
+ if (*type == NULL) {
+ fprintf(stderr, "type not present!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int pkcs11_del_obj
+(
+ ENGINE * e,
+ int slot_nr,
+ char *type_str,
+ unsigned char *id,
+ size_t id_len,
+ char *label
+)
+{
+ PKCS11_SLOT *slot_list, *slot;
+ PKCS11_SLOT *found_slot = NULL;
+ PKCS11_TOKEN *tok;
+ PKCS11_KEY *keys, *ret_key = NULL;
+ unsigned int slot_count, key_count;
+ char flags[64];
+ int n,m, type, retval = -1;
+#define TYPE_PRIVKEY 1
+#define TYPE_PUBKEY 2
+#define TYPE_CERT 3
+
+ if (!strcmp(type_str, "privkey")) {
+ type = TYPE_PRIVKEY;
+ } else if (!strcmp(type_str, "pubkey")) {
+ type = TYPE_PUBKEY;
+ } else if (!strcmp(type_str, "cert")) {
+ type = TYPE_CERT;
+ } else {
+ fprintf(stderr, "invalid object type(%s)\n", type_str);
+ return retval;
+ }
+
+ if (ctx == NULL) {
+ pkcs11_init(e);
+ }
+
+ if (PKCS11_enumerate_slots(ctx, &slot_list, &slot_count)) {
+ fprintf(stderr, "failed to enumerate slots\n");
+ return retval;
+ }
+
+ if (verbose) {
+ fprintf(stderr, "Found %u slots\n", slot_count);
+ }
+
+ for (n = 0; n < slot_count; n++) {
+ slot = slot_list + n;
+ flags[0] = '\0';
+ if (slot->token) {
+ if (!slot->token->initialized)
+ strcat(flags, "uninitialized, ");
+ else if (!slot->token->userPinSet)
+ strcat(flags, "no pin, ");
+ if (slot->token->loginRequired)
+ strcat(flags, "login, ");
+ if (slot->token->readOnly)
+ strcat(flags, "ro, ");
+ } else {
+ strcpy(flags, "no token");
+ }
+ if ((m = strlen(flags)) != 0) {
+ flags[m - 2] = '\0';
+ }
+
+ if (slot_nr != -1 &&
+ slot_nr == PKCS11_get_slotid_from_slot(slot)) {
+ found_slot = slot;
+ }
+
+ if (verbose) {
+ fprintf(stderr, "[%lu] %-25.25s %-16s",
+ PKCS11_get_slotid_from_slot(slot),
+ slot->description, flags);
+ if (slot->token) {
+ fprintf(stderr, " (%s)",
+ slot->token->label[0] ?
+ slot->token->label : "no label");
+ }
+ fprintf(stderr, "\n");
+ }
+ }
+
+ if (found_slot) {
+ slot = found_slot;
+ } else {
+ fprintf(stderr, "Invalid slot number: %d\n", (int)slot_nr);
+ goto err_out;
+ }
+
+ tok = slot->token;
+
+ if (tok == NULL) {
+ fprintf(stderr, "Found empty token; \n");
+ goto err_out;
+ }
+
+ if (verbose) {
+ fprintf(stderr, "Found slot: %s\n", slot->description);
+ fprintf(stderr, "Found token: %s\n", slot->token->label);
+ }
+
+ if ((tok->loginRequired) && (do_login(slot))) {
+ fprintf(stderr, "failed to login\n");
+ goto err_out;
+ }
+
+ switch(type) {
+ case TYPE_CERT:
+ if (PKCS11_remove_certificate(tok, label, id, id_len)) {
+ fprintf(stderr, "failed to delete certificate\n");
+ goto err_out;
+ }
+ break;
+
+ case TYPE_PUBKEY:
+ if (PKCS11_remove_public_key(tok, label, id, id_len)) {
+ fprintf(stderr, "failed to delete public key\n");
+ goto err_out;
+ }
+ break;
+
+ case TYPE_PRIVKEY:
+ if (PKCS11_remove_private_key(tok, label, id, id_len)) {
+ fprintf(stderr, "failed to delete private key\n");
+ goto err_out;
+ }
+ break;
+
+ default:
+ fprintf(stderr, "object type(%s) not supported\n", type_str);
+ goto err_out;
+ break;
+ }
+
+ retval = 0;
+err_out:
+ PKCS11_release_all_slots(ctx, slot_list, slot_count);
+ return retval;
+}
+
+int get_pubkey_cmd(ENGINE * e, const char *p)
+{
+ int n, rv = 0;
+ unsigned char key_id[MAX_VALUE_LEN / 2];
+ size_t key_id_len = sizeof(key_id);
+ char *key_label = NULL;
+ char *key_file = NULL;
+ int slot_nr = -1;
+ unsigned char *pp, *data = NULL;
+ int data_len = 0;
+ FILE *f;
+ EVP_PKEY *pk;
+ RSA *rsa;
+
+ if (!p || !*p) {
+ fprintf(stderr, "no parameter\n");
+ return 0;
+ }
+
+ n = parse_key_string(p, &slot_nr, key_id, &key_id_len,
+ &key_label, &key_file);
+ if (n) {
+ fprintf(stderr,
+ "supported format: slot_<slot>:id_<id>:label_<label>:key_<filename>\n");
+ fprintf(stderr,
+ "where <slot> is the slot number as normal integer,\n");
+ fprintf(stderr,
+ "and <id> is the id number as hex string.\n");
+ fprintf(stderr,
+ "and <label> is the textual key label string.\n");
+ fprintf(stderr,
+ "and <filename> is the key filename with full path.\n");
+ goto get_pubkey_err_out;
+ }
+
+ f = fopen(key_file, "wb");
+ if (f == NULL) {
+ fprintf(stderr, "Couldn't open key file \"%s\"\n", key_file);
+ goto get_pubkey_err_out;
+ }
+
+ /* No ID specified */
+ if (key_id_len == sizeof(key_id))
+ key_id_len = 0;
+
+ if (verbose) {
+ fprintf(stderr, "Getting public key in slot(%d) with label(%s) and id(",
+ slot_nr, key_label);
+ for (n = 0; n < key_id_len; n++)
+ fprintf(stderr, "%02x", key_id[n]);
+ fprintf(stderr, ")\n");
+ }
+
+ pk = pkcs11_load_key(e, slot_nr, key_id, key_id_len, key_label, NULL, NULL, 0);
+ if (pk == NULL) {
+ fprintf(stderr, "PKCS11_load_public_key returned NULL\n");
+ goto get_pubkey_err_out;
+ }
+
+ rsa = EVP_PKEY_get1_RSA(pk);
+ if (rsa == NULL) {
+ fprintf(stderr, "Couldn't retrieve RSA key form EVP_PKEY\n");
+ goto get_pubkey_err_out;
+ }
+
+#if 0
+ /* To store in DER format */
+ data_len = i2d_RSAPublicKey(rsa, NULL);
+ if ((data = (unsigned char *)malloc(data_len)) == NULL) {
+ fprintf(stderr, "couldn't allocate memory for key\n");
+ goto get_pubkey_err_out;
+ }
+ pp = data;
+ data_len = i2d_RSAPublicKey(rsa, &pp);
+ n = fwrite(data, 1, data_len, f);
+
+ if (n != data_len) {
+ fprintf(stderr, "Couldn't write to file \"%s\"\n", key_file);
+ goto get_pubkey_err_out;
+ }
+#endif
+ if (!PEM_write_RSA_PUBKEY(f, rsa)) {
+ fprintf(stderr, "Couldn't write to file \"%s\"\n", key_file);
+ goto get_pubkey_err_out;
+ }
+
+ rv = 1;
+
+get_pubkey_err_out:
+ if (f) fclose(f);
+ if (data) free(data);
+ return rv;
+
+}
+
+static int parse_key_string
+(
+ const char *key_get_str,
+ int *slot,
+ unsigned char *id,
+ size_t * id_len,
+ char **label,
+ char **key_file
+)
+{
+ char *token;
+ const char *sep = ":";
+ char *str = (char *)key_get_str;
+
+ if (!key_get_str)
+ return -1;
+
+ /* Default values */
+ *slot = 0;
+ *label = NULL;
+ *key_file = NULL;
+
+ token = strtok(str, sep);
+
+ while (token) {
+
+ /* slot identifier */
+ if (!strncmp(token, "slot_", 5)) {
+ /* slot is a decimal number */
+ if (sscanf(token + 5, "%d", slot) != 1) {
+ fprintf(stderr, "slot number not deciphered!\n");
+ return -1;
+ }
+ } else if (!strncmp(token, "id_", 3)) {
+ /* certificate ID */
+ /* id is hexadecimal number */
+ if (!hex_to_bin(token + 3, id, id_len)) {
+ fprintf(stderr, "id not deciphered!\n");
+ return -1;
+ }
+ } else if (!strncmp(token, "label_", 6)) {
+ /* label */
+ /* label is string */
+ *label = strdup(token + 6);
+ if (*label == NULL) {
+ fprintf(stderr, "label not deciphered!\n");
+ return -1;
+ }
+ } else if ((key_file) && (!strncmp(token, "key_", 4))) {
+ /* key file name */
+ *key_file = strdup(token + 4);
+ if (*key_file == NULL) {
+ fprintf(stderr, "key file not deciphered!\n");
+ return -1;
+ }
+ }
+ token = strtok(NULL, sep);
+ } /* end while(token) */
+
+ if ((key_file) && (*key_file == NULL)) {
+ fprintf(stderr, "key file name not present!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/src/engine_pkcs11.h b/src/engine_pkcs11.h
index 2159330dd737ff57b672686b47b3e9d3b42098b0..5fc32ee36e0330df75a49e4bb51ff87ff6e10f70 100644 (file)
--- a/src/engine_pkcs11.h
+++ b/src/engine_pkcs11.h
/*
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
* Copyright (c) 2002 Juha Yrjölä. All rights reserved.
* Copyright (c) 2001 Markus Friedl.
* Copyright (c) 2003 Kevin Stefanik
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/*****************************************************************************
+ ChangeLog (01/04/2013):
+ Added following new functionalities
+ - API to list objects on the token
+ - API to store certificate to token
+ - API to generate & store RSA key pair to token
+ - API to get RSA public key from token
+ - API to Delete object from token
+ *****************************************************************************/
+
#ifndef _ENGINE_PKCS11_H
#define _ENGINE_PKCS11_H
EVP_PKEY *pkcs11_load_private_key(ENGINE * e, const char *s_key_id,
UI_METHOD * ui_method, void *callback_data);
+int list_token_objects
+(
+ ENGINE * e,
+ long slot_nr /* slot number */
+);
+
+int store_cert_cmd(ENGINE * e, const char *p);
+
+int store_cert_ctrl(ENGINE * e, void *p);
+
+int gen_key_cmd(ENGINE * e, const char *p);
+
+int del_obj_cmd(ENGINE * e, const char *p);
+
+int get_pubkey_cmd(ENGINE * e, const char *p);
+
#endif
+
diff --git a/src/hw_pkcs11.c b/src/hw_pkcs11.c
index 24806ff07704ffde052151b713d7d6d27679d6c3..18f41959d05c67f27da00c40ec0db729ad9bc0e8 100644 (file)
--- a/src/hw_pkcs11.c
+++ b/src/hw_pkcs11.c
/* ====================================================================
* Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
* Portions Copyright (c) 2003 Kevin Stefanik (kstef@mtppi.org)
+ * Portions Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*
*/
+/*****************************************************************************
+ ChangeLog (01/04/2013):
+ Added following new functionalities
+ - API to list objects on the token
+ - API to store certificate to token
+ - API to generate & store RSA key pair to token
+ - API to get RSA public key from token
+ - API to Delete object from token
+ *****************************************************************************/
+
#include <config.h>
#include <stdio.h>
#include <string.h>
#define CMD_QUIET (ENGINE_CMD_BASE+4)
#define CMD_LOAD_CERT_CTRL (ENGINE_CMD_BASE+5)
#define CMD_INIT_ARGS (ENGINE_CMD_BASE+6)
+#define CMD_LIST_OBJS (ENGINE_CMD_BASE+7)
+#define CMD_STORE_CERT (ENGINE_CMD_BASE+8)
+#define CMD_STORE_CERT_CTRL (ENGINE_CMD_BASE+9)
+#define CMD_GEN_KEY (ENGINE_CMD_BASE+10)
+#define CMD_DEL_OBJ (ENGINE_CMD_BASE+11)
+#define CMD_GET_PUBKEY (ENGINE_CMD_BASE+12)
static int pkcs11_engine_destroy(ENGINE * e);
static int pkcs11_engine_ctrl(ENGINE * e, int cmd, long i, void *p,
ENGINE_CMD_FLAG_NO_INPUT},
{CMD_LOAD_CERT_CTRL,
"LOAD_CERT_CTRL",
- "Get the certificate from card",
+ "Get the certificate from token",
ENGINE_CMD_FLAG_INTERNAL},
{CMD_INIT_ARGS,
"INIT_ARGS",
"Specifies additional initialization arguments to the pkcs11 module",
ENGINE_CMD_FLAG_STRING},
+ {CMD_LIST_OBJS,
+ "LIST_OBJS",
+ "List the objects from token",
+ ENGINE_CMD_FLAG_NUMERIC},
+ {CMD_STORE_CERT,
+ "STORE_CERT",
+ "Store X.509 certificate to token",
+ ENGINE_CMD_FLAG_STRING},
+ {CMD_STORE_CERT_CTRL,
+ "STORE_CERT_CTRL",
+ "Store X.509 certificate to token",
+ ENGINE_CMD_FLAG_INTERNAL},
+ {CMD_GEN_KEY,
+ "GEN_KEY",
+ "Generate & store RSA key pair to token",
+ ENGINE_CMD_FLAG_STRING},
+ {CMD_DEL_OBJ,
+ "DEL_OBJ",
+ "Delete objects from token",
+ ENGINE_CMD_FLAG_STRING},
+ {CMD_GET_PUBKEY,
+ "GET_PUBKEY",
+ "Get Public Key from token",
+ ENGINE_CMD_FLAG_STRING},
{0, NULL, NULL, 0}
};
return load_cert_ctrl(e, p);
case CMD_INIT_ARGS:
return set_init_args((const char *)p);
+ case CMD_LIST_OBJS:
+ return list_token_objects(e, i);
+ case CMD_STORE_CERT:
+ return store_cert_cmd(e, (const char *)p);
+ case CMD_STORE_CERT_CTRL:
+ return store_cert_ctrl(e, p);
+ case CMD_GEN_KEY:
+ return gen_key_cmd(e, (const char *)p);
+ case CMD_DEL_OBJ:
+ return del_obj_cmd(e, (const char *)p);
+ case CMD_GET_PUBKEY:
+ return get_pubkey_cmd(e, (const char *)p);
default:
break;
}