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
37 #define OBJECT_ID_MASK 0xfff
38 #define HANDLE_OBJECT_ID(h) ((h) & OBJECT_ID_MASK)
39 #define OBJECT_ID(obj) HANDLE_OBJECT_ID((obj)->object_handle)
43 CK_ATTRIBUTE attribute;
48 CK_OBJECT_HANDLE object_handle;
49 struct st_attr *attrs;
54 static struct soft_token {
55 CK_VOID_PTR application;
60 struct st_object **objs;
69 struct session_state {
70 CK_SESSION_HANDLE session_handle;
73 CK_ATTRIBUTE *attributes;
74 CK_ULONG num_attributes;
79 CK_MECHANISM_PTR sign_mechanism;
81 CK_MECHANISM_PTR verify_mechanism;
83 #define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0]))
87 static hx509_context context;
90 application_error(const char *fmt, ...)
96 if (soft_token.flags.app_error_fatal)
101 st_logf(const char *fmt, ...)
104 if (soft_token.logfile == NULL)
107 vfprintf(soft_token.logfile, fmt, ap);
109 fflush(soft_token.logfile);
115 if (context == NULL) {
116 int ret = hx509_context_init(&context);
118 return CKR_GENERAL_ERROR;
123 #define INIT_CONTEXT() { CK_RV icret = init_context(); if (icret) return icret; }
126 snprintf_fill(char *str, size_t size, char fillchar, const char *fmt, ...)
130 len = vsnprintf(str, size, fmt, ap);
132 if (len < 0 || len > size)
135 str[len++] = fillchar;
139 #define printf error_use_st_logf
142 #define VERIFY_SESSION_HANDLE(s, state) \
145 ret = verify_session_handle(s, state); \
146 if (ret != CKR_OK) { \
147 /* return CKR_OK */; \
152 verify_session_handle(CK_SESSION_HANDLE hSession,
153 struct session_state **state)
157 for (i = 0; i < MAX_NUM_SESSION; i++){
158 if (soft_token.state[i].session_handle == hSession)
161 if (i == MAX_NUM_SESSION) {
162 application_error("use of invalid handle: 0x%08lx\n",
163 (unsigned long)hSession);
164 return CKR_SESSION_HANDLE_INVALID;
167 *state = &soft_token.state[i];
172 object_handle_to_object(CK_OBJECT_HANDLE handle,
173 struct st_object **object)
175 int i = HANDLE_OBJECT_ID(handle);
178 if (i >= soft_token.object.num_objs)
179 return CKR_ARGUMENTS_BAD;
180 if (soft_token.object.objs[i] == NULL)
181 return CKR_ARGUMENTS_BAD;
182 if (soft_token.object.objs[i]->object_handle != handle)
183 return CKR_ARGUMENTS_BAD;
184 *object = soft_token.object.objs[i];
189 attributes_match(const struct st_object *obj,
190 const CK_ATTRIBUTE *attributes,
191 CK_ULONG num_attributes)
196 st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj));
198 for (i = 0; i < num_attributes; i++) {
200 for (j = 0; j < obj->num_attributes; j++) {
201 if (attributes[i].type == obj->attrs[j].attribute.type &&
202 attributes[i].ulValueLen == obj->attrs[j].attribute.ulValueLen &&
203 memcmp(attributes[i].pValue, obj->attrs[j].attribute.pValue,
204 attributes[i].ulValueLen) == 0) {
210 st_logf("type %d attribute have no match\n", attributes[i].type);
214 st_logf("attribute matches\n");
219 print_attributes(const CK_ATTRIBUTE *attributes,
220 CK_ULONG num_attributes)
224 st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes);
226 for (i = 0; i < num_attributes; i++) {
228 switch (attributes[i].type) {
231 if (attributes[i].ulValueLen != sizeof(CK_BBOOL)) {
232 application_error("token attribute wrong length\n");
235 ck_true = attributes[i].pValue;
236 st_logf("token: %s", *ck_true ? "TRUE" : "FALSE");
240 CK_OBJECT_CLASS *class;
241 if (attributes[i].ulValueLen != sizeof(CK_ULONG)) {
242 application_error("class attribute wrong length\n");
245 class = attributes[i].pValue;
248 case CKO_CERTIFICATE:
249 st_logf("certificate");
252 st_logf("public key");
254 case CKO_PRIVATE_KEY:
255 st_logf("private key");
258 st_logf("secret key");
260 case CKO_DOMAIN_PARAMETERS:
261 st_logf("domain parameters");
264 st_logf("[class %lx]", (long unsigned)*class);
275 case CKA_APPLICATION:
276 st_logf("application");
285 st_logf("[unknown 0x%08lx]", (unsigned long)attributes[i].type);
292 static struct st_object *
295 struct st_object *o, **objs;
298 o = malloc(sizeof(*o));
301 memset(o, 0, sizeof(*o));
303 o->num_attributes = 0;
305 for (i = 0; i < soft_token.object.num_objs; i++) {
306 if (soft_token.object.objs == NULL) {
307 soft_token.object.objs[i] = o;
311 if (i == soft_token.object.num_objs) {
312 objs = realloc(soft_token.object.objs,
313 (soft_token.object.num_objs + 1) * sizeof(soft_token.object.objs[0]));
318 soft_token.object.objs = objs;
319 soft_token.object.objs[soft_token.object.num_objs++] = o;
321 soft_token.object.objs[i]->object_handle =
322 (random() & (~OBJECT_ID_MASK)) | i;
328 add_object_attribute(struct st_object *o,
330 CK_ATTRIBUTE_TYPE type,
337 i = o->num_attributes;
338 a = realloc(o->attrs, (i + 1) * sizeof(o->attrs[0]));
340 return CKR_DEVICE_MEMORY;
342 o->attrs[i].secret = secret;
343 o->attrs[i].attribute.type = type;
344 o->attrs[i].attribute.pValue = malloc(ulValueLen);
345 if (o->attrs[i].attribute.pValue == NULL && ulValueLen != 0)
346 return CKR_DEVICE_MEMORY;
347 memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen);
348 o->attrs[i].attribute.ulValueLen = ulValueLen;
355 add_pubkey_info(hx509_context hxctx, struct st_object *o,
356 CK_KEY_TYPE key_type, hx509_cert cert)
359 CK_BYTE *modulus = NULL;
360 size_t modulus_len = 0;
361 CK_ULONG modulus_bits = 0;
362 CK_BYTE *exponent = NULL;
363 size_t exponent_len = 0;
365 if (key_type != CKK_RSA)
367 if (_hx509_cert_private_key(cert) == NULL)
370 num = _hx509_private_key_get_internal(context,
371 _hx509_cert_private_key(cert),
374 return CKR_GENERAL_ERROR;
375 modulus_bits = BN_num_bits(num);
377 modulus_len = BN_num_bytes(num);
378 modulus = malloc(modulus_len);
379 BN_bn2bin(num, modulus);
382 add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len);
383 add_object_attribute(o, 0, CKA_MODULUS_BITS,
384 &modulus_bits, sizeof(modulus_bits));
388 num = _hx509_private_key_get_internal(context,
389 _hx509_cert_private_key(cert),
392 return CKR_GENERAL_ERROR;
394 exponent_len = BN_num_bytes(num);
395 exponent = malloc(exponent_len);
396 BN_bn2bin(num, exponent);
399 add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT,
400 exponent, exponent_len);
414 add_cert(hx509_context hxctx, void *ctx, hx509_cert cert)
416 struct foo *foo = (struct foo *)ctx;
417 struct st_object *o = NULL;
418 CK_OBJECT_CLASS type;
419 CK_BBOOL bool_true = CK_TRUE;
420 CK_BBOOL bool_false = CK_FALSE;
421 CK_CERTIFICATE_TYPE cert_type = CKC_X_509;
422 CK_KEY_TYPE key_type;
423 CK_MECHANISM_TYPE mech_type;
424 CK_RV ret = CKR_GENERAL_ERROR;
426 heim_octet_string cert_data, subject_data, issuer_data, serial_data;
428 st_logf("adding certificate\n");
430 serial_data.data = NULL;
431 serial_data.length = 0;
432 cert_data = subject_data = issuer_data = serial_data;
434 hret = hx509_cert_binary(hxctx, cert, &cert_data);
441 hret = hx509_cert_get_issuer(cert, &name);
444 hret = hx509_name_binary(name, &issuer_data);
445 hx509_name_free(&name);
449 hret = hx509_cert_get_subject(cert, &name);
452 hret = hx509_name_binary(name, &subject_data);
453 hx509_name_free(&name);
459 AlgorithmIdentifier alg;
461 hret = hx509_cert_get_SPKI_AlgorithmIdentifier(context, cert, &alg);
463 ret = CKR_DEVICE_MEMORY;
467 key_type = CKK_RSA; /* XXX */
469 free_AlgorithmIdentifier(&alg);
473 type = CKO_CERTIFICATE;
476 ret = CKR_DEVICE_MEMORY;
480 o->cert = hx509_cert_ref(cert);
482 add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
483 add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
484 add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
485 add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
486 add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
488 add_object_attribute(o, 0, CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type));
489 add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
491 add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
492 add_object_attribute(o, 0, CKA_ISSUER, issuer_data.data, issuer_data.length);
493 add_object_attribute(o, 0, CKA_SERIAL_NUMBER, serial_data.data, serial_data.length);
494 add_object_attribute(o, 0, CKA_VALUE, cert_data.data, cert_data.length);
495 add_object_attribute(o, 0, CKA_TRUSTED, &bool_false, sizeof(bool_false));
497 st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o));
499 type = CKO_PUBLIC_KEY;
502 ret = CKR_DEVICE_MEMORY;
505 o->cert = hx509_cert_ref(cert);
507 add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
508 add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
509 add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
510 add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
511 add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
513 add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
514 add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
515 add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */
516 add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */
517 add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
518 add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
519 mech_type = CKM_RSA_X_509;
520 add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
522 add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
523 add_object_attribute(o, 0, CKA_ENCRYPT, &bool_true, sizeof(bool_true));
524 add_object_attribute(o, 0, CKA_VERIFY, &bool_true, sizeof(bool_true));
525 add_object_attribute(o, 0, CKA_VERIFY_RECOVER, &bool_false, sizeof(bool_false));
526 add_object_attribute(o, 0, CKA_WRAP, &bool_true, sizeof(bool_true));
527 add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true));
529 add_pubkey_info(hxctx, o, key_type, cert);
531 st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o));
533 if (hx509_cert_have_private_key(cert)) {
536 type = CKO_PRIVATE_KEY;
539 ret = CKR_DEVICE_MEMORY;
542 o->cert = hx509_cert_ref(cert);
544 add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
545 add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
546 add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false));
547 add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
548 add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
550 add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
551 add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
552 add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */
553 add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */
554 add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
555 add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
556 mech_type = CKM_RSA_X_509;
557 add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
559 add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
560 add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true));
561 add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true));
563 add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags));
565 add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true));
566 add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true));
567 add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false));
568 add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true));
569 add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true));
570 add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false));
572 add_pubkey_info(hxctx, o, key_type, cert);
578 st_logf("something went wrong when adding cert!\n");
582 hx509_xfree(cert_data.data);
583 hx509_xfree(serial_data.data);
584 hx509_xfree(issuer_data.data);
585 hx509_xfree(subject_data.data);
591 add_certificate(const char *cert_file,
597 hx509_lock lock = NULL;
605 flags |= HX509_CERTS_UNPROTECT_ALL;
609 asprintf(&str, "PASS:%s", pin);
611 hx509_lock_init(context, &lock);
612 hx509_lock_command_string(lock, str);
614 memset(str, 0, strlen(str));
618 ret = hx509_certs_init(context, cert_file, flags, lock, &certs);
620 st_logf("failed to open file %s\n", cert_file);
621 return CKR_GENERAL_ERROR;
624 ret = hx509_certs_iter(context, certs, add_cert, &foo);
625 hx509_certs_free(&certs);
627 st_logf("failed adding certs from file %s\n", cert_file);
628 return CKR_GENERAL_ERROR;
635 find_object_final(struct session_state *state)
637 if (state->find.attributes) {
640 for (i = 0; i < state->find.num_attributes; i++) {
641 if (state->find.attributes[i].pValue)
642 free(state->find.attributes[i].pValue);
644 free(state->find.attributes);
645 state->find.attributes = NULL;
646 state->find.num_attributes = 0;
647 state->find.next_object = -1;
652 reset_crypto_state(struct session_state *state)
654 state->sign_object = -1;
655 if (state->sign_mechanism)
656 free(state->sign_mechanism);
657 state->sign_mechanism = NULL_PTR;
658 state->verify_object = -1;
659 if (state->verify_mechanism)
660 free(state->verify_mechanism);
661 state->verify_mechanism = NULL_PTR;
665 close_session(struct session_state *state)
667 if (state->find.attributes) {
668 application_error("application didn't do C_FindObjectsFinal\n");
669 find_object_final(state);
672 state->session_handle = CK_INVALID_HANDLE;
673 soft_token.application = NULL_PTR;
674 soft_token.notify = NULL_PTR;
675 reset_crypto_state(state);
681 return soft_token.open_sessions > 0 ? "yes" : "no";
685 read_conf_file(const char *fn, CK_USER_TYPE userType, const char *pin)
687 char buf[1024], *type, *s, *p;
691 CK_RV failed = CKR_OK;
695 st_logf("can't open configuration file %s\n", fn);
696 return CKR_GENERAL_ERROR;
699 while(fgets(buf, sizeof(buf), f) != NULL) {
700 buf[strcspn(buf, "\n")] = '\0';
704 st_logf("line: %s\n", buf);
715 type = strtok_r(p, "\t", &s);
719 if (strcasecmp("certificate", type) == 0) {
720 char *cert, *id, *label;
722 id = strtok_r(NULL, "\t", &s);
727 st_logf("id: %s\n", id);
728 label = strtok_r(NULL, "\t", &s);
730 st_logf("no label\n");
733 cert = strtok_r(NULL, "\t", &s);
735 st_logf("no certfiicate store\n");
739 st_logf("adding: %s: %s in file %s\n", id, label, cert);
741 ret = add_certificate(cert, pin, id, label);
744 } else if (strcasecmp("debug", type) == 0) {
747 name = strtok_r(NULL, "\t", &s);
749 st_logf("no filename\n");
753 if (soft_token.logfile)
754 fclose(soft_token.logfile);
756 if (strcasecmp(name, "stdout") == 0)
757 soft_token.logfile = stdout;
759 soft_token.logfile = fopen(name, "a");
760 if (soft_token.logfile == NULL)
761 st_logf("failed to open file: %s\n", name);
763 } else if (strcasecmp("app-fatal", type) == 0) {
766 name = strtok_r(NULL, "\t", &s);
768 st_logf("argument to app-fatal\n");
772 if (strcmp(name, "true") == 0 || strcmp(name, "on") == 0)
773 soft_token.flags.app_error_fatal = 1;
774 else if (strcmp(name, "false") == 0 || strcmp(name, "off") == 0)
775 soft_token.flags.app_error_fatal = 0;
777 st_logf("unknown app-fatal: %s\n", name);
780 st_logf("unknown type: %s\n", type);
790 func_not_supported(void)
792 st_logf("function not supported\n");
793 return CKR_FUNCTION_NOT_SUPPORTED;
797 C_Initialize(CK_VOID_PTR a)
799 CK_C_INITIALIZE_ARGS_PTR args = a;
803 st_logf("Initialize\n");
807 OpenSSL_add_all_algorithms();
809 srandom(getpid() ^ time(NULL));
811 for (i = 0; i < MAX_NUM_SESSION; i++) {
812 soft_token.state[i].session_handle = CK_INVALID_HANDLE;
813 soft_token.state[i].find.attributes = NULL;
814 soft_token.state[i].find.num_attributes = 0;
815 soft_token.state[i].find.next_object = -1;
816 reset_crypto_state(&soft_token.state[i]);
819 soft_token.flags.hardware_slot = 1;
820 soft_token.flags.app_error_fatal = 0;
821 soft_token.flags.login_done = 0;
823 soft_token.object.objs = NULL;
824 soft_token.object.num_objs = 0;
826 soft_token.logfile = NULL;
828 soft_token.logfile = stdout;
831 soft_token.logfile = fopen("/tmp/log-pkcs11.txt", "a");
835 st_logf("\tCreateMutex:\t%p\n", args->CreateMutex);
836 st_logf("\tDestroyMutext\t%p\n", args->DestroyMutex);
837 st_logf("\tLockMutext\t%p\n", args->LockMutex);
838 st_logf("\tUnlockMutext\t%p\n", args->UnlockMutex);
839 st_logf("\tFlags\t%04x\n", (unsigned int)args->flags);
843 char *fn = NULL, *home = NULL;
845 if (getuid() == geteuid()) {
846 fn = getenv("SOFTPKCS11RC");
849 home = getenv("HOME");
851 if (fn == NULL && home == NULL) {
852 struct passwd *pw = getpwuid(getuid());
858 asprintf(&fn, "%s/.soft-token.rc", home);
860 fn = strdup("/etc/soft-token.rc");
863 soft_token.config_file = fn;
867 * This operations doesn't return CKR_OK if any of the
868 * certificates failes to be unparsed (ie password protected).
870 ret = read_conf_file(soft_token.config_file, CKU_USER, NULL);
872 soft_token.flags.login_done = 1;
878 C_Finalize(CK_VOID_PTR args)
884 st_logf("Finalize\n");
886 for (i = 0; i < MAX_NUM_SESSION; i++) {
887 if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) {
888 application_error("application finalized without "
889 "closing session\n");
890 close_session(&soft_token.state[i]);
898 C_GetInfo(CK_INFO_PTR args)
902 st_logf("GetInfo\n");
904 memset(args, 17, sizeof(*args));
905 args->cryptokiVersion.major = 2;
906 args->cryptokiVersion.minor = 10;
907 snprintf_fill((char *)args->manufacturerID,
908 sizeof(args->manufacturerID),
910 "Heimdal hx509 SoftToken");
911 snprintf_fill((char *)args->libraryDescription,
912 sizeof(args->libraryDescription), ' ',
913 "Heimdal hx509 SoftToken");
914 args->libraryVersion.major = 2;
915 args->libraryVersion.minor = 0;
920 extern CK_FUNCTION_LIST funcs;
923 C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
927 *ppFunctionList = &funcs;
932 C_GetSlotList(CK_BBOOL tokenPresent,
933 CK_SLOT_ID_PTR pSlotList,
934 CK_ULONG_PTR pulCount)
937 st_logf("GetSlotList: %s\n",
938 tokenPresent ? "tokenPresent" : "token not Present");
946 C_GetSlotInfo(CK_SLOT_ID slotID,
947 CK_SLOT_INFO_PTR pInfo)
950 st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID, has_session());
952 memset(pInfo, 18, sizeof(*pInfo));
955 return CKR_ARGUMENTS_BAD;
957 snprintf_fill((char *)pInfo->slotDescription,
958 sizeof(pInfo->slotDescription),
960 "Heimdal hx509 SoftToken (slot)");
961 snprintf_fill((char *)pInfo->manufacturerID,
962 sizeof(pInfo->manufacturerID),
964 "Heimdal hx509 SoftToken (slot)");
965 pInfo->flags = CKF_TOKEN_PRESENT;
966 if (soft_token.flags.hardware_slot)
967 pInfo->flags |= CKF_HW_SLOT;
968 pInfo->hardwareVersion.major = 1;
969 pInfo->hardwareVersion.minor = 0;
970 pInfo->firmwareVersion.major = 1;
971 pInfo->firmwareVersion.minor = 0;
977 C_GetTokenInfo(CK_SLOT_ID slotID,
978 CK_TOKEN_INFO_PTR pInfo)
981 st_logf("GetTokenInfo: %s\n", has_session());
983 memset(pInfo, 19, sizeof(*pInfo));
985 snprintf_fill((char *)pInfo->label,
986 sizeof(pInfo->label),
988 "Heimdal hx509 SoftToken (token)");
989 snprintf_fill((char *)pInfo->manufacturerID,
990 sizeof(pInfo->manufacturerID),
992 "Heimdal hx509 SoftToken (token)");
993 snprintf_fill((char *)pInfo->model,
994 sizeof(pInfo->model),
996 "Heimdal hx509 SoftToken (token)");
997 snprintf_fill((char *)pInfo->serialNumber,
998 sizeof(pInfo->serialNumber),
1002 CKF_TOKEN_INITIALIZED |
1003 CKF_USER_PIN_INITIALIZED;
1005 if (soft_token.flags.login_done == 0)
1006 pInfo->flags |= CKF_LOGIN_REQUIRED;
1009 CKF_RESTORE_KEY_NOT_NEEDED |
1011 pInfo->ulMaxSessionCount = MAX_NUM_SESSION;
1012 pInfo->ulSessionCount = soft_token.open_sessions;
1013 pInfo->ulMaxRwSessionCount = MAX_NUM_SESSION;
1014 pInfo->ulRwSessionCount = soft_token.open_sessions;
1015 pInfo->ulMaxPinLen = 1024;
1016 pInfo->ulMinPinLen = 0;
1017 pInfo->ulTotalPublicMemory = 4711;
1018 pInfo->ulFreePublicMemory = 4712;
1019 pInfo->ulTotalPrivateMemory = 4713;
1020 pInfo->ulFreePrivateMemory = 4714;
1021 pInfo->hardwareVersion.major = 2;
1022 pInfo->hardwareVersion.minor = 0;
1023 pInfo->firmwareVersion.major = 2;
1024 pInfo->firmwareVersion.minor = 0;
1030 C_GetMechanismList(CK_SLOT_ID slotID,
1031 CK_MECHANISM_TYPE_PTR pMechanismList,
1032 CK_ULONG_PTR pulCount)
1035 st_logf("GetMechanismList\n");
1038 if (pMechanismList == NULL_PTR)
1040 pMechanismList[1] = CKM_RSA_PKCS;
1046 C_GetMechanismInfo(CK_SLOT_ID slotID,
1047 CK_MECHANISM_TYPE type,
1048 CK_MECHANISM_INFO_PTR pInfo)
1051 st_logf("GetMechanismInfo: slot %d type: %d\n",
1052 (int)slotID, (int)type);
1053 memset(pInfo, 0, sizeof(*pInfo));
1059 C_InitToken(CK_SLOT_ID slotID,
1060 CK_UTF8CHAR_PTR pPin,
1062 CK_UTF8CHAR_PTR pLabel)
1065 st_logf("InitToken: slot %d\n", (int)slotID);
1066 return CKR_FUNCTION_NOT_SUPPORTED;
1070 C_OpenSession(CK_SLOT_ID slotID,
1072 CK_VOID_PTR pApplication,
1074 CK_SESSION_HANDLE_PTR phSession)
1078 st_logf("OpenSession: slot: %d\n", (int)slotID);
1080 if (soft_token.open_sessions == MAX_NUM_SESSION)
1081 return CKR_SESSION_COUNT;
1083 soft_token.application = pApplication;
1084 soft_token.notify = Notify;
1086 for (i = 0; i < MAX_NUM_SESSION; i++)
1087 if (soft_token.state[i].session_handle == CK_INVALID_HANDLE)
1089 if (i == MAX_NUM_SESSION)
1092 soft_token.open_sessions++;
1094 soft_token.state[i].session_handle =
1095 (CK_SESSION_HANDLE)(random() & 0xfffff);
1096 *phSession = soft_token.state[i].session_handle;
1102 C_CloseSession(CK_SESSION_HANDLE hSession)
1104 struct session_state *state;
1106 st_logf("CloseSession\n");
1108 if (verify_session_handle(hSession, &state) != CKR_OK)
1109 application_error("closed session not open");
1111 close_session(state);
1117 C_CloseAllSessions(CK_SLOT_ID slotID)
1122 st_logf("CloseAllSessions\n");
1124 for (i = 0; i < MAX_NUM_SESSION; i++)
1125 if (soft_token.state[i].session_handle != CK_INVALID_HANDLE)
1126 close_session(&soft_token.state[i]);
1132 C_GetSessionInfo(CK_SESSION_HANDLE hSession,
1133 CK_SESSION_INFO_PTR pInfo)
1135 st_logf("GetSessionInfo\n");
1138 VERIFY_SESSION_HANDLE(hSession, NULL);
1140 memset(pInfo, 20, sizeof(*pInfo));
1143 if (soft_token.flags.login_done)
1144 pInfo->state = CKS_RO_USER_FUNCTIONS;
1146 pInfo->state = CKS_RO_PUBLIC_SESSION;
1147 pInfo->flags = CKF_SERIAL_SESSION;
1148 pInfo->ulDeviceError = 0;
1154 C_Login(CK_SESSION_HANDLE hSession,
1155 CK_USER_TYPE userType,
1156 CK_UTF8CHAR_PTR pPin,
1165 VERIFY_SESSION_HANDLE(hSession, NULL);
1167 if (pPin != NULL_PTR) {
1168 asprintf(&pin, "%.*s", (int)ulPinLen, pPin);
1169 st_logf("type: %d password: %s\n", (int)userType, pin);
1176 ret = read_conf_file(soft_token.config_file, userType, pin);
1178 soft_token.flags.login_done = 1;
1182 return soft_token.flags.login_done ? CKR_OK : CKR_PIN_INCORRECT;
1186 C_Logout(CK_SESSION_HANDLE hSession)
1188 st_logf("Logout\n");
1191 VERIFY_SESSION_HANDLE(hSession, NULL);
1192 return CKR_FUNCTION_NOT_SUPPORTED;
1196 C_GetObjectSize(CK_SESSION_HANDLE hSession,
1197 CK_OBJECT_HANDLE hObject,
1198 CK_ULONG_PTR pulSize)
1200 st_logf("GetObjectSize\n");
1203 VERIFY_SESSION_HANDLE(hSession, NULL);
1204 return CKR_FUNCTION_NOT_SUPPORTED;
1208 C_GetAttributeValue(CK_SESSION_HANDLE hSession,
1209 CK_OBJECT_HANDLE hObject,
1210 CK_ATTRIBUTE_PTR pTemplate,
1213 struct session_state *state;
1214 struct st_object *obj;
1221 st_logf("GetAttributeValue: %lx\n",
1222 (unsigned long)HANDLE_OBJECT_ID(hObject));
1223 VERIFY_SESSION_HANDLE(hSession, &state);
1225 if ((ret = object_handle_to_object(hObject, &obj)) != CKR_OK) {
1226 st_logf("object not found: %lx\n",
1227 (unsigned long)HANDLE_OBJECT_ID(hObject));
1231 for (i = 0; i < ulCount; i++) {
1232 st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate[i].type);
1233 for (j = 0; j < obj->num_attributes; j++) {
1234 if (obj->attrs[j].secret) {
1235 pTemplate[i].ulValueLen = (CK_ULONG)-1;
1238 if (pTemplate[i].type == obj->attrs[j].attribute.type) {
1239 if (pTemplate[i].pValue != NULL_PTR && obj->attrs[j].secret == 0) {
1240 if (pTemplate[i].ulValueLen >= obj->attrs[j].attribute.ulValueLen)
1241 memcpy(pTemplate[i].pValue, obj->attrs[j].attribute.pValue,
1242 obj->attrs[j].attribute.ulValueLen);
1244 pTemplate[i].ulValueLen = obj->attrs[j].attribute.ulValueLen;
1248 if (j == obj->num_attributes) {
1249 st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate[i].type);
1250 pTemplate[i].ulValueLen = (CK_ULONG)-1;
1258 C_FindObjectsInit(CK_SESSION_HANDLE hSession,
1259 CK_ATTRIBUTE_PTR pTemplate,
1262 struct session_state *state;
1264 st_logf("FindObjectsInit\n");
1268 VERIFY_SESSION_HANDLE(hSession, &state);
1270 if (state->find.next_object != -1) {
1271 application_error("application didn't do C_FindObjectsFinal\n");
1272 find_object_final(state);
1277 print_attributes(pTemplate, ulCount);
1279 state->find.attributes =
1280 calloc(1, ulCount * sizeof(state->find.attributes[0]));
1281 if (state->find.attributes == NULL)
1282 return CKR_DEVICE_MEMORY;
1283 for (i = 0; i < ulCount; i++) {
1284 state->find.attributes[i].pValue =
1285 malloc(pTemplate[i].ulValueLen);
1286 if (state->find.attributes[i].pValue == NULL) {
1287 find_object_final(state);
1288 return CKR_DEVICE_MEMORY;
1290 memcpy(state->find.attributes[i].pValue,
1291 pTemplate[i].pValue, pTemplate[i].ulValueLen);
1292 state->find.attributes[i].type = pTemplate[i].type;
1293 state->find.attributes[i].ulValueLen = pTemplate[i].ulValueLen;
1295 state->find.num_attributes = ulCount;
1296 state->find.next_object = 0;
1298 st_logf("find all objects\n");
1299 state->find.attributes = NULL;
1300 state->find.num_attributes = 0;
1301 state->find.next_object = 0;
1308 C_FindObjects(CK_SESSION_HANDLE hSession,
1309 CK_OBJECT_HANDLE_PTR phObject,
1310 CK_ULONG ulMaxObjectCount,
1311 CK_ULONG_PTR pulObjectCount)
1313 struct session_state *state;
1318 st_logf("FindObjects\n");
1320 VERIFY_SESSION_HANDLE(hSession, &state);
1322 if (state->find.next_object == -1) {
1323 application_error("application didn't do C_FindObjectsInit\n");
1324 return CKR_ARGUMENTS_BAD;
1326 if (ulMaxObjectCount == 0) {
1327 application_error("application asked for 0 objects\n");
1328 return CKR_ARGUMENTS_BAD;
1330 *pulObjectCount = 0;
1331 for (i = state->find.next_object; i < soft_token.object.num_objs; i++) {
1332 st_logf("FindObjects: %d\n", i);
1333 state->find.next_object = i + 1;
1334 if (attributes_match(soft_token.object.objs[i],
1335 state->find.attributes,
1336 state->find.num_attributes)) {
1337 *phObject++ = soft_token.object.objs[i]->object_handle;
1339 (*pulObjectCount)++;
1340 if (ulMaxObjectCount == 0)
1348 C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
1350 struct session_state *state;
1354 st_logf("FindObjectsFinal\n");
1355 VERIFY_SESSION_HANDLE(hSession, &state);
1356 find_object_final(state);
1361 commonInit(CK_ATTRIBUTE *attr_match, int attr_match_len,
1362 const CK_MECHANISM_TYPE *mechs, int mechs_len,
1363 const CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey,
1364 struct st_object **o)
1370 if ((ret = object_handle_to_object(hKey, o)) != CKR_OK)
1373 ret = attributes_match(*o, attr_match, attr_match_len);
1375 application_error("called commonInit on key that doesn't "
1376 "support required attr");
1377 return CKR_ARGUMENTS_BAD;
1380 for (i = 0; i < mechs_len; i++)
1381 if (mechs[i] == pMechanism->mechanism)
1383 if (i == mechs_len) {
1384 application_error("called mech (%08lx) not supported\n",
1385 pMechanism->mechanism);
1386 return CKR_ARGUMENTS_BAD;
1393 dup_mechanism(CK_MECHANISM_PTR *dup, const CK_MECHANISM_PTR pMechanism)
1397 p = malloc(sizeof(*p));
1399 return CKR_DEVICE_MEMORY;
1404 memcpy(p, pMechanism, sizeof(*p));
1410 C_DigestInit(CK_SESSION_HANDLE hSession,
1411 CK_MECHANISM_PTR pMechanism)
1413 st_logf("DigestInit\n");
1415 VERIFY_SESSION_HANDLE(hSession, NULL);
1416 return CKR_FUNCTION_NOT_SUPPORTED;
1420 C_SignInit(CK_SESSION_HANDLE hSession,
1421 CK_MECHANISM_PTR pMechanism,
1422 CK_OBJECT_HANDLE hKey)
1424 struct session_state *state;
1425 CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS };
1426 CK_BBOOL bool_true = CK_TRUE;
1427 CK_ATTRIBUTE attr[] = {
1428 { CKA_SIGN, &bool_true, sizeof(bool_true) }
1430 struct st_object *o;
1434 st_logf("SignInit\n");
1435 VERIFY_SESSION_HANDLE(hSession, &state);
1437 ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1438 mechs, sizeof(mechs)/sizeof(mechs[0]),
1439 pMechanism, hKey, &o);
1443 ret = dup_mechanism(&state->sign_mechanism, pMechanism);
1445 state->sign_object = OBJECT_ID(o);
1451 C_Sign(CK_SESSION_HANDLE hSession,
1454 CK_BYTE_PTR pSignature,
1455 CK_ULONG_PTR pulSignatureLen)
1457 struct session_state *state;
1458 struct st_object *o;
1461 const AlgorithmIdentifier *alg;
1462 heim_octet_string sig, data;
1466 VERIFY_SESSION_HANDLE(hSession, &state);
1471 if (state->sign_object == -1)
1472 return CKR_ARGUMENTS_BAD;
1474 if (pulSignatureLen == NULL) {
1475 st_logf("signature len NULL\n");
1476 ret = CKR_ARGUMENTS_BAD;
1480 if (pData == NULL_PTR) {
1481 st_logf("data NULL\n");
1482 ret = CKR_ARGUMENTS_BAD;
1486 o = soft_token.object.objs[state->sign_object];
1488 if (hx509_cert_have_private_key(o->cert) == 0) {
1489 st_logf("private key NULL\n");
1490 return CKR_ARGUMENTS_BAD;
1493 switch(state->sign_mechanism->mechanism) {
1495 alg = hx509_signature_rsa_pkcs1_x509();
1498 ret = CKR_FUNCTION_NOT_SUPPORTED;
1503 data.length = ulDataLen;
1505 hret = _hx509_create_signature(context,
1506 _hx509_cert_private_key(o->cert),
1512 ret = CKR_DEVICE_ERROR;
1515 *pulSignatureLen = sig.length;
1517 if (pSignature != NULL_PTR)
1518 memcpy(pSignature, sig.data, sig.length);
1523 memset(sig.data, 0, sig.length);
1524 der_free_octet_string(&sig);
1530 C_SignUpdate(CK_SESSION_HANDLE hSession,
1535 st_logf("SignUpdate\n");
1536 VERIFY_SESSION_HANDLE(hSession, NULL);
1537 return CKR_FUNCTION_NOT_SUPPORTED;
1542 C_SignFinal(CK_SESSION_HANDLE hSession,
1543 CK_BYTE_PTR pSignature,
1544 CK_ULONG_PTR pulSignatureLen)
1547 st_logf("SignUpdate\n");
1548 VERIFY_SESSION_HANDLE(hSession, NULL);
1549 return CKR_FUNCTION_NOT_SUPPORTED;
1553 C_VerifyInit(CK_SESSION_HANDLE hSession,
1554 CK_MECHANISM_PTR pMechanism,
1555 CK_OBJECT_HANDLE hKey)
1557 struct session_state *state;
1558 CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS };
1559 CK_BBOOL bool_true = CK_TRUE;
1560 CK_ATTRIBUTE attr[] = {
1561 { CKA_VERIFY, &bool_true, sizeof(bool_true) }
1563 struct st_object *o;
1567 st_logf("VerifyInit\n");
1568 VERIFY_SESSION_HANDLE(hSession, &state);
1570 ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1571 mechs, sizeof(mechs)/sizeof(mechs[0]),
1572 pMechanism, hKey, &o);
1576 ret = dup_mechanism(&state->verify_mechanism, pMechanism);
1578 state->verify_object = OBJECT_ID(o);
1584 C_Verify(CK_SESSION_HANDLE hSession,
1587 CK_BYTE_PTR pSignature,
1588 CK_ULONG ulSignatureLen)
1590 struct session_state *state;
1591 struct st_object *o;
1592 const AlgorithmIdentifier *alg;
1595 heim_octet_string data, sig;
1598 st_logf("Verify\n");
1599 VERIFY_SESSION_HANDLE(hSession, &state);
1601 if (state->verify_object == -1)
1602 return CKR_ARGUMENTS_BAD;
1604 o = soft_token.object.objs[state->verify_object];
1606 switch(state->verify_mechanism->mechanism) {
1608 alg = hx509_signature_rsa_pkcs1_x509();
1611 ret = CKR_FUNCTION_NOT_SUPPORTED;
1616 sig.length = ulDataLen;
1617 data.data = pSignature;
1618 data.length = ulSignatureLen;
1620 hret = _hx509_verify_signature(context,
1621 _hx509_get_cert(o->cert),
1626 ret = CKR_GENERAL_ERROR;
1637 C_VerifyUpdate(CK_SESSION_HANDLE hSession,
1642 st_logf("VerifyUpdate\n");
1643 VERIFY_SESSION_HANDLE(hSession, NULL);
1644 return CKR_FUNCTION_NOT_SUPPORTED;
1648 C_VerifyFinal(CK_SESSION_HANDLE hSession,
1649 CK_BYTE_PTR pSignature,
1650 CK_ULONG ulSignatureLen)
1653 st_logf("VerifyFinal\n");
1654 VERIFY_SESSION_HANDLE(hSession, NULL);
1655 return CKR_FUNCTION_NOT_SUPPORTED;
1659 C_GenerateRandom(CK_SESSION_HANDLE hSession,
1660 CK_BYTE_PTR RandomData,
1661 CK_ULONG ulRandomLen)
1664 st_logf("GenerateRandom\n");
1665 VERIFY_SESSION_HANDLE(hSession, NULL);
1666 return CKR_FUNCTION_NOT_SUPPORTED;
1670 CK_FUNCTION_LIST funcs = {
1682 (void *)func_not_supported, /* C_InitPIN */
1683 (void *)func_not_supported, /* C_SetPIN */
1688 (void *)func_not_supported, /* C_GetOperationState */
1689 (void *)func_not_supported, /* C_SetOperationState */
1692 (void *)func_not_supported, /* C_CreateObject */
1693 (void *)func_not_supported, /* C_CopyObject */
1694 (void *)func_not_supported, /* C_DestroyObject */
1695 (void *)func_not_supported, /* C_GetObjectSize */
1696 C_GetAttributeValue,
1697 (void *)func_not_supported, /* C_SetAttributeValue */
1701 (void *)func_not_supported, /* C_EncryptInit, */
1702 (void *)func_not_supported, /* C_Encrypt, */
1703 (void *)func_not_supported, /* C_EncryptUpdate, */
1704 (void *)func_not_supported, /* C_EncryptFinal, */
1705 (void *)func_not_supported, /* C_DecryptInit, */
1706 (void *)func_not_supported, /* C_Decrypt, */
1707 (void *)func_not_supported, /* C_DecryptUpdate, */
1708 (void *)func_not_supported, /* C_DecryptFinal, */
1710 (void *)func_not_supported, /* C_Digest */
1711 (void *)func_not_supported, /* C_DigestUpdate */
1712 (void *)func_not_supported, /* C_DigestKey */
1713 (void *)func_not_supported, /* C_DigestFinal */
1718 (void *)func_not_supported, /* C_SignRecoverInit */
1719 (void *)func_not_supported, /* C_SignRecover */
1724 (void *)func_not_supported, /* C_VerifyRecoverInit */
1725 (void *)func_not_supported, /* C_VerifyRecover */
1726 (void *)func_not_supported, /* C_DigestEncryptUpdate */
1727 (void *)func_not_supported, /* C_DecryptDigestUpdate */
1728 (void *)func_not_supported, /* C_SignEncryptUpdate */
1729 (void *)func_not_supported, /* C_DecryptVerifyUpdate */
1730 (void *)func_not_supported, /* C_GenerateKey */
1731 (void *)func_not_supported, /* C_GenerateKeyPair */
1732 (void *)func_not_supported, /* C_WrapKey */
1733 (void *)func_not_supported, /* C_UnwrapKey */
1734 (void *)func_not_supported, /* C_DeriveKey */
1735 (void *)func_not_supported, /* C_SeedRandom */
1737 (void *)func_not_supported, /* C_GetFunctionStatus */
1738 (void *)func_not_supported, /* C_CancelFunction */
1739 (void *)func_not_supported /* C_WaitForSlotEvent */