Use DES_set_key_unchecked().
[heimdal.git] / lib / hx509 / softp11.c
blobc0acb9e11c37a28d96e16c1844f66d8abb0f4ffa
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 #include "hx_locl.h"
35 #include "pkcs11.h"
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)
42 struct st_attr {
43 CK_ATTRIBUTE attribute;
44 int secret;
47 struct st_object {
48 CK_OBJECT_HANDLE object_handle;
49 struct st_attr *attrs;
50 int num_attributes;
51 hx509_cert cert;
54 static struct soft_token {
55 CK_VOID_PTR application;
56 CK_NOTIFY notify;
57 char *config_file;
58 hx509_certs certs;
59 struct {
60 struct st_object **objs;
61 int num_objs;
62 } object;
63 struct {
64 int hardware_slot;
65 int app_error_fatal;
66 int login_done;
67 } flags;
68 int open_sessions;
69 struct session_state {
70 CK_SESSION_HANDLE session_handle;
72 struct {
73 CK_ATTRIBUTE *attributes;
74 CK_ULONG num_attributes;
75 int next_object;
76 } find;
78 int sign_object;
79 CK_MECHANISM_PTR sign_mechanism;
80 int verify_object;
81 CK_MECHANISM_PTR verify_mechanism;
82 } state[10];
83 #define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0]))
84 FILE *logfile;
85 } soft_token;
87 static hx509_context context;
89 static void
90 application_error(const char *fmt, ...)
92 va_list ap;
93 va_start(ap, fmt);
94 vprintf(fmt, ap);
95 va_end(ap);
96 if (soft_token.flags.app_error_fatal)
97 abort();
100 static void
101 st_logf(const char *fmt, ...)
103 va_list ap;
104 if (soft_token.logfile == NULL)
105 return;
106 va_start(ap, fmt);
107 vfprintf(soft_token.logfile, fmt, ap);
108 va_end(ap);
109 fflush(soft_token.logfile);
112 static CK_RV
113 init_context(void)
115 if (context == NULL) {
116 int ret = hx509_context_init(&context);
117 if (ret)
118 return CKR_GENERAL_ERROR;
120 return CKR_OK;
123 #define INIT_CONTEXT() { CK_RV icret = init_context(); if (icret) return icret; }
125 static void
126 snprintf_fill(char *str, size_t size, char fillchar, const char *fmt, ...)
128 int len;
129 va_list ap;
130 va_start(ap, fmt);
131 len = vsnprintf(str, size, fmt, ap);
132 va_end(ap);
133 if (len < 0 || len > size)
134 return;
135 while(len < size)
136 str[len++] = fillchar;
139 #ifndef TEST_APP
140 #define printf error_use_st_logf
141 #endif
143 #define VERIFY_SESSION_HANDLE(s, state) \
145 CK_RV ret; \
146 ret = verify_session_handle(s, state); \
147 if (ret != CKR_OK) { \
148 /* return CKR_OK */; \
152 static CK_RV
153 verify_session_handle(CK_SESSION_HANDLE hSession,
154 struct session_state **state)
156 int i;
158 for (i = 0; i < MAX_NUM_SESSION; i++){
159 if (soft_token.state[i].session_handle == hSession)
160 break;
162 if (i == MAX_NUM_SESSION) {
163 application_error("use of invalid handle: 0x%08lx\n",
164 (unsigned long)hSession);
165 return CKR_SESSION_HANDLE_INVALID;
167 if (state)
168 *state = &soft_token.state[i];
169 return CKR_OK;
172 static CK_RV
173 object_handle_to_object(CK_OBJECT_HANDLE handle,
174 struct st_object **object)
176 int i = HANDLE_OBJECT_ID(handle);
178 *object = NULL;
179 if (i >= soft_token.object.num_objs)
180 return CKR_ARGUMENTS_BAD;
181 if (soft_token.object.objs[i] == NULL)
182 return CKR_ARGUMENTS_BAD;
183 if (soft_token.object.objs[i]->object_handle != handle)
184 return CKR_ARGUMENTS_BAD;
185 *object = soft_token.object.objs[i];
186 return CKR_OK;
189 static int
190 attributes_match(const struct st_object *obj,
191 const CK_ATTRIBUTE *attributes,
192 CK_ULONG num_attributes)
194 CK_ULONG i;
195 int j;
197 st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj));
199 for (i = 0; i < num_attributes; i++) {
200 int match = 0;
201 for (j = 0; j < obj->num_attributes; j++) {
202 if (attributes[i].type == obj->attrs[j].attribute.type &&
203 attributes[i].ulValueLen == obj->attrs[j].attribute.ulValueLen &&
204 memcmp(attributes[i].pValue, obj->attrs[j].attribute.pValue,
205 attributes[i].ulValueLen) == 0) {
206 match = 1;
207 break;
210 if (match == 0) {
211 st_logf("type %d attribute have no match\n", attributes[i].type);
212 return 0;
215 st_logf("attribute matches\n");
216 return 1;
219 static void
220 print_attributes(const CK_ATTRIBUTE *attributes,
221 CK_ULONG num_attributes)
223 CK_ULONG i;
225 st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes);
227 for (i = 0; i < num_attributes; i++) {
228 st_logf(" type: ");
229 switch (attributes[i].type) {
230 case CKA_TOKEN: {
231 CK_BBOOL *ck_true;
232 if (attributes[i].ulValueLen != sizeof(CK_BBOOL)) {
233 application_error("token attribute wrong length\n");
234 break;
236 ck_true = attributes[i].pValue;
237 st_logf("token: %s", *ck_true ? "TRUE" : "FALSE");
238 break;
240 case CKA_CLASS: {
241 CK_OBJECT_CLASS *class;
242 if (attributes[i].ulValueLen != sizeof(CK_ULONG)) {
243 application_error("class attribute wrong length\n");
244 break;
246 class = attributes[i].pValue;
247 st_logf("class ");
248 switch (*class) {
249 case CKO_CERTIFICATE:
250 st_logf("certificate");
251 break;
252 case CKO_PUBLIC_KEY:
253 st_logf("public key");
254 break;
255 case CKO_PRIVATE_KEY:
256 st_logf("private key");
257 break;
258 case CKO_SECRET_KEY:
259 st_logf("secret key");
260 break;
261 case CKO_DOMAIN_PARAMETERS:
262 st_logf("domain parameters");
263 break;
264 default:
265 st_logf("[class %lx]", (long unsigned)*class);
266 break;
268 break;
270 case CKA_PRIVATE:
271 st_logf("private");
272 break;
273 case CKA_LABEL:
274 st_logf("label");
275 break;
276 case CKA_APPLICATION:
277 st_logf("application");
278 break;
279 case CKA_VALUE:
280 st_logf("value");
281 break;
282 case CKA_ID:
283 st_logf("id");
284 break;
285 default:
286 st_logf("[unknown 0x%08lx]", (unsigned long)attributes[i].type);
287 break;
289 st_logf("\n");
293 static struct st_object *
294 add_st_object(void)
296 struct st_object *o, **objs;
297 int i;
299 o = malloc(sizeof(*o));
300 if (o == NULL)
301 return NULL;
302 memset(o, 0, sizeof(*o));
303 o->attrs = NULL;
304 o->num_attributes = 0;
306 for (i = 0; i < soft_token.object.num_objs; i++) {
307 if (soft_token.object.objs == NULL) {
308 soft_token.object.objs[i] = o;
309 break;
312 if (i == soft_token.object.num_objs) {
313 objs = realloc(soft_token.object.objs,
314 (soft_token.object.num_objs + 1) * sizeof(soft_token.object.objs[0]));
315 if (objs == NULL) {
316 free(o);
317 return NULL;
319 soft_token.object.objs = objs;
320 soft_token.object.objs[soft_token.object.num_objs++] = o;
322 soft_token.object.objs[i]->object_handle =
323 (random() & (~OBJECT_ID_MASK)) | i;
325 return o;
328 static CK_RV
329 add_object_attribute(struct st_object *o,
330 int secret,
331 CK_ATTRIBUTE_TYPE type,
332 CK_VOID_PTR pValue,
333 CK_ULONG ulValueLen)
335 struct st_attr *a;
336 int i;
338 i = o->num_attributes;
339 a = realloc(o->attrs, (i + 1) * sizeof(o->attrs[0]));
340 if (a == NULL)
341 return CKR_DEVICE_MEMORY;
342 o->attrs = a;
343 o->attrs[i].secret = secret;
344 o->attrs[i].attribute.type = type;
345 o->attrs[i].attribute.pValue = malloc(ulValueLen);
346 if (o->attrs[i].attribute.pValue == NULL && ulValueLen != 0)
347 return CKR_DEVICE_MEMORY;
348 memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen);
349 o->attrs[i].attribute.ulValueLen = ulValueLen;
350 o->num_attributes++;
352 return CKR_OK;
355 static CK_RV
356 add_pubkey_info(hx509_context hxctx, struct st_object *o,
357 CK_KEY_TYPE key_type, hx509_cert cert)
359 BIGNUM *num;
360 CK_BYTE *modulus = NULL;
361 size_t modulus_len = 0;
362 CK_ULONG modulus_bits = 0;
363 CK_BYTE *exponent = NULL;
364 size_t exponent_len = 0;
366 if (key_type != CKK_RSA)
367 return CKR_OK;
368 if (_hx509_cert_private_key(cert) == NULL)
369 return CKR_OK;
371 num = _hx509_private_key_get_internal(context,
372 _hx509_cert_private_key(cert),
373 "rsa-modulus");
374 if (num == NULL)
375 return CKR_GENERAL_ERROR;
376 modulus_bits = BN_num_bits(num);
378 modulus_len = BN_num_bytes(num);
379 modulus = malloc(modulus_len);
380 BN_bn2bin(num, modulus);
381 BN_free(num);
383 add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len);
384 add_object_attribute(o, 0, CKA_MODULUS_BITS,
385 &modulus_bits, sizeof(modulus_bits));
387 free(modulus);
389 num = _hx509_private_key_get_internal(context,
390 _hx509_cert_private_key(cert),
391 "rsa-exponent");
392 if (num == NULL)
393 return CKR_GENERAL_ERROR;
395 exponent_len = BN_num_bytes(num);
396 exponent = malloc(exponent_len);
397 BN_bn2bin(num, exponent);
398 BN_free(num);
400 add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT,
401 exponent, exponent_len);
403 free(exponent);
405 return CKR_OK;
409 struct foo {
410 char *label;
411 char *id;
414 static int
415 add_cert(hx509_context hxctx, void *ctx, hx509_cert cert)
417 struct foo *foo = (struct foo *)ctx;
418 struct st_object *o = NULL;
419 CK_OBJECT_CLASS type;
420 CK_BBOOL bool_true = CK_TRUE;
421 CK_BBOOL bool_false = CK_FALSE;
422 CK_CERTIFICATE_TYPE cert_type = CKC_X_509;
423 CK_KEY_TYPE key_type;
424 CK_MECHANISM_TYPE mech_type;
425 CK_RV ret = CKR_GENERAL_ERROR;
426 int hret;
427 heim_octet_string cert_data, subject_data, issuer_data, serial_data;
429 st_logf("adding certificate\n");
431 serial_data.data = NULL;
432 serial_data.length = 0;
433 cert_data = subject_data = issuer_data = serial_data;
435 hret = hx509_cert_binary(hxctx, cert, &cert_data);
436 if (hret)
437 goto out;
440 hx509_name name;
442 hret = hx509_cert_get_issuer(cert, &name);
443 if (hret)
444 goto out;
445 hret = hx509_name_binary(name, &issuer_data);
446 hx509_name_free(&name);
447 if (hret)
448 goto out;
450 hret = hx509_cert_get_subject(cert, &name);
451 if (hret)
452 goto out;
453 hret = hx509_name_binary(name, &subject_data);
454 hx509_name_free(&name);
455 if (hret)
456 goto out;
460 AlgorithmIdentifier alg;
462 hret = hx509_cert_get_SPKI_AlgorithmIdentifier(context, cert, &alg);
463 if (hret) {
464 ret = CKR_DEVICE_MEMORY;
465 goto out;
468 key_type = CKK_RSA; /* XXX */
470 free_AlgorithmIdentifier(&alg);
474 type = CKO_CERTIFICATE;
475 o = add_st_object();
476 if (o == NULL) {
477 ret = CKR_DEVICE_MEMORY;
478 goto out;
481 o->cert = hx509_cert_ref(cert);
483 add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
484 add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
485 add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
486 add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
487 add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
489 add_object_attribute(o, 0, CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type));
490 add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
492 add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
493 add_object_attribute(o, 0, CKA_ISSUER, issuer_data.data, issuer_data.length);
494 add_object_attribute(o, 0, CKA_SERIAL_NUMBER, serial_data.data, serial_data.length);
495 add_object_attribute(o, 0, CKA_VALUE, cert_data.data, cert_data.length);
496 add_object_attribute(o, 0, CKA_TRUSTED, &bool_false, sizeof(bool_false));
498 st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o));
500 type = CKO_PUBLIC_KEY;
501 o = add_st_object();
502 if (o == NULL) {
503 ret = CKR_DEVICE_MEMORY;
504 goto out;
506 o->cert = hx509_cert_ref(cert);
508 add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
509 add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
510 add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
511 add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
512 add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
514 add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
515 add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
516 add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */
517 add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */
518 add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
519 add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
520 mech_type = CKM_RSA_X_509;
521 add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
523 add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
524 add_object_attribute(o, 0, CKA_ENCRYPT, &bool_true, sizeof(bool_true));
525 add_object_attribute(o, 0, CKA_VERIFY, &bool_true, sizeof(bool_true));
526 add_object_attribute(o, 0, CKA_VERIFY_RECOVER, &bool_false, sizeof(bool_false));
527 add_object_attribute(o, 0, CKA_WRAP, &bool_true, sizeof(bool_true));
528 add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true));
530 add_pubkey_info(hxctx, o, key_type, cert);
532 st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o));
534 if (hx509_cert_have_private_key(cert)) {
535 CK_FLAGS flags;
537 type = CKO_PRIVATE_KEY;
538 o = add_st_object();
539 if (o == NULL) {
540 ret = CKR_DEVICE_MEMORY;
541 goto out;
543 o->cert = hx509_cert_ref(cert);
545 add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
546 add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
547 add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false));
548 add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
549 add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
551 add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
552 add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
553 add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */
554 add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */
555 add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
556 add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
557 mech_type = CKM_RSA_X_509;
558 add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
560 add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
561 add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true));
562 add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true));
563 flags = 0;
564 add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags));
566 add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true));
567 add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true));
568 add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false));
569 add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true));
570 add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true));
571 add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false));
573 add_pubkey_info(hxctx, o, key_type, cert);
576 ret = CKR_OK;
577 out:
578 if (ret != CKR_OK) {
579 st_logf("something went wrong when adding cert!\n");
581 /* XXX wack o */;
583 hx509_xfree(cert_data.data);
584 hx509_xfree(serial_data.data);
585 hx509_xfree(issuer_data.data);
586 hx509_xfree(subject_data.data);
588 return 0;
591 static CK_RV
592 add_certificate(const char *cert_file,
593 const char *pin,
594 char *id,
595 char *label)
597 hx509_certs certs;
598 hx509_lock lock = NULL;
599 int ret, flags = 0;
601 struct foo foo;
602 foo.id = id;
603 foo.label = label;
605 if (pin == NULL)
606 flags |= HX509_CERTS_UNPROTECT_ALL;
608 if (pin) {
609 char *str;
610 asprintf(&str, "PASS:%s", pin);
612 hx509_lock_init(context, &lock);
613 hx509_lock_command_string(lock, str);
615 memset(str, 0, strlen(str));
616 free(str);
619 ret = hx509_certs_init(context, cert_file, flags, lock, &certs);
620 if (ret) {
621 st_logf("failed to open file %s\n", cert_file);
622 return CKR_GENERAL_ERROR;
625 ret = hx509_certs_iter(context, certs, add_cert, &foo);
626 hx509_certs_free(&certs);
627 if (ret) {
628 st_logf("failed adding certs from file %s\n", cert_file);
629 return CKR_GENERAL_ERROR;
632 return CKR_OK;
635 static void
636 find_object_final(struct session_state *state)
638 if (state->find.attributes) {
639 CK_ULONG i;
641 for (i = 0; i < state->find.num_attributes; i++) {
642 if (state->find.attributes[i].pValue)
643 free(state->find.attributes[i].pValue);
645 free(state->find.attributes);
646 state->find.attributes = NULL;
647 state->find.num_attributes = 0;
648 state->find.next_object = -1;
652 static void
653 reset_crypto_state(struct session_state *state)
655 state->sign_object = -1;
656 if (state->sign_mechanism)
657 free(state->sign_mechanism);
658 state->sign_mechanism = NULL_PTR;
659 state->verify_object = -1;
660 if (state->verify_mechanism)
661 free(state->verify_mechanism);
662 state->verify_mechanism = NULL_PTR;
665 static void
666 close_session(struct session_state *state)
668 if (state->find.attributes) {
669 application_error("application didn't do C_FindObjectsFinal\n");
670 find_object_final(state);
673 state->session_handle = CK_INVALID_HANDLE;
674 soft_token.application = NULL_PTR;
675 soft_token.notify = NULL_PTR;
676 reset_crypto_state(state);
679 static const char *
680 has_session(void)
682 return soft_token.open_sessions > 0 ? "yes" : "no";
685 static CK_RV
686 read_conf_file(const char *fn, CK_USER_TYPE userType, const char *pin)
688 char buf[1024], *type, *s, *p;
689 int anchor;
690 FILE *f;
691 CK_RV ret = CKR_OK;
692 CK_RV failed = CKR_OK;
694 f = fopen(fn, "r");
695 if (f == NULL) {
696 st_logf("can't open configuration file %s\n", fn);
697 return CKR_GENERAL_ERROR;
700 while(fgets(buf, sizeof(buf), f) != NULL) {
701 buf[strcspn(buf, "\n")] = '\0';
703 anchor = 0;
705 st_logf("line: %s\n", buf);
707 p = buf;
708 while (isspace((unsigned char)*p))
709 p++;
710 if (*p == '#')
711 continue;
712 while (isspace((unsigned char)*p))
713 p++;
715 s = NULL;
716 type = strtok_r(p, "\t", &s);
717 if (type == NULL)
718 continue;
720 if (strcasecmp("certificate", type) == 0) {
721 char *cert, *id, *label;
723 id = strtok_r(NULL, "\t", &s);
724 if (id == NULL) {
725 st_logf("no id\n");
726 continue;
728 st_logf("id: %s\n", id);
729 label = strtok_r(NULL, "\t", &s);
730 if (label == NULL) {
731 st_logf("no label\n");
732 continue;
734 cert = strtok_r(NULL, "\t", &s);
735 if (cert == NULL) {
736 st_logf("no certfiicate store\n");
737 continue;
740 st_logf("adding: %s: %s in file %s\n", id, label, cert);
742 ret = add_certificate(cert, pin, id, label);
743 if (ret)
744 failed = ret;
745 } else if (strcasecmp("debug", type) == 0) {
746 char *name;
748 name = strtok_r(NULL, "\t", &s);
749 if (name == NULL) {
750 st_logf("no filename\n");
751 continue;
754 if (soft_token.logfile)
755 fclose(soft_token.logfile);
757 if (strcasecmp(name, "stdout") == 0)
758 soft_token.logfile = stdout;
759 else
760 soft_token.logfile = fopen(name, "a");
761 if (soft_token.logfile == NULL)
762 st_logf("failed to open file: %s\n", name);
764 } else if (strcasecmp("app-fatal", type) == 0) {
765 char *name;
767 name = strtok_r(NULL, "\t", &s);
768 if (name == NULL) {
769 st_logf("argument to app-fatal\n");
770 continue;
773 if (strcmp(name, "true") == 0 || strcmp(name, "on") == 0)
774 soft_token.flags.app_error_fatal = 1;
775 else if (strcmp(name, "false") == 0 || strcmp(name, "off") == 0)
776 soft_token.flags.app_error_fatal = 0;
777 else
778 st_logf("unknown app-fatal: %s\n", name);
780 } else {
781 st_logf("unknown type: %s\n", type);
785 fclose(f);
787 return failed;
790 static CK_RV
791 func_not_supported(void)
793 st_logf("function not supported\n");
794 return CKR_FUNCTION_NOT_SUPPORTED;
797 CK_RV
798 C_Initialize(CK_VOID_PTR a)
800 CK_C_INITIALIZE_ARGS_PTR args = a;
801 CK_RV ret;
802 int i;
804 st_logf("Initialize\n");
806 INIT_CONTEXT();
808 OpenSSL_add_all_algorithms();
810 srandom(getpid() ^ time(NULL));
812 for (i = 0; i < MAX_NUM_SESSION; i++) {
813 soft_token.state[i].session_handle = CK_INVALID_HANDLE;
814 soft_token.state[i].find.attributes = NULL;
815 soft_token.state[i].find.num_attributes = 0;
816 soft_token.state[i].find.next_object = -1;
817 reset_crypto_state(&soft_token.state[i]);
820 soft_token.flags.hardware_slot = 1;
821 soft_token.flags.app_error_fatal = 0;
822 soft_token.flags.login_done = 0;
824 soft_token.object.objs = NULL;
825 soft_token.object.num_objs = 0;
827 soft_token.logfile = NULL;
828 #if 0
829 soft_token.logfile = stdout;
830 #endif
831 #if 0
832 soft_token.logfile = fopen("/tmp/log-pkcs11.txt", "a");
833 #endif
835 if (a != NULL_PTR) {
836 st_logf("\tCreateMutex:\t%p\n", args->CreateMutex);
837 st_logf("\tDestroyMutext\t%p\n", args->DestroyMutex);
838 st_logf("\tLockMutext\t%p\n", args->LockMutex);
839 st_logf("\tUnlockMutext\t%p\n", args->UnlockMutex);
840 st_logf("\tFlags\t%04x\n", (unsigned int)args->flags);
844 char *fn = NULL, *home = NULL;
846 if (getuid() == geteuid()) {
847 fn = getenv("SOFTPKCS11RC");
848 if (fn)
849 fn = strdup(fn);
850 home = getenv("HOME");
852 if (fn == NULL && home == NULL) {
853 struct passwd *pw = getpwuid(getuid());
854 if(pw != NULL)
855 home = pw->pw_dir;
857 if (fn == NULL) {
858 if (home)
859 asprintf(&fn, "%s/.soft-token.rc", home);
860 else
861 fn = strdup("/etc/soft-token.rc");
864 soft_token.config_file = fn;
868 * This operations doesn't return CKR_OK if any of the
869 * certificates failes to be unparsed (ie password protected).
871 ret = read_conf_file(soft_token.config_file, CKU_USER, NULL);
872 if (ret == CKR_OK)
873 soft_token.flags.login_done = 1;
875 return CKR_OK;
878 CK_RV
879 C_Finalize(CK_VOID_PTR args)
881 int i;
883 INIT_CONTEXT();
885 st_logf("Finalize\n");
887 for (i = 0; i < MAX_NUM_SESSION; i++) {
888 if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) {
889 application_error("application finalized without "
890 "closing session\n");
891 close_session(&soft_token.state[i]);
895 return CKR_OK;
898 CK_RV
899 C_GetInfo(CK_INFO_PTR args)
901 INIT_CONTEXT();
903 st_logf("GetInfo\n");
905 memset(args, 17, sizeof(*args));
906 args->cryptokiVersion.major = 2;
907 args->cryptokiVersion.minor = 10;
908 snprintf_fill((char *)args->manufacturerID,
909 sizeof(args->manufacturerID),
910 ' ',
911 "Heimdal hx509 SoftToken");
912 snprintf_fill((char *)args->libraryDescription,
913 sizeof(args->libraryDescription), ' ',
914 "Heimdal hx509 SoftToken");
915 args->libraryVersion.major = 2;
916 args->libraryVersion.minor = 0;
918 return CKR_OK;
921 extern CK_FUNCTION_LIST funcs;
923 CK_RV
924 C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
926 INIT_CONTEXT();
928 *ppFunctionList = &funcs;
929 return CKR_OK;
932 CK_RV
933 C_GetSlotList(CK_BBOOL tokenPresent,
934 CK_SLOT_ID_PTR pSlotList,
935 CK_ULONG_PTR pulCount)
937 INIT_CONTEXT();
938 st_logf("GetSlotList: %s\n",
939 tokenPresent ? "tokenPresent" : "token not Present");
940 if (pSlotList)
941 pSlotList[0] = 1;
942 *pulCount = 1;
943 return CKR_OK;
946 CK_RV
947 C_GetSlotInfo(CK_SLOT_ID slotID,
948 CK_SLOT_INFO_PTR pInfo)
950 INIT_CONTEXT();
951 st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID, has_session());
953 memset(pInfo, 18, sizeof(*pInfo));
955 if (slotID != 1)
956 return CKR_ARGUMENTS_BAD;
958 snprintf_fill((char *)pInfo->slotDescription,
959 sizeof(pInfo->slotDescription),
960 ' ',
961 "Heimdal hx509 SoftToken (slot)");
962 snprintf_fill((char *)pInfo->manufacturerID,
963 sizeof(pInfo->manufacturerID),
964 ' ',
965 "Heimdal hx509 SoftToken (slot)");
966 pInfo->flags = CKF_TOKEN_PRESENT;
967 if (soft_token.flags.hardware_slot)
968 pInfo->flags |= CKF_HW_SLOT;
969 pInfo->hardwareVersion.major = 1;
970 pInfo->hardwareVersion.minor = 0;
971 pInfo->firmwareVersion.major = 1;
972 pInfo->firmwareVersion.minor = 0;
974 return CKR_OK;
977 CK_RV
978 C_GetTokenInfo(CK_SLOT_ID slotID,
979 CK_TOKEN_INFO_PTR pInfo)
981 INIT_CONTEXT();
982 st_logf("GetTokenInfo: %s\n", has_session());
984 memset(pInfo, 19, sizeof(*pInfo));
986 snprintf_fill((char *)pInfo->label,
987 sizeof(pInfo->label),
988 ' ',
989 "Heimdal hx509 SoftToken (token)");
990 snprintf_fill((char *)pInfo->manufacturerID,
991 sizeof(pInfo->manufacturerID),
992 ' ',
993 "Heimdal hx509 SoftToken (token)");
994 snprintf_fill((char *)pInfo->model,
995 sizeof(pInfo->model),
996 ' ',
997 "Heimdal hx509 SoftToken (token)");
998 snprintf_fill((char *)pInfo->serialNumber,
999 sizeof(pInfo->serialNumber),
1000 ' ',
1001 "4711");
1002 pInfo->flags =
1003 CKF_TOKEN_INITIALIZED |
1004 CKF_USER_PIN_INITIALIZED;
1006 if (soft_token.flags.login_done == 0)
1007 pInfo->flags |= CKF_LOGIN_REQUIRED;
1009 /* CFK_RNG |
1010 CKF_RESTORE_KEY_NOT_NEEDED |
1012 pInfo->ulMaxSessionCount = MAX_NUM_SESSION;
1013 pInfo->ulSessionCount = soft_token.open_sessions;
1014 pInfo->ulMaxRwSessionCount = MAX_NUM_SESSION;
1015 pInfo->ulRwSessionCount = soft_token.open_sessions;
1016 pInfo->ulMaxPinLen = 1024;
1017 pInfo->ulMinPinLen = 0;
1018 pInfo->ulTotalPublicMemory = 4711;
1019 pInfo->ulFreePublicMemory = 4712;
1020 pInfo->ulTotalPrivateMemory = 4713;
1021 pInfo->ulFreePrivateMemory = 4714;
1022 pInfo->hardwareVersion.major = 2;
1023 pInfo->hardwareVersion.minor = 0;
1024 pInfo->firmwareVersion.major = 2;
1025 pInfo->firmwareVersion.minor = 0;
1027 return CKR_OK;
1030 CK_RV
1031 C_GetMechanismList(CK_SLOT_ID slotID,
1032 CK_MECHANISM_TYPE_PTR pMechanismList,
1033 CK_ULONG_PTR pulCount)
1035 INIT_CONTEXT();
1036 st_logf("GetMechanismList\n");
1038 *pulCount = 1;
1039 if (pMechanismList == NULL_PTR)
1040 return CKR_OK;
1041 pMechanismList[1] = CKM_RSA_PKCS;
1043 return CKR_OK;
1046 CK_RV
1047 C_GetMechanismInfo(CK_SLOT_ID slotID,
1048 CK_MECHANISM_TYPE type,
1049 CK_MECHANISM_INFO_PTR pInfo)
1051 INIT_CONTEXT();
1052 st_logf("GetMechanismInfo: slot %d type: %d\n",
1053 (int)slotID, (int)type);
1054 memset(pInfo, 0, sizeof(*pInfo));
1056 return CKR_OK;
1059 CK_RV
1060 C_InitToken(CK_SLOT_ID slotID,
1061 CK_UTF8CHAR_PTR pPin,
1062 CK_ULONG ulPinLen,
1063 CK_UTF8CHAR_PTR pLabel)
1065 INIT_CONTEXT();
1066 st_logf("InitToken: slot %d\n", (int)slotID);
1067 return CKR_FUNCTION_NOT_SUPPORTED;
1070 CK_RV
1071 C_OpenSession(CK_SLOT_ID slotID,
1072 CK_FLAGS flags,
1073 CK_VOID_PTR pApplication,
1074 CK_NOTIFY Notify,
1075 CK_SESSION_HANDLE_PTR phSession)
1077 int i;
1078 INIT_CONTEXT();
1079 st_logf("OpenSession: slot: %d\n", (int)slotID);
1081 if (soft_token.open_sessions == MAX_NUM_SESSION)
1082 return CKR_SESSION_COUNT;
1084 soft_token.application = pApplication;
1085 soft_token.notify = Notify;
1087 for (i = 0; i < MAX_NUM_SESSION; i++)
1088 if (soft_token.state[i].session_handle == CK_INVALID_HANDLE)
1089 break;
1090 if (i == MAX_NUM_SESSION)
1091 abort();
1093 soft_token.open_sessions++;
1095 soft_token.state[i].session_handle =
1096 (CK_SESSION_HANDLE)(random() & 0xfffff);
1097 *phSession = soft_token.state[i].session_handle;
1099 return CKR_OK;
1102 CK_RV
1103 C_CloseSession(CK_SESSION_HANDLE hSession)
1105 struct session_state *state;
1106 INIT_CONTEXT();
1107 st_logf("CloseSession\n");
1109 if (verify_session_handle(hSession, &state) != CKR_OK)
1110 application_error("closed session not open");
1111 else
1112 close_session(state);
1114 return CKR_OK;
1117 CK_RV
1118 C_CloseAllSessions(CK_SLOT_ID slotID)
1120 int i;
1121 INIT_CONTEXT();
1123 st_logf("CloseAllSessions\n");
1125 for (i = 0; i < MAX_NUM_SESSION; i++)
1126 if (soft_token.state[i].session_handle != CK_INVALID_HANDLE)
1127 close_session(&soft_token.state[i]);
1129 return CKR_OK;
1132 CK_RV
1133 C_GetSessionInfo(CK_SESSION_HANDLE hSession,
1134 CK_SESSION_INFO_PTR pInfo)
1136 st_logf("GetSessionInfo\n");
1137 INIT_CONTEXT();
1139 VERIFY_SESSION_HANDLE(hSession, NULL);
1141 memset(pInfo, 20, sizeof(*pInfo));
1143 pInfo->slotID = 1;
1144 if (soft_token.flags.login_done)
1145 pInfo->state = CKS_RO_USER_FUNCTIONS;
1146 else
1147 pInfo->state = CKS_RO_PUBLIC_SESSION;
1148 pInfo->flags = CKF_SERIAL_SESSION;
1149 pInfo->ulDeviceError = 0;
1151 return CKR_OK;
1154 CK_RV
1155 C_Login(CK_SESSION_HANDLE hSession,
1156 CK_USER_TYPE userType,
1157 CK_UTF8CHAR_PTR pPin,
1158 CK_ULONG ulPinLen)
1160 char *pin = NULL;
1161 CK_RV ret;
1162 INIT_CONTEXT();
1164 st_logf("Login\n");
1166 VERIFY_SESSION_HANDLE(hSession, NULL);
1168 if (pPin != NULL_PTR) {
1169 asprintf(&pin, "%.*s", (int)ulPinLen, pPin);
1170 st_logf("type: %d password: %s\n", (int)userType, pin);
1174 * Login
1177 ret = read_conf_file(soft_token.config_file, userType, pin);
1178 if (ret == CKR_OK)
1179 soft_token.flags.login_done = 1;
1181 free(pin);
1183 return soft_token.flags.login_done ? CKR_OK : CKR_PIN_INCORRECT;
1186 CK_RV
1187 C_Logout(CK_SESSION_HANDLE hSession)
1189 st_logf("Logout\n");
1190 INIT_CONTEXT();
1192 VERIFY_SESSION_HANDLE(hSession, NULL);
1193 return CKR_FUNCTION_NOT_SUPPORTED;
1196 CK_RV
1197 C_GetObjectSize(CK_SESSION_HANDLE hSession,
1198 CK_OBJECT_HANDLE hObject,
1199 CK_ULONG_PTR pulSize)
1201 st_logf("GetObjectSize\n");
1202 INIT_CONTEXT();
1204 VERIFY_SESSION_HANDLE(hSession, NULL);
1205 return CKR_FUNCTION_NOT_SUPPORTED;
1208 CK_RV
1209 C_GetAttributeValue(CK_SESSION_HANDLE hSession,
1210 CK_OBJECT_HANDLE hObject,
1211 CK_ATTRIBUTE_PTR pTemplate,
1212 CK_ULONG ulCount)
1214 struct session_state *state;
1215 struct st_object *obj;
1216 CK_ULONG i;
1217 CK_RV ret;
1218 int j;
1220 INIT_CONTEXT();
1222 st_logf("GetAttributeValue: %lx\n",
1223 (unsigned long)HANDLE_OBJECT_ID(hObject));
1224 VERIFY_SESSION_HANDLE(hSession, &state);
1226 if ((ret = object_handle_to_object(hObject, &obj)) != CKR_OK) {
1227 st_logf("object not found: %lx\n",
1228 (unsigned long)HANDLE_OBJECT_ID(hObject));
1229 return ret;
1232 for (i = 0; i < ulCount; i++) {
1233 st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate[i].type);
1234 for (j = 0; j < obj->num_attributes; j++) {
1235 if (obj->attrs[j].secret) {
1236 pTemplate[i].ulValueLen = (CK_ULONG)-1;
1237 break;
1239 if (pTemplate[i].type == obj->attrs[j].attribute.type) {
1240 if (pTemplate[i].pValue != NULL_PTR && obj->attrs[j].secret == 0) {
1241 if (pTemplate[i].ulValueLen >= obj->attrs[j].attribute.ulValueLen)
1242 memcpy(pTemplate[i].pValue, obj->attrs[j].attribute.pValue,
1243 obj->attrs[j].attribute.ulValueLen);
1245 pTemplate[i].ulValueLen = obj->attrs[j].attribute.ulValueLen;
1246 break;
1249 if (j == obj->num_attributes) {
1250 st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate[i].type);
1251 pTemplate[i].ulValueLen = (CK_ULONG)-1;
1255 return CKR_OK;
1258 CK_RV
1259 C_FindObjectsInit(CK_SESSION_HANDLE hSession,
1260 CK_ATTRIBUTE_PTR pTemplate,
1261 CK_ULONG ulCount)
1263 struct session_state *state;
1265 st_logf("FindObjectsInit\n");
1267 INIT_CONTEXT();
1269 VERIFY_SESSION_HANDLE(hSession, &state);
1271 if (state->find.next_object != -1) {
1272 application_error("application didn't do C_FindObjectsFinal\n");
1273 find_object_final(state);
1275 if (ulCount) {
1276 CK_ULONG i;
1278 print_attributes(pTemplate, ulCount);
1280 state->find.attributes =
1281 calloc(1, ulCount * sizeof(state->find.attributes[0]));
1282 if (state->find.attributes == NULL)
1283 return CKR_DEVICE_MEMORY;
1284 for (i = 0; i < ulCount; i++) {
1285 state->find.attributes[i].pValue =
1286 malloc(pTemplate[i].ulValueLen);
1287 if (state->find.attributes[i].pValue == NULL) {
1288 find_object_final(state);
1289 return CKR_DEVICE_MEMORY;
1291 memcpy(state->find.attributes[i].pValue,
1292 pTemplate[i].pValue, pTemplate[i].ulValueLen);
1293 state->find.attributes[i].type = pTemplate[i].type;
1294 state->find.attributes[i].ulValueLen = pTemplate[i].ulValueLen;
1296 state->find.num_attributes = ulCount;
1297 state->find.next_object = 0;
1298 } else {
1299 st_logf("find all objects\n");
1300 state->find.attributes = NULL;
1301 state->find.num_attributes = 0;
1302 state->find.next_object = 0;
1305 return CKR_OK;
1308 CK_RV
1309 C_FindObjects(CK_SESSION_HANDLE hSession,
1310 CK_OBJECT_HANDLE_PTR phObject,
1311 CK_ULONG ulMaxObjectCount,
1312 CK_ULONG_PTR pulObjectCount)
1314 struct session_state *state;
1315 int i;
1317 INIT_CONTEXT();
1319 st_logf("FindObjects\n");
1321 VERIFY_SESSION_HANDLE(hSession, &state);
1323 if (state->find.next_object == -1) {
1324 application_error("application didn't do C_FindObjectsInit\n");
1325 return CKR_ARGUMENTS_BAD;
1327 if (ulMaxObjectCount == 0) {
1328 application_error("application asked for 0 objects\n");
1329 return CKR_ARGUMENTS_BAD;
1331 *pulObjectCount = 0;
1332 for (i = state->find.next_object; i < soft_token.object.num_objs; i++) {
1333 st_logf("FindObjects: %d\n", i);
1334 state->find.next_object = i + 1;
1335 if (attributes_match(soft_token.object.objs[i],
1336 state->find.attributes,
1337 state->find.num_attributes)) {
1338 *phObject++ = soft_token.object.objs[i]->object_handle;
1339 ulMaxObjectCount--;
1340 (*pulObjectCount)++;
1341 if (ulMaxObjectCount == 0)
1342 break;
1345 return CKR_OK;
1348 CK_RV
1349 C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
1351 struct session_state *state;
1353 INIT_CONTEXT();
1355 st_logf("FindObjectsFinal\n");
1356 VERIFY_SESSION_HANDLE(hSession, &state);
1357 find_object_final(state);
1358 return CKR_OK;
1361 static CK_RV
1362 commonInit(CK_ATTRIBUTE *attr_match, int attr_match_len,
1363 const CK_MECHANISM_TYPE *mechs, int mechs_len,
1364 const CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey,
1365 struct st_object **o)
1367 CK_RV ret;
1368 int i;
1370 *o = NULL;
1371 if ((ret = object_handle_to_object(hKey, o)) != CKR_OK)
1372 return ret;
1374 ret = attributes_match(*o, attr_match, attr_match_len);
1375 if (!ret) {
1376 application_error("called commonInit on key that doesn't "
1377 "support required attr");
1378 return CKR_ARGUMENTS_BAD;
1381 for (i = 0; i < mechs_len; i++)
1382 if (mechs[i] == pMechanism->mechanism)
1383 break;
1384 if (i == mechs_len) {
1385 application_error("called mech (%08lx) not supported\n",
1386 pMechanism->mechanism);
1387 return CKR_ARGUMENTS_BAD;
1389 return CKR_OK;
1393 static CK_RV
1394 dup_mechanism(CK_MECHANISM_PTR *dup, const CK_MECHANISM_PTR pMechanism)
1396 CK_MECHANISM_PTR p;
1398 p = malloc(sizeof(*p));
1399 if (p == NULL)
1400 return CKR_DEVICE_MEMORY;
1402 if (*dup)
1403 free(*dup);
1404 *dup = p;
1405 memcpy(p, pMechanism, sizeof(*p));
1407 return CKR_OK;
1410 CK_RV
1411 C_DigestInit(CK_SESSION_HANDLE hSession,
1412 CK_MECHANISM_PTR pMechanism)
1414 st_logf("DigestInit\n");
1415 INIT_CONTEXT();
1416 VERIFY_SESSION_HANDLE(hSession, NULL);
1417 return CKR_FUNCTION_NOT_SUPPORTED;
1420 CK_RV
1421 C_SignInit(CK_SESSION_HANDLE hSession,
1422 CK_MECHANISM_PTR pMechanism,
1423 CK_OBJECT_HANDLE hKey)
1425 struct session_state *state;
1426 CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS };
1427 CK_BBOOL bool_true = CK_TRUE;
1428 CK_ATTRIBUTE attr[] = {
1429 { CKA_SIGN, &bool_true, sizeof(bool_true) }
1431 struct st_object *o;
1432 CK_RV ret;
1434 INIT_CONTEXT();
1435 st_logf("SignInit\n");
1436 VERIFY_SESSION_HANDLE(hSession, &state);
1438 ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1439 mechs, sizeof(mechs)/sizeof(mechs[0]),
1440 pMechanism, hKey, &o);
1441 if (ret)
1442 return ret;
1444 ret = dup_mechanism(&state->sign_mechanism, pMechanism);
1445 if (ret == CKR_OK)
1446 state->sign_object = OBJECT_ID(o);
1448 return CKR_OK;
1451 CK_RV
1452 C_Sign(CK_SESSION_HANDLE hSession,
1453 CK_BYTE_PTR pData,
1454 CK_ULONG ulDataLen,
1455 CK_BYTE_PTR pSignature,
1456 CK_ULONG_PTR pulSignatureLen)
1458 struct session_state *state;
1459 struct st_object *o;
1460 CK_RV ret;
1461 uint hret;
1462 const AlgorithmIdentifier *alg;
1463 heim_octet_string sig, data;
1465 INIT_CONTEXT();
1466 st_logf("Sign\n");
1467 VERIFY_SESSION_HANDLE(hSession, &state);
1469 sig.data = NULL;
1470 sig.length = 0;
1472 if (state->sign_object == -1)
1473 return CKR_ARGUMENTS_BAD;
1475 if (pulSignatureLen == NULL) {
1476 st_logf("signature len NULL\n");
1477 ret = CKR_ARGUMENTS_BAD;
1478 goto out;
1481 if (pData == NULL_PTR) {
1482 st_logf("data NULL\n");
1483 ret = CKR_ARGUMENTS_BAD;
1484 goto out;
1487 o = soft_token.object.objs[state->sign_object];
1489 if (hx509_cert_have_private_key(o->cert) == 0) {
1490 st_logf("private key NULL\n");
1491 return CKR_ARGUMENTS_BAD;
1494 switch(state->sign_mechanism->mechanism) {
1495 case CKM_RSA_PKCS:
1496 alg = hx509_signature_rsa_pkcs1_x509();
1497 break;
1498 default:
1499 ret = CKR_FUNCTION_NOT_SUPPORTED;
1500 goto out;
1503 data.data = pData;
1504 data.length = ulDataLen;
1506 hret = _hx509_create_signature(context,
1507 _hx509_cert_private_key(o->cert),
1508 alg,
1509 &data,
1510 NULL,
1511 &sig);
1512 if (hret) {
1513 ret = CKR_DEVICE_ERROR;
1514 goto out;
1516 *pulSignatureLen = sig.length;
1518 if (pSignature != NULL_PTR)
1519 memcpy(pSignature, sig.data, sig.length);
1521 ret = CKR_OK;
1522 out:
1523 if (sig.data) {
1524 memset(sig.data, 0, sig.length);
1525 der_free_octet_string(&sig);
1527 return ret;
1530 CK_RV
1531 C_SignUpdate(CK_SESSION_HANDLE hSession,
1532 CK_BYTE_PTR pPart,
1533 CK_ULONG ulPartLen)
1535 INIT_CONTEXT();
1536 st_logf("SignUpdate\n");
1537 VERIFY_SESSION_HANDLE(hSession, NULL);
1538 return CKR_FUNCTION_NOT_SUPPORTED;
1542 CK_RV
1543 C_SignFinal(CK_SESSION_HANDLE hSession,
1544 CK_BYTE_PTR pSignature,
1545 CK_ULONG_PTR pulSignatureLen)
1547 INIT_CONTEXT();
1548 st_logf("SignUpdate\n");
1549 VERIFY_SESSION_HANDLE(hSession, NULL);
1550 return CKR_FUNCTION_NOT_SUPPORTED;
1553 CK_RV
1554 C_VerifyInit(CK_SESSION_HANDLE hSession,
1555 CK_MECHANISM_PTR pMechanism,
1556 CK_OBJECT_HANDLE hKey)
1558 struct session_state *state;
1559 CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS };
1560 CK_BBOOL bool_true = CK_TRUE;
1561 CK_ATTRIBUTE attr[] = {
1562 { CKA_VERIFY, &bool_true, sizeof(bool_true) }
1564 struct st_object *o;
1565 CK_RV ret;
1567 INIT_CONTEXT();
1568 st_logf("VerifyInit\n");
1569 VERIFY_SESSION_HANDLE(hSession, &state);
1571 ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1572 mechs, sizeof(mechs)/sizeof(mechs[0]),
1573 pMechanism, hKey, &o);
1574 if (ret)
1575 return ret;
1577 ret = dup_mechanism(&state->verify_mechanism, pMechanism);
1578 if (ret == CKR_OK)
1579 state->verify_object = OBJECT_ID(o);
1581 return ret;
1584 CK_RV
1585 C_Verify(CK_SESSION_HANDLE hSession,
1586 CK_BYTE_PTR pData,
1587 CK_ULONG ulDataLen,
1588 CK_BYTE_PTR pSignature,
1589 CK_ULONG ulSignatureLen)
1591 struct session_state *state;
1592 struct st_object *o;
1593 const AlgorithmIdentifier *alg;
1594 CK_RV ret;
1595 int hret;
1596 heim_octet_string data, sig;
1598 INIT_CONTEXT();
1599 st_logf("Verify\n");
1600 VERIFY_SESSION_HANDLE(hSession, &state);
1602 if (state->verify_object == -1)
1603 return CKR_ARGUMENTS_BAD;
1605 o = soft_token.object.objs[state->verify_object];
1607 switch(state->verify_mechanism->mechanism) {
1608 case CKM_RSA_PKCS:
1609 alg = hx509_signature_rsa_pkcs1_x509();
1610 break;
1611 default:
1612 ret = CKR_FUNCTION_NOT_SUPPORTED;
1613 goto out;
1616 sig.data = pData;
1617 sig.length = ulDataLen;
1618 data.data = pSignature;
1619 data.length = ulSignatureLen;
1621 hret = _hx509_verify_signature(context,
1622 _hx509_get_cert(o->cert),
1623 alg,
1624 &data,
1625 &sig);
1626 if (hret) {
1627 ret = CKR_GENERAL_ERROR;
1628 goto out;
1630 ret = CKR_OK;
1632 out:
1633 return ret;
1637 CK_RV
1638 C_VerifyUpdate(CK_SESSION_HANDLE hSession,
1639 CK_BYTE_PTR pPart,
1640 CK_ULONG ulPartLen)
1642 INIT_CONTEXT();
1643 st_logf("VerifyUpdate\n");
1644 VERIFY_SESSION_HANDLE(hSession, NULL);
1645 return CKR_FUNCTION_NOT_SUPPORTED;
1648 CK_RV
1649 C_VerifyFinal(CK_SESSION_HANDLE hSession,
1650 CK_BYTE_PTR pSignature,
1651 CK_ULONG ulSignatureLen)
1653 INIT_CONTEXT();
1654 st_logf("VerifyFinal\n");
1655 VERIFY_SESSION_HANDLE(hSession, NULL);
1656 return CKR_FUNCTION_NOT_SUPPORTED;
1659 CK_RV
1660 C_GenerateRandom(CK_SESSION_HANDLE hSession,
1661 CK_BYTE_PTR RandomData,
1662 CK_ULONG ulRandomLen)
1664 INIT_CONTEXT();
1665 st_logf("GenerateRandom\n");
1666 VERIFY_SESSION_HANDLE(hSession, NULL);
1667 return CKR_FUNCTION_NOT_SUPPORTED;
1671 CK_FUNCTION_LIST funcs = {
1672 { 2, 11 },
1673 C_Initialize,
1674 C_Finalize,
1675 C_GetInfo,
1676 C_GetFunctionList,
1677 C_GetSlotList,
1678 C_GetSlotInfo,
1679 C_GetTokenInfo,
1680 C_GetMechanismList,
1681 C_GetMechanismInfo,
1682 C_InitToken,
1683 (void *)func_not_supported, /* C_InitPIN */
1684 (void *)func_not_supported, /* C_SetPIN */
1685 C_OpenSession,
1686 C_CloseSession,
1687 C_CloseAllSessions,
1688 C_GetSessionInfo,
1689 (void *)func_not_supported, /* C_GetOperationState */
1690 (void *)func_not_supported, /* C_SetOperationState */
1691 C_Login,
1692 C_Logout,
1693 (void *)func_not_supported, /* C_CreateObject */
1694 (void *)func_not_supported, /* C_CopyObject */
1695 (void *)func_not_supported, /* C_DestroyObject */
1696 (void *)func_not_supported, /* C_GetObjectSize */
1697 C_GetAttributeValue,
1698 (void *)func_not_supported, /* C_SetAttributeValue */
1699 C_FindObjectsInit,
1700 C_FindObjects,
1701 C_FindObjectsFinal,
1702 (void *)func_not_supported, /* C_EncryptInit, */
1703 (void *)func_not_supported, /* C_Encrypt, */
1704 (void *)func_not_supported, /* C_EncryptUpdate, */
1705 (void *)func_not_supported, /* C_EncryptFinal, */
1706 (void *)func_not_supported, /* C_DecryptInit, */
1707 (void *)func_not_supported, /* C_Decrypt, */
1708 (void *)func_not_supported, /* C_DecryptUpdate, */
1709 (void *)func_not_supported, /* C_DecryptFinal, */
1710 C_DigestInit,
1711 (void *)func_not_supported, /* C_Digest */
1712 (void *)func_not_supported, /* C_DigestUpdate */
1713 (void *)func_not_supported, /* C_DigestKey */
1714 (void *)func_not_supported, /* C_DigestFinal */
1715 C_SignInit,
1716 C_Sign,
1717 C_SignUpdate,
1718 C_SignFinal,
1719 (void *)func_not_supported, /* C_SignRecoverInit */
1720 (void *)func_not_supported, /* C_SignRecover */
1721 C_VerifyInit,
1722 C_Verify,
1723 C_VerifyUpdate,
1724 C_VerifyFinal,
1725 (void *)func_not_supported, /* C_VerifyRecoverInit */
1726 (void *)func_not_supported, /* C_VerifyRecover */
1727 (void *)func_not_supported, /* C_DigestEncryptUpdate */
1728 (void *)func_not_supported, /* C_DecryptDigestUpdate */
1729 (void *)func_not_supported, /* C_SignEncryptUpdate */
1730 (void *)func_not_supported, /* C_DecryptVerifyUpdate */
1731 (void *)func_not_supported, /* C_GenerateKey */
1732 (void *)func_not_supported, /* C_GenerateKeyPair */
1733 (void *)func_not_supported, /* C_WrapKey */
1734 (void *)func_not_supported, /* C_UnwrapKey */
1735 (void *)func_not_supported, /* C_DeriveKey */
1736 (void *)func_not_supported, /* C_SeedRandom */
1737 C_GenerateRandom,
1738 (void *)func_not_supported, /* C_GetFunctionStatus */
1739 (void *)func_not_supported, /* C_CancelFunction */
1740 (void *)func_not_supported /* C_WaitForSlotEvent */