b79fb47ee45a5c67aeae567ae4c6da6bd037f7b0
[keystone-linux/engine-pkcs11.git] / src / engine_pkcs11.c
1 /*
2  * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
3  * Copyright (c) 2002 Juha Yrjölä.  All rights reserved.
4  * Copyright (c) 2001 Markus Friedl.
5  * Copyright (c) 2002 Olaf Kirch
6  * Copyright (c) 2003 Kevin Stefanik
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
29 /*****************************************************************************
30  ChangeLog (01/04/2013):
31   Added following new functionalities
32    - API to list objects on the token
33    - API to store certificate to token
34    - API to generate & store RSA key pair to token
35    - API to get RSA public key from token
36    - API to Delete object from token
37  *****************************************************************************/
39 #include <config.h>
40 #include <stdio.h>
41 #include <limits.h>
42 #include <string.h>
43 #include <openssl/crypto.h>
44 #include <openssl/objects.h>
45 #include <openssl/engine.h>
46 #include <libp11.h>
47 #include "engine_pkcs11.h"
48 #include <syslog.h>
50 #ifdef _WIN32
51 #define strncasecmp strnicmp
52 #endif
54 #define fail(msg) { Log(LOG_ERR,msg); return NULL;}
56 /** The maximum length of an internally-allocated PIN */
57 #define MAX_PIN_LENGTH   32
58 #define FLAGS_LEN 64
59 /* Maximum size of a token object */
60 #define MAX_OBJECT_SIZE 5000
62 struct cert_info {
63         unsigned char *id;
64         size_t id_len;
65         char *label;
66         X509 *x509;
67 };
69 struct enum_certs_ctrl_param {
70         int slot_nr;
71         int cnt;
72         struct cert_info *info;
73 };
75 struct cert_ctrl_params {
76         int slot_nr;
77         unsigned char *cert_id;
78         size_t cert_id_len;
79         char *cert_label;
80         X509 *cert;
81 };
83 static int do_login(PKCS11_SLOT *slot);
84 static int pkcs11_store_cert
85 (
86         ENGINE * e,
87         int slot_nr,
88         unsigned char *cert_id,
89         size_t cert_id_len,
90         char *cert_label,
91         X509 *x
92 );
93 static int parse_cert_store_string
94 (
95         const char *cert_store_str,
96         int *slot,
97         unsigned char *id,
98         size_t * id_len,
99         char **label,
100         char **cert_file
101 );
102 static int parse_key_gen_string
104         const char *key_gen_str,
105         int *slot,
106         int *key_size,
107         unsigned char *id,
108         size_t * id_len,
109         char **label
110 );
111 static int pkcs11_gen_key
113         ENGINE * e,
114         int slot_nr,
115         unsigned int key_size,
116         unsigned char *key_id,
117         size_t key_id_len,
118         char *key_label
119 );
120 static int pkcs11_del_obj
122         ENGINE * e,
123         int slot_nr,
124         char *type_str,
125         unsigned char *id,
126         size_t id_len,
127         char *label
128 );
129 static int parse_del_obj_string
131         const char *del_obj_str,
132         int *slot,
133         char **type,
134         unsigned char *id,
135         size_t * id_len,
136         char **label
137 );
138 static int parse_key_string
140         const char *pubkey_get_str,
141         int *slot,
142         unsigned char *id,
143         size_t * id_len,
144         char **label,
145         char **key_file
146 );
148 static PKCS11_CTX *ctx = NULL;
150 /** 
151  * The PIN used for login. Cache for the get_pin function.
152  * The memory for this PIN is always owned internally,
153  * and may be freed as necessary. Before freeing, the PIN 
154  * must be whitened, to prevent security holes.
155  */
156 static char *pin = NULL;
157 static int pin_length = 0;
159 static int verbose = 0;
161 static char *module = NULL;
163 static char *init_args = NULL;
165 static void Log(int const loglevel, char const * const format, ...)
167         char tmp[256];
168         va_list args;
170         va_start(args, format);
171         vsnprintf(tmp, 256, format, args);
172         va_end(args);
174         // log it
175         syslog(loglevel, "engine_pkcs11: %s", tmp);
176         fprintf(stdout, "%s\n", tmp);
180 int set_module(const char *modulename)
182         module = modulename ? strdup(modulename) : NULL;
183         return 1;
186 /**
187  * Set the PIN used for login. A copy of the PIN shall be made.
188  *
189  * If the PIN cannot be assigned, the value 0 shall be returned
190  * and errno shall be set as follows:
191  *
192  *   EINVAL - a NULL PIN was supplied
193  *   ENOMEM - insufficient memory to copy the PIN
194  *
195  * @param _pin the pin to use for login. Must not be NULL.
196  *
197  * @return 1 on success, 0 on failure.
198  */
199 int set_pin(const char *_pin)
201         /* Pre-condition check */
202         if (_pin == NULL) {
203                 errno = EINVAL;
204                 return 0;
205         }
207         /* Copy the PIN. If the string cannot be copied, NULL
208            shall be returned and errno shall be set. */
209         pin = strdup(_pin);
210         if (pin != NULL)
211                 pin_length = strlen(pin);
213         return (pin != NULL);
216 int inc_verbose(void)
218         verbose++;
219         return 1;
222 /* either get the pin code from the supplied callback data, or get the pin
223  * via asking our self. In both cases keep a copy of the pin code in the
224  * pin variable (strdup'ed copy). */
225 static int get_pin(UI_METHOD * ui_method, void *callback_data)
227         UI *ui;
228         struct {
229                 const void *password;
230                 const char *prompt_info;
231         } *mycb = callback_data;
233         /* pin in the call back data, copy and use */
234         if (mycb != NULL && mycb->password) {
235                 pin = (char *)calloc(MAX_PIN_LENGTH, sizeof(char));
236                 if (!pin)
237                         return 0;
238                 strncpy(pin,mycb->password,MAX_PIN_LENGTH);
239                 pin_length = MAX_PIN_LENGTH;
240                 return 1;
241         }
243         /* call ui to ask for a pin */
244         ui = UI_new();
245         if (ui_method != NULL)
246                 UI_set_method(ui, ui_method);
247         if (callback_data != NULL)
248                 UI_set_app_data(ui, callback_data);
250         if (!UI_add_input_string
251             (ui, "PKCS#11 token PIN: ", 0, pin, 1, MAX_PIN_LENGTH)) {
252                 Log(LOG_ERR, "UI_add_input_string failed");
253                 UI_free(ui);
254                 return 0;
255         }
256         if (UI_process(ui)) {
257                 Log(LOG_ERR,  "UI_process failed");
258                 UI_free(ui);
259                 return 0;
260         }
261         UI_free(ui);
262         return 1;
265 int set_init_args(const char *init_args_orig)
267         init_args = init_args_orig ? strdup(init_args_orig) : NULL;
268         return 1;
271 static void free_pkcs11_ctx()
273         if (ctx) {
274                 PKCS11_CTX_unload(ctx);
275                 PKCS11_CTX_free(ctx);
276                 ctx = NULL;
277         }
280 int pkcs11_finish(ENGINE * engine)
282         if (verbose) {
283                 Log(LOG_INFO,  "engine finish");
284         }
286         free_pkcs11_ctx();
288         if (pin != NULL) {
289                 OPENSSL_cleanse(pin, pin_length);
290                 free(pin);
291                 pin = NULL;
292                 pin_length = 0;
293         }
294         return 1;
297 int pkcs11_init(ENGINE * engine)
299         if (verbose) {
300                 Log(LOG_INFO,  "initializing engine");
301         }
302         ctx = PKCS11_CTX_new();
303         PKCS11_CTX_init_args(ctx, init_args);
304         if (PKCS11_CTX_load(ctx, module) < 0) {
305                 Log(LOG_ERR,  "unable to load module %s", module);
306                 return 0;
307         }
308         return 1;
311 int pkcs11_rsa_finish(RSA * rsa)
313         if (pin) {
314                 OPENSSL_cleanse(pin, pin_length);
315                 free(pin);
316                 pin = NULL;
317                 pin_length = 0;
318         }
319         if (module) {
320                 free(module);
321                 module = NULL;
322         }
323         /* need to free RSA_ex_data? */
324         return 1;
327 static int hex_to_bin(const char *in, unsigned char *out, size_t * outlen)
329         size_t left, count = 0;
331         if (in == NULL || *in == '\0') {
332                 *outlen = 0;
333                 return 1;
334         }
336         left = *outlen;
338         while (*in != '\0') {
339                 int byte = 0, nybbles = 2;
341                 while (nybbles-- && *in && *in != ':') {
342                         char c;
343                         byte <<= 4;
344                         c = *in++;
345                         if ('0' <= c && c <= '9')
346                                 c -= '0';
347                         else if ('a' <= c && c <= 'f')
348                                 c = c - 'a' + 10;
349                         else if ('A' <= c && c <= 'F')
350                                 c = c - 'A' + 10;
351                         else {
352                                 Log(LOG_ERR,
353                                         "hex_to_bin(): invalid char '%c' in hex string",
354                                         c);
355                                 *outlen = 0;
356                                 return 0;
357                         }
358                         byte |= c;
359                 }
360                 if (*in == ':')
361                         in++;
362                 if (left <= 0) {
363                         Log(LOG_ERR,  "hex_to_bin(): hex string too long");
364                         *outlen = 0;
365                         return 0;
366                 }
367                 out[count++] = (unsigned char)byte;
368                 left--;
369         }
371         *outlen = count;
372         return 1;
375 static int str_to_dec(char const * const inPtr, int *dst) {
376         int ret = 1;
377         long val;
379         char *endptr;
381         errno = 0;      /* To distinguish success/failure after call */
382         val = strtol(inPtr, &endptr, 10);
384         /* Check for various possible errors */
385         if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0)) {
386                 Log(LOG_ERR, "String to dec conversion failed");
387                 ret = 0;
388         }
389         if (endptr == inPtr) {
390                 Log(LOG_ERR, "No digits were found");
391                 ret = 0;
392         }
393         if(ret) {
394                 *dst = (int)val;
395         }
396         return ret;
399 /* parse string containing slot and id information */
401 static int parse_slot_id_string(const char *slot_id, int *slot,
402                                 unsigned char *id, size_t * id_len,
403                                 char **label)
405         int n, i;
407         if (!slot_id)
408                 return 0;
410         /* support for several formats */
411 #define HEXDIGITS "01234567890ABCDEFabcdef"
412 #define DIGITS "0123456789"
414         /* first: pure hex number (id, slot is 0) */
415         if (strspn(slot_id, HEXDIGITS) == strlen(slot_id)) {
416                 /* ah, easiest case: only hex. */
417                 if ((strlen(slot_id) + 1) / 2 > *id_len) {
418                         Log(LOG_ERR,  "id string too long!");
419                         return 0;
420                 }
421                 *slot = 0;
422                 return hex_to_bin(slot_id, id, id_len);
423         }
425         /* second: slot:id. slot is an digital int. */
426         if (str_to_dec(slot_id, &n) == 1) {
427                 i = strspn(slot_id, DIGITS);
429                 if (slot_id[i] != ':') {
430                         Log(LOG_ERR,  "could not parse string!");
431                         return 0;
432                 }
433                 i++;
434                 if (slot_id[i] == 0) {
435                         *slot = n;
436                         *id_len = 0;
437                         return 1;
438                 }
439                 if (strspn(slot_id + i, HEXDIGITS) + i != strlen(slot_id)) {
440                         Log(LOG_ERR,  "could not parse string!");
441                         return 0;
442                 }
443                 /* ah, rest is hex */
444                 if ((strlen(slot_id) - i + 1) / 2 > *id_len) {
445                         Log(LOG_ERR,  "id string too long!");
446                         return 0;
447                 }
448                 *slot = n;
449                 return hex_to_bin(slot_id + i, id, id_len);
450         }
452         /* third: id_<id>  */
453         if (strncmp(slot_id, "id_", 3) == 0) {
454                 if (strspn(slot_id + 3, HEXDIGITS) + 3 != strlen(slot_id)) {
455                         Log(LOG_ERR,  "could not parse string!");
456                         return 0;
457                 }
458                 /* ah, rest is hex */
459                 if ((strlen(slot_id) - 3 + 1) / 2 > *id_len) {
460                         Log(LOG_ERR,  "id string too long!");
461                         return 0;
462                 }
463                 *slot = 0;
464                 return hex_to_bin(slot_id + 3, id, id_len);
465         }
467         /* label_<label>  */
468         if (strncmp(slot_id, "label_", 6) == 0) {
469                 *label = strdup(slot_id + 6);
470                 return *label != NULL;
471         }
473         /* last try: it has to be slot_<slot> and then "-id_<cert>" */
475         if (strncmp(slot_id, "slot_", 5) != 0) {
476                 Log(LOG_ERR,  "format not recognized!");
477                 return 0;
478         }
480         /* slot is an digital int. */
481         if (str_to_dec(slot_id + 5, &n) != 1) {
482                 Log(LOG_ERR,  "slot number not deciphered!");
483                 return 0;
484         }
486         i = strspn(slot_id + 5, DIGITS);
488         if (slot_id[i + 5] == 0) {
489                 *slot = n;
490                 *id_len = 0;
491                 return 1; 
492         }
494         if (slot_id[i + 5] != '-') {
495                 Log(LOG_ERR,  "could not parse string!");
496                 return 0;
497         }
499         i = 5 + i + 1;
501         /* now followed by "id_" */
502         if (strncmp(slot_id + i, "id_", 3) == 0) {
503                 if (strspn(slot_id + i + 3, HEXDIGITS) + 3 + i !=
504                     strlen(slot_id)) {
505                         Log(LOG_ERR,  "could not parse string!");
506                         return 0;
507                 }
508                 /* ah, rest is hex */
509                 if ((strlen(slot_id) - i - 3 + 1) / 2 > *id_len) {
510                         Log(LOG_ERR,  "id string too long!");
511                         return 0;
512                 }
513                 *slot = n;
514                 return hex_to_bin(slot_id + i + 3, id, id_len);
515         }
517         /* ... or "label_" */
518         if (strncmp(slot_id + i, "label_", 6) == 0) {
519                 *slot = n;
520                 return (*label = strdup(slot_id + i + 6)) != NULL;
521         }
523         Log(LOG_ERR,  "could not parse string!");
524         return 0;
527 #define MAX_VALUE_LEN   200
529 static X509 *pkcs11_load_cert
531         ENGINE * e,
532         int slot_nr,
533         unsigned char *cert_id,
534         size_t cert_id_len,
535         char *cert_label,
536         struct cert_info **cert_info,
537         int *cert_cnt,
538         int enumerate
541         PKCS11_SLOT *slot_list, *slot;
542         PKCS11_SLOT *found_slot = NULL;
543         PKCS11_TOKEN *tok;
544         PKCS11_CERT *certs, *selected_cert = NULL;
545         X509 *x509 = NULL;
546         unsigned int slot_count, cert_count, n, m;
547         char flags[FLAGS_LEN];
548         int local_init = 0;
550         if (ctx == NULL) {
551                 pkcs11_init(e);
552                 local_init = 1;
553         }
555         if (PKCS11_enumerate_slots(ctx, &slot_list, &slot_count) < 0) {
556                 fail("failed to enumerate slots");
557         }
558         if (verbose) {
559                 Log(LOG_INFO,  "Found %u slot%s", slot_count,
560                         (slot_count <= 1) ? "" : "s");
561         }
563         for (n = 0; n < slot_count; n++) {
564                 slot = slot_list + n;
565                 flags[0] = '\0';
566                 if (slot->token) {
567                         if (!slot->token->initialized)
568                                 strncat(flags, "uninitialized, ", (FLAGS_LEN - strlen(flags) - 1));
569                         else if (!slot->token->userPinSet)
570                                 strncat(flags, "no pin, ", (FLAGS_LEN - strlen(flags) - 1));
571                         if (slot->token->loginRequired)
572                                 strncat(flags, "login, ", (FLAGS_LEN - strlen(flags) - 1));
573                         if (slot->token->readOnly)
574                                 strncat(flags, "ro, ", (FLAGS_LEN - strlen(flags) - 1));
575                 } else {
576                         strncpy(flags, "no token", sizeof(flags));
577                 }
578                 if ((m = strlen(flags)) != 0) {
579                         flags[m - 2] = '\0';
580                 }
582                 if (slot_nr != -1 &&
583                         slot_nr == PKCS11_get_slotid_from_slot(slot)) {
584                         found_slot = slot;
585                 }
587                 if (verbose) {
588                         Log(LOG_INFO,  "[%lu] %-25.25s  %-16s",
589                                 PKCS11_get_slotid_from_slot(slot),
590                                 slot->description, flags);
591                         if (slot->token) {
592                                 Log(LOG_INFO,  "  (%s)",
593                                         slot->token->label[0] ?
594                                         slot->token->label : "no label");
595                         }
596                 }
597         }
599         if (found_slot) {
600                 slot = found_slot; 
601         } else {
602                 Log(LOG_ERR,  "Invalid slot number: %d", (int)slot_nr);
603                 goto err_out;
604         }
606         tok = slot->token;
608         if (tok == NULL) {
609                 Log(LOG_ERR,  "Found empty token; ");
610                 goto err_out;
611         }
613         if (verbose) {
614                 Log(LOG_INFO,  "Found slot:  %s", slot->description);
615                 Log(LOG_INFO,  "Found token: %s", slot->token->label);
616         }
618         if ((tok->loginRequired) && (do_login(slot))) {
619                 Log(LOG_ERR,  "failed to login");
620                 goto err_out;
621         }
623         if (PKCS11_enumerate_certs(tok, &certs, &cert_count)) {
624                 Log(LOG_ERR,  "unable to enumerate certificates");
625                 goto err_out;
626         }
628         if (verbose) {
629                 Log(LOG_INFO,  "Found %u cert%s:", cert_count,
630                         (cert_count <= 1) ? "" : "s");
631         }
633         if (!cert_count)
634                 goto out;
636         if (enumerate) {
637                 *cert_info = calloc(cert_count, sizeof(struct cert_info));
638                 if (!*cert_info)
639                         goto err_out;
641                 /* Copy all certificates */
642                 for (n = 0; n < cert_count; n++) {
643                         PKCS11_CERT *k = certs + n;
644                         struct cert_info *c = *cert_info + n;
646                         if (k->id_len) {
647                                 c->id = malloc(k->id_len);
648                                 if (!c->id)
649                                         goto err_out;
650                                 memcpy(c->id, k->id, k->id_len);
651                                 c->id_len = k->id_len;
652                         }
653                         if (strlen(k->label))
654                                 c->label = strdup(k->label);
655                         c->x509 = X509_dup(k->x509);
656                 }
657                 *cert_cnt = n;
658                 goto out;
659         }
661         /* Find the matching cert */
662         if (cert_id_len || cert_label) {
663                 for (n = 0; n < cert_count; n++) {
664                         PKCS11_CERT *k = certs + n;
666                         if (cert_label == NULL) {
667                                 if (cert_id_len != 0 && k->id_len == cert_id_len &&
668                                 memcmp(k->id, cert_id, cert_id_len) == 0) {
669                                         selected_cert = k;
670                                 }
671                         } else {
672                                 if (strcmp(k->label, cert_label) == 0) {
673                                         selected_cert = k;
674                                 }
675                         }
676                 }
677         } else {
678                 selected_cert = certs;  /* use first */
679         }
681         if (selected_cert == NULL) {
682                 Log(LOG_ERR,  "certificate not found.");
683                 goto err_out;
684         }
686         x509 = X509_dup(selected_cert->x509);
687         goto out;
689 err_out:
690         if (*cert_info) {
691                 for (n = 0; n < cert_count; n++) {
692                         PKCS11_CERT *k = certs + n;
693                         struct cert_info *c = *cert_info + n;
695                         if (!c->id)
696                                 free(c->id);
697                         if (!c->label)
698                                 free(c->label);
699                         if (!c->x509)
700                                 X509_free(c->x509);
701                 }
702                 free(*cert_info);
703                 *cert_info = NULL;
704         }
706         PKCS11_release_all_slots(ctx, slot_list, slot_count);
708 out:
709         if (local_init) {
710                 free_pkcs11_ctx();
711         }
712         return x509;
715 int load_cert_ctrl(ENGINE * e, void *p)
717         struct cert_ctrl_params *params = p;
719         if (params->cert != NULL)
720                 return 0;
722         params->cert = pkcs11_load_cert(e, params->slot_nr, params->cert_id,
723                                 params->cert_id_len, params->cert_label,
724                                 NULL, NULL, 0);
726         if (params->cert == NULL)
727                 return 0;
729         return 1;
733 int enumerate_certs_ctrl(ENGINE * e, void *p)
735         struct enum_certs_ctrl_param *params = p;
737         if (params->info != NULL)
738                 return 0;
740         pkcs11_load_cert(e, params->slot_nr, 0, 0, NULL,
741                         &params->info, &params->cnt, 1);
743         if (params->info == NULL)
744                 return 0;
746         return 1;
750 static EVP_PKEY *pkcs11_load_key
752         ENGINE * e,
753         int slot_nr,
754         unsigned char *key_id,
755         size_t key_id_len,
756         char *key_label,
757         UI_METHOD * ui_method,
758         void *callback_data,
759         int isPrivate
762         PKCS11_SLOT *slot_list, *slot;
763         PKCS11_SLOT *found_slot = NULL;
764         PKCS11_TOKEN *tok;
765         PKCS11_KEY *keys, *selected_key = NULL;
766         PKCS11_CERT *certs;
767         EVP_PKEY *pk = NULL;
768         unsigned int slot_count, cert_count, key_count, n, m;
769         char flags[FLAGS_LEN];
770         int local_init = 0;
772         if (ctx == NULL) {
773                 pkcs11_init(e);
774                 local_init = 1;
775         }
777         if (PKCS11_enumerate_slots(ctx, &slot_list, &slot_count) < 0)
778                 fail("failed to enumerate slots");
780         if (verbose) {
781                 Log(LOG_INFO,  "Found %u slot%s", slot_count,
782                         (slot_count <= 1) ? "" : "s");
783         }
785         for (n = 0; n < slot_count; n++) {
786                 slot = slot_list + n;
787                 flags[0] = '\0';
788                 if (slot->token) {
789                         if (!slot->token->initialized)
790                                 strncat(flags, "uninitialized, ", FLAGS_LEN - strlen(flags) - 1);
791                         else if (!slot->token->userPinSet)
792                                 strncat(flags, "no pin, ", FLAGS_LEN - strlen(flags) - 1);
793                         if (slot->token->loginRequired)
794                                 strncat(flags, "login, ", FLAGS_LEN - strlen(flags) - 1);
795                         if (slot->token->readOnly)
796                                 strncat(flags, "ro, ", FLAGS_LEN - strlen(flags) - 1);
797                 } else {
798                         strncpy(flags, "no token", sizeof(flags));
799                 }
800                 if ((m = strlen(flags)) != 0) {
801                         flags[m - 2] = '\0';
802                 }
804                 if (slot_nr != -1 &&
805                         slot_nr == PKCS11_get_slotid_from_slot(slot)) {
806                         found_slot = slot;
807                 }
809                 if (verbose) {
810                         Log(LOG_INFO,  "[%lu] %-25.25s  %-16s",
811                                 PKCS11_get_slotid_from_slot(slot),
812                                 slot->description, flags);
813                         if (slot->token) {
814                                 Log(LOG_INFO,  "  (%s)",
815                                         slot->token->label[0] ?
816                                         slot->token->label : "no label");
817                         }
818                 }
819         }
821         if (slot_nr == -1) {
822                 if (!(slot = PKCS11_find_token(ctx, slot_list, slot_count)))
823                         fail("didn't find any tokens");
824         } else if (found_slot) {
825                 slot = found_slot;
826         } else {
827                 Log(LOG_ERR,  "Invalid slot number: %d", slot_nr);
828                 PKCS11_release_all_slots(ctx, slot_list, slot_count);
829                 goto out;
830         }
831         tok = slot->token;
833         if (tok == NULL) {
834                 Log(LOG_INFO,  "Found empty token; ");
835                 PKCS11_release_all_slots(ctx, slot_list, slot_count);
836                 goto out;
837         }
839         if (isPrivate && !tok->userPinSet && !tok->readOnly) {
840                 Log(LOG_INFO,  "Found slot without user PIN");
841                 PKCS11_release_all_slots(ctx, slot_list, slot_count);
842                 goto out;
843         }
845         if (verbose) {
846                 Log(LOG_INFO,  "Found slot:  %s", slot->description);
847                 Log(LOG_INFO,  "Found token: %s", slot->token->label);
848         }
850 #ifdef DEBUG
851         if (PKCS11_enumerate_certs(tok, &certs, &cert_count))
852                 fail("unable to enumerate certificates");
854         if (verbose) {
855                 Log(LOG_INFO,  "Found %u certificate%s:", cert_count,
856                         (cert_count <= 1) ? "" : "s");
857                 for (n = 0; n < cert_count; n++) {
858                         PKCS11_CERT *c = certs + n;
859                         char *dn = NULL;
861                         Log(LOG_INFO,  "  %2u   %s", n + 1, c->label);
862                         if (c->x509)
863                                 dn = X509_NAME_oneline(X509_get_subject_name
864                                                        (c->x509), NULL, 0);
865                         if (dn) {
866                                 Log(LOG_INFO,  " (%s)", dn);
867                                 OPENSSL_free(dn);
868                         }
869                 }
870         }
871 #endif
873         /* Perform login to the token if required */
874         if (tok->loginRequired) {
875                 /* If the token has a secure login (i.e., an external keypad),
876                    then use a NULL pin. Otherwise, check if a PIN exists. If
877                    not, allocate and obtain a new PIN. */
878                 if (tok->secureLogin) {
879                         /* Free the PIN if it has already been 
880                            assigned (i.e, cached by get_pin) */
881                         if (pin != NULL) {
882                                 OPENSSL_cleanse(pin, pin_length);
883                                 free(pin);
884                                 pin = NULL;
885                                 pin_length = 0;
886                         }
887                 } else if (pin == NULL) {
888                         pin = (char *)calloc(MAX_PIN_LENGTH, sizeof(char));
889                         pin_length = MAX_PIN_LENGTH;
890                         if (pin == NULL) {
891                                 fail("Could not allocate memory for PIN");
892                         }
893                         if (!get_pin(ui_method, callback_data) ) {
894                                 OPENSSL_cleanse(pin, pin_length);
895                                 free(pin);
896                                 pin = NULL;
897                                 pin_length = 0;
898                                 fail("No pin code was entered");
899                         }
900                 }
902                 /* Now login in with the (possibly NULL) pin */
903                 if (PKCS11_login(slot, 0, pin)) {
904                         /* Login failed, so free the PIN if present */
905                         if (pin != NULL) {
906                                 OPENSSL_cleanse(pin, pin_length);
907                                 free(pin);
908                                 pin = NULL;
909                                 pin_length = 0;
910                         }
911                         fail("Login failed");
912                 }
913                 /* Login successful, PIN retained in case further logins are 
914                    required. This will occur on subsequent calls to the
915                    pkcs11_load_key function. Subsequent login calls should be
916                    relatively fast (the token should maintain its own login
917                    state), although there may still be a slight performance 
918                    penalty. We could maintain state noting that successful
919                    login has been performed, but this state may not be updated
920                    if the token is removed and reinserted between calls. It
921                    seems safer to retain the PIN and peform a login on each
922                    call to pkcs11_load_key, even if this may not be strictly
923                    necessary. */
924                 /* TODO when does PIN get freed after successful login? */
925                 /* TODO confirm that multiple login attempts do not introduce
926                    significant performance penalties */
928         }
930         /* Make sure there is at least one private key on the token */
931         if (PKCS11_enumerate_keys(tok, &keys, &key_count)) {
932                 fail("unable to enumerate keys");
933         }
934         if (key_count == 0) {
935                 fail("No keys found.");
936         }
938         if (verbose) {
939                 Log(LOG_INFO,  "Found %u key%s:", key_count,
940                         (key_count <= 1) ? "" : "s");
941         }
942         if ((key_id_len != 0) || (key_label != NULL)) {
943                 for (n = 0; n < key_count; n++) {
944                         PKCS11_KEY *k = keys + n;
946                         if (verbose) {
947                                 Log(LOG_INFO,  "  %2u %c%c %s", n + 1,
948                                         k->isPrivate ? 'P' : ' ',
949                                         k->needLogin ? 'L' : ' ', k->label);
950                         }
952                         if (!!isPrivate != !!(k->isPrivate)) continue;
954                         if (key_label == NULL) {
955                                 if (key_id_len != 0 && k->id_len == key_id_len
956                                     && (memcmp(k->id, key_id, key_id_len) == 0)) {
957                                         selected_key = k;
958                                 }
959                         } else {
960                                 if (strcmp(k->label, key_label) == 0) {
961                                         selected_key = k;
962                                 }
963                         }
964                 }
965         } else {
966                 selected_key = keys;    /* use first */
967         }
969         if (selected_key == NULL) {
970                 Log(LOG_ERR,  "key not found.");
971                 goto out;
972         }
974         if (isPrivate) {
975                 pk = PKCS11_get_private_key(selected_key);
976         } else {
977                 pk = PKCS11_get_public_key(selected_key);
978         }
980 out:
981         if (local_init) {
982                 free_pkcs11_ctx();
983         }
985         return pk;
988 EVP_PKEY *pkcs11_load_public_key(ENGINE * e, const char *s_key_id,
989                                  UI_METHOD * ui_method, void *callback_data)
991         int n;
992         unsigned char key_id[MAX_VALUE_LEN / 2];
993         size_t key_id_len = sizeof(key_id);
994         char *key_label = NULL;
995         int slot_nr = -1;
996         EVP_PKEY *pk;
998         n = parse_key_string(s_key_id, &slot_nr, key_id, &key_id_len,
999                                 &key_label, NULL);
1000         if (n) {
1001                 Log(LOG_INFO,
1002                         "supported format: slot_<slot>:id_<id>:label_<label>");
1003                 Log(LOG_INFO,
1004                         "where <slot> is the slot number as normal integer,");
1005                 Log(LOG_INFO,
1006                         "and <id> is the id number as hex string.");
1007                 Log(LOG_INFO,
1008                         "and <label> is the textual key label string.");
1009                 return NULL;
1010         }
1012         pk = pkcs11_load_key(e, slot_nr, key_id, key_id_len, key_label,
1013                         ui_method, callback_data, 0);
1014         if (pk == NULL)
1015                 Log(LOG_INFO,  "PKCS11_load_public_key returned NULL");
1017     if (key_label) free(key_label);
1018         return pk;
1021 EVP_PKEY *pkcs11_load_private_key(ENGINE * e, const char *s_key_id,
1022                                   UI_METHOD * ui_method, void *callback_data)
1024         int n;
1025         unsigned char key_id[MAX_VALUE_LEN / 2];
1026         size_t key_id_len = sizeof(key_id);
1027         char *key_label = NULL;
1028         int slot_nr = -1;
1029         EVP_PKEY *pk;
1031         n = parse_key_string(s_key_id, &slot_nr, key_id, &key_id_len,
1032                                 &key_label, NULL);
1033         if (n) {
1034                 Log(LOG_INFO,
1035                         "supported format: slot_<slot>:id_<id>:label_<label>");
1036                 Log(LOG_INFO,
1037                         "where <slot> is the slot number as normal integer,");
1038                 Log(LOG_INFO,
1039                         "and <id> is the id number as hex string.");
1040                 Log(LOG_INFO,
1041                         "and <label> is the textual key label string.");
1042                 return NULL;
1043         }
1045         pk = pkcs11_load_key(e, slot_nr, key_id, key_id_len, key_label,
1046                         ui_method, callback_data, 1);
1047         if (pk == NULL)
1048                 Log(LOG_INFO,  "PKCS11_get_private_key returned NULL");
1050     if (key_label) free(key_label);
1051         return pk;
1054 int list_token_objects
1056         ENGINE * e,
1057         long slot_nr /* slot number */
1060         PKCS11_SLOT *slot_list, *slot, *found_slot = NULL;
1061         PKCS11_TOKEN *tok;
1062         PKCS11_CERT *certs;
1063         PKCS11_KEY *keys;
1064         unsigned int slot_count, cert_count, key_count, m, n, i;
1065         char flags[FLAGS_LEN];
1066         int local_init = 0;
1067         int ret_val = 0;
1069         if (verbose) {
1070                 Log(LOG_INFO,  "Displaying token objects from slot %d", (int)slot_nr);
1071         }
1073         if (ctx == NULL) {
1074                 pkcs11_init(e);
1075                 local_init = 1;
1076         }
1077         if (PKCS11_enumerate_slots(ctx, &slot_list, &slot_count)) {
1078                 Log(LOG_ERR,  "failed to enumerate slots");
1079                 goto out;
1080         }
1082         if (verbose) {
1083                 Log(LOG_INFO,  "Found %u slots", slot_count);
1084         }
1086         for (n = 0; n < slot_count; n++) {
1087                 slot = slot_list + n;
1088                 flags[0] = '\0';
1089                 if (slot->token) {
1090                         if (!slot->token->initialized)
1091                                 strncat(flags, "uninitialized, ", (FLAGS_LEN - strlen(flags) - 1));
1092                         else if (!slot->token->userPinSet)
1093                                 strncat(flags, "no pin, ", (FLAGS_LEN - strlen(flags) - 1));
1094                         if (slot->token->loginRequired)
1095                                 strncat(flags, "login, ", (FLAGS_LEN - strlen(flags) - 1));
1096                         if (slot->token->readOnly)
1097                                 strncat(flags, "ro, ", (FLAGS_LEN - strlen(flags) - 1));
1098                 } else {
1099                         strncpy(flags, "no token", sizeof(flags));
1100                 }
1101                 if ((m = strlen(flags)) != 0) {
1102                         flags[m - 2] = '\0';
1103                 }
1105                 if (slot_nr != -1 &&
1106                         slot_nr == PKCS11_get_slotid_from_slot(slot)) {
1107                         found_slot = slot;
1108                 }
1110                 if (verbose) {
1111                         Log(LOG_INFO,  "[%lu] %-25.25s  %-16s",
1112                                 PKCS11_get_slotid_from_slot(slot),
1113                                 slot->description, flags);
1114                         if (slot->token) {
1115                                 Log(LOG_INFO,  "  (%s)",
1116                                         slot->token->label[0] ?
1117                                         slot->token->label : "no label");
1118                         }
1119                 }
1120         }
1122         if (found_slot) {
1123                 slot = found_slot; 
1124         } else {
1125                 Log(LOG_ERR,  "Invalid slot number: %d", (int)slot_nr);
1126                 PKCS11_release_all_slots(ctx, slot_list, slot_count);
1127                 goto out;
1128         }
1130         tok = slot->token;
1132         if (tok == NULL) {
1133                 Log(LOG_ERR,  "Found empty token; ");
1134                 PKCS11_release_all_slots(ctx, slot_list, slot_count);
1135                 goto out;
1136         }
1138         if (verbose) {
1139                 Log(LOG_INFO,  "Found slot:  %s", slot->description);
1140                 Log(LOG_INFO,  "Found token: %s", slot->token->label);
1141         }
1143         if ((tok->loginRequired) && (do_login(slot))) {
1144                 Log(LOG_ERR,  "failed to login");
1145                 PKCS11_release_all_slots(ctx, slot_list, slot_count);
1146                 goto out;
1147         }
1149         if (PKCS11_enumerate_certs(tok, &certs, &cert_count)) {
1150                 Log(LOG_ERR,  "unable to enumerate certificates");
1151                 PKCS11_release_all_slots(ctx, slot_list, slot_count);
1152                 goto out;
1153         }
1155         for (n=0; n<cert_count; n++) {
1156                 char tmp[MAX_VALUE_LEN];
1157                 PKCS11_CERT *c = certs + n;
1158                 char *dn = NULL;
1160                 Log(LOG_INFO,  "Certificate Object:");
1161                 Log(LOG_INFO,  "\ttype: X.509 cert");
1162                 Log(LOG_INFO,  "\tlabel: %s", c->label);
1163                 for (i = 0; i < c->id_len; i++) {
1164                         snprintf(&tmp[i*2], 2, "%02x", c->id[i]);
1165                 }
1166                 Log(LOG_INFO,  "\tID: %s", tmp);
1168                 if (c->x509)
1169                         dn = X509_NAME_oneline(X509_get_subject_name(c->x509),
1170                                                 NULL, 0);
1171                 if (dn) {
1172                         Log(LOG_INFO,  "\tname: %s", dn);
1173                         OPENSSL_free(dn);
1174                 }
1175         }
1177         if (PKCS11_enumerate_keys(tok, &keys, &key_count)) {
1178                 Log(LOG_ERR,  "unable to enumerate keys");
1179                 PKCS11_release_all_slots(ctx, slot_list, slot_count);
1180                 goto out;
1181         }
1183         for (n=0; n<key_count; n++) {
1184                 char tmp[MAX_VALUE_LEN];
1186                 PKCS11_KEY *k = keys + n;
1188                 if (k->isPrivate) {
1189                         Log(LOG_INFO,  "Private Key Object:");
1190                         Log(LOG_INFO,  "\ttype: RSA");
1191                 } else {
1192                         Log(LOG_INFO,  "Public Key Object:");
1193                         Log(LOG_INFO,  "\ttype: RSA %d bits",
1194                                 (PKCS11_get_key_size(k)*8)); 
1195                 }
1196                 Log(LOG_INFO,  "\tlabel: %s", k->label);
1197                 for (i = 0; i < k->id_len; i++) {
1198                         snprintf(&tmp[i*2], 2, "%02x", k->id[i]);
1199                 }
1200                 Log(LOG_INFO,  "\tID: %s", tmp);
1201         }
1203         ret_val = 1;
1205 out:
1206         if (local_init) {
1207                 free_pkcs11_ctx();
1208         }
1210         return ret_val;
1213 static int do_login(PKCS11_SLOT *slot)
1215         PKCS11_TOKEN *tok = slot->token;
1217         if (pin == NULL) {
1218                 Log(LOG_INFO,  "PIN not set");
1219                 return -1;
1220         }
1222         /* Now login in with the (possibly NULL) pin */
1223         if (PKCS11_login(slot, 0, pin)) {
1224         /* Login failed, so free the PIN if present */
1225                 if (pin != NULL) {
1226                         OPENSSL_cleanse(pin, pin_length);
1227                         free(pin);
1228                         pin = NULL;
1229                         pin_length = 0;
1230                 }
1231                 Log(LOG_ERR,  "Login failed");
1232                 return -1;
1233         }
1234         return 0;
1237 int store_cert_ctrl(ENGINE * e, void *p)
1239         struct cert_ctrl_params *params = p;
1241         if (params->cert == NULL)
1242                 return 0;
1244         if (pkcs11_store_cert(e, params->slot_nr, params->cert_id,
1245                                                 params->cert_id_len, params->cert_label, params->cert))
1246                 return 0;
1248         return 1;
1251 int store_cert_cmd(ENGINE * e, const char *p)
1253         int n, rv=0;
1254         unsigned char cert_id[MAX_VALUE_LEN / 2];
1255         size_t cert_id_len = sizeof(cert_id);
1256         char *cert_label = NULL;
1257         char *cert_file = NULL;
1258         int slot_nr = -1;
1259         unsigned char data[MAX_OBJECT_SIZE];
1260         const unsigned char *pp = data;
1261         int data_len = 0;
1262         FILE *f = NULL;
1263         X509 *x;
1265         if (!p || !*p) {
1266                 Log(LOG_ERR,  "no parameter");
1267                 return 0;
1268         }
1270         n = parse_cert_store_string(p, &slot_nr, cert_id, &cert_id_len,
1271                                                                 &cert_label, &cert_file);
1272         if (n) {
1273                 Log(LOG_INFO,
1274                         "supported format: slot_<slot>:id_<id>:label_<label>:cert_<filename>");
1275                 Log(LOG_INFO,
1276                         "where <slot> is the slot number as normal integer,");
1277                 Log(LOG_INFO,
1278                         "and <id> is the id number as hex string.");
1279                 Log(LOG_INFO,
1280                         "and <label> is the textual cert label string.");
1281                 Log(LOG_INFO,
1282                         "and <filename> is the cert filename with full path.");
1283                 goto store_cert_err_out;
1284         }
1286         f = fopen(cert_file, "rb");
1287         if (f == NULL) {
1288                 Log(LOG_ERR,  "Couldn't open cert file \"%s\"", cert_file);
1289                 goto store_cert_err_out;
1290         }
1292         data_len = fread(data, 1, sizeof(data), f);
1294         if (data_len < 0) {
1295                 Log(LOG_ERR,  "Couldn't read from file \"%s\"", cert_file);
1296                 goto store_cert_err_out;
1297         }
1299         x = d2i_X509(NULL, &pp, data_len); 
1300         if (!x) {
1301                 Log(LOG_ERR,  "OpenSSL cert parse error");
1302                 goto store_cert_err_out;
1303         }
1305         /* No ID specified */
1306         if (cert_id_len == sizeof(cert_id))
1307                 cert_id_len = 0;
1309         if (verbose) {
1310                 char tmp[MAX_VALUE_LEN];
1311                 for (n = 0; n < cert_id_len; n++) {
1312                         snprintf(&tmp[n*2], 2, "%02x", cert_id[n]);
1313                 }
1314                 Log(LOG_INFO, "Storing cert(%s) in slot(%d) with label(%s) and id(%s)",
1315                         cert_file, slot_nr, cert_label, tmp);
1316         }
1318         if (pkcs11_store_cert(e, slot_nr, cert_id, cert_id_len, cert_label, x))
1319                 goto store_cert_err_out;
1321         rv = 1;
1323 store_cert_err_out:
1324         if (f) fclose(f);
1325     if (cert_label) free(cert_label);
1326     if (cert_file) free(cert_file);
1327         return rv;
1330 static int pkcs11_store_cert
1332         ENGINE * e,
1333         int slot_nr,
1334         unsigned char *cert_id,
1335         size_t cert_id_len,
1336         char *cert_label,
1337         X509 *x
1340         PKCS11_SLOT *slot_list, *slot;
1341         PKCS11_SLOT *found_slot = NULL;
1342         PKCS11_TOKEN *tok;
1343         PKCS11_CERT *certs, *ret_cert = NULL;
1344         unsigned int slot_count, cert_count;
1345         char flags[FLAGS_LEN];
1346         int n,m;
1347         int ret_val = -1;
1348         int local_init = 0;
1350         if (ctx == NULL) {
1351                 pkcs11_init(e);
1352                 local_init = 1;
1353         }
1355         if (PKCS11_enumerate_slots(ctx, &slot_list, &slot_count)) {
1356                 Log(LOG_ERR,  "failed to enumerate slots");
1357                 goto out;
1358         }
1360         if (verbose) {
1361                 Log(LOG_INFO,  "Found %u slots", slot_count);
1362         }
1364         for (n = 0; n < slot_count; n++) {
1365                 slot = slot_list + n;
1366                 flags[0] = '\0';
1367                 if (slot->token) {
1368                         if (!slot->token->initialized)
1369                                 strncat(flags, "uninitialized, ", FLAGS_LEN - strlen(flags) - 1);
1370                         else if (!slot->token->userPinSet)
1371                                 strncat(flags, "no pin, ", FLAGS_LEN - strlen(flags) - 1);
1372                         if (slot->token->loginRequired)
1373                                 strncat(flags, "login, ", FLAGS_LEN - strlen(flags) - 1);
1374                         if (slot->token->readOnly)
1375                                 strncat(flags, "ro, ", FLAGS_LEN - strlen(flags) - 1);
1376                 } else {
1377                         strncpy(flags, "no token", sizeof(flags));
1378                 }
1379                 if ((m = strlen(flags)) != 0) {
1380                         flags[m - 2] = '\0';
1381                 }
1383                 if (slot_nr != -1 &&
1384                         slot_nr == PKCS11_get_slotid_from_slot(slot)) {
1385                         found_slot = slot;
1386                 }
1388                 if (verbose) {
1389                         Log(LOG_INFO,  "[%lu] %-25.25s  %-16s",
1390                                 PKCS11_get_slotid_from_slot(slot),
1391                                 slot->description, flags);
1392                         if (slot->token) {
1393                                 Log(LOG_INFO,  "  (%s)",
1394                                         slot->token->label[0] ?
1395                                         slot->token->label : "no label");
1396                         }
1397                 }
1398         }
1400         if (found_slot) {
1401                 slot = found_slot; 
1402         } else {
1403                 Log(LOG_ERR,  "Invalid slot number: %d", (int)slot_nr);
1404                 goto err_out;
1405         }
1407         tok = slot->token;
1409         if (tok == NULL) {
1410                 Log(LOG_ERR,  "Found empty token; ");
1411                 goto err_out;
1412         }
1414         if (verbose) {
1415                 Log(LOG_INFO,  "Found slot:  %s", slot->description);
1416                 Log(LOG_INFO,  "Found token: %s", slot->token->label);
1417         }
1419         if ((tok->loginRequired) && (do_login(slot))) {
1420                 Log(LOG_ERR,  "failed to login");
1421                 goto err_out;
1422         }
1424         /* Enumerate certs to initialize libp11 cert count */
1425         if (PKCS11_enumerate_certs(tok, &certs, &cert_count)) {
1426                 Log(LOG_ERR,  "unable to enumerate certificates");
1427                 goto err_out;
1428         }
1430         if (PKCS11_store_certificate(tok, x, cert_label, cert_id,
1431                                                                 cert_id_len, &ret_cert)) {
1432                 Log(LOG_ERR,  "failed to store cert");
1433                 goto err_out;
1434         }
1436         ret_val = 0;
1437         goto out;
1439 err_out:
1440         PKCS11_release_all_slots(ctx, slot_list, slot_count);
1442 out:
1443         if(local_init) {
1444                 free_pkcs11_ctx();
1445         }
1447         return ret_val;
1450 static int parse_cert_store_string
1452         const char *cert_store_str,
1453         int *slot,
1454         unsigned char *id,
1455         size_t * id_len,
1456         char **label,
1457         char **cert_file
1460         char *token;
1461         const char *sep = ":";
1462         char *str, *lasts;
1463     int rv = -1;
1465         if (!cert_store_str)
1466                 return -1;
1468         str = strdup(cert_store_str);
1469         if (str == NULL)
1470                 return -1;
1472         /* Default values */
1473         *slot = 0;
1474         *label = NULL;
1475         *cert_file = NULL;
1477         token = strtok_r(str, sep, &lasts);
1479         while (token) {
1481                 /* slot identifier */
1482                 if (!strncmp(token, "slot_", 5)) {
1483                         /* slot is a decimal number */
1484                         if (str_to_dec(token + 5, slot) != 1) {
1485                                 Log(LOG_ERR,  "slot number not deciphered!");
1486                 goto err;
1487                         }
1488                 } else if (!strncmp(token, "id_", 3)) {
1489                         /* certificate ID */
1490                         /* id is hexadecimal number */
1491                         if (!hex_to_bin(token + 3, id, id_len)) {
1492                                 Log(LOG_ERR,  "id not deciphered!");
1493                 goto err;
1494                         }
1495                 } else if (!strncmp(token, "label_", 6)) {
1496                         /* label */
1497                         /*  label is string */
1498                         *label = strdup(token + 6);
1499                         if (*label == NULL) {
1500                                 Log(LOG_ERR,  "label not deciphered!");
1501                 goto err;
1502                         }
1503                 } else if (!strncmp(token, "cert_", 5)) {
1504                         /* cert file name */
1505                         *cert_file = strdup(token + 5);
1506                         if (*cert_file == NULL) {
1507                                 Log(LOG_ERR,  "cert file not deciphered!");
1508                 goto err;
1509                         }
1510                 }
1511                 token = strtok_r(NULL, sep, &lasts);
1512         } /* end while(token) */
1514         if (*cert_file == NULL) {
1515                 Log(LOG_ERR,  "cert file name not present!");
1516                 goto err;
1517         }
1519     rv = 0;     
1521 err: 
1522     if (str) free(str);
1523     if (rv && *label) { free(*label); *label = NULL; }
1524     if (rv && *cert_file) { free(*cert_file); *cert_file = NULL; }
1525     return rv;
1528 int gen_key_cmd(ENGINE * e, const char *p)
1530         int key_size, n;
1531         unsigned char key_id[MAX_VALUE_LEN / 2];
1532         size_t key_id_len = sizeof(key_id);
1533         char *key_label = NULL;
1534         int slot_nr = -1;
1535     int rv = 0;
1537         if (!p || !*p) {
1538                 Log(LOG_ERR,  "no parameter");
1539                 return 0;
1540         }
1542         n = parse_key_gen_string(p, &slot_nr, &key_size, key_id, &key_id_len,
1543                                                          &key_label);
1544         if (n) {
1545                 Log(LOG_INFO,
1546                         "supported format: slot_<slot>:size_<size>:id_<id>:label_<label>");
1547                 Log(LOG_INFO,
1548                         "where <slot> is the slot number as normal integer,");
1549                 Log(LOG_INFO,
1550                         "and <size> is the RSA key size in bits.");
1551                 Log(LOG_INFO,
1552                         "and <id> is the id number as hex string.");
1553                 Log(LOG_INFO,
1554                         "and <label> is the textual cert label string.");
1555                 goto gen_key_err_out;
1556         }
1558         if (verbose) {
1559                 char tmp[MAX_VALUE_LEN];
1560                 for (n = 0; n < key_id_len; n++) {
1561                         snprintf(&tmp[n*2], 2, "%02x", key_id[n]);
1562                 }
1563                 Log(LOG_INFO, "Generating %dbits RSA key in slot(%d) with label(%s) and id(s)",
1564                         key_size, slot_nr, key_label, tmp);
1565         }
1567         if (pkcs11_gen_key(e, slot_nr, (unsigned int)key_size, key_id, key_id_len, key_label))
1568                 goto gen_key_err_out;
1570         rv = 1;
1572 gen_key_err_out:
1573     if (key_label) free(key_label);
1574         return rv;
1578 static int parse_key_gen_string
1580         const char *key_gen_str,
1581         int *slot,
1582         int *key_size,
1583         unsigned char *id,
1584         size_t * id_len,
1585         char **label
1588         char *token;
1589         const char *sep = ":";
1590         char *str, *lasts;
1591     int rv = -1;
1593         if (!key_gen_str)
1594                 return -1;
1596         str = strdup(key_gen_str);
1597         if (str == NULL)
1598                 return -1;
1600         /* Default values */
1601         *slot = 0;
1602         *label = NULL;
1603         *key_size = -1;
1605         token = strtok_r(str, sep, &lasts);
1607         while (token) {
1609                 /* slot identifier */
1610                 if (!strncmp(token, "slot_", 5)) {
1611                         /* slot is a decimal number */
1612                         if (str_to_dec(token + 5, slot) != 1) {
1613                                 Log(LOG_ERR,  "slot number not deciphered!");
1614                 goto err;
1615                         }
1616                 } else if (!strncmp(token, "id_", 3)) {
1617                         /* certificate ID */
1618                         /* id is hexadecimal number */
1619                         if (!hex_to_bin(token + 3, id, id_len)) {
1620                                 Log(LOG_ERR,  "id not deciphered!");
1621                 goto err;
1622                         }
1623                 } else if (!strncmp(token, "label_", 6)) {
1624                         /* label */
1625                         /*  label is string */
1626                         *label = strdup(token + 6);
1627                         if (*label == NULL) {
1628                                 Log(LOG_ERR,  "label not deciphered!");
1629                 goto err;
1630                         }
1631                 } else if (!strncmp(token, "size_", 5)) {
1632                         /* key size in bits */
1633                         if (str_to_dec(token + 5, key_size) != 1) {
1634                                 Log(LOG_ERR,  "key size not deciphered!");
1635                 goto err;
1636                         }
1637                 }
1638                 token = strtok_r(NULL, sep, &lasts);
1639         } /* end while(token) */
1641         if (*key_size == -1) {
1642                 Log(LOG_ERR,  "key size not present!");
1643         goto err;
1644         }
1646         rv = 0;
1647 err:
1648     if (str) free(str);
1649     if (rv && *label) { free(*label); *label = NULL; }
1650     return rv;
1653 static int pkcs11_gen_key
1655         ENGINE * e,
1656         int slot_nr,
1657         unsigned int key_size,
1658         unsigned char *key_id,
1659         size_t key_id_len,
1660         char *key_label
1663         PKCS11_SLOT *slot_list, *slot;
1664         PKCS11_SLOT *found_slot = NULL;
1665         PKCS11_TOKEN *tok;
1666         PKCS11_KEY *keys, *ret_key = NULL;
1667         unsigned int slot_count, key_count;
1668         char flags[FLAGS_LEN];
1669         int n,m;
1670         int ret_val = -1;
1671         int local_init = 0;
1673         if (ctx == NULL) {
1674                 pkcs11_init(e);
1675                 local_init = 1;
1676         }
1678         if (PKCS11_enumerate_slots(ctx, &slot_list, &slot_count)) {
1679                 Log(LOG_ERR,  "failed to enumerate slots");
1680                 goto out;
1681         }
1683         if (verbose) {
1684                 Log(LOG_INFO,  "Found %u slots", slot_count);
1685         }
1687         for (n = 0; n < slot_count; n++) {
1688                 slot = slot_list + n;
1689                 flags[0] = '\0';
1690                 if (slot->token) {
1691                         if (!slot->token->initialized)
1692                                 strncat(flags, "uninitialized, ", (FLAGS_LEN - strlen(flags) - 1));
1693                         else if (!slot->token->userPinSet)
1694                                 strncat(flags, "no pin, ", (FLAGS_LEN - strlen(flags) - 1));
1695                         if (slot->token->loginRequired)
1696                                 strncat(flags, "login, ", (FLAGS_LEN - strlen(flags) - 1));
1697                         if (slot->token->readOnly)
1698                                 strncat(flags, "ro, ", (FLAGS_LEN - strlen(flags) - 1));
1699                 } else {
1700                         strncpy(flags, "no token", sizeof(flags));
1701                 }
1702                 if ((m = strlen(flags)) != 0) {
1703                         flags[m - 2] = '\0';
1704                 }
1706                 if (slot_nr != -1 &&
1707                         slot_nr == PKCS11_get_slotid_from_slot(slot)) {
1708                         found_slot = slot;
1709                 }
1711                 if (verbose) {
1712                         Log(LOG_INFO,  "[%lu] %-25.25s  %-16s",
1713                                 PKCS11_get_slotid_from_slot(slot),
1714                                 slot->description, flags);
1715                         if (slot->token) {
1716                                 Log(LOG_INFO,  "  (%s)",
1717                                         slot->token->label[0] ?
1718                                         slot->token->label : "no label");
1719                         }
1720                 }
1721         }
1723         if (found_slot) {
1724                 slot = found_slot; 
1725         } else {
1726                 Log(LOG_ERR,  "Invalid slot number: %d", (int)slot_nr);
1727                 goto err_out;
1728         }
1730         tok = slot->token;
1732         if (tok == NULL) {
1733                 Log(LOG_ERR,  "Found empty token; ");
1734                 goto err_out;
1735         }
1737         if (verbose) {
1738                 Log(LOG_INFO,  "Found slot:  %s", slot->description);
1739                 Log(LOG_INFO,  "Found token: %s", slot->token->label);
1740         }
1742         if ((tok->loginRequired) && (do_login(slot))) {
1743                 Log(LOG_ERR,  "failed to login");
1744                 goto err_out;
1745         }
1747         /* Enumerate keys to initialize libp11 key count */
1748         if (PKCS11_enumerate_keys(tok, &keys, &key_count)) {
1749                 Log(LOG_ERR,  "unable to enumerate keys");
1750                 goto err_out;
1751         }
1753         if (PKCS11_generate_key(tok, EVP_PKEY_RSA, key_size, key_label,
1754                                                         key_id, key_id_len)) {
1755                 Log(LOG_ERR,  "failed to generate RSA key pair");
1756                 goto err_out;
1757         }
1759         ret_val = 0;
1760         goto out;
1762 err_out:
1763         PKCS11_release_all_slots(ctx, slot_list, slot_count);
1764 out:
1765         if (local_init) {
1766                 free_pkcs11_ctx();
1767         }
1768         return ret_val;
1771 int del_obj_cmd(ENGINE * e, const char *p)
1773         int n;
1774         unsigned char id[MAX_VALUE_LEN / 2];
1775         size_t id_len = sizeof(id);
1776         char *label = NULL, *type = NULL;
1777         int slot_nr = -1;
1778     int rv = 0;
1780         if (!p || !*p) {
1781                 Log(LOG_ERR,  "no parameter");
1782                 return 0;
1783         }
1785         n = parse_del_obj_string(p, &slot_nr, &type, id, &id_len, &label);
1786         if (n) {
1787                 Log(LOG_INFO,
1788                         "supported format: slot_<slot>:type_<type>:id_<id>:label_<label>");
1789                 Log(LOG_INFO,
1790                         "where <slot> is the slot number as normal integer,");
1791                 Log(LOG_INFO,
1792                         "and <type> is the object type (privkey/pubkey/cert)");
1793                 Log(LOG_INFO,
1794                         "and <id> is the id number as hex string.");
1795                 Log(LOG_INFO,
1796                         "and <label> is the textual label string.");
1797                 goto err;
1798         }
1800         /* No ID specified */
1801         if (id_len == sizeof(id)) {
1802                 id_len = 0;
1803         }
1805         if (verbose) {
1806                 char tmp[MAX_VALUE_LEN];
1807                 for (n = 0; n < id_len; n++) {
1808                         snprintf(&tmp[n*2], 2, "%02x", id[n]);
1809                 }
1810                 Log(LOG_INFO, "Deleting object type(%s) from slot(%d) with label(%s) and id(%s)",
1811                         type, slot_nr, label, tmp);
1812         }
1814         if (pkcs11_del_obj(e, slot_nr, type, id, id_len, label))
1815                 goto err;
1817         rv = 1;
1819 err:
1820     if (label) free(label);
1821     if (type) free(type);
1822     return rv;
1825 static int parse_del_obj_string
1827         const char *del_obj_str,
1828         int *slot,
1829         char **type,
1830         unsigned char *id,
1831         size_t * id_len,
1832         char **label
1835         char *token;
1836         const char *sep = ":";
1837         char *str, *lasts;
1838     int rv = -1;
1840         if (!del_obj_str)
1841                 return -1;
1843         str = strdup(del_obj_str);
1844         if (str == NULL)
1845                 return -1;
1847         /* Default values */
1848         *slot = 0;
1849         *label = NULL;
1850         *type = NULL;
1852         token = strtok_r(str, sep, &lasts);
1854         while (token) {
1856                 /* slot identifier */
1857                 if (!strncmp(token, "slot_", 5)) {
1858                         /* slot is a decimal number */
1859                         if (str_to_dec(token + 5, slot) != 1) {
1860                                 Log(LOG_ERR,  "slot number not deciphered!");
1861                 goto err;
1862                         }
1863                 } else if (!strncmp(token, "id_", 3)) {
1864                         /* certificate ID */
1865                         /* id is hexadecimal number */
1866                         if (!hex_to_bin(token + 3, id, id_len)) {
1867                                 Log(LOG_ERR,  "id not deciphered!");
1868                 goto err;
1869                         }
1870                 } else if (!strncmp(token, "label_", 6)) {
1871                         /* label */
1872                         /*  label is string */
1873                         *label = strdup(token + 6);
1874                         if (*label == NULL) {
1875                                 Log(LOG_ERR,  "label not deciphered!");
1876                 goto err;
1877                         }
1878                 } else if (!strncmp(token, "type_", 5)) {
1879                         /* Object type */
1880                         *type = strdup(token + 5);
1881                         if (*type == NULL) {
1882                                 Log(LOG_ERR,  "type not deciphered!");
1883                 goto err;
1884                         }
1885                 }
1886                 token = strtok_r(NULL, sep, &lasts);
1887         } /* end while(token) */
1889         if (*type == NULL) {
1890                 Log(LOG_ERR,  "type not present!");
1891         goto err;
1892         }
1894         rv = 0;
1895 err:
1896     if (str) free(str);
1897     if (rv && *label) { free(*label); *label = NULL; }
1898     if (rv && *type) { free(*type); *type = NULL; }
1899     return rv;
1902 static int pkcs11_del_obj
1904         ENGINE * e,
1905         int slot_nr,
1906         char *type_str,
1907         unsigned char *id,
1908         size_t id_len,
1909         char *label
1912         PKCS11_SLOT *slot_list, *slot;
1913         PKCS11_SLOT *found_slot = NULL;
1914         PKCS11_TOKEN *tok;
1915         PKCS11_KEY *keys, *ret_key = NULL;
1916         unsigned int slot_count, key_count;
1917         char flags[FLAGS_LEN];
1918         int n,m, type, retval = -1;
1919         int local_init = 0;
1920 #define TYPE_PRIVKEY    1
1921 #define TYPE_PUBKEY     2
1922 #define TYPE_CERT       3
1924         if (!strcmp(type_str, "privkey")) {
1925                 type = TYPE_PRIVKEY;
1926         } else if (!strcmp(type_str, "pubkey")) {
1927                 type = TYPE_PUBKEY;
1928         } else if (!strcmp(type_str, "cert")) {
1929                 type = TYPE_CERT;
1930         } else {
1931                 Log(LOG_ERR,  "invalid object type(%s)", type_str);
1932                 goto out;
1933         }
1935         if (ctx == NULL) {
1936                 pkcs11_init(e);
1937                 local_init = 1;
1938         }
1940         if (PKCS11_enumerate_slots(ctx, &slot_list, &slot_count)) {
1941                 Log(LOG_ERR,  "failed to enumerate slots");
1942                 goto out;
1943         }
1945         if (verbose) {
1946                 Log(LOG_INFO,  "Found %u slots", slot_count);
1947         }
1949         for (n = 0; n < slot_count; n++) {
1950                 slot = slot_list + n;
1951                 flags[0] = '\0';
1952                 if (slot->token) {
1953                         if (!slot->token->initialized)
1954                                 strncat(flags, "uninitialized, ", (FLAGS_LEN - strlen(flags) - 1));
1955                         else if (!slot->token->userPinSet)
1956                                 strncat(flags, "no pin, ", (FLAGS_LEN - strlen(flags) - 1));
1957                         if (slot->token->loginRequired)
1958                                 strncat(flags, "login, ", (FLAGS_LEN - strlen(flags) - 1));
1959                         if (slot->token->readOnly)
1960                                 strncat(flags, "ro, ", (FLAGS_LEN - strlen(flags) - 1));
1961                 } else {
1962                         strncpy(flags, "no token", sizeof(flags));
1963                 }
1964                 if ((m = strlen(flags)) != 0) {
1965                         flags[m - 2] = '\0';
1966                 }
1968                 if (slot_nr != -1 &&
1969                         slot_nr == PKCS11_get_slotid_from_slot(slot)) {
1970                         found_slot = slot;
1971                 }
1973                 if (verbose) {
1974                         Log(LOG_INFO, "[%lu] %-25.25s  %-16s",
1975                                 PKCS11_get_slotid_from_slot(slot),
1976                                 slot->description, flags);
1977                         if (slot->token) {
1978                                 Log(LOG_INFO, "  (%s)",
1979                                         slot->token->label[0] ?
1980                                         slot->token->label : "no label");
1981                         }
1982                 }
1983         }
1985         if (found_slot) {
1986                 slot = found_slot; 
1987         } else {
1988                 Log(LOG_ERR,  "Invalid slot number: %d", (int)slot_nr);
1989                 goto err_out;
1990         }
1992         tok = slot->token;
1994         if (tok == NULL) {
1995                 Log(LOG_ERR,  "Found empty token; ");
1996                 goto err_out;
1997         }
1999         if (verbose) {
2000                 Log(LOG_INFO,  "Found slot:  %s", slot->description);
2001                 Log(LOG_INFO,  "Found token: %s", slot->token->label);
2002         }
2004         if ((tok->loginRequired) && (do_login(slot))) {
2005                 Log(LOG_ERR,  "failed to login");
2006                 goto err_out;
2007         }
2009         switch(type) {
2010                 case TYPE_CERT:
2011                         if (PKCS11_remove_certificate(tok, label, id, id_len)) {
2012                                 Log(LOG_ERR,  "failed to delete certificate");
2013                                 goto err_out;
2014                         }
2015                         break;
2017                 case TYPE_PUBKEY:
2018                         if (PKCS11_remove_public_key(tok, label, id, id_len)) {
2019                                 Log(LOG_ERR,  "failed to delete public key");
2020                                 goto err_out;
2021                         }
2022                         break;
2024                 case TYPE_PRIVKEY:
2025                         if (PKCS11_remove_private_key(tok, label, id, id_len)) {
2026                                 Log(LOG_ERR,  "failed to delete private key");
2027                                 goto err_out;
2028                         }
2029                         break;
2031                 default:
2032                         Log(LOG_ERR,  "object type(%s) not supported", type_str);
2033                         goto err_out;
2034                         break;
2035         }
2037         retval = 0;
2038 err_out:
2039         PKCS11_release_all_slots(ctx, slot_list, slot_count);
2040 out:
2041         if (local_init) {
2042                 free_pkcs11_ctx();
2043         }
2044         return retval;
2047 int get_pubkey_cmd(ENGINE * e, const char *p)
2049         int n, rv = 0;
2050         unsigned char key_id[MAX_VALUE_LEN / 2];
2051         size_t key_id_len = sizeof(key_id);
2052         char *key_label = NULL;
2053         char *key_file = NULL;
2054         int slot_nr = -1;
2055         unsigned char *pp, *data = NULL;
2056         int data_len = 0;
2057         FILE *f = NULL;
2058         EVP_PKEY *pk;
2059         RSA *rsa;
2061         if (!p || !*p) {
2062                 Log(LOG_ERR,  "no parameter");
2063                 return 0;
2064         }
2066         n = parse_key_string(p, &slot_nr, key_id, &key_id_len,
2067                                 &key_label, &key_file);
2068         if (n) {
2069                 Log(LOG_INFO,
2070                         "supported format: slot_<slot>:id_<id>:label_<label>:key_<filename>");
2071                 Log(LOG_INFO,
2072                         "where <slot> is the slot number as normal integer,");
2073                 Log(LOG_INFO,
2074                         "and <id> is the id number as hex string.");
2075                 Log(LOG_INFO,
2076                         "and <label> is the textual key label string.");
2077                 Log(LOG_INFO,
2078                         "and <filename> is the key filename with full path.");
2079                 goto get_pubkey_err_out;
2080         }
2082         f = fopen(key_file, "wb");
2083         if (f == NULL) {
2084                 Log(LOG_ERR,  "Couldn't open key file \"%s\"", key_file);
2085                 goto get_pubkey_err_out;
2086         }
2088         /* No ID specified */
2089         if (key_id_len == sizeof(key_id))
2090                 key_id_len = 0;
2092         if (verbose) {
2093                 char tmp[MAX_VALUE_LEN];
2094                 for (n = 0; n < key_id_len; n++) {
2095                         snprintf(&tmp[n*2], 2, "%02x", key_id[n]);
2096                 }
2097                 Log(LOG_INFO, "Getting public key in slot(%d) with label(%s) and id(%s)",
2098                         slot_nr, key_label, tmp);
2099         }
2101         pk = pkcs11_load_key(e, slot_nr, key_id, key_id_len, key_label, NULL, NULL, 0);
2102         if (pk == NULL) {
2103                 Log(LOG_ERR,  "PKCS11_load_public_key returned NULL");
2104                 goto get_pubkey_err_out;
2105         }
2107         rsa = EVP_PKEY_get1_RSA(pk);
2108         if (rsa == NULL) {
2109                 Log(LOG_ERR,  "Couldn't retrieve RSA key form EVP_PKEY");
2110                 goto get_pubkey_err_out;
2111         }
2113 #if 0
2114         /* To store in DER format */
2115         data_len = i2d_RSAPublicKey(rsa, NULL); 
2116         if ((data = (unsigned char *)malloc(data_len)) == NULL) {
2117                 Log(LOG_ERR,  "couldn't allocate memory for key");
2118                 goto get_pubkey_err_out;
2119         }
2120         pp = data;
2121         data_len = i2d_RSAPublicKey(rsa, &pp); 
2122         n = fwrite(data, 1, data_len, f);
2124         if (n != data_len) {
2125                 Log(LOG_ERR,  "Couldn't write to file \"%s\"", key_file);
2126                 goto get_pubkey_err_out;
2127         }
2128 #endif
2129         if (!PEM_write_RSA_PUBKEY(f, rsa)) {
2130                 Log(LOG_ERR,  "Couldn't write to file \"%s\"", key_file);
2131                 goto get_pubkey_err_out;
2132         }
2134         rv = 1;
2136 get_pubkey_err_out:
2137         if (f) fclose(f);
2138         if (key_label) free(key_label);
2139         if (key_file) free(key_file);
2140         return rv;
2144 static int parse_key_string
2146         const char *key_get_str,
2147         int *slot,
2148         unsigned char *id,
2149         size_t * id_len,
2150         char **label,
2151         char **key_file
2154         char *token;
2155         const char *sep = ":";
2156         char *str, *lasts;
2157     int rv = -1;
2159         if (!key_get_str) {
2160                 return -1;
2161         }
2162         str = strdup(key_get_str);
2163         if (str == NULL) {
2164                 return -1;
2165         }
2166         /* Default values */
2167         *slot = 0;
2168         *label = NULL;
2169         if (key_file) {
2170                 *key_file = NULL;
2171         }
2172         token = strtok_r(str, sep, &lasts);
2174         while (token) {
2176                 /* slot identifier */
2177                 if (!strncmp(token, "slot_", 5)) {
2178                         /* slot is a decimal number */
2179                         if (str_to_dec(token + 5, slot) != 1) {
2180                                 Log(LOG_ERR,  "slot number not deciphered!");
2181                                 goto err;
2182                         }
2183                 } else if (!strncmp(token, "id_", 3)) {
2184                         /* certificate ID */
2185                         /* id is hexadecimal number */
2186                         if (!hex_to_bin(token + 3, id, id_len)) {
2187                                 Log(LOG_ERR,  "id not deciphered!");
2188                                 goto err;
2189                         }
2190                 } else if (!strncmp(token, "label_", 6)) {
2191                         /* label */
2192                         /*  label is string */
2193                         *label = strdup(token + 6);
2194                         if (*label == NULL) {
2195                                 Log(LOG_ERR,  "label not deciphered!");
2196                                 goto err;
2197                         }
2198                 } else if ((key_file) && (!strncmp(token, "key_", 4))) {
2199                         /* key file name */
2200                         *key_file = strdup(token + 4);
2201                         if (*key_file == NULL) {
2202                                 Log(LOG_ERR,  "key file not deciphered!");
2203                                 goto err;
2204                         }
2205                 }
2206                 token = strtok_r(NULL, sep, &lasts);
2207         } /* end while(token) */
2209         if ((key_file) && (*key_file == NULL)) {
2210                 Log(LOG_ERR,  "key file name not present!");
2211                 goto err;
2212         }
2214         rv = 0;
2216 err:
2217         if (str) free(str);
2218     if (rv && *label) { free(*label); *label = NULL; }
2219     if (rv && *key_file) { free(*key_file); *key_file = NULL; }
2220         return rv;