cf/largefile.m4: Fix build with autoconf-2.72
[heimdal.git] / lib / hx509 / softp11.c
blob75f675579c77d6ccc24bf4074870f62677d88582
1 /*
2 * Copyright (c) 2004 - 2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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
31 * SUCH DAMAGE.
34 #define CRYPTOKI_EXPORTS 1
36 #include "hx_locl.h"
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)
43 #ifndef HAVE_RANDOM
44 #define random() rand()
45 #define srandom(s) srand(s)
46 #endif
48 #ifdef _WIN32
49 #include <shlobj.h>
50 #endif
52 struct st_attr {
53 CK_ATTRIBUTE attribute;
54 int secret;
57 struct st_object {
58 CK_OBJECT_HANDLE object_handle;
59 struct st_attr *attrs;
60 int num_attributes;
61 hx509_cert cert;
64 static struct soft_token {
65 CK_VOID_PTR application;
66 CK_NOTIFY notify;
67 char *config_file;
68 hx509_certs certs;
69 struct {
70 struct st_object **objs;
71 int num_objs;
72 } object;
73 struct {
74 int hardware_slot;
75 int app_error_fatal;
76 int login_done;
77 } flags;
78 int open_sessions;
79 struct session_state {
80 CK_SESSION_HANDLE session_handle;
82 struct {
83 CK_ATTRIBUTE *attributes;
84 CK_ULONG num_attributes;
85 int next_object;
86 } find;
88 int sign_object;
89 CK_MECHANISM_PTR sign_mechanism;
90 int verify_object;
91 CK_MECHANISM_PTR verify_mechanism;
92 } state[10];
93 #define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0]))
94 FILE *logfile;
95 } soft_token;
97 static hx509_context context;
99 static void
100 application_error(const char *fmt, ...)
102 va_list ap;
103 va_start(ap, fmt);
104 vprintf(fmt, ap);
105 va_end(ap);
106 if (soft_token.flags.app_error_fatal)
107 abort();
110 static void
111 st_logf(const char *fmt, ...)
113 va_list ap;
114 if (soft_token.logfile == NULL)
115 return;
116 va_start(ap, fmt);
117 vfprintf(soft_token.logfile, fmt, ap);
118 va_end(ap);
119 fflush(soft_token.logfile);
122 static CK_RV
123 init_context(void)
125 if (context == NULL) {
126 int ret = hx509_context_init(&context);
127 if (ret)
128 return CKR_GENERAL_ERROR;
130 return CKR_OK;
133 #define INIT_CONTEXT() { CK_RV icret = init_context(); if (icret) return icret; }
135 static void
136 snprintf_fill(char *str, size_t size, char fillchar, const char *fmt, ...)
138 int len;
139 va_list ap;
140 va_start(ap, fmt);
141 len = vsnprintf(str, size, fmt, ap);
142 va_end(ap);
143 if (len < 0 || (size_t)len > size)
144 return;
145 while ((size_t)len < size)
146 str[len++] = fillchar;
149 #ifndef TEST_APP
150 #define printf error_use_st_logf
151 #endif
153 #define VERIFY_SESSION_HANDLE(s, state) \
155 CK_RV xret; \
156 xret = verify_session_handle(s, state); \
157 if (xret != CKR_OK) { \
158 /* return CKR_OK */; \
162 static CK_RV
163 verify_session_handle(CK_SESSION_HANDLE hSession,
164 struct session_state **state)
166 size_t i;
168 for (i = 0; i < MAX_NUM_SESSION; i++){
169 if (soft_token.state[i].session_handle == hSession)
170 break;
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;
177 if (state)
178 *state = &soft_token.state[i];
179 return CKR_OK;
182 static CK_RV
183 object_handle_to_object(CK_OBJECT_HANDLE handle,
184 struct st_object **object)
186 int i = HANDLE_OBJECT_ID(handle);
188 *object = NULL;
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];
196 return CKR_OK;
199 static int
200 attributes_match(const struct st_object *obj,
201 const CK_ATTRIBUTE *attributes,
202 CK_ULONG num_attributes)
204 CK_ULONG i;
205 int j;
207 st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj));
209 for (i = 0; i < num_attributes; i++) {
210 int match = 0;
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) {
216 match = 1;
217 break;
220 if (match == 0) {
221 st_logf("type %d attribute have no match\n", attributes[i].type);
222 return 0;
225 st_logf("attribute matches\n");
226 return 1;
229 static void
230 print_attributes(const CK_ATTRIBUTE *attributes,
231 CK_ULONG num_attributes)
233 CK_ULONG i;
235 st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes);
237 for (i = 0; i < num_attributes; i++) {
238 st_logf(" type: ");
239 switch (attributes[i].type) {
240 case CKA_TOKEN: {
241 CK_BBOOL *ck_true;
242 if (attributes[i].ulValueLen != sizeof(CK_BBOOL)) {
243 application_error("token attribute wrong length\n");
244 break;
246 ck_true = attributes[i].pValue;
247 st_logf("token: %s", *ck_true ? "TRUE" : "FALSE");
248 break;
250 case CKA_CLASS: {
251 CK_OBJECT_CLASS *class;
252 if (attributes[i].ulValueLen != sizeof(CK_ULONG)) {
253 application_error("class attribute wrong length\n");
254 break;
256 class = attributes[i].pValue;
257 st_logf("class ");
258 switch (*class) {
259 case CKO_CERTIFICATE:
260 st_logf("certificate");
261 break;
262 case CKO_PUBLIC_KEY:
263 st_logf("public key");
264 break;
265 case CKO_PRIVATE_KEY:
266 st_logf("private key");
267 break;
268 case CKO_SECRET_KEY:
269 st_logf("secret key");
270 break;
271 case CKO_DOMAIN_PARAMETERS:
272 st_logf("domain parameters");
273 break;
274 default:
275 st_logf("[class %lx]", (long unsigned)*class);
276 break;
278 break;
280 case CKA_PRIVATE:
281 st_logf("private");
282 break;
283 case CKA_LABEL:
284 st_logf("label");
285 break;
286 case CKA_APPLICATION:
287 st_logf("application");
288 break;
289 case CKA_VALUE:
290 st_logf("value");
291 break;
292 case CKA_ID:
293 st_logf("id");
294 break;
295 default:
296 st_logf("[unknown 0x%08lx]", (unsigned long)attributes[i].type);
297 break;
299 st_logf("\n");
303 static struct st_object *
304 add_st_object(void)
306 struct st_object *o, **objs;
307 int i;
309 o = calloc(1, sizeof(*o));
310 if (o == NULL)
311 return NULL;
313 for (i = 0; i < soft_token.object.num_objs; i++) {
314 if (soft_token.object.objs[i] == NULL) {
315 soft_token.object.objs[i] = o;
316 break;
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]));
322 if (objs == NULL) {
323 free(o);
324 return NULL;
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;
332 return o;
335 static CK_RV
336 add_object_attribute(struct st_object *o,
337 int secret,
338 CK_ATTRIBUTE_TYPE type,
339 CK_VOID_PTR pValue,
340 CK_ULONG ulValueLen)
342 struct st_attr *a;
343 int i;
345 if (pValue == NULL && ulValueLen)
346 return CKR_ARGUMENTS_BAD;
348 i = o->num_attributes;
349 a = realloc(o->attrs, (i + 1) * sizeof(o->attrs[0]));
350 if (a == NULL)
351 return CKR_DEVICE_MEMORY;
352 o->attrs = a;
353 o->attrs[i].secret = secret;
354 o->attrs[i].attribute.type = type;
355 o->attrs[i].attribute.pValue = malloc(ulValueLen);
356 if (o->attrs[i].attribute.pValue == NULL && ulValueLen != 0)
357 return CKR_DEVICE_MEMORY;
358 if (ulValueLen)
359 memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen);
360 o->attrs[i].attribute.ulValueLen = ulValueLen;
361 o->num_attributes++;
363 return CKR_OK;
366 static CK_RV
367 add_pubkey_info(hx509_context hxctx, struct st_object *o,
368 CK_KEY_TYPE key_type, hx509_cert cert)
370 BIGNUM *num;
371 CK_BYTE *modulus = NULL;
372 size_t modulus_len = 0;
373 CK_ULONG modulus_bits = 0;
374 CK_BYTE *exponent = NULL;
375 size_t exponent_len = 0;
377 if (key_type != CKK_RSA)
378 return CKR_OK;
379 if (_hx509_cert_private_key(cert) == NULL)
380 return CKR_OK;
382 num = _hx509_private_key_get_internal(context,
383 _hx509_cert_private_key(cert),
384 "rsa-modulus");
385 if (num == NULL)
386 return CKR_GENERAL_ERROR;
387 modulus_bits = BN_num_bits(num);
389 modulus_len = BN_num_bytes(num);
390 modulus = malloc(modulus_len);
391 BN_bn2bin(num, modulus);
392 BN_free(num);
394 add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len);
395 add_object_attribute(o, 0, CKA_MODULUS_BITS,
396 &modulus_bits, sizeof(modulus_bits));
398 free(modulus);
400 num = _hx509_private_key_get_internal(context,
401 _hx509_cert_private_key(cert),
402 "rsa-exponent");
403 if (num == NULL)
404 return CKR_GENERAL_ERROR;
406 exponent_len = BN_num_bytes(num);
407 exponent = malloc(exponent_len);
408 BN_bn2bin(num, exponent);
409 BN_free(num);
411 add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT,
412 exponent, exponent_len);
414 free(exponent);
416 return CKR_OK;
420 struct foo {
421 char *label;
422 char *id;
425 static int HX509_LIB_CALL
426 add_cert(hx509_context hxctx, void *ctx, hx509_cert cert)
428 static char empty[] = "";
429 struct foo *foo = (struct foo *)ctx;
430 struct st_object *o = NULL;
431 CK_OBJECT_CLASS type;
432 CK_BBOOL bool_true = CK_TRUE;
433 CK_BBOOL bool_false = CK_FALSE;
434 CK_CERTIFICATE_TYPE cert_type = CKC_X_509;
435 CK_KEY_TYPE key_type;
436 CK_MECHANISM_TYPE mech_type;
437 CK_RV ret = CKR_GENERAL_ERROR;
438 int hret;
439 heim_octet_string cert_data, subject_data, issuer_data, serial_data;
441 st_logf("adding certificate\n");
443 serial_data.data = NULL;
444 serial_data.length = 0;
445 cert_data = subject_data = issuer_data = serial_data;
447 hret = hx509_cert_binary(hxctx, cert, &cert_data);
448 if (hret)
449 goto out;
452 hx509_name name;
454 hret = hx509_cert_get_issuer(cert, &name);
455 if (hret)
456 goto out;
457 hret = hx509_name_binary(name, &issuer_data);
458 hx509_name_free(&name);
459 if (hret)
460 goto out;
462 hret = hx509_cert_get_subject(cert, &name);
463 if (hret)
464 goto out;
465 hret = hx509_name_binary(name, &subject_data);
466 hx509_name_free(&name);
467 if (hret)
468 goto out;
472 AlgorithmIdentifier alg;
474 hret = hx509_cert_get_SPKI_AlgorithmIdentifier(context, cert, &alg);
475 if (hret) {
476 ret = CKR_DEVICE_MEMORY;
477 goto out;
480 key_type = CKK_RSA; /* XXX */
482 free_AlgorithmIdentifier(&alg);
486 type = CKO_CERTIFICATE;
487 o = add_st_object();
488 if (o == NULL) {
489 ret = CKR_DEVICE_MEMORY;
490 goto out;
493 o->cert = hx509_cert_ref(cert);
495 add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
496 add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
497 add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
498 add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
499 add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
501 add_object_attribute(o, 0, CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type));
502 add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
504 add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
505 add_object_attribute(o, 0, CKA_ISSUER, issuer_data.data, issuer_data.length);
506 add_object_attribute(o, 0, CKA_SERIAL_NUMBER, serial_data.data, serial_data.length);
507 add_object_attribute(o, 0, CKA_VALUE, cert_data.data, cert_data.length);
508 add_object_attribute(o, 0, CKA_TRUSTED, &bool_false, sizeof(bool_false));
510 st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o));
512 type = CKO_PUBLIC_KEY;
513 o = add_st_object();
514 if (o == NULL) {
515 ret = CKR_DEVICE_MEMORY;
516 goto out;
518 o->cert = hx509_cert_ref(cert);
520 add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
521 add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
522 add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
523 add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
524 add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
526 add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
527 add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
528 add_object_attribute(o, 0, CKA_START_DATE, empty, 1); /* XXX */
529 add_object_attribute(o, 0, CKA_END_DATE, empty, 1); /* XXX */
530 add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
531 add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
532 mech_type = CKM_RSA_X_509;
533 add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
535 add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
536 add_object_attribute(o, 0, CKA_ENCRYPT, &bool_true, sizeof(bool_true));
537 add_object_attribute(o, 0, CKA_VERIFY, &bool_true, sizeof(bool_true));
538 add_object_attribute(o, 0, CKA_VERIFY_RECOVER, &bool_false, sizeof(bool_false));
539 add_object_attribute(o, 0, CKA_WRAP, &bool_true, sizeof(bool_true));
540 add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true));
542 add_pubkey_info(hxctx, o, key_type, cert);
544 st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o));
546 if (hx509_cert_have_private_key(cert)) {
547 CK_FLAGS flags;
549 type = CKO_PRIVATE_KEY;
551 /* Note to static analyzers: `o' is still referred to via globals */
552 o = add_st_object();
553 if (o == NULL) {
554 ret = CKR_DEVICE_MEMORY;
555 goto out;
557 o->cert = hx509_cert_ref(cert);
559 add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
560 add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
561 add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false));
562 add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
563 add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
565 add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
566 add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
567 add_object_attribute(o, 0, CKA_START_DATE, empty, 1); /* XXX */
568 add_object_attribute(o, 0, CKA_END_DATE, empty, 1); /* XXX */
569 add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
570 add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
571 mech_type = CKM_RSA_X_509;
572 add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
574 add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
575 add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true));
576 add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true));
577 flags = 0;
578 add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags));
580 add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true));
581 add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true));
582 add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false));
583 add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true));
584 add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true));
585 add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false));
587 add_pubkey_info(hxctx, o, key_type, cert);
590 ret = CKR_OK;
591 out:
592 if (ret != CKR_OK) {
593 st_logf("something went wrong when adding cert!\n");
595 /* XXX wack o */;
597 hx509_xfree(cert_data.data);
598 hx509_xfree(serial_data.data);
599 hx509_xfree(issuer_data.data);
600 hx509_xfree(subject_data.data);
602 /* Note to static analyzers: `o' is still referred to via globals */
603 return 0;
606 static CK_RV
607 add_certificate(const char *cert_file,
608 const char *pin,
609 char *id,
610 char *label)
612 hx509_certs certs;
613 hx509_lock lock = NULL;
614 int ret, flags = 0;
616 struct foo foo;
617 foo.id = id;
618 foo.label = label;
620 if (pin == NULL)
621 flags |= HX509_CERTS_UNPROTECT_ALL;
623 if (pin) {
624 char *str;
625 ret = asprintf(&str, "PASS:%s", pin);
626 if (ret == -1 || !str) {
627 st_logf("failed to allocate memory\n");
628 return CKR_GENERAL_ERROR;
631 hx509_lock_init(context, &lock);
632 hx509_lock_command_string(lock, str);
634 memset(str, 0, strlen(str));
635 free(str);
638 ret = hx509_certs_init(context, cert_file, flags, lock, &certs);
639 if (ret) {
640 st_logf("failed to open file %s\n", cert_file);
641 return CKR_GENERAL_ERROR;
644 ret = hx509_certs_iter_f(context, certs, add_cert, &foo);
645 hx509_certs_free(&certs);
646 if (ret) {
647 st_logf("failed adding certs from file %s\n", cert_file);
648 return CKR_GENERAL_ERROR;
651 return CKR_OK;
654 static void
655 find_object_final(struct session_state *state)
657 if (state->find.attributes) {
658 CK_ULONG i;
660 for (i = 0; i < state->find.num_attributes; i++) {
661 if (state->find.attributes[i].pValue)
662 free(state->find.attributes[i].pValue);
664 free(state->find.attributes);
665 state->find.attributes = NULL;
666 state->find.num_attributes = 0;
667 state->find.next_object = -1;
671 static void
672 reset_crypto_state(struct session_state *state)
674 state->sign_object = -1;
675 if (state->sign_mechanism)
676 free(state->sign_mechanism);
677 state->sign_mechanism = NULL_PTR;
678 state->verify_object = -1;
679 if (state->verify_mechanism)
680 free(state->verify_mechanism);
681 state->verify_mechanism = NULL_PTR;
684 static void
685 close_session(struct session_state *state)
687 if (state->find.attributes) {
688 application_error("application didn't do C_FindObjectsFinal\n");
689 find_object_final(state);
692 state->session_handle = CK_INVALID_HANDLE;
693 soft_token.application = NULL_PTR;
694 soft_token.notify = NULL_PTR;
695 reset_crypto_state(state);
698 static const char *
699 has_session(void)
701 return soft_token.open_sessions > 0 ? "yes" : "no";
704 static CK_RV
705 read_conf_file(const char *fn, CK_USER_TYPE userType, const char *pin)
707 char buf[1024], *type, *s, *p;
708 FILE *f;
709 CK_RV ret = CKR_OK;
710 CK_RV failed = CKR_OK;
712 if (fn == NULL) {
713 st_logf("Can't open configuration file. No file specified\n");
714 return CKR_GENERAL_ERROR;
717 f = fopen(fn, "r");
718 if (f == NULL) {
719 st_logf("can't open configuration file %s\n", fn);
720 return CKR_GENERAL_ERROR;
722 rk_cloexec_file(f);
724 while(fgets(buf, sizeof(buf), f) != NULL) {
725 buf[strcspn(buf, "\n")] = '\0';
727 st_logf("line: %s\n", buf);
729 p = buf;
730 while (isspace((unsigned char)*p))
731 p++;
732 if (*p == '#')
733 continue;
734 while (isspace((unsigned char)*p))
735 p++;
737 s = NULL;
738 type = strtok_r(p, "\t", &s);
739 if (type == NULL)
740 continue;
742 if (strcasecmp("certificate", type) == 0) {
743 char *cert, *id, *label;
745 id = strtok_r(NULL, "\t", &s);
746 if (id == NULL) {
747 st_logf("no id\n");
748 continue;
750 st_logf("id: %s\n", id);
751 label = strtok_r(NULL, "\t", &s);
752 if (label == NULL) {
753 st_logf("no label\n");
754 continue;
756 cert = strtok_r(NULL, "\t", &s);
757 if (cert == NULL) {
758 st_logf("no certfiicate store\n");
759 continue;
762 st_logf("adding: %s: %s in file %s\n", id, label, cert);
764 ret = add_certificate(cert, pin, id, label);
765 if (ret)
766 failed = ret;
767 } else if (strcasecmp("debug", type) == 0) {
768 char *name;
770 name = strtok_r(NULL, "\t", &s);
771 if (name == NULL) {
772 st_logf("no filename\n");
773 continue;
776 if (soft_token.logfile)
777 fclose(soft_token.logfile);
779 if (strcasecmp(name, "stdout") == 0)
780 soft_token.logfile = stdout;
781 else {
782 soft_token.logfile = fopen(name, "a");
783 if (soft_token.logfile)
784 rk_cloexec_file(soft_token.logfile);
786 if (soft_token.logfile == NULL)
787 st_logf("failed to open file: %s\n", name);
789 } else if (strcasecmp("app-fatal", type) == 0) {
790 char *name;
792 name = strtok_r(NULL, "\t", &s);
793 if (name == NULL) {
794 st_logf("argument to app-fatal\n");
795 continue;
798 if (strcmp(name, "true") == 0 || strcmp(name, "on") == 0)
799 soft_token.flags.app_error_fatal = 1;
800 else if (strcmp(name, "false") == 0 || strcmp(name, "off") == 0)
801 soft_token.flags.app_error_fatal = 0;
802 else
803 st_logf("unknown app-fatal: %s\n", name);
805 } else {
806 st_logf("unknown type: %s\n", type);
810 fclose(f);
812 return failed;
815 static CK_RV
816 func_not_supported(void)
818 st_logf("function not supported\n");
819 return CKR_FUNCTION_NOT_SUPPORTED;
822 static char *
823 get_config_file_for_user(void)
825 char *fn;
826 int ret;
828 fn = secure_getenv("SOFTPKCS11RC");
829 if (fn)
830 fn = strdup(fn);
831 if (fn == NULL) {
832 char homebuf[MAX_PATH];
833 const char *home = roken_get_appdatadir(homebuf, sizeof(homebuf));
835 if (home) {
836 ret = asprintf(&fn, "%s/.soft-token.rc", home);
837 if (ret == -1)
838 fn = NULL;
839 } else {
840 #ifndef WIN32
841 fn = strdup("/etc/soft-token.rc");
842 #endif
846 return fn;
850 CK_RV CK_SPEC
851 C_Initialize(CK_VOID_PTR a)
853 CK_C_INITIALIZE_ARGS_PTR args = a;
854 CK_RV ret;
855 size_t i;
857 st_logf("Initialize\n");
859 INIT_CONTEXT();
861 OpenSSL_add_all_algorithms();
863 srandom(getpid() ^ (int) time(NULL));
865 for (i = 0; i < MAX_NUM_SESSION; i++) {
866 soft_token.state[i].session_handle = CK_INVALID_HANDLE;
867 soft_token.state[i].find.attributes = NULL;
868 soft_token.state[i].find.num_attributes = 0;
869 soft_token.state[i].find.next_object = -1;
870 reset_crypto_state(&soft_token.state[i]);
873 soft_token.flags.hardware_slot = 1;
874 soft_token.flags.app_error_fatal = 0;
875 soft_token.flags.login_done = 0;
877 soft_token.object.objs = NULL;
878 soft_token.object.num_objs = 0;
880 soft_token.logfile = NULL;
881 #if 0
882 soft_token.logfile = stdout;
883 #endif
884 #if 0
885 soft_token.logfile = fopen("/tmp/log-pkcs11.txt", "a");
886 #endif
888 if (a != NULL_PTR) {
889 st_logf("\tCreateMutex:\t%p\n", args->CreateMutex);
890 st_logf("\tDestroyMutext\t%p\n", args->DestroyMutex);
891 st_logf("\tLockMutext\t%p\n", args->LockMutex);
892 st_logf("\tUnlockMutext\t%p\n", args->UnlockMutex);
893 st_logf("\tFlags\t%04x\n", (unsigned int)args->flags);
896 soft_token.config_file = get_config_file_for_user();
899 * This operations doesn't return CKR_OK if any of the
900 * certificates failes to be unparsed (ie password protected).
902 ret = read_conf_file(soft_token.config_file, CKU_USER, NULL);
903 if (ret == CKR_OK)
904 soft_token.flags.login_done = 1;
906 return CKR_OK;
909 CK_RV
910 C_Finalize(CK_VOID_PTR args)
912 size_t i;
914 INIT_CONTEXT();
916 st_logf("Finalize\n");
918 for (i = 0; i < MAX_NUM_SESSION; i++) {
919 if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) {
920 application_error("application finalized without "
921 "closing session\n");
922 close_session(&soft_token.state[i]);
926 return CKR_OK;
929 CK_RV
930 C_GetInfo(CK_INFO_PTR args)
932 INIT_CONTEXT();
934 st_logf("GetInfo\n");
936 memset(args, 17, sizeof(*args));
937 args->cryptokiVersion.major = 2;
938 args->cryptokiVersion.minor = 10;
939 snprintf_fill((char *)args->manufacturerID,
940 sizeof(args->manufacturerID),
941 ' ',
942 "Heimdal hx509 SoftToken");
943 snprintf_fill((char *)args->libraryDescription,
944 sizeof(args->libraryDescription), ' ',
945 "Heimdal hx509 SoftToken");
946 args->libraryVersion.major = 2;
947 args->libraryVersion.minor = 0;
949 return CKR_OK;
952 extern CK_FUNCTION_LIST funcs;
954 CK_RV
955 C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
957 INIT_CONTEXT();
959 *ppFunctionList = &funcs;
960 return CKR_OK;
963 CK_RV
964 C_GetSlotList(CK_BBOOL tokenPresent,
965 CK_SLOT_ID_PTR pSlotList,
966 CK_ULONG_PTR pulCount)
968 INIT_CONTEXT();
969 st_logf("GetSlotList: %s\n",
970 tokenPresent ? "tokenPresent" : "token not Present");
971 if (pSlotList)
972 pSlotList[0] = 1;
973 *pulCount = 1;
974 return CKR_OK;
977 CK_RV
978 C_GetSlotInfo(CK_SLOT_ID slotID,
979 CK_SLOT_INFO_PTR pInfo)
981 INIT_CONTEXT();
982 st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID, has_session());
984 memset(pInfo, 18, sizeof(*pInfo));
986 if (slotID != 1)
987 return CKR_ARGUMENTS_BAD;
989 snprintf_fill((char *)pInfo->slotDescription,
990 sizeof(pInfo->slotDescription),
991 ' ',
992 "Heimdal hx509 SoftToken (slot)");
993 snprintf_fill((char *)pInfo->manufacturerID,
994 sizeof(pInfo->manufacturerID),
995 ' ',
996 "Heimdal hx509 SoftToken (slot)");
997 pInfo->flags = CKF_TOKEN_PRESENT;
998 if (soft_token.flags.hardware_slot)
999 pInfo->flags |= CKF_HW_SLOT;
1000 pInfo->hardwareVersion.major = 1;
1001 pInfo->hardwareVersion.minor = 0;
1002 pInfo->firmwareVersion.major = 1;
1003 pInfo->firmwareVersion.minor = 0;
1005 return CKR_OK;
1008 CK_RV
1009 C_GetTokenInfo(CK_SLOT_ID slotID,
1010 CK_TOKEN_INFO_PTR pInfo)
1012 INIT_CONTEXT();
1013 st_logf("GetTokenInfo: %s\n", has_session());
1015 memset(pInfo, 19, sizeof(*pInfo));
1017 snprintf_fill((char *)pInfo->label,
1018 sizeof(pInfo->label),
1019 ' ',
1020 "Heimdal hx509 SoftToken (token)");
1021 snprintf_fill((char *)pInfo->manufacturerID,
1022 sizeof(pInfo->manufacturerID),
1023 ' ',
1024 "Heimdal hx509 SoftToken (token)");
1025 snprintf_fill((char *)pInfo->model,
1026 sizeof(pInfo->model),
1027 ' ',
1028 "Heimdal hx509 SoftToken (token)");
1029 snprintf_fill((char *)pInfo->serialNumber,
1030 sizeof(pInfo->serialNumber),
1031 ' ',
1032 "4711");
1033 pInfo->flags =
1034 CKF_TOKEN_INITIALIZED |
1035 CKF_USER_PIN_INITIALIZED;
1037 if (soft_token.flags.login_done == 0)
1038 pInfo->flags |= CKF_LOGIN_REQUIRED;
1040 /* CFK_RNG |
1041 CKF_RESTORE_KEY_NOT_NEEDED |
1043 pInfo->ulMaxSessionCount = MAX_NUM_SESSION;
1044 pInfo->ulSessionCount = soft_token.open_sessions;
1045 pInfo->ulMaxRwSessionCount = MAX_NUM_SESSION;
1046 pInfo->ulRwSessionCount = soft_token.open_sessions;
1047 pInfo->ulMaxPinLen = 1024;
1048 pInfo->ulMinPinLen = 0;
1049 pInfo->ulTotalPublicMemory = 4711;
1050 pInfo->ulFreePublicMemory = 4712;
1051 pInfo->ulTotalPrivateMemory = 4713;
1052 pInfo->ulFreePrivateMemory = 4714;
1053 pInfo->hardwareVersion.major = 2;
1054 pInfo->hardwareVersion.minor = 0;
1055 pInfo->firmwareVersion.major = 2;
1056 pInfo->firmwareVersion.minor = 0;
1058 return CKR_OK;
1061 CK_RV
1062 C_GetMechanismList(CK_SLOT_ID slotID,
1063 CK_MECHANISM_TYPE_PTR pMechanismList,
1064 CK_ULONG_PTR pulCount)
1066 INIT_CONTEXT();
1067 st_logf("GetMechanismList\n");
1069 *pulCount = 1;
1070 if (pMechanismList == NULL_PTR)
1071 return CKR_OK;
1072 pMechanismList[0] = CKM_RSA_PKCS;
1074 return CKR_OK;
1077 CK_RV
1078 C_GetMechanismInfo(CK_SLOT_ID slotID,
1079 CK_MECHANISM_TYPE type,
1080 CK_MECHANISM_INFO_PTR pInfo)
1082 INIT_CONTEXT();
1083 st_logf("GetMechanismInfo: slot %d type: %d\n",
1084 (int)slotID, (int)type);
1085 memset(pInfo, 0, sizeof(*pInfo));
1087 return CKR_OK;
1090 CK_RV
1091 C_InitToken(CK_SLOT_ID slotID,
1092 CK_UTF8CHAR_PTR pPin,
1093 CK_ULONG ulPinLen,
1094 CK_UTF8CHAR_PTR pLabel)
1096 INIT_CONTEXT();
1097 st_logf("InitToken: slot %d\n", (int)slotID);
1098 return CKR_FUNCTION_NOT_SUPPORTED;
1101 CK_RV
1102 C_OpenSession(CK_SLOT_ID slotID,
1103 CK_FLAGS flags,
1104 CK_VOID_PTR pApplication,
1105 CK_NOTIFY Notify,
1106 CK_SESSION_HANDLE_PTR phSession)
1108 size_t i;
1109 INIT_CONTEXT();
1110 st_logf("OpenSession: slot: %d\n", (int)slotID);
1112 if (soft_token.open_sessions == MAX_NUM_SESSION)
1113 return CKR_SESSION_COUNT;
1115 soft_token.application = pApplication;
1116 soft_token.notify = Notify;
1118 for (i = 0; i < MAX_NUM_SESSION; i++)
1119 if (soft_token.state[i].session_handle == CK_INVALID_HANDLE)
1120 break;
1121 if (i == MAX_NUM_SESSION)
1122 abort();
1124 soft_token.open_sessions++;
1126 soft_token.state[i].session_handle =
1127 (CK_SESSION_HANDLE)(random() & 0xfffff);
1128 *phSession = soft_token.state[i].session_handle;
1130 return CKR_OK;
1133 CK_RV
1134 C_CloseSession(CK_SESSION_HANDLE hSession)
1136 struct session_state *state;
1137 INIT_CONTEXT();
1138 st_logf("CloseSession\n");
1140 if (verify_session_handle(hSession, &state) != CKR_OK)
1141 application_error("closed session not open");
1142 else
1143 close_session(state);
1145 return CKR_OK;
1148 CK_RV
1149 C_CloseAllSessions(CK_SLOT_ID slotID)
1151 size_t i;
1152 INIT_CONTEXT();
1154 st_logf("CloseAllSessions\n");
1156 for (i = 0; i < MAX_NUM_SESSION; i++)
1157 if (soft_token.state[i].session_handle != CK_INVALID_HANDLE)
1158 close_session(&soft_token.state[i]);
1160 return CKR_OK;
1163 CK_RV
1164 C_GetSessionInfo(CK_SESSION_HANDLE hSession,
1165 CK_SESSION_INFO_PTR pInfo)
1167 st_logf("GetSessionInfo\n");
1168 INIT_CONTEXT();
1170 VERIFY_SESSION_HANDLE(hSession, NULL);
1172 memset(pInfo, 20, sizeof(*pInfo));
1174 pInfo->slotID = 1;
1175 if (soft_token.flags.login_done)
1176 pInfo->state = CKS_RO_USER_FUNCTIONS;
1177 else
1178 pInfo->state = CKS_RO_PUBLIC_SESSION;
1179 pInfo->flags = CKF_SERIAL_SESSION;
1180 pInfo->ulDeviceError = 0;
1182 return CKR_OK;
1185 CK_RV
1186 C_Login(CK_SESSION_HANDLE hSession,
1187 CK_USER_TYPE userType,
1188 CK_UTF8CHAR_PTR pPin,
1189 CK_ULONG ulPinLen)
1191 char *pin = NULL;
1192 CK_RV ret;
1193 INIT_CONTEXT();
1195 st_logf("Login\n");
1197 VERIFY_SESSION_HANDLE(hSession, NULL);
1199 if (pPin != NULL_PTR) {
1200 int aret;
1202 aret = asprintf(&pin, "%.*s", (int)ulPinLen, pPin);
1203 if (aret != -1 && pin)
1204 st_logf("type: %d password: %s\n", (int)userType, pin);
1205 else
1206 st_logf("memory error: asprintf failed\n");
1210 * Login
1213 ret = read_conf_file(soft_token.config_file, userType, pin);
1214 if (ret == CKR_OK)
1215 soft_token.flags.login_done = 1;
1217 free(pin);
1219 return soft_token.flags.login_done ? CKR_OK : CKR_PIN_INCORRECT;
1222 CK_RV
1223 C_Logout(CK_SESSION_HANDLE hSession)
1225 st_logf("Logout\n");
1226 INIT_CONTEXT();
1228 VERIFY_SESSION_HANDLE(hSession, NULL);
1229 return CKR_FUNCTION_NOT_SUPPORTED;
1232 CK_RV
1233 C_GetObjectSize(CK_SESSION_HANDLE hSession,
1234 CK_OBJECT_HANDLE hObject,
1235 CK_ULONG_PTR pulSize)
1237 st_logf("GetObjectSize\n");
1238 INIT_CONTEXT();
1240 VERIFY_SESSION_HANDLE(hSession, NULL);
1241 return CKR_FUNCTION_NOT_SUPPORTED;
1244 CK_RV
1245 C_GetAttributeValue(CK_SESSION_HANDLE hSession,
1246 CK_OBJECT_HANDLE hObject,
1247 CK_ATTRIBUTE_PTR pTemplate,
1248 CK_ULONG ulCount)
1250 struct session_state *state;
1251 struct st_object *obj;
1252 CK_ULONG i;
1253 CK_RV ret;
1254 int j;
1256 INIT_CONTEXT();
1258 st_logf("GetAttributeValue: %lx\n",
1259 (unsigned long)HANDLE_OBJECT_ID(hObject));
1260 VERIFY_SESSION_HANDLE(hSession, &state);
1262 if ((ret = object_handle_to_object(hObject, &obj)) != CKR_OK) {
1263 st_logf("object not found: %lx\n",
1264 (unsigned long)HANDLE_OBJECT_ID(hObject));
1265 return ret;
1268 for (i = 0; i < ulCount; i++) {
1269 st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate[i].type);
1270 for (j = 0; j < obj->num_attributes; j++) {
1271 if (obj->attrs[j].secret) {
1272 pTemplate[i].ulValueLen = (CK_ULONG)-1;
1273 break;
1275 if (pTemplate[i].type == obj->attrs[j].attribute.type) {
1276 if (pTemplate[i].pValue != NULL_PTR && obj->attrs[j].secret == 0) {
1277 if (pTemplate[i].ulValueLen >= obj->attrs[j].attribute.ulValueLen)
1278 memcpy(pTemplate[i].pValue, obj->attrs[j].attribute.pValue,
1279 obj->attrs[j].attribute.ulValueLen);
1281 pTemplate[i].ulValueLen = obj->attrs[j].attribute.ulValueLen;
1282 break;
1285 if (j == obj->num_attributes) {
1286 st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate[i].type);
1287 pTemplate[i].ulValueLen = (CK_ULONG)-1;
1291 return CKR_OK;
1294 CK_RV
1295 C_FindObjectsInit(CK_SESSION_HANDLE hSession,
1296 CK_ATTRIBUTE_PTR pTemplate,
1297 CK_ULONG ulCount)
1299 struct session_state *state;
1301 st_logf("FindObjectsInit\n");
1303 INIT_CONTEXT();
1305 VERIFY_SESSION_HANDLE(hSession, &state);
1307 if (state->find.next_object != -1) {
1308 application_error("application didn't do C_FindObjectsFinal\n");
1309 find_object_final(state);
1311 if (ulCount) {
1312 CK_ULONG i;
1314 print_attributes(pTemplate, ulCount);
1316 state->find.attributes =
1317 calloc(1, ulCount * sizeof(state->find.attributes[0]));
1318 if (state->find.attributes == NULL)
1319 return CKR_DEVICE_MEMORY;
1320 for (i = 0; i < ulCount; i++) {
1321 state->find.attributes[i].pValue =
1322 malloc(pTemplate[i].ulValueLen);
1323 if (state->find.attributes[i].pValue == NULL) {
1324 find_object_final(state);
1325 return CKR_DEVICE_MEMORY;
1327 memcpy(state->find.attributes[i].pValue,
1328 pTemplate[i].pValue, pTemplate[i].ulValueLen);
1329 state->find.attributes[i].type = pTemplate[i].type;
1330 state->find.attributes[i].ulValueLen = pTemplate[i].ulValueLen;
1332 state->find.num_attributes = ulCount;
1333 state->find.next_object = 0;
1334 } else {
1335 st_logf("find all objects\n");
1336 state->find.attributes = NULL;
1337 state->find.num_attributes = 0;
1338 state->find.next_object = 0;
1341 return CKR_OK;
1344 CK_RV
1345 C_FindObjects(CK_SESSION_HANDLE hSession,
1346 CK_OBJECT_HANDLE_PTR phObject,
1347 CK_ULONG ulMaxObjectCount,
1348 CK_ULONG_PTR pulObjectCount)
1350 struct session_state *state;
1351 int i;
1353 INIT_CONTEXT();
1355 st_logf("FindObjects\n");
1357 VERIFY_SESSION_HANDLE(hSession, &state);
1359 if (state->find.next_object == -1) {
1360 application_error("application didn't do C_FindObjectsInit\n");
1361 return CKR_ARGUMENTS_BAD;
1363 if (ulMaxObjectCount == 0) {
1364 application_error("application asked for 0 objects\n");
1365 return CKR_ARGUMENTS_BAD;
1367 *pulObjectCount = 0;
1368 for (i = state->find.next_object; i < soft_token.object.num_objs; i++) {
1369 st_logf("FindObjects: %d\n", i);
1370 state->find.next_object = i + 1;
1371 if (attributes_match(soft_token.object.objs[i],
1372 state->find.attributes,
1373 state->find.num_attributes)) {
1374 *phObject++ = soft_token.object.objs[i]->object_handle;
1375 ulMaxObjectCount--;
1376 (*pulObjectCount)++;
1377 if (ulMaxObjectCount == 0)
1378 break;
1381 return CKR_OK;
1384 CK_RV
1385 C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
1387 struct session_state *state;
1389 INIT_CONTEXT();
1391 st_logf("FindObjectsFinal\n");
1392 VERIFY_SESSION_HANDLE(hSession, &state);
1393 find_object_final(state);
1394 return CKR_OK;
1397 static CK_RV
1398 commonInit(CK_ATTRIBUTE *attr_match, int attr_match_len,
1399 const CK_MECHANISM_TYPE *mechs, int mechs_len,
1400 const CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey,
1401 struct st_object **o)
1403 CK_RV ret;
1404 int i;
1406 *o = NULL;
1407 if ((ret = object_handle_to_object(hKey, o)) != CKR_OK)
1408 return ret;
1410 ret = attributes_match(*o, attr_match, attr_match_len);
1411 if (!ret) {
1412 application_error("called commonInit on key that doesn't "
1413 "support required attr");
1414 return CKR_ARGUMENTS_BAD;
1417 for (i = 0; i < mechs_len; i++)
1418 if (mechs[i] == pMechanism->mechanism)
1419 break;
1420 if (i == mechs_len) {
1421 application_error("called mech (%08lx) not supported\n",
1422 pMechanism->mechanism);
1423 return CKR_ARGUMENTS_BAD;
1425 return CKR_OK;
1429 static CK_RV
1430 dup_mechanism(CK_MECHANISM_PTR *dp, const CK_MECHANISM_PTR pMechanism)
1432 CK_MECHANISM_PTR p;
1434 p = malloc(sizeof(*p));
1435 if (p == NULL)
1436 return CKR_DEVICE_MEMORY;
1438 if (*dp)
1439 free(*dp);
1440 *dp = p;
1441 memcpy(p, pMechanism, sizeof(*p));
1443 return CKR_OK;
1446 CK_RV
1447 C_DigestInit(CK_SESSION_HANDLE hSession,
1448 CK_MECHANISM_PTR pMechanism)
1450 st_logf("DigestInit\n");
1451 INIT_CONTEXT();
1452 VERIFY_SESSION_HANDLE(hSession, NULL);
1453 return CKR_FUNCTION_NOT_SUPPORTED;
1456 CK_RV
1457 C_SignInit(CK_SESSION_HANDLE hSession,
1458 CK_MECHANISM_PTR pMechanism,
1459 CK_OBJECT_HANDLE hKey)
1461 struct session_state *state;
1462 CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS };
1463 CK_BBOOL bool_true = CK_TRUE;
1464 CK_ATTRIBUTE attr[] = {
1465 { CKA_SIGN, &bool_true, sizeof(bool_true) }
1467 struct st_object *o;
1468 CK_RV ret;
1470 INIT_CONTEXT();
1471 st_logf("SignInit\n");
1472 VERIFY_SESSION_HANDLE(hSession, &state);
1474 ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1475 mechs, sizeof(mechs)/sizeof(mechs[0]),
1476 pMechanism, hKey, &o);
1477 if (ret)
1478 return ret;
1480 ret = dup_mechanism(&state->sign_mechanism, pMechanism);
1481 if (ret == CKR_OK)
1482 state->sign_object = OBJECT_ID(o);
1484 return CKR_OK;
1487 CK_RV
1488 C_Sign(CK_SESSION_HANDLE hSession,
1489 CK_BYTE_PTR pData,
1490 CK_ULONG ulDataLen,
1491 CK_BYTE_PTR pSignature,
1492 CK_ULONG_PTR pulSignatureLen)
1494 struct session_state *state;
1495 struct st_object *o;
1496 CK_RV ret;
1497 int hret;
1498 const AlgorithmIdentifier *alg;
1499 heim_octet_string sig, data;
1501 INIT_CONTEXT();
1502 st_logf("Sign\n");
1503 VERIFY_SESSION_HANDLE(hSession, &state);
1505 sig.data = NULL;
1506 sig.length = 0;
1508 if (state->sign_object == -1)
1509 return CKR_ARGUMENTS_BAD;
1511 if (pulSignatureLen == NULL) {
1512 st_logf("signature len NULL\n");
1513 ret = CKR_ARGUMENTS_BAD;
1514 goto out;
1517 if (pData == NULL_PTR) {
1518 st_logf("data NULL\n");
1519 ret = CKR_ARGUMENTS_BAD;
1520 goto out;
1523 o = soft_token.object.objs[state->sign_object];
1525 if (hx509_cert_have_private_key(o->cert) == 0) {
1526 st_logf("private key NULL\n");
1527 return CKR_ARGUMENTS_BAD;
1530 switch(state->sign_mechanism->mechanism) {
1531 case CKM_RSA_PKCS:
1532 alg = hx509_signature_rsa_pkcs1_x509();
1533 break;
1534 default:
1535 ret = CKR_FUNCTION_NOT_SUPPORTED;
1536 goto out;
1539 data.data = pData;
1540 data.length = ulDataLen;
1542 hret = _hx509_create_signature(context,
1543 _hx509_cert_private_key(o->cert),
1544 alg,
1545 &data,
1546 NULL,
1547 &sig);
1548 if (hret) {
1549 ret = CKR_DEVICE_ERROR;
1550 goto out;
1552 *pulSignatureLen = sig.length;
1554 if (pSignature != NULL_PTR)
1555 memcpy(pSignature, sig.data, sig.length);
1557 ret = CKR_OK;
1558 out:
1559 if (sig.data) {
1560 memset(sig.data, 0, sig.length);
1561 der_free_octet_string(&sig);
1563 return ret;
1566 CK_RV
1567 C_SignUpdate(CK_SESSION_HANDLE hSession,
1568 CK_BYTE_PTR pPart,
1569 CK_ULONG ulPartLen)
1571 INIT_CONTEXT();
1572 st_logf("SignUpdate\n");
1573 VERIFY_SESSION_HANDLE(hSession, NULL);
1574 return CKR_FUNCTION_NOT_SUPPORTED;
1578 CK_RV
1579 C_SignFinal(CK_SESSION_HANDLE hSession,
1580 CK_BYTE_PTR pSignature,
1581 CK_ULONG_PTR pulSignatureLen)
1583 INIT_CONTEXT();
1584 st_logf("SignUpdate\n");
1585 VERIFY_SESSION_HANDLE(hSession, NULL);
1586 return CKR_FUNCTION_NOT_SUPPORTED;
1589 CK_RV
1590 C_VerifyInit(CK_SESSION_HANDLE hSession,
1591 CK_MECHANISM_PTR pMechanism,
1592 CK_OBJECT_HANDLE hKey)
1594 struct session_state *state;
1595 CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS };
1596 CK_BBOOL bool_true = CK_TRUE;
1597 CK_ATTRIBUTE attr[] = {
1598 { CKA_VERIFY, &bool_true, sizeof(bool_true) }
1600 struct st_object *o;
1601 CK_RV ret;
1603 INIT_CONTEXT();
1604 st_logf("VerifyInit\n");
1605 VERIFY_SESSION_HANDLE(hSession, &state);
1607 ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1608 mechs, sizeof(mechs)/sizeof(mechs[0]),
1609 pMechanism, hKey, &o);
1610 if (ret)
1611 return ret;
1613 ret = dup_mechanism(&state->verify_mechanism, pMechanism);
1614 if (ret == CKR_OK)
1615 state->verify_object = OBJECT_ID(o);
1617 return ret;
1620 CK_RV
1621 C_Verify(CK_SESSION_HANDLE hSession,
1622 CK_BYTE_PTR pData,
1623 CK_ULONG ulDataLen,
1624 CK_BYTE_PTR pSignature,
1625 CK_ULONG ulSignatureLen)
1627 struct session_state *state;
1628 struct st_object *o;
1629 const AlgorithmIdentifier *alg;
1630 CK_RV ret;
1631 int hret;
1632 heim_octet_string data, sig;
1634 INIT_CONTEXT();
1635 st_logf("Verify\n");
1636 VERIFY_SESSION_HANDLE(hSession, &state);
1638 if (state->verify_object == -1)
1639 return CKR_ARGUMENTS_BAD;
1641 o = soft_token.object.objs[state->verify_object];
1643 switch(state->verify_mechanism->mechanism) {
1644 case CKM_RSA_PKCS:
1645 alg = hx509_signature_rsa_pkcs1_x509();
1646 break;
1647 default:
1648 ret = CKR_FUNCTION_NOT_SUPPORTED;
1649 goto out;
1652 sig.data = pData;
1653 sig.length = ulDataLen;
1654 data.data = pSignature;
1655 data.length = ulSignatureLen;
1657 hret = _hx509_verify_signature(context,
1658 o->cert,
1659 alg,
1660 &data,
1661 &sig);
1662 if (hret) {
1663 ret = CKR_GENERAL_ERROR;
1664 goto out;
1666 ret = CKR_OK;
1668 out:
1669 return ret;
1673 CK_RV
1674 C_VerifyUpdate(CK_SESSION_HANDLE hSession,
1675 CK_BYTE_PTR pPart,
1676 CK_ULONG ulPartLen)
1678 INIT_CONTEXT();
1679 st_logf("VerifyUpdate\n");
1680 VERIFY_SESSION_HANDLE(hSession, NULL);
1681 return CKR_FUNCTION_NOT_SUPPORTED;
1684 CK_RV
1685 C_VerifyFinal(CK_SESSION_HANDLE hSession,
1686 CK_BYTE_PTR pSignature,
1687 CK_ULONG ulSignatureLen)
1689 INIT_CONTEXT();
1690 st_logf("VerifyFinal\n");
1691 VERIFY_SESSION_HANDLE(hSession, NULL);
1692 return CKR_FUNCTION_NOT_SUPPORTED;
1695 CK_RV
1696 C_GenerateRandom(CK_SESSION_HANDLE hSession,
1697 CK_BYTE_PTR RandomData,
1698 CK_ULONG ulRandomLen)
1700 INIT_CONTEXT();
1701 st_logf("GenerateRandom\n");
1702 VERIFY_SESSION_HANDLE(hSession, NULL);
1703 return CKR_FUNCTION_NOT_SUPPORTED;
1707 CK_FUNCTION_LIST funcs = {
1708 { 2, 11 },
1709 C_Initialize,
1710 C_Finalize,
1711 C_GetInfo,
1712 C_GetFunctionList,
1713 C_GetSlotList,
1714 C_GetSlotInfo,
1715 C_GetTokenInfo,
1716 C_GetMechanismList,
1717 C_GetMechanismInfo,
1718 C_InitToken,
1719 (void *)func_not_supported, /* C_InitPIN */
1720 (void *)func_not_supported, /* C_SetPIN */
1721 C_OpenSession,
1722 C_CloseSession,
1723 C_CloseAllSessions,
1724 C_GetSessionInfo,
1725 (void *)func_not_supported, /* C_GetOperationState */
1726 (void *)func_not_supported, /* C_SetOperationState */
1727 C_Login,
1728 C_Logout,
1729 (void *)func_not_supported, /* C_CreateObject */
1730 (void *)func_not_supported, /* C_CopyObject */
1731 (void *)func_not_supported, /* C_DestroyObject */
1732 (void *)func_not_supported, /* C_GetObjectSize */
1733 C_GetAttributeValue,
1734 (void *)func_not_supported, /* C_SetAttributeValue */
1735 C_FindObjectsInit,
1736 C_FindObjects,
1737 C_FindObjectsFinal,
1738 (void *)func_not_supported, /* C_EncryptInit, */
1739 (void *)func_not_supported, /* C_Encrypt, */
1740 (void *)func_not_supported, /* C_EncryptUpdate, */
1741 (void *)func_not_supported, /* C_EncryptFinal, */
1742 (void *)func_not_supported, /* C_DecryptInit, */
1743 (void *)func_not_supported, /* C_Decrypt, */
1744 (void *)func_not_supported, /* C_DecryptUpdate, */
1745 (void *)func_not_supported, /* C_DecryptFinal, */
1746 C_DigestInit,
1747 (void *)func_not_supported, /* C_Digest */
1748 (void *)func_not_supported, /* C_DigestUpdate */
1749 (void *)func_not_supported, /* C_DigestKey */
1750 (void *)func_not_supported, /* C_DigestFinal */
1751 C_SignInit,
1752 C_Sign,
1753 C_SignUpdate,
1754 C_SignFinal,
1755 (void *)func_not_supported, /* C_SignRecoverInit */
1756 (void *)func_not_supported, /* C_SignRecover */
1757 C_VerifyInit,
1758 C_Verify,
1759 C_VerifyUpdate,
1760 C_VerifyFinal,
1761 (void *)func_not_supported, /* C_VerifyRecoverInit */
1762 (void *)func_not_supported, /* C_VerifyRecover */
1763 (void *)func_not_supported, /* C_DigestEncryptUpdate */
1764 (void *)func_not_supported, /* C_DecryptDigestUpdate */
1765 (void *)func_not_supported, /* C_SignEncryptUpdate */
1766 (void *)func_not_supported, /* C_DecryptVerifyUpdate */
1767 (void *)func_not_supported, /* C_GenerateKey */
1768 (void *)func_not_supported, /* C_GenerateKeyPair */
1769 (void *)func_not_supported, /* C_WrapKey */
1770 (void *)func_not_supported, /* C_UnwrapKey */
1771 (void *)func_not_supported, /* C_DeriveKey */
1772 (void *)func_not_supported, /* C_SeedRandom */
1773 C_GenerateRandom,
1774 (void *)func_not_supported, /* C_GetFunctionStatus */
1775 (void *)func_not_supported, /* C_CancelFunction */
1776 (void *)func_not_supported /* C_WaitForSlotEvent */