2 * Copyright (c) 2004 - 2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * 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.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #define CRYPTOKI_EXPORTS 1
37 #include "ref/pkcs11.h"
39 #define OBJECT_ID_MASK 0xfff
40 #define HANDLE_OBJECT_ID(h) ((h) & OBJECT_ID_MASK)
41 #define OBJECT_ID(obj) HANDLE_OBJECT_ID((obj)->object_handle)
44 #define random() rand()
45 #define srandom(s) srand(s)
53 CK_ATTRIBUTE attribute;
58 CK_OBJECT_HANDLE object_handle;
59 struct st_attr *attrs;
64 static struct soft_token {
65 CK_VOID_PTR application;
70 struct st_object **objs;
79 struct session_state {
80 CK_SESSION_HANDLE session_handle;
83 CK_ATTRIBUTE *attributes;
84 CK_ULONG num_attributes;
89 CK_MECHANISM_PTR sign_mechanism;
91 CK_MECHANISM_PTR verify_mechanism;
93 #define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0]))
97 static hx509_context context;
100 application_error(const char *fmt, ...)
106 if (soft_token.flags.app_error_fatal)
111 st_logf(const char *fmt, ...)
114 if (soft_token.logfile == NULL)
117 vfprintf(soft_token.logfile, fmt, ap);
119 fflush(soft_token.logfile);
125 if (context == NULL) {
126 int ret = hx509_context_init(&context);
128 return CKR_GENERAL_ERROR;
133 #define INIT_CONTEXT() { CK_RV icret = init_context(); if (icret) return icret; }
136 snprintf_fill(char *str, size_t size, char fillchar, const char *fmt, ...)
141 len = vsnprintf(str, size, fmt, ap);
143 if (len < 0 || (size_t)len > size)
145 while ((size_t)len < size)
146 str[len++] = fillchar;
150 #define printf error_use_st_logf
153 #define VERIFY_SESSION_HANDLE(s, state) \
156 xret = verify_session_handle(s, state); \
157 if (xret != CKR_OK) { \
158 /* return CKR_OK */; \
163 verify_session_handle(CK_SESSION_HANDLE hSession,
164 struct session_state **state)
168 for (i = 0; i < MAX_NUM_SESSION; i++){
169 if (soft_token.state[i].session_handle == hSession)
172 if (i == MAX_NUM_SESSION) {
173 application_error("use of invalid handle: 0x%08lx\n",
174 (unsigned long)hSession);
175 return CKR_SESSION_HANDLE_INVALID;
178 *state = &soft_token.state[i];
183 object_handle_to_object(CK_OBJECT_HANDLE handle,
184 struct st_object **object)
186 int i = HANDLE_OBJECT_ID(handle);
189 if (i >= soft_token.object.num_objs)
190 return CKR_ARGUMENTS_BAD;
191 if (soft_token.object.objs[i] == NULL)
192 return CKR_ARGUMENTS_BAD;
193 if (soft_token.object.objs[i]->object_handle != handle)
194 return CKR_ARGUMENTS_BAD;
195 *object = soft_token.object.objs[i];
200 attributes_match(const struct st_object *obj,
201 const CK_ATTRIBUTE *attributes,
202 CK_ULONG num_attributes)
207 st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj));
209 for (i = 0; i < num_attributes; i++) {
211 for (j = 0; j < obj->num_attributes; j++) {
212 if (attributes[i].type == obj->attrs[j].attribute.type &&
213 attributes[i].ulValueLen == obj->attrs[j].attribute.ulValueLen &&
214 memcmp(attributes[i].pValue, obj->attrs[j].attribute.pValue,
215 attributes[i].ulValueLen) == 0) {
221 st_logf("type %d attribute have no match\n", attributes[i].type);
225 st_logf("attribute matches\n");
230 print_attributes(const CK_ATTRIBUTE *attributes,
231 CK_ULONG num_attributes)
235 st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes);
237 for (i = 0; i < num_attributes; i++) {
239 switch (attributes[i].type) {
242 if (attributes[i].ulValueLen != sizeof(CK_BBOOL)) {
243 application_error("token attribute wrong length\n");
246 ck_true = attributes[i].pValue;
247 st_logf("token: %s", *ck_true ? "TRUE" : "FALSE");
251 CK_OBJECT_CLASS *class;
252 if (attributes[i].ulValueLen != sizeof(CK_ULONG)) {
253 application_error("class attribute wrong length\n");
256 class = attributes[i].pValue;
259 case CKO_CERTIFICATE:
260 st_logf("certificate");
263 st_logf("public key");
265 case CKO_PRIVATE_KEY:
266 st_logf("private key");
269 st_logf("secret key");
271 case CKO_DOMAIN_PARAMETERS:
272 st_logf("domain parameters");
275 st_logf("[class %lx]", (long unsigned)*class);
286 case CKA_APPLICATION:
287 st_logf("application");
296 st_logf("[unknown 0x%08lx]", (unsigned long)attributes[i].type);
303 static struct st_object *
306 struct st_object *o, **objs;
309 o = calloc(1, sizeof(*o));
313 for (i = 0; i < soft_token.object.num_objs; i++) {
314 if (soft_token.object.objs == NULL) {
315 soft_token.object.objs[i] = o;
319 if (i == soft_token.object.num_objs) {
320 objs = realloc(soft_token.object.objs,
321 (soft_token.object.num_objs + 1) * sizeof(soft_token.object.objs[0]));
326 soft_token.object.objs = objs;
327 soft_token.object.objs[soft_token.object.num_objs++] = o;
329 soft_token.object.objs[i]->object_handle =
330 (random() & (~OBJECT_ID_MASK)) | i;
336 add_object_attribute(struct st_object *o,
338 CK_ATTRIBUTE_TYPE type,
345 i = o->num_attributes;
346 a = realloc(o->attrs, (i + 1) * sizeof(o->attrs[0]));
348 return CKR_DEVICE_MEMORY;
350 o->attrs[i].secret = secret;
351 o->attrs[i].attribute.type = type;
352 o->attrs[i].attribute.pValue = malloc(ulValueLen);
353 if (o->attrs[i].attribute.pValue == NULL && ulValueLen != 0)
354 return CKR_DEVICE_MEMORY;
355 memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen);
356 o->attrs[i].attribute.ulValueLen = ulValueLen;
363 add_pubkey_info(hx509_context hxctx, struct st_object *o,
364 CK_KEY_TYPE key_type, hx509_cert cert)
367 CK_BYTE *modulus = NULL;
368 size_t modulus_len = 0;
369 CK_ULONG modulus_bits = 0;
370 CK_BYTE *exponent = NULL;
371 size_t exponent_len = 0;
373 if (key_type != CKK_RSA)
375 if (_hx509_cert_private_key(cert) == NULL)
378 num = _hx509_private_key_get_internal(context,
379 _hx509_cert_private_key(cert),
382 return CKR_GENERAL_ERROR;
383 modulus_bits = BN_num_bits(num);
385 modulus_len = BN_num_bytes(num);
386 modulus = malloc(modulus_len);
387 BN_bn2bin(num, modulus);
390 add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len);
391 add_object_attribute(o, 0, CKA_MODULUS_BITS,
392 &modulus_bits, sizeof(modulus_bits));
396 num = _hx509_private_key_get_internal(context,
397 _hx509_cert_private_key(cert),
400 return CKR_GENERAL_ERROR;
402 exponent_len = BN_num_bytes(num);
403 exponent = malloc(exponent_len);
404 BN_bn2bin(num, exponent);
407 add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT,
408 exponent, exponent_len);
421 static int HX509_LIB_CALL
422 add_cert(hx509_context hxctx, void *ctx, hx509_cert cert)
424 static char empty[] = "";
425 struct foo *foo = (struct foo *)ctx;
426 struct st_object *o = NULL;
427 CK_OBJECT_CLASS type;
428 CK_BBOOL bool_true = CK_TRUE;
429 CK_BBOOL bool_false = CK_FALSE;
430 CK_CERTIFICATE_TYPE cert_type = CKC_X_509;
431 CK_KEY_TYPE key_type;
432 CK_MECHANISM_TYPE mech_type;
433 CK_RV ret = CKR_GENERAL_ERROR;
435 heim_octet_string cert_data, subject_data, issuer_data, serial_data;
437 st_logf("adding certificate\n");
439 serial_data.data = NULL;
440 serial_data.length = 0;
441 cert_data = subject_data = issuer_data = serial_data;
443 hret = hx509_cert_binary(hxctx, cert, &cert_data);
450 hret = hx509_cert_get_issuer(cert, &name);
453 hret = hx509_name_binary(name, &issuer_data);
454 hx509_name_free(&name);
458 hret = hx509_cert_get_subject(cert, &name);
461 hret = hx509_name_binary(name, &subject_data);
462 hx509_name_free(&name);
468 AlgorithmIdentifier alg;
470 hret = hx509_cert_get_SPKI_AlgorithmIdentifier(context, cert, &alg);
472 ret = CKR_DEVICE_MEMORY;
476 key_type = CKK_RSA; /* XXX */
478 free_AlgorithmIdentifier(&alg);
482 type = CKO_CERTIFICATE;
485 ret = CKR_DEVICE_MEMORY;
489 o->cert = hx509_cert_ref(cert);
491 add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
492 add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
493 add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
494 add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
495 add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
497 add_object_attribute(o, 0, CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type));
498 add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
500 add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
501 add_object_attribute(o, 0, CKA_ISSUER, issuer_data.data, issuer_data.length);
502 add_object_attribute(o, 0, CKA_SERIAL_NUMBER, serial_data.data, serial_data.length);
503 add_object_attribute(o, 0, CKA_VALUE, cert_data.data, cert_data.length);
504 add_object_attribute(o, 0, CKA_TRUSTED, &bool_false, sizeof(bool_false));
506 st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o));
508 type = CKO_PUBLIC_KEY;
511 ret = CKR_DEVICE_MEMORY;
514 o->cert = hx509_cert_ref(cert);
516 add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
517 add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
518 add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
519 add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
520 add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
522 add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
523 add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
524 add_object_attribute(o, 0, CKA_START_DATE, empty, 1); /* XXX */
525 add_object_attribute(o, 0, CKA_END_DATE, empty, 1); /* XXX */
526 add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
527 add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
528 mech_type = CKM_RSA_X_509;
529 add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
531 add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
532 add_object_attribute(o, 0, CKA_ENCRYPT, &bool_true, sizeof(bool_true));
533 add_object_attribute(o, 0, CKA_VERIFY, &bool_true, sizeof(bool_true));
534 add_object_attribute(o, 0, CKA_VERIFY_RECOVER, &bool_false, sizeof(bool_false));
535 add_object_attribute(o, 0, CKA_WRAP, &bool_true, sizeof(bool_true));
536 add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true));
538 add_pubkey_info(hxctx, o, key_type, cert);
540 st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o));
542 if (hx509_cert_have_private_key(cert)) {
545 type = CKO_PRIVATE_KEY;
547 /* Note to static analyzers: `o' is still referred to via globals */
550 ret = CKR_DEVICE_MEMORY;
553 o->cert = hx509_cert_ref(cert);
555 add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
556 add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
557 add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false));
558 add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
559 add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
561 add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
562 add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
563 add_object_attribute(o, 0, CKA_START_DATE, empty, 1); /* XXX */
564 add_object_attribute(o, 0, CKA_END_DATE, empty, 1); /* XXX */
565 add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
566 add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
567 mech_type = CKM_RSA_X_509;
568 add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
570 add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
571 add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true));
572 add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true));
574 add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags));
576 add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true));
577 add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true));
578 add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false));
579 add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true));
580 add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true));
581 add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false));
583 add_pubkey_info(hxctx, o, key_type, cert);
589 st_logf("something went wrong when adding cert!\n");
593 hx509_xfree(cert_data.data);
594 hx509_xfree(serial_data.data);
595 hx509_xfree(issuer_data.data);
596 hx509_xfree(subject_data.data);
598 /* Note to static analyzers: `o' is still referred to via globals */
603 add_certificate(const char *cert_file,
609 hx509_lock lock = NULL;
617 flags |= HX509_CERTS_UNPROTECT_ALL;
621 ret = asprintf(&str, "PASS:%s", pin);
622 if (ret == -1 || !str) {
623 st_logf("failed to allocate memory\n");
624 return CKR_GENERAL_ERROR;
627 hx509_lock_init(context, &lock);
628 hx509_lock_command_string(lock, str);
630 memset(str, 0, strlen(str));
634 ret = hx509_certs_init(context, cert_file, flags, lock, &certs);
636 st_logf("failed to open file %s\n", cert_file);
637 return CKR_GENERAL_ERROR;
640 ret = hx509_certs_iter_f(context, certs, add_cert, &foo);
641 hx509_certs_free(&certs);
643 st_logf("failed adding certs from file %s\n", cert_file);
644 return CKR_GENERAL_ERROR;
651 find_object_final(struct session_state *state)
653 if (state->find.attributes) {
656 for (i = 0; i < state->find.num_attributes; i++) {
657 if (state->find.attributes[i].pValue)
658 free(state->find.attributes[i].pValue);
660 free(state->find.attributes);
661 state->find.attributes = NULL;
662 state->find.num_attributes = 0;
663 state->find.next_object = -1;
668 reset_crypto_state(struct session_state *state)
670 state->sign_object = -1;
671 if (state->sign_mechanism)
672 free(state->sign_mechanism);
673 state->sign_mechanism = NULL_PTR;
674 state->verify_object = -1;
675 if (state->verify_mechanism)
676 free(state->verify_mechanism);
677 state->verify_mechanism = NULL_PTR;
681 close_session(struct session_state *state)
683 if (state->find.attributes) {
684 application_error("application didn't do C_FindObjectsFinal\n");
685 find_object_final(state);
688 state->session_handle = CK_INVALID_HANDLE;
689 soft_token.application = NULL_PTR;
690 soft_token.notify = NULL_PTR;
691 reset_crypto_state(state);
697 return soft_token.open_sessions > 0 ? "yes" : "no";
701 read_conf_file(const char *fn, CK_USER_TYPE userType, const char *pin)
703 char buf[1024], *type, *s, *p;
706 CK_RV failed = CKR_OK;
709 st_logf("Can't open configuration file. No file specified\n");
710 return CKR_GENERAL_ERROR;
715 st_logf("can't open configuration file %s\n", fn);
716 return CKR_GENERAL_ERROR;
720 while(fgets(buf, sizeof(buf), f) != NULL) {
721 buf[strcspn(buf, "\n")] = '\0';
723 st_logf("line: %s\n", buf);
726 while (isspace((unsigned char)*p))
730 while (isspace((unsigned char)*p))
734 type = strtok_r(p, "\t", &s);
738 if (strcasecmp("certificate", type) == 0) {
739 char *cert, *id, *label;
741 id = strtok_r(NULL, "\t", &s);
746 st_logf("id: %s\n", id);
747 label = strtok_r(NULL, "\t", &s);
749 st_logf("no label\n");
752 cert = strtok_r(NULL, "\t", &s);
754 st_logf("no certfiicate store\n");
758 st_logf("adding: %s: %s in file %s\n", id, label, cert);
760 ret = add_certificate(cert, pin, id, label);
763 } else if (strcasecmp("debug", type) == 0) {
766 name = strtok_r(NULL, "\t", &s);
768 st_logf("no filename\n");
772 if (soft_token.logfile)
773 fclose(soft_token.logfile);
775 if (strcasecmp(name, "stdout") == 0)
776 soft_token.logfile = stdout;
778 soft_token.logfile = fopen(name, "a");
779 if (soft_token.logfile)
780 rk_cloexec_file(soft_token.logfile);
782 if (soft_token.logfile == NULL)
783 st_logf("failed to open file: %s\n", name);
785 } else if (strcasecmp("app-fatal", type) == 0) {
788 name = strtok_r(NULL, "\t", &s);
790 st_logf("argument to app-fatal\n");
794 if (strcmp(name, "true") == 0 || strcmp(name, "on") == 0)
795 soft_token.flags.app_error_fatal = 1;
796 else if (strcmp(name, "false") == 0 || strcmp(name, "off") == 0)
797 soft_token.flags.app_error_fatal = 0;
799 st_logf("unknown app-fatal: %s\n", name);
802 st_logf("unknown type: %s\n", type);
812 func_not_supported(void)
814 st_logf("function not supported\n");
815 return CKR_FUNCTION_NOT_SUPPORTED;
819 get_config_file_for_user(void)
824 fn = secure_getenv("SOFTPKCS11RC");
828 char homebuf[MAX_PATH];
829 const char *home = roken_get_appdatadir(homebuf, sizeof(homebuf));
832 ret = asprintf(&fn, "%s/.soft-token.rc", home);
837 fn = strdup("/etc/soft-token.rc");
847 C_Initialize(CK_VOID_PTR a)
849 CK_C_INITIALIZE_ARGS_PTR args = a;
853 st_logf("Initialize\n");
857 OpenSSL_add_all_algorithms();
859 srandom(getpid() ^ (int) time(NULL));
861 for (i = 0; i < MAX_NUM_SESSION; i++) {
862 soft_token.state[i].session_handle = CK_INVALID_HANDLE;
863 soft_token.state[i].find.attributes = NULL;
864 soft_token.state[i].find.num_attributes = 0;
865 soft_token.state[i].find.next_object = -1;
866 reset_crypto_state(&soft_token.state[i]);
869 soft_token.flags.hardware_slot = 1;
870 soft_token.flags.app_error_fatal = 0;
871 soft_token.flags.login_done = 0;
873 soft_token.object.objs = NULL;
874 soft_token.object.num_objs = 0;
876 soft_token.logfile = NULL;
878 soft_token.logfile = stdout;
881 soft_token.logfile = fopen("/tmp/log-pkcs11.txt", "a");
885 st_logf("\tCreateMutex:\t%p\n", args->CreateMutex);
886 st_logf("\tDestroyMutext\t%p\n", args->DestroyMutex);
887 st_logf("\tLockMutext\t%p\n", args->LockMutex);
888 st_logf("\tUnlockMutext\t%p\n", args->UnlockMutex);
889 st_logf("\tFlags\t%04x\n", (unsigned int)args->flags);
892 soft_token.config_file = get_config_file_for_user();
895 * This operations doesn't return CKR_OK if any of the
896 * certificates failes to be unparsed (ie password protected).
898 ret = read_conf_file(soft_token.config_file, CKU_USER, NULL);
900 soft_token.flags.login_done = 1;
906 C_Finalize(CK_VOID_PTR args)
912 st_logf("Finalize\n");
914 for (i = 0; i < MAX_NUM_SESSION; i++) {
915 if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) {
916 application_error("application finalized without "
917 "closing session\n");
918 close_session(&soft_token.state[i]);
926 C_GetInfo(CK_INFO_PTR args)
930 st_logf("GetInfo\n");
932 memset(args, 17, sizeof(*args));
933 args->cryptokiVersion.major = 2;
934 args->cryptokiVersion.minor = 10;
935 snprintf_fill((char *)args->manufacturerID,
936 sizeof(args->manufacturerID),
938 "Heimdal hx509 SoftToken");
939 snprintf_fill((char *)args->libraryDescription,
940 sizeof(args->libraryDescription), ' ',
941 "Heimdal hx509 SoftToken");
942 args->libraryVersion.major = 2;
943 args->libraryVersion.minor = 0;
948 extern CK_FUNCTION_LIST funcs;
951 C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
955 *ppFunctionList = &funcs;
960 C_GetSlotList(CK_BBOOL tokenPresent,
961 CK_SLOT_ID_PTR pSlotList,
962 CK_ULONG_PTR pulCount)
965 st_logf("GetSlotList: %s\n",
966 tokenPresent ? "tokenPresent" : "token not Present");
974 C_GetSlotInfo(CK_SLOT_ID slotID,
975 CK_SLOT_INFO_PTR pInfo)
978 st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID, has_session());
980 memset(pInfo, 18, sizeof(*pInfo));
983 return CKR_ARGUMENTS_BAD;
985 snprintf_fill((char *)pInfo->slotDescription,
986 sizeof(pInfo->slotDescription),
988 "Heimdal hx509 SoftToken (slot)");
989 snprintf_fill((char *)pInfo->manufacturerID,
990 sizeof(pInfo->manufacturerID),
992 "Heimdal hx509 SoftToken (slot)");
993 pInfo->flags = CKF_TOKEN_PRESENT;
994 if (soft_token.flags.hardware_slot)
995 pInfo->flags |= CKF_HW_SLOT;
996 pInfo->hardwareVersion.major = 1;
997 pInfo->hardwareVersion.minor = 0;
998 pInfo->firmwareVersion.major = 1;
999 pInfo->firmwareVersion.minor = 0;
1005 C_GetTokenInfo(CK_SLOT_ID slotID,
1006 CK_TOKEN_INFO_PTR pInfo)
1009 st_logf("GetTokenInfo: %s\n", has_session());
1011 memset(pInfo, 19, sizeof(*pInfo));
1013 snprintf_fill((char *)pInfo->label,
1014 sizeof(pInfo->label),
1016 "Heimdal hx509 SoftToken (token)");
1017 snprintf_fill((char *)pInfo->manufacturerID,
1018 sizeof(pInfo->manufacturerID),
1020 "Heimdal hx509 SoftToken (token)");
1021 snprintf_fill((char *)pInfo->model,
1022 sizeof(pInfo->model),
1024 "Heimdal hx509 SoftToken (token)");
1025 snprintf_fill((char *)pInfo->serialNumber,
1026 sizeof(pInfo->serialNumber),
1030 CKF_TOKEN_INITIALIZED |
1031 CKF_USER_PIN_INITIALIZED;
1033 if (soft_token.flags.login_done == 0)
1034 pInfo->flags |= CKF_LOGIN_REQUIRED;
1037 CKF_RESTORE_KEY_NOT_NEEDED |
1039 pInfo->ulMaxSessionCount = MAX_NUM_SESSION;
1040 pInfo->ulSessionCount = soft_token.open_sessions;
1041 pInfo->ulMaxRwSessionCount = MAX_NUM_SESSION;
1042 pInfo->ulRwSessionCount = soft_token.open_sessions;
1043 pInfo->ulMaxPinLen = 1024;
1044 pInfo->ulMinPinLen = 0;
1045 pInfo->ulTotalPublicMemory = 4711;
1046 pInfo->ulFreePublicMemory = 4712;
1047 pInfo->ulTotalPrivateMemory = 4713;
1048 pInfo->ulFreePrivateMemory = 4714;
1049 pInfo->hardwareVersion.major = 2;
1050 pInfo->hardwareVersion.minor = 0;
1051 pInfo->firmwareVersion.major = 2;
1052 pInfo->firmwareVersion.minor = 0;
1058 C_GetMechanismList(CK_SLOT_ID slotID,
1059 CK_MECHANISM_TYPE_PTR pMechanismList,
1060 CK_ULONG_PTR pulCount)
1063 st_logf("GetMechanismList\n");
1066 if (pMechanismList == NULL_PTR)
1068 pMechanismList[0] = CKM_RSA_PKCS;
1074 C_GetMechanismInfo(CK_SLOT_ID slotID,
1075 CK_MECHANISM_TYPE type,
1076 CK_MECHANISM_INFO_PTR pInfo)
1079 st_logf("GetMechanismInfo: slot %d type: %d\n",
1080 (int)slotID, (int)type);
1081 memset(pInfo, 0, sizeof(*pInfo));
1087 C_InitToken(CK_SLOT_ID slotID,
1088 CK_UTF8CHAR_PTR pPin,
1090 CK_UTF8CHAR_PTR pLabel)
1093 st_logf("InitToken: slot %d\n", (int)slotID);
1094 return CKR_FUNCTION_NOT_SUPPORTED;
1098 C_OpenSession(CK_SLOT_ID slotID,
1100 CK_VOID_PTR pApplication,
1102 CK_SESSION_HANDLE_PTR phSession)
1106 st_logf("OpenSession: slot: %d\n", (int)slotID);
1108 if (soft_token.open_sessions == MAX_NUM_SESSION)
1109 return CKR_SESSION_COUNT;
1111 soft_token.application = pApplication;
1112 soft_token.notify = Notify;
1114 for (i = 0; i < MAX_NUM_SESSION; i++)
1115 if (soft_token.state[i].session_handle == CK_INVALID_HANDLE)
1117 if (i == MAX_NUM_SESSION)
1120 soft_token.open_sessions++;
1122 soft_token.state[i].session_handle =
1123 (CK_SESSION_HANDLE)(random() & 0xfffff);
1124 *phSession = soft_token.state[i].session_handle;
1130 C_CloseSession(CK_SESSION_HANDLE hSession)
1132 struct session_state *state;
1134 st_logf("CloseSession\n");
1136 if (verify_session_handle(hSession, &state) != CKR_OK)
1137 application_error("closed session not open");
1139 close_session(state);
1145 C_CloseAllSessions(CK_SLOT_ID slotID)
1150 st_logf("CloseAllSessions\n");
1152 for (i = 0; i < MAX_NUM_SESSION; i++)
1153 if (soft_token.state[i].session_handle != CK_INVALID_HANDLE)
1154 close_session(&soft_token.state[i]);
1160 C_GetSessionInfo(CK_SESSION_HANDLE hSession,
1161 CK_SESSION_INFO_PTR pInfo)
1163 st_logf("GetSessionInfo\n");
1166 VERIFY_SESSION_HANDLE(hSession, NULL);
1168 memset(pInfo, 20, sizeof(*pInfo));
1171 if (soft_token.flags.login_done)
1172 pInfo->state = CKS_RO_USER_FUNCTIONS;
1174 pInfo->state = CKS_RO_PUBLIC_SESSION;
1175 pInfo->flags = CKF_SERIAL_SESSION;
1176 pInfo->ulDeviceError = 0;
1182 C_Login(CK_SESSION_HANDLE hSession,
1183 CK_USER_TYPE userType,
1184 CK_UTF8CHAR_PTR pPin,
1193 VERIFY_SESSION_HANDLE(hSession, NULL);
1195 if (pPin != NULL_PTR) {
1198 aret = asprintf(&pin, "%.*s", (int)ulPinLen, pPin);
1199 if (aret != -1 && pin)
1200 st_logf("type: %d password: %s\n", (int)userType, pin);
1202 st_logf("memory error: asprintf failed\n");
1209 ret = read_conf_file(soft_token.config_file, userType, pin);
1211 soft_token.flags.login_done = 1;
1215 return soft_token.flags.login_done ? CKR_OK : CKR_PIN_INCORRECT;
1219 C_Logout(CK_SESSION_HANDLE hSession)
1221 st_logf("Logout\n");
1224 VERIFY_SESSION_HANDLE(hSession, NULL);
1225 return CKR_FUNCTION_NOT_SUPPORTED;
1229 C_GetObjectSize(CK_SESSION_HANDLE hSession,
1230 CK_OBJECT_HANDLE hObject,
1231 CK_ULONG_PTR pulSize)
1233 st_logf("GetObjectSize\n");
1236 VERIFY_SESSION_HANDLE(hSession, NULL);
1237 return CKR_FUNCTION_NOT_SUPPORTED;
1241 C_GetAttributeValue(CK_SESSION_HANDLE hSession,
1242 CK_OBJECT_HANDLE hObject,
1243 CK_ATTRIBUTE_PTR pTemplate,
1246 struct session_state *state;
1247 struct st_object *obj;
1254 st_logf("GetAttributeValue: %lx\n",
1255 (unsigned long)HANDLE_OBJECT_ID(hObject));
1256 VERIFY_SESSION_HANDLE(hSession, &state);
1258 if ((ret = object_handle_to_object(hObject, &obj)) != CKR_OK) {
1259 st_logf("object not found: %lx\n",
1260 (unsigned long)HANDLE_OBJECT_ID(hObject));
1264 for (i = 0; i < ulCount; i++) {
1265 st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate[i].type);
1266 for (j = 0; j < obj->num_attributes; j++) {
1267 if (obj->attrs[j].secret) {
1268 pTemplate[i].ulValueLen = (CK_ULONG)-1;
1271 if (pTemplate[i].type == obj->attrs[j].attribute.type) {
1272 if (pTemplate[i].pValue != NULL_PTR && obj->attrs[j].secret == 0) {
1273 if (pTemplate[i].ulValueLen >= obj->attrs[j].attribute.ulValueLen)
1274 memcpy(pTemplate[i].pValue, obj->attrs[j].attribute.pValue,
1275 obj->attrs[j].attribute.ulValueLen);
1277 pTemplate[i].ulValueLen = obj->attrs[j].attribute.ulValueLen;
1281 if (j == obj->num_attributes) {
1282 st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate[i].type);
1283 pTemplate[i].ulValueLen = (CK_ULONG)-1;
1291 C_FindObjectsInit(CK_SESSION_HANDLE hSession,
1292 CK_ATTRIBUTE_PTR pTemplate,
1295 struct session_state *state;
1297 st_logf("FindObjectsInit\n");
1301 VERIFY_SESSION_HANDLE(hSession, &state);
1303 if (state->find.next_object != -1) {
1304 application_error("application didn't do C_FindObjectsFinal\n");
1305 find_object_final(state);
1310 print_attributes(pTemplate, ulCount);
1312 state->find.attributes =
1313 calloc(1, ulCount * sizeof(state->find.attributes[0]));
1314 if (state->find.attributes == NULL)
1315 return CKR_DEVICE_MEMORY;
1316 for (i = 0; i < ulCount; i++) {
1317 state->find.attributes[i].pValue =
1318 malloc(pTemplate[i].ulValueLen);
1319 if (state->find.attributes[i].pValue == NULL) {
1320 find_object_final(state);
1321 return CKR_DEVICE_MEMORY;
1323 memcpy(state->find.attributes[i].pValue,
1324 pTemplate[i].pValue, pTemplate[i].ulValueLen);
1325 state->find.attributes[i].type = pTemplate[i].type;
1326 state->find.attributes[i].ulValueLen = pTemplate[i].ulValueLen;
1328 state->find.num_attributes = ulCount;
1329 state->find.next_object = 0;
1331 st_logf("find all objects\n");
1332 state->find.attributes = NULL;
1333 state->find.num_attributes = 0;
1334 state->find.next_object = 0;
1341 C_FindObjects(CK_SESSION_HANDLE hSession,
1342 CK_OBJECT_HANDLE_PTR phObject,
1343 CK_ULONG ulMaxObjectCount,
1344 CK_ULONG_PTR pulObjectCount)
1346 struct session_state *state;
1351 st_logf("FindObjects\n");
1353 VERIFY_SESSION_HANDLE(hSession, &state);
1355 if (state->find.next_object == -1) {
1356 application_error("application didn't do C_FindObjectsInit\n");
1357 return CKR_ARGUMENTS_BAD;
1359 if (ulMaxObjectCount == 0) {
1360 application_error("application asked for 0 objects\n");
1361 return CKR_ARGUMENTS_BAD;
1363 *pulObjectCount = 0;
1364 for (i = state->find.next_object; i < soft_token.object.num_objs; i++) {
1365 st_logf("FindObjects: %d\n", i);
1366 state->find.next_object = i + 1;
1367 if (attributes_match(soft_token.object.objs[i],
1368 state->find.attributes,
1369 state->find.num_attributes)) {
1370 *phObject++ = soft_token.object.objs[i]->object_handle;
1372 (*pulObjectCount)++;
1373 if (ulMaxObjectCount == 0)
1381 C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
1383 struct session_state *state;
1387 st_logf("FindObjectsFinal\n");
1388 VERIFY_SESSION_HANDLE(hSession, &state);
1389 find_object_final(state);
1394 commonInit(CK_ATTRIBUTE *attr_match, int attr_match_len,
1395 const CK_MECHANISM_TYPE *mechs, int mechs_len,
1396 const CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey,
1397 struct st_object **o)
1403 if ((ret = object_handle_to_object(hKey, o)) != CKR_OK)
1406 ret = attributes_match(*o, attr_match, attr_match_len);
1408 application_error("called commonInit on key that doesn't "
1409 "support required attr");
1410 return CKR_ARGUMENTS_BAD;
1413 for (i = 0; i < mechs_len; i++)
1414 if (mechs[i] == pMechanism->mechanism)
1416 if (i == mechs_len) {
1417 application_error("called mech (%08lx) not supported\n",
1418 pMechanism->mechanism);
1419 return CKR_ARGUMENTS_BAD;
1426 dup_mechanism(CK_MECHANISM_PTR *dp, const CK_MECHANISM_PTR pMechanism)
1430 p = malloc(sizeof(*p));
1432 return CKR_DEVICE_MEMORY;
1437 memcpy(p, pMechanism, sizeof(*p));
1443 C_DigestInit(CK_SESSION_HANDLE hSession,
1444 CK_MECHANISM_PTR pMechanism)
1446 st_logf("DigestInit\n");
1448 VERIFY_SESSION_HANDLE(hSession, NULL);
1449 return CKR_FUNCTION_NOT_SUPPORTED;
1453 C_SignInit(CK_SESSION_HANDLE hSession,
1454 CK_MECHANISM_PTR pMechanism,
1455 CK_OBJECT_HANDLE hKey)
1457 struct session_state *state;
1458 CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS };
1459 CK_BBOOL bool_true = CK_TRUE;
1460 CK_ATTRIBUTE attr[] = {
1461 { CKA_SIGN, &bool_true, sizeof(bool_true) }
1463 struct st_object *o;
1467 st_logf("SignInit\n");
1468 VERIFY_SESSION_HANDLE(hSession, &state);
1470 ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1471 mechs, sizeof(mechs)/sizeof(mechs[0]),
1472 pMechanism, hKey, &o);
1476 ret = dup_mechanism(&state->sign_mechanism, pMechanism);
1478 state->sign_object = OBJECT_ID(o);
1484 C_Sign(CK_SESSION_HANDLE hSession,
1487 CK_BYTE_PTR pSignature,
1488 CK_ULONG_PTR pulSignatureLen)
1490 struct session_state *state;
1491 struct st_object *o;
1494 const AlgorithmIdentifier *alg;
1495 heim_octet_string sig, data;
1499 VERIFY_SESSION_HANDLE(hSession, &state);
1504 if (state->sign_object == -1)
1505 return CKR_ARGUMENTS_BAD;
1507 if (pulSignatureLen == NULL) {
1508 st_logf("signature len NULL\n");
1509 ret = CKR_ARGUMENTS_BAD;
1513 if (pData == NULL_PTR) {
1514 st_logf("data NULL\n");
1515 ret = CKR_ARGUMENTS_BAD;
1519 o = soft_token.object.objs[state->sign_object];
1521 if (hx509_cert_have_private_key(o->cert) == 0) {
1522 st_logf("private key NULL\n");
1523 return CKR_ARGUMENTS_BAD;
1526 switch(state->sign_mechanism->mechanism) {
1528 alg = hx509_signature_rsa_pkcs1_x509();
1531 ret = CKR_FUNCTION_NOT_SUPPORTED;
1536 data.length = ulDataLen;
1538 hret = _hx509_create_signature(context,
1539 _hx509_cert_private_key(o->cert),
1545 ret = CKR_DEVICE_ERROR;
1548 *pulSignatureLen = sig.length;
1550 if (pSignature != NULL_PTR)
1551 memcpy(pSignature, sig.data, sig.length);
1556 memset(sig.data, 0, sig.length);
1557 der_free_octet_string(&sig);
1563 C_SignUpdate(CK_SESSION_HANDLE hSession,
1568 st_logf("SignUpdate\n");
1569 VERIFY_SESSION_HANDLE(hSession, NULL);
1570 return CKR_FUNCTION_NOT_SUPPORTED;
1575 C_SignFinal(CK_SESSION_HANDLE hSession,
1576 CK_BYTE_PTR pSignature,
1577 CK_ULONG_PTR pulSignatureLen)
1580 st_logf("SignUpdate\n");
1581 VERIFY_SESSION_HANDLE(hSession, NULL);
1582 return CKR_FUNCTION_NOT_SUPPORTED;
1586 C_VerifyInit(CK_SESSION_HANDLE hSession,
1587 CK_MECHANISM_PTR pMechanism,
1588 CK_OBJECT_HANDLE hKey)
1590 struct session_state *state;
1591 CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS };
1592 CK_BBOOL bool_true = CK_TRUE;
1593 CK_ATTRIBUTE attr[] = {
1594 { CKA_VERIFY, &bool_true, sizeof(bool_true) }
1596 struct st_object *o;
1600 st_logf("VerifyInit\n");
1601 VERIFY_SESSION_HANDLE(hSession, &state);
1603 ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1604 mechs, sizeof(mechs)/sizeof(mechs[0]),
1605 pMechanism, hKey, &o);
1609 ret = dup_mechanism(&state->verify_mechanism, pMechanism);
1611 state->verify_object = OBJECT_ID(o);
1617 C_Verify(CK_SESSION_HANDLE hSession,
1620 CK_BYTE_PTR pSignature,
1621 CK_ULONG ulSignatureLen)
1623 struct session_state *state;
1624 struct st_object *o;
1625 const AlgorithmIdentifier *alg;
1628 heim_octet_string data, sig;
1631 st_logf("Verify\n");
1632 VERIFY_SESSION_HANDLE(hSession, &state);
1634 if (state->verify_object == -1)
1635 return CKR_ARGUMENTS_BAD;
1637 o = soft_token.object.objs[state->verify_object];
1639 switch(state->verify_mechanism->mechanism) {
1641 alg = hx509_signature_rsa_pkcs1_x509();
1644 ret = CKR_FUNCTION_NOT_SUPPORTED;
1649 sig.length = ulDataLen;
1650 data.data = pSignature;
1651 data.length = ulSignatureLen;
1653 hret = _hx509_verify_signature(context,
1659 ret = CKR_GENERAL_ERROR;
1670 C_VerifyUpdate(CK_SESSION_HANDLE hSession,
1675 st_logf("VerifyUpdate\n");
1676 VERIFY_SESSION_HANDLE(hSession, NULL);
1677 return CKR_FUNCTION_NOT_SUPPORTED;
1681 C_VerifyFinal(CK_SESSION_HANDLE hSession,
1682 CK_BYTE_PTR pSignature,
1683 CK_ULONG ulSignatureLen)
1686 st_logf("VerifyFinal\n");
1687 VERIFY_SESSION_HANDLE(hSession, NULL);
1688 return CKR_FUNCTION_NOT_SUPPORTED;
1692 C_GenerateRandom(CK_SESSION_HANDLE hSession,
1693 CK_BYTE_PTR RandomData,
1694 CK_ULONG ulRandomLen)
1697 st_logf("GenerateRandom\n");
1698 VERIFY_SESSION_HANDLE(hSession, NULL);
1699 return CKR_FUNCTION_NOT_SUPPORTED;
1703 CK_FUNCTION_LIST funcs = {
1715 (void *)func_not_supported, /* C_InitPIN */
1716 (void *)func_not_supported, /* C_SetPIN */
1721 (void *)func_not_supported, /* C_GetOperationState */
1722 (void *)func_not_supported, /* C_SetOperationState */
1725 (void *)func_not_supported, /* C_CreateObject */
1726 (void *)func_not_supported, /* C_CopyObject */
1727 (void *)func_not_supported, /* C_DestroyObject */
1728 (void *)func_not_supported, /* C_GetObjectSize */
1729 C_GetAttributeValue,
1730 (void *)func_not_supported, /* C_SetAttributeValue */
1734 (void *)func_not_supported, /* C_EncryptInit, */
1735 (void *)func_not_supported, /* C_Encrypt, */
1736 (void *)func_not_supported, /* C_EncryptUpdate, */
1737 (void *)func_not_supported, /* C_EncryptFinal, */
1738 (void *)func_not_supported, /* C_DecryptInit, */
1739 (void *)func_not_supported, /* C_Decrypt, */
1740 (void *)func_not_supported, /* C_DecryptUpdate, */
1741 (void *)func_not_supported, /* C_DecryptFinal, */
1743 (void *)func_not_supported, /* C_Digest */
1744 (void *)func_not_supported, /* C_DigestUpdate */
1745 (void *)func_not_supported, /* C_DigestKey */
1746 (void *)func_not_supported, /* C_DigestFinal */
1751 (void *)func_not_supported, /* C_SignRecoverInit */
1752 (void *)func_not_supported, /* C_SignRecover */
1757 (void *)func_not_supported, /* C_VerifyRecoverInit */
1758 (void *)func_not_supported, /* C_VerifyRecover */
1759 (void *)func_not_supported, /* C_DigestEncryptUpdate */
1760 (void *)func_not_supported, /* C_DecryptDigestUpdate */
1761 (void *)func_not_supported, /* C_SignEncryptUpdate */
1762 (void *)func_not_supported, /* C_DecryptVerifyUpdate */
1763 (void *)func_not_supported, /* C_GenerateKey */
1764 (void *)func_not_supported, /* C_GenerateKeyPair */
1765 (void *)func_not_supported, /* C_WrapKey */
1766 (void *)func_not_supported, /* C_UnwrapKey */
1767 (void *)func_not_supported, /* C_DeriveKey */
1768 (void *)func_not_supported, /* C_SeedRandom */
1770 (void *)func_not_supported, /* C_GetFunctionStatus */
1771 (void *)func_not_supported, /* C_CancelFunction */
1772 (void *)func_not_supported /* C_WaitForSlotEvent */