1 /*
2 * Copyright (c) 2004 - 2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 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.
20 *
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.
32 */
33
34 #define CRYPTOKI_EXPORTS 1
35
36 #include "hx_locl.h"
37 #include "pkcs11.h"
38
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)
42
43 #ifndef HAVE_RANDOM
44 #define random() rand()
45 #define srandom(s) srand(s)
46 #endif
47
48 #ifdef _WIN32
49 #include <shlobj.h>
50 #endif
51
52 struct st_attr {
53 CK_ATTRIBUTE attribute;
54 int secret;
55 };
56
57 struct st_object {
58 CK_OBJECT_HANDLE object_handle;
59 struct st_attr *attrs;
60 int num_attributes;
61 hx509_cert cert;
62 };
63
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;
81
82 struct {
83 CK_ATTRIBUTE *attributes;
84 CK_ULONG num_attributes;
85 int next_object;
86 } find;
87
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;
96
97 static hx509_context context;
98
99 static void
application_error(const char * fmt,...)100 application_error(const char *fmt, ...)
101 {
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();
108 }
109
110 static void
st_logf(const char * fmt,...)111 st_logf(const char *fmt, ...)
112 {
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);
120 }
121
122 static CK_RV
init_context(void)123 init_context(void)
124 {
125 if (context == NULL) {
126 int ret = hx509_context_init(&context);
127 if (ret)
128 return CKR_GENERAL_ERROR;
129 }
130 return CKR_OK;
131 }
132
133 #define INIT_CONTEXT() { CK_RV icret = init_context(); if (icret) return icret; }
134
135 static void
snprintf_fill(char * str,size_t size,char fillchar,const char * fmt,...)136 snprintf_fill(char *str, size_t size, char fillchar, const char *fmt, ...)
137 {
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;
147 }
148
149 #ifndef TEST_APP
150 #define printf error_use_st_logf
151 #endif
152
153 #define VERIFY_SESSION_HANDLE(s, state) \
154 { \
155 CK_RV xret; \
156 xret = verify_session_handle(s, state); \
157 if (xret != CKR_OK) { \
158 /* return CKR_OK */; \
159 } \
160 }
161
162 static CK_RV
verify_session_handle(CK_SESSION_HANDLE hSession,struct session_state ** state)163 verify_session_handle(CK_SESSION_HANDLE hSession,
164 struct session_state **state)
165 {
166 size_t i;
167
168 for (i = 0; i < MAX_NUM_SESSION; i++){
169 if (soft_token.state[i].session_handle == hSession)
170 break;
171 }
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;
176 }
177 if (state)
178 *state = &soft_token.state[i];
179 return CKR_OK;
180 }
181
182 static CK_RV
object_handle_to_object(CK_OBJECT_HANDLE handle,struct st_object ** object)183 object_handle_to_object(CK_OBJECT_HANDLE handle,
184 struct st_object **object)
185 {
186 int i = HANDLE_OBJECT_ID(handle);
187
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;
197 }
198
199 static int
attributes_match(const struct st_object * obj,const CK_ATTRIBUTE * attributes,CK_ULONG num_attributes)200 attributes_match(const struct st_object *obj,
201 const CK_ATTRIBUTE *attributes,
202 CK_ULONG num_attributes)
203 {
204 CK_ULONG i;
205 int j;
206
207 st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj));
208
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;
218 }
219 }
220 if (match == 0) {
221 st_logf("type %d attribute have no match\n", attributes[i].type);
222 return 0;
223 }
224 }
225 st_logf("attribute matches\n");
226 return 1;
227 }
228
229 static void
print_attributes(const CK_ATTRIBUTE * attributes,CK_ULONG num_attributes)230 print_attributes(const CK_ATTRIBUTE *attributes,
231 CK_ULONG num_attributes)
232 {
233 CK_ULONG i;
234
235 st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes);
236
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;
245 }
246 ck_true = attributes[i].pValue;
247 st_logf("token: %s", *ck_true ? "TRUE" : "FALSE");
248 break;
249 }
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;
255 }
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;
277 }
278 break;
279 }
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;
298 }
299 st_logf("\n");
300 }
301 }
302
303 static struct st_object *
add_st_object(void)304 add_st_object(void)
305 {
306 struct st_object *o, **objs;
307 int i;
308
309 o = calloc(1, sizeof(*o));
310 if (o == NULL)
311 return NULL;
312
313 for (i = 0; i < soft_token.object.num_objs; i++) {
314 if (soft_token.object.objs == NULL) {
315 soft_token.object.objs[i] = o;
316 break;
317 }
318 }
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;
325 }
326 soft_token.object.objs = objs;
327 soft_token.object.objs[soft_token.object.num_objs++] = o;
328 }
329 soft_token.object.objs[i]->object_handle =
330 (random() & (~OBJECT_ID_MASK)) | i;
331
332 return o;
333 }
334
335 static CK_RV
add_object_attribute(struct st_object * o,int secret,CK_ATTRIBUTE_TYPE type,CK_VOID_PTR pValue,CK_ULONG ulValueLen)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)
341 {
342 struct st_attr *a;
343 int i;
344
345 if (pValue == NULL && ulValueLen)
346 return CKR_ARGUMENTS_BAD;
347
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++;
362
363 return CKR_OK;
364 }
365
366 static CK_RV
add_pubkey_info(hx509_context hxctx,struct st_object * o,CK_KEY_TYPE key_type,hx509_cert cert)367 add_pubkey_info(hx509_context hxctx, struct st_object *o,
368 CK_KEY_TYPE key_type, hx509_cert cert)
369 {
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;
376
377 if (key_type != CKK_RSA)
378 return CKR_OK;
379 if (_hx509_cert_private_key(cert) == NULL)
380 return CKR_OK;
381
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);
388
389 modulus_len = BN_num_bytes(num);
390 modulus = malloc(modulus_len);
391 BN_bn2bin(num, modulus);
392 BN_free(num);
393
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));
397
398 free(modulus);
399
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;
405
406 exponent_len = BN_num_bytes(num);
407 exponent = malloc(exponent_len);
408 BN_bn2bin(num, exponent);
409 BN_free(num);
410
411 add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT,
412 exponent, exponent_len);
413
414 free(exponent);
415
416 return CKR_OK;
417 }
418
419
420 struct foo {
421 char *label;
422 char *id;
423 };
424
425 static int
add_cert(hx509_context hxctx,void * ctx,hx509_cert cert)426 add_cert(hx509_context hxctx, void *ctx, hx509_cert cert)
427 {
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;
440
441 st_logf("adding certificate\n");
442
443 serial_data.data = NULL;
444 serial_data.length = 0;
445 cert_data = subject_data = issuer_data = serial_data;
446
447 hret = hx509_cert_binary(hxctx, cert, &cert_data);
448 if (hret)
449 goto out;
450
451 {
452 hx509_name name;
453
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;
461
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;
469 }
470
471 {
472 AlgorithmIdentifier alg;
473
474 hret = hx509_cert_get_SPKI_AlgorithmIdentifier(context, cert, &alg);
475 if (hret) {
476 ret = CKR_DEVICE_MEMORY;
477 goto out;
478 }
479
480 key_type = CKK_RSA; /* XXX */
481
482 free_AlgorithmIdentifier(&alg);
483 }
484
485
486 type = CKO_CERTIFICATE;
487 o = add_st_object();
488 if (o == NULL) {
489 ret = CKR_DEVICE_MEMORY;
490 goto out;
491 }
492
493 o->cert = hx509_cert_ref(cert);
494
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));
500
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));
503
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));
509
510 st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o));
511
512 type = CKO_PUBLIC_KEY;
513 o = add_st_object();
514 if (o == NULL) {
515 ret = CKR_DEVICE_MEMORY;
516 goto out;
517 }
518 o->cert = hx509_cert_ref(cert);
519
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));
525
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));
534
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));
541
542 add_pubkey_info(hxctx, o, key_type, cert);
543
544 st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o));
545
546 if (hx509_cert_have_private_key(cert)) {
547 CK_FLAGS flags;
548
549 type = CKO_PRIVATE_KEY;
550 o = add_st_object();
551 if (o == NULL) {
552 ret = CKR_DEVICE_MEMORY;
553 goto out;
554 }
555 o->cert = hx509_cert_ref(cert);
556
557 add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
558 add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
559 add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false));
560 add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
561 add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
562
563 add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
564 add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
565 add_object_attribute(o, 0, CKA_START_DATE, empty, 1); /* XXX */
566 add_object_attribute(o, 0, CKA_END_DATE, empty, 1); /* XXX */
567 add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
568 add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
569 mech_type = CKM_RSA_X_509;
570 add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
571
572 add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
573 add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true));
574 add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true));
575 flags = 0;
576 add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags));
577
578 add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true));
579 add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true));
580 add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false));
581 add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true));
582 add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true));
583 add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false));
584
585 add_pubkey_info(hxctx, o, key_type, cert);
586 }
587
588 ret = CKR_OK;
589 out:
590 if (ret != CKR_OK) {
591 st_logf("something went wrong when adding cert!\n");
592
593 /* XXX wack o */;
594 }
595 hx509_xfree(cert_data.data);
596 hx509_xfree(serial_data.data);
597 hx509_xfree(issuer_data.data);
598 hx509_xfree(subject_data.data);
599
600 return 0;
601 }
602
603 static CK_RV
add_certificate(const char * cert_file,const char * pin,char * id,char * label)604 add_certificate(const char *cert_file,
605 const char *pin,
606 char *id,
607 char *label)
608 {
609 hx509_certs certs;
610 hx509_lock lock = NULL;
611 int ret, flags = 0;
612
613 struct foo foo;
614 foo.id = id;
615 foo.label = label;
616
617 if (pin == NULL)
618 flags |= HX509_CERTS_UNPROTECT_ALL;
619
620 if (pin) {
621 char *str;
622 asprintf(&str, "PASS:%s", pin);
623
624 hx509_lock_init(context, &lock);
625 hx509_lock_command_string(lock, str);
626
627 memset(str, 0, strlen(str));
628 free(str);
629 }
630
631 ret = hx509_certs_init(context, cert_file, flags, lock, &certs);
632 if (ret) {
633 st_logf("failed to open file %s\n", cert_file);
634 return CKR_GENERAL_ERROR;
635 }
636
637 ret = hx509_certs_iter_f(context, certs, add_cert, &foo);
638 hx509_certs_free(&certs);
639 if (ret) {
640 st_logf("failed adding certs from file %s\n", cert_file);
641 return CKR_GENERAL_ERROR;
642 }
643
644 return CKR_OK;
645 }
646
647 static void
find_object_final(struct session_state * state)648 find_object_final(struct session_state *state)
649 {
650 if (state->find.attributes) {
651 CK_ULONG i;
652
653 for (i = 0; i < state->find.num_attributes; i++) {
654 if (state->find.attributes[i].pValue)
655 free(state->find.attributes[i].pValue);
656 }
657 free(state->find.attributes);
658 state->find.attributes = NULL;
659 state->find.num_attributes = 0;
660 state->find.next_object = -1;
661 }
662 }
663
664 static void
reset_crypto_state(struct session_state * state)665 reset_crypto_state(struct session_state *state)
666 {
667 state->sign_object = -1;
668 if (state->sign_mechanism)
669 free(state->sign_mechanism);
670 state->sign_mechanism = NULL_PTR;
671 state->verify_object = -1;
672 if (state->verify_mechanism)
673 free(state->verify_mechanism);
674 state->verify_mechanism = NULL_PTR;
675 }
676
677 static void
close_session(struct session_state * state)678 close_session(struct session_state *state)
679 {
680 if (state->find.attributes) {
681 application_error("application didn't do C_FindObjectsFinal\n");
682 find_object_final(state);
683 }
684
685 state->session_handle = CK_INVALID_HANDLE;
686 soft_token.application = NULL_PTR;
687 soft_token.notify = NULL_PTR;
688 reset_crypto_state(state);
689 }
690
691 static const char *
has_session(void)692 has_session(void)
693 {
694 return soft_token.open_sessions > 0 ? "yes" : "no";
695 }
696
697 static CK_RV
read_conf_file(const char * fn,CK_USER_TYPE userType,const char * pin)698 read_conf_file(const char *fn, CK_USER_TYPE userType, const char *pin)
699 {
700 char buf[1024], *type, *s, *p;
701 FILE *f;
702 CK_RV ret = CKR_OK;
703 CK_RV failed = CKR_OK;
704
705 if (fn == NULL) {
706 st_logf("Can't open configuration file. No file specified\n");
707 return CKR_GENERAL_ERROR;
708 }
709
710 f = fopen(fn, "r");
711 if (f == NULL) {
712 st_logf("can't open configuration file %s\n", fn);
713 return CKR_GENERAL_ERROR;
714 }
715 rk_cloexec_file(f);
716
717 while(fgets(buf, sizeof(buf), f) != NULL) {
718 buf[strcspn(buf, "\n")] = '\0';
719
720 st_logf("line: %s\n", buf);
721
722 p = buf;
723 while (isspace((unsigned char)*p))
724 p++;
725 if (*p == '#')
726 continue;
727 while (isspace((unsigned char)*p))
728 p++;
729
730 s = NULL;
731 type = strtok_r(p, "\t", &s);
732 if (type == NULL)
733 continue;
734
735 if (strcasecmp("certificate", type) == 0) {
736 char *cert, *id, *label;
737
738 id = strtok_r(NULL, "\t", &s);
739 if (id == NULL) {
740 st_logf("no id\n");
741 continue;
742 }
743 st_logf("id: %s\n", id);
744 label = strtok_r(NULL, "\t", &s);
745 if (label == NULL) {
746 st_logf("no label\n");
747 continue;
748 }
749 cert = strtok_r(NULL, "\t", &s);
750 if (cert == NULL) {
751 st_logf("no certfiicate store\n");
752 continue;
753 }
754
755 st_logf("adding: %s: %s in file %s\n", id, label, cert);
756
757 ret = add_certificate(cert, pin, id, label);
758 if (ret)
759 failed = ret;
760 } else if (strcasecmp("debug", type) == 0) {
761 char *name;
762
763 name = strtok_r(NULL, "\t", &s);
764 if (name == NULL) {
765 st_logf("no filename\n");
766 continue;
767 }
768
769 if (soft_token.logfile)
770 fclose(soft_token.logfile);
771
772 if (strcasecmp(name, "stdout") == 0)
773 soft_token.logfile = stdout;
774 else {
775 soft_token.logfile = fopen(name, "a");
776 if (soft_token.logfile)
777 rk_cloexec_file(soft_token.logfile);
778 }
779 if (soft_token.logfile == NULL)
780 st_logf("failed to open file: %s\n", name);
781
782 } else if (strcasecmp("app-fatal", type) == 0) {
783 char *name;
784
785 name = strtok_r(NULL, "\t", &s);
786 if (name == NULL) {
787 st_logf("argument to app-fatal\n");
788 continue;
789 }
790
791 if (strcmp(name, "true") == 0 || strcmp(name, "on") == 0)
792 soft_token.flags.app_error_fatal = 1;
793 else if (strcmp(name, "false") == 0 || strcmp(name, "off") == 0)
794 soft_token.flags.app_error_fatal = 0;
795 else
796 st_logf("unknown app-fatal: %s\n", name);
797
798 } else {
799 st_logf("unknown type: %s\n", type);
800 }
801 }
802
803 fclose(f);
804
805 return failed;
806 }
807
808 static CK_RV
func_not_supported(void)809 func_not_supported(void)
810 {
811 st_logf("function not supported\n");
812 return CKR_FUNCTION_NOT_SUPPORTED;
813 }
814
815 static char *
get_config_file_for_user(void)816 get_config_file_for_user(void)
817 {
818 char *fn = NULL;
819
820 #ifndef _WIN32
821 char *home = NULL;
822
823 if (!issuid()) {
824 fn = getenv("SOFTPKCS11RC");
825 if (fn)
826 fn = strdup(fn);
827 home = getenv("HOME");
828 }
829 if (fn == NULL && home == NULL) {
830 struct passwd *pw = getpwuid(getuid());
831 if(pw != NULL)
832 home = pw->pw_dir;
833 }
834 if (fn == NULL) {
835 if (home)
836 asprintf(&fn, "%s/.soft-token.rc", home);
837 else
838 fn = strdup("/etc/soft-token.rc");
839 }
840 #else /* Windows */
841
842 char appdatafolder[MAX_PATH];
843
844 fn = getenv("SOFTPKCS11RC");
845
846 /* Retrieve the roaming AppData folder for the current user. The
847 current user is the user account represented by the current
848 thread token. */
849
850 if (fn == NULL &&
851 SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, appdatafolder))) {
852
853 asprintf(&fn, "%s\\.soft-token.rc", appdatafolder);
854 }
855
856 #endif /* _WIN32 */
857
858 return fn;
859 }
860
861
862 CK_RV CK_SPEC
C_Initialize(CK_VOID_PTR a)863 C_Initialize(CK_VOID_PTR a)
864 {
865 CK_C_INITIALIZE_ARGS_PTR args = a;
866 CK_RV ret;
867 size_t i;
868
869 st_logf("Initialize\n");
870
871 INIT_CONTEXT();
872
873 OpenSSL_add_all_algorithms();
874
875 srandom(getpid() ^ (int) time(NULL));
876
877 for (i = 0; i < MAX_NUM_SESSION; i++) {
878 soft_token.state[i].session_handle = CK_INVALID_HANDLE;
879 soft_token.state[i].find.attributes = NULL;
880 soft_token.state[i].find.num_attributes = 0;
881 soft_token.state[i].find.next_object = -1;
882 reset_crypto_state(&soft_token.state[i]);
883 }
884
885 soft_token.flags.hardware_slot = 1;
886 soft_token.flags.app_error_fatal = 0;
887 soft_token.flags.login_done = 0;
888
889 soft_token.object.objs = NULL;
890 soft_token.object.num_objs = 0;
891
892 soft_token.logfile = NULL;
893 #if 0
894 soft_token.logfile = stdout;
895 #endif
896 #if 0
897 soft_token.logfile = fopen("/tmp/log-pkcs11.txt", "a");
898 #endif
899
900 if (a != NULL_PTR) {
901 st_logf("\tCreateMutex:\t%p\n", args->CreateMutex);
902 st_logf("\tDestroyMutext\t%p\n", args->DestroyMutex);
903 st_logf("\tLockMutext\t%p\n", args->LockMutex);
904 st_logf("\tUnlockMutext\t%p\n", args->UnlockMutex);
905 st_logf("\tFlags\t%04x\n", (unsigned int)args->flags);
906 }
907
908 soft_token.config_file = get_config_file_for_user();
909
910 /*
911 * This operations doesn't return CKR_OK if any of the
912 * certificates failes to be unparsed (ie password protected).
913 */
914 ret = read_conf_file(soft_token.config_file, CKU_USER, NULL);
915 if (ret == CKR_OK)
916 soft_token.flags.login_done = 1;
917
918 return CKR_OK;
919 }
920
921 CK_RV
C_Finalize(CK_VOID_PTR args)922 C_Finalize(CK_VOID_PTR args)
923 {
924 size_t i;
925
926 INIT_CONTEXT();
927
928 st_logf("Finalize\n");
929
930 for (i = 0; i < MAX_NUM_SESSION; i++) {
931 if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) {
932 application_error("application finalized without "
933 "closing session\n");
934 close_session(&soft_token.state[i]);
935 }
936 }
937
938 return CKR_OK;
939 }
940
941 CK_RV
C_GetInfo(CK_INFO_PTR args)942 C_GetInfo(CK_INFO_PTR args)
943 {
944 INIT_CONTEXT();
945
946 st_logf("GetInfo\n");
947
948 memset(args, 17, sizeof(*args));
949 args->cryptokiVersion.major = 2;
950 args->cryptokiVersion.minor = 10;
951 snprintf_fill((char *)args->manufacturerID,
952 sizeof(args->manufacturerID),
953 ' ',
954 "Heimdal hx509 SoftToken");
955 snprintf_fill((char *)args->libraryDescription,
956 sizeof(args->libraryDescription), ' ',
957 "Heimdal hx509 SoftToken");
958 args->libraryVersion.major = 2;
959 args->libraryVersion.minor = 0;
960
961 return CKR_OK;
962 }
963
964 extern CK_FUNCTION_LIST funcs;
965
966 CK_RV
C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)967 C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
968 {
969 INIT_CONTEXT();
970
971 *ppFunctionList = &funcs;
972 return CKR_OK;
973 }
974
975 CK_RV
C_GetSlotList(CK_BBOOL tokenPresent,CK_SLOT_ID_PTR pSlotList,CK_ULONG_PTR pulCount)976 C_GetSlotList(CK_BBOOL tokenPresent,
977 CK_SLOT_ID_PTR pSlotList,
978 CK_ULONG_PTR pulCount)
979 {
980 INIT_CONTEXT();
981 st_logf("GetSlotList: %s\n",
982 tokenPresent ? "tokenPresent" : "token not Present");
983 if (pSlotList)
984 pSlotList[0] = 1;
985 *pulCount = 1;
986 return CKR_OK;
987 }
988
989 CK_RV
C_GetSlotInfo(CK_SLOT_ID slotID,CK_SLOT_INFO_PTR pInfo)990 C_GetSlotInfo(CK_SLOT_ID slotID,
991 CK_SLOT_INFO_PTR pInfo)
992 {
993 INIT_CONTEXT();
994 st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID, has_session());
995
996 memset(pInfo, 18, sizeof(*pInfo));
997
998 if (slotID != 1)
999 return CKR_ARGUMENTS_BAD;
1000
1001 snprintf_fill((char *)pInfo->slotDescription,
1002 sizeof(pInfo->slotDescription),
1003 ' ',
1004 "Heimdal hx509 SoftToken (slot)");
1005 snprintf_fill((char *)pInfo->manufacturerID,
1006 sizeof(pInfo->manufacturerID),
1007 ' ',
1008 "Heimdal hx509 SoftToken (slot)");
1009 pInfo->flags = CKF_TOKEN_PRESENT;
1010 if (soft_token.flags.hardware_slot)
1011 pInfo->flags |= CKF_HW_SLOT;
1012 pInfo->hardwareVersion.major = 1;
1013 pInfo->hardwareVersion.minor = 0;
1014 pInfo->firmwareVersion.major = 1;
1015 pInfo->firmwareVersion.minor = 0;
1016
1017 return CKR_OK;
1018 }
1019
1020 CK_RV
C_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)1021 C_GetTokenInfo(CK_SLOT_ID slotID,
1022 CK_TOKEN_INFO_PTR pInfo)
1023 {
1024 INIT_CONTEXT();
1025 st_logf("GetTokenInfo: %s\n", has_session());
1026
1027 memset(pInfo, 19, sizeof(*pInfo));
1028
1029 snprintf_fill((char *)pInfo->label,
1030 sizeof(pInfo->label),
1031 ' ',
1032 "Heimdal hx509 SoftToken (token)");
1033 snprintf_fill((char *)pInfo->manufacturerID,
1034 sizeof(pInfo->manufacturerID),
1035 ' ',
1036 "Heimdal hx509 SoftToken (token)");
1037 snprintf_fill((char *)pInfo->model,
1038 sizeof(pInfo->model),
1039 ' ',
1040 "Heimdal hx509 SoftToken (token)");
1041 snprintf_fill((char *)pInfo->serialNumber,
1042 sizeof(pInfo->serialNumber),
1043 ' ',
1044 "4711");
1045 pInfo->flags =
1046 CKF_TOKEN_INITIALIZED |
1047 CKF_USER_PIN_INITIALIZED;
1048
1049 if (soft_token.flags.login_done == 0)
1050 pInfo->flags |= CKF_LOGIN_REQUIRED;
1051
1052 /* CFK_RNG |
1053 CKF_RESTORE_KEY_NOT_NEEDED |
1054 */
1055 pInfo->ulMaxSessionCount = MAX_NUM_SESSION;
1056 pInfo->ulSessionCount = soft_token.open_sessions;
1057 pInfo->ulMaxRwSessionCount = MAX_NUM_SESSION;
1058 pInfo->ulRwSessionCount = soft_token.open_sessions;
1059 pInfo->ulMaxPinLen = 1024;
1060 pInfo->ulMinPinLen = 0;
1061 pInfo->ulTotalPublicMemory = 4711;
1062 pInfo->ulFreePublicMemory = 4712;
1063 pInfo->ulTotalPrivateMemory = 4713;
1064 pInfo->ulFreePrivateMemory = 4714;
1065 pInfo->hardwareVersion.major = 2;
1066 pInfo->hardwareVersion.minor = 0;
1067 pInfo->firmwareVersion.major = 2;
1068 pInfo->firmwareVersion.minor = 0;
1069
1070 return CKR_OK;
1071 }
1072
1073 CK_RV
C_GetMechanismList(CK_SLOT_ID slotID,CK_MECHANISM_TYPE_PTR pMechanismList,CK_ULONG_PTR pulCount)1074 C_GetMechanismList(CK_SLOT_ID slotID,
1075 CK_MECHANISM_TYPE_PTR pMechanismList,
1076 CK_ULONG_PTR pulCount)
1077 {
1078 INIT_CONTEXT();
1079 st_logf("GetMechanismList\n");
1080
1081 *pulCount = 1;
1082 if (pMechanismList == NULL_PTR)
1083 return CKR_OK;
1084 pMechanismList[1] = CKM_RSA_PKCS;
1085
1086 return CKR_OK;
1087 }
1088
1089 CK_RV
C_GetMechanismInfo(CK_SLOT_ID slotID,CK_MECHANISM_TYPE type,CK_MECHANISM_INFO_PTR pInfo)1090 C_GetMechanismInfo(CK_SLOT_ID slotID,
1091 CK_MECHANISM_TYPE type,
1092 CK_MECHANISM_INFO_PTR pInfo)
1093 {
1094 INIT_CONTEXT();
1095 st_logf("GetMechanismInfo: slot %d type: %d\n",
1096 (int)slotID, (int)type);
1097 memset(pInfo, 0, sizeof(*pInfo));
1098
1099 return CKR_OK;
1100 }
1101
1102 CK_RV
C_InitToken(CK_SLOT_ID slotID,CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen,CK_UTF8CHAR_PTR pLabel)1103 C_InitToken(CK_SLOT_ID slotID,
1104 CK_UTF8CHAR_PTR pPin,
1105 CK_ULONG ulPinLen,
1106 CK_UTF8CHAR_PTR pLabel)
1107 {
1108 INIT_CONTEXT();
1109 st_logf("InitToken: slot %d\n", (int)slotID);
1110 return CKR_FUNCTION_NOT_SUPPORTED;
1111 }
1112
1113 CK_RV
C_OpenSession(CK_SLOT_ID slotID,CK_FLAGS flags,CK_VOID_PTR pApplication,CK_NOTIFY Notify,CK_SESSION_HANDLE_PTR phSession)1114 C_OpenSession(CK_SLOT_ID slotID,
1115 CK_FLAGS flags,
1116 CK_VOID_PTR pApplication,
1117 CK_NOTIFY Notify,
1118 CK_SESSION_HANDLE_PTR phSession)
1119 {
1120 size_t i;
1121 INIT_CONTEXT();
1122 st_logf("OpenSession: slot: %d\n", (int)slotID);
1123
1124 if (soft_token.open_sessions == MAX_NUM_SESSION)
1125 return CKR_SESSION_COUNT;
1126
1127 soft_token.application = pApplication;
1128 soft_token.notify = Notify;
1129
1130 for (i = 0; i < MAX_NUM_SESSION; i++)
1131 if (soft_token.state[i].session_handle == CK_INVALID_HANDLE)
1132 break;
1133 if (i == MAX_NUM_SESSION)
1134 abort();
1135
1136 soft_token.open_sessions++;
1137
1138 soft_token.state[i].session_handle =
1139 (CK_SESSION_HANDLE)(random() & 0xfffff);
1140 *phSession = soft_token.state[i].session_handle;
1141
1142 return CKR_OK;
1143 }
1144
1145 CK_RV
C_CloseSession(CK_SESSION_HANDLE hSession)1146 C_CloseSession(CK_SESSION_HANDLE hSession)
1147 {
1148 struct session_state *state;
1149 INIT_CONTEXT();
1150 st_logf("CloseSession\n");
1151
1152 if (verify_session_handle(hSession, &state) != CKR_OK)
1153 application_error("closed session not open");
1154 else
1155 close_session(state);
1156
1157 return CKR_OK;
1158 }
1159
1160 CK_RV
C_CloseAllSessions(CK_SLOT_ID slotID)1161 C_CloseAllSessions(CK_SLOT_ID slotID)
1162 {
1163 size_t i;
1164 INIT_CONTEXT();
1165
1166 st_logf("CloseAllSessions\n");
1167
1168 for (i = 0; i < MAX_NUM_SESSION; i++)
1169 if (soft_token.state[i].session_handle != CK_INVALID_HANDLE)
1170 close_session(&soft_token.state[i]);
1171
1172 return CKR_OK;
1173 }
1174
1175 CK_RV
C_GetSessionInfo(CK_SESSION_HANDLE hSession,CK_SESSION_INFO_PTR pInfo)1176 C_GetSessionInfo(CK_SESSION_HANDLE hSession,
1177 CK_SESSION_INFO_PTR pInfo)
1178 {
1179 st_logf("GetSessionInfo\n");
1180 INIT_CONTEXT();
1181
1182 VERIFY_SESSION_HANDLE(hSession, NULL);
1183
1184 memset(pInfo, 20, sizeof(*pInfo));
1185
1186 pInfo->slotID = 1;
1187 if (soft_token.flags.login_done)
1188 pInfo->state = CKS_RO_USER_FUNCTIONS;
1189 else
1190 pInfo->state = CKS_RO_PUBLIC_SESSION;
1191 pInfo->flags = CKF_SERIAL_SESSION;
1192 pInfo->ulDeviceError = 0;
1193
1194 return CKR_OK;
1195 }
1196
1197 CK_RV
C_Login(CK_SESSION_HANDLE hSession,CK_USER_TYPE userType,CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen)1198 C_Login(CK_SESSION_HANDLE hSession,
1199 CK_USER_TYPE userType,
1200 CK_UTF8CHAR_PTR pPin,
1201 CK_ULONG ulPinLen)
1202 {
1203 char *pin = NULL;
1204 CK_RV ret;
1205 INIT_CONTEXT();
1206
1207 st_logf("Login\n");
1208
1209 VERIFY_SESSION_HANDLE(hSession, NULL);
1210
1211 if (pPin != NULL_PTR) {
1212 asprintf(&pin, "%.*s", (int)ulPinLen, pPin);
1213 st_logf("type: %d password: %s\n", (int)userType, pin);
1214 }
1215
1216 /*
1217 * Login
1218 */
1219
1220 ret = read_conf_file(soft_token.config_file, userType, pin);
1221 if (ret == CKR_OK)
1222 soft_token.flags.login_done = 1;
1223
1224 free(pin);
1225
1226 return soft_token.flags.login_done ? CKR_OK : CKR_PIN_INCORRECT;
1227 }
1228
1229 CK_RV
C_Logout(CK_SESSION_HANDLE hSession)1230 C_Logout(CK_SESSION_HANDLE hSession)
1231 {
1232 st_logf("Logout\n");
1233 INIT_CONTEXT();
1234
1235 VERIFY_SESSION_HANDLE(hSession, NULL);
1236 return CKR_FUNCTION_NOT_SUPPORTED;
1237 }
1238
1239 CK_RV
C_GetObjectSize(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ULONG_PTR pulSize)1240 C_GetObjectSize(CK_SESSION_HANDLE hSession,
1241 CK_OBJECT_HANDLE hObject,
1242 CK_ULONG_PTR pulSize)
1243 {
1244 st_logf("GetObjectSize\n");
1245 INIT_CONTEXT();
1246
1247 VERIFY_SESSION_HANDLE(hSession, NULL);
1248 return CKR_FUNCTION_NOT_SUPPORTED;
1249 }
1250
1251 CK_RV
C_GetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)1252 C_GetAttributeValue(CK_SESSION_HANDLE hSession,
1253 CK_OBJECT_HANDLE hObject,
1254 CK_ATTRIBUTE_PTR pTemplate,
1255 CK_ULONG ulCount)
1256 {
1257 struct session_state *state;
1258 struct st_object *obj;
1259 CK_ULONG i;
1260 CK_RV ret;
1261 int j;
1262
1263 INIT_CONTEXT();
1264
1265 st_logf("GetAttributeValue: %lx\n",
1266 (unsigned long)HANDLE_OBJECT_ID(hObject));
1267 VERIFY_SESSION_HANDLE(hSession, &state);
1268
1269 if ((ret = object_handle_to_object(hObject, &obj)) != CKR_OK) {
1270 st_logf("object not found: %lx\n",
1271 (unsigned long)HANDLE_OBJECT_ID(hObject));
1272 return ret;
1273 }
1274
1275 for (i = 0; i < ulCount; i++) {
1276 st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate[i].type);
1277 for (j = 0; j < obj->num_attributes; j++) {
1278 if (obj->attrs[j].secret) {
1279 pTemplate[i].ulValueLen = (CK_ULONG)-1;
1280 break;
1281 }
1282 if (pTemplate[i].type == obj->attrs[j].attribute.type) {
1283 if (pTemplate[i].pValue != NULL_PTR && obj->attrs[j].secret == 0) {
1284 if (pTemplate[i].ulValueLen >= obj->attrs[j].attribute.ulValueLen)
1285 memcpy(pTemplate[i].pValue, obj->attrs[j].attribute.pValue,
1286 obj->attrs[j].attribute.ulValueLen);
1287 }
1288 pTemplate[i].ulValueLen = obj->attrs[j].attribute.ulValueLen;
1289 break;
1290 }
1291 }
1292 if (j == obj->num_attributes) {
1293 st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate[i].type);
1294 pTemplate[i].ulValueLen = (CK_ULONG)-1;
1295 }
1296
1297 }
1298 return CKR_OK;
1299 }
1300
1301 CK_RV
C_FindObjectsInit(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)1302 C_FindObjectsInit(CK_SESSION_HANDLE hSession,
1303 CK_ATTRIBUTE_PTR pTemplate,
1304 CK_ULONG ulCount)
1305 {
1306 struct session_state *state;
1307
1308 st_logf("FindObjectsInit\n");
1309
1310 INIT_CONTEXT();
1311
1312 VERIFY_SESSION_HANDLE(hSession, &state);
1313
1314 if (state->find.next_object != -1) {
1315 application_error("application didn't do C_FindObjectsFinal\n");
1316 find_object_final(state);
1317 }
1318 if (ulCount) {
1319 CK_ULONG i;
1320
1321 print_attributes(pTemplate, ulCount);
1322
1323 state->find.attributes =
1324 calloc(1, ulCount * sizeof(state->find.attributes[0]));
1325 if (state->find.attributes == NULL)
1326 return CKR_DEVICE_MEMORY;
1327 for (i = 0; i < ulCount; i++) {
1328 state->find.attributes[i].pValue =
1329 malloc(pTemplate[i].ulValueLen);
1330 if (state->find.attributes[i].pValue == NULL) {
1331 find_object_final(state);
1332 return CKR_DEVICE_MEMORY;
1333 }
1334 memcpy(state->find.attributes[i].pValue,
1335 pTemplate[i].pValue, pTemplate[i].ulValueLen);
1336 state->find.attributes[i].type = pTemplate[i].type;
1337 state->find.attributes[i].ulValueLen = pTemplate[i].ulValueLen;
1338 }
1339 state->find.num_attributes = ulCount;
1340 state->find.next_object = 0;
1341 } else {
1342 st_logf("find all objects\n");
1343 state->find.attributes = NULL;
1344 state->find.num_attributes = 0;
1345 state->find.next_object = 0;
1346 }
1347
1348 return CKR_OK;
1349 }
1350
1351 CK_RV
C_FindObjects(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE_PTR phObject,CK_ULONG ulMaxObjectCount,CK_ULONG_PTR pulObjectCount)1352 C_FindObjects(CK_SESSION_HANDLE hSession,
1353 CK_OBJECT_HANDLE_PTR phObject,
1354 CK_ULONG ulMaxObjectCount,
1355 CK_ULONG_PTR pulObjectCount)
1356 {
1357 struct session_state *state;
1358 int i;
1359
1360 INIT_CONTEXT();
1361
1362 st_logf("FindObjects\n");
1363
1364 VERIFY_SESSION_HANDLE(hSession, &state);
1365
1366 if (state->find.next_object == -1) {
1367 application_error("application didn't do C_FindObjectsInit\n");
1368 return CKR_ARGUMENTS_BAD;
1369 }
1370 if (ulMaxObjectCount == 0) {
1371 application_error("application asked for 0 objects\n");
1372 return CKR_ARGUMENTS_BAD;
1373 }
1374 *pulObjectCount = 0;
1375 for (i = state->find.next_object; i < soft_token.object.num_objs; i++) {
1376 st_logf("FindObjects: %d\n", i);
1377 state->find.next_object = i + 1;
1378 if (attributes_match(soft_token.object.objs[i],
1379 state->find.attributes,
1380 state->find.num_attributes)) {
1381 *phObject++ = soft_token.object.objs[i]->object_handle;
1382 ulMaxObjectCount--;
1383 (*pulObjectCount)++;
1384 if (ulMaxObjectCount == 0)
1385 break;
1386 }
1387 }
1388 return CKR_OK;
1389 }
1390
1391 CK_RV
C_FindObjectsFinal(CK_SESSION_HANDLE hSession)1392 C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
1393 {
1394 struct session_state *state;
1395
1396 INIT_CONTEXT();
1397
1398 st_logf("FindObjectsFinal\n");
1399 VERIFY_SESSION_HANDLE(hSession, &state);
1400 find_object_final(state);
1401 return CKR_OK;
1402 }
1403
1404 static CK_RV
commonInit(CK_ATTRIBUTE * attr_match,int attr_match_len,const CK_MECHANISM_TYPE * mechs,int mechs_len,const CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey,struct st_object ** o)1405 commonInit(CK_ATTRIBUTE *attr_match, int attr_match_len,
1406 const CK_MECHANISM_TYPE *mechs, int mechs_len,
1407 const CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey,
1408 struct st_object **o)
1409 {
1410 CK_RV ret;
1411 int i;
1412
1413 *o = NULL;
1414 if ((ret = object_handle_to_object(hKey, o)) != CKR_OK)
1415 return ret;
1416
1417 ret = attributes_match(*o, attr_match, attr_match_len);
1418 if (!ret) {
1419 application_error("called commonInit on key that doesn't "
1420 "support required attr");
1421 return CKR_ARGUMENTS_BAD;
1422 }
1423
1424 for (i = 0; i < mechs_len; i++)
1425 if (mechs[i] == pMechanism->mechanism)
1426 break;
1427 if (i == mechs_len) {
1428 application_error("called mech (%08lx) not supported\n",
1429 pMechanism->mechanism);
1430 return CKR_ARGUMENTS_BAD;
1431 }
1432 return CKR_OK;
1433 }
1434
1435
1436 static CK_RV
dup_mechanism(CK_MECHANISM_PTR * dp,const CK_MECHANISM_PTR pMechanism)1437 dup_mechanism(CK_MECHANISM_PTR *dp, const CK_MECHANISM_PTR pMechanism)
1438 {
1439 CK_MECHANISM_PTR p;
1440
1441 p = malloc(sizeof(*p));
1442 if (p == NULL)
1443 return CKR_DEVICE_MEMORY;
1444
1445 if (*dp)
1446 free(*dp);
1447 *dp = p;
1448 memcpy(p, pMechanism, sizeof(*p));
1449
1450 return CKR_OK;
1451 }
1452
1453 CK_RV
C_DigestInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism)1454 C_DigestInit(CK_SESSION_HANDLE hSession,
1455 CK_MECHANISM_PTR pMechanism)
1456 {
1457 st_logf("DigestInit\n");
1458 INIT_CONTEXT();
1459 VERIFY_SESSION_HANDLE(hSession, NULL);
1460 return CKR_FUNCTION_NOT_SUPPORTED;
1461 }
1462
1463 CK_RV
C_SignInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)1464 C_SignInit(CK_SESSION_HANDLE hSession,
1465 CK_MECHANISM_PTR pMechanism,
1466 CK_OBJECT_HANDLE hKey)
1467 {
1468 struct session_state *state;
1469 CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS };
1470 CK_BBOOL bool_true = CK_TRUE;
1471 CK_ATTRIBUTE attr[] = {
1472 { CKA_SIGN, &bool_true, sizeof(bool_true) }
1473 };
1474 struct st_object *o;
1475 CK_RV ret;
1476
1477 INIT_CONTEXT();
1478 st_logf("SignInit\n");
1479 VERIFY_SESSION_HANDLE(hSession, &state);
1480
1481 ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1482 mechs, sizeof(mechs)/sizeof(mechs[0]),
1483 pMechanism, hKey, &o);
1484 if (ret)
1485 return ret;
1486
1487 ret = dup_mechanism(&state->sign_mechanism, pMechanism);
1488 if (ret == CKR_OK)
1489 state->sign_object = OBJECT_ID(o);
1490
1491 return CKR_OK;
1492 }
1493
1494 CK_RV
C_Sign(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen)1495 C_Sign(CK_SESSION_HANDLE hSession,
1496 CK_BYTE_PTR pData,
1497 CK_ULONG ulDataLen,
1498 CK_BYTE_PTR pSignature,
1499 CK_ULONG_PTR pulSignatureLen)
1500 {
1501 struct session_state *state;
1502 struct st_object *o;
1503 CK_RV ret;
1504 int hret;
1505 const AlgorithmIdentifier *alg;
1506 heim_octet_string sig, data;
1507
1508 INIT_CONTEXT();
1509 st_logf("Sign\n");
1510 VERIFY_SESSION_HANDLE(hSession, &state);
1511
1512 sig.data = NULL;
1513 sig.length = 0;
1514
1515 if (state->sign_object == -1)
1516 return CKR_ARGUMENTS_BAD;
1517
1518 if (pulSignatureLen == NULL) {
1519 st_logf("signature len NULL\n");
1520 ret = CKR_ARGUMENTS_BAD;
1521 goto out;
1522 }
1523
1524 if (pData == NULL_PTR) {
1525 st_logf("data NULL\n");
1526 ret = CKR_ARGUMENTS_BAD;
1527 goto out;
1528 }
1529
1530 o = soft_token.object.objs[state->sign_object];
1531
1532 if (hx509_cert_have_private_key(o->cert) == 0) {
1533 st_logf("private key NULL\n");
1534 return CKR_ARGUMENTS_BAD;
1535 }
1536
1537 switch(state->sign_mechanism->mechanism) {
1538 case CKM_RSA_PKCS:
1539 alg = hx509_signature_rsa_pkcs1_x509();
1540 break;
1541 default:
1542 ret = CKR_FUNCTION_NOT_SUPPORTED;
1543 goto out;
1544 }
1545
1546 data.data = pData;
1547 data.length = ulDataLen;
1548
1549 hret = _hx509_create_signature(context,
1550 _hx509_cert_private_key(o->cert),
1551 alg,
1552 &data,
1553 NULL,
1554 &sig);
1555 if (hret) {
1556 ret = CKR_DEVICE_ERROR;
1557 goto out;
1558 }
1559 *pulSignatureLen = sig.length;
1560
1561 if (pSignature != NULL_PTR)
1562 memcpy(pSignature, sig.data, sig.length);
1563
1564 ret = CKR_OK;
1565 out:
1566 if (sig.data) {
1567 memset(sig.data, 0, sig.length);
1568 der_free_octet_string(&sig);
1569 }
1570 return ret;
1571 }
1572
1573 CK_RV
C_SignUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)1574 C_SignUpdate(CK_SESSION_HANDLE hSession,
1575 CK_BYTE_PTR pPart,
1576 CK_ULONG ulPartLen)
1577 {
1578 INIT_CONTEXT();
1579 st_logf("SignUpdate\n");
1580 VERIFY_SESSION_HANDLE(hSession, NULL);
1581 return CKR_FUNCTION_NOT_SUPPORTED;
1582 }
1583
1584
1585 CK_RV
C_SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen)1586 C_SignFinal(CK_SESSION_HANDLE hSession,
1587 CK_BYTE_PTR pSignature,
1588 CK_ULONG_PTR pulSignatureLen)
1589 {
1590 INIT_CONTEXT();
1591 st_logf("SignUpdate\n");
1592 VERIFY_SESSION_HANDLE(hSession, NULL);
1593 return CKR_FUNCTION_NOT_SUPPORTED;
1594 }
1595
1596 CK_RV
C_VerifyInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)1597 C_VerifyInit(CK_SESSION_HANDLE hSession,
1598 CK_MECHANISM_PTR pMechanism,
1599 CK_OBJECT_HANDLE hKey)
1600 {
1601 struct session_state *state;
1602 CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS };
1603 CK_BBOOL bool_true = CK_TRUE;
1604 CK_ATTRIBUTE attr[] = {
1605 { CKA_VERIFY, &bool_true, sizeof(bool_true) }
1606 };
1607 struct st_object *o;
1608 CK_RV ret;
1609
1610 INIT_CONTEXT();
1611 st_logf("VerifyInit\n");
1612 VERIFY_SESSION_HANDLE(hSession, &state);
1613
1614 ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1615 mechs, sizeof(mechs)/sizeof(mechs[0]),
1616 pMechanism, hKey, &o);
1617 if (ret)
1618 return ret;
1619
1620 ret = dup_mechanism(&state->verify_mechanism, pMechanism);
1621 if (ret == CKR_OK)
1622 state->verify_object = OBJECT_ID(o);
1623
1624 return ret;
1625 }
1626
1627 CK_RV
C_Verify(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)1628 C_Verify(CK_SESSION_HANDLE hSession,
1629 CK_BYTE_PTR pData,
1630 CK_ULONG ulDataLen,
1631 CK_BYTE_PTR pSignature,
1632 CK_ULONG ulSignatureLen)
1633 {
1634 struct session_state *state;
1635 struct st_object *o;
1636 const AlgorithmIdentifier *alg;
1637 CK_RV ret;
1638 int hret;
1639 heim_octet_string data, sig;
1640
1641 INIT_CONTEXT();
1642 st_logf("Verify\n");
1643 VERIFY_SESSION_HANDLE(hSession, &state);
1644
1645 if (state->verify_object == -1)
1646 return CKR_ARGUMENTS_BAD;
1647
1648 o = soft_token.object.objs[state->verify_object];
1649
1650 switch(state->verify_mechanism->mechanism) {
1651 case CKM_RSA_PKCS:
1652 alg = hx509_signature_rsa_pkcs1_x509();
1653 break;
1654 default:
1655 ret = CKR_FUNCTION_NOT_SUPPORTED;
1656 goto out;
1657 }
1658
1659 sig.data = pData;
1660 sig.length = ulDataLen;
1661 data.data = pSignature;
1662 data.length = ulSignatureLen;
1663
1664 hret = _hx509_verify_signature(context,
1665 o->cert,
1666 alg,
1667 &data,
1668 &sig);
1669 if (hret) {
1670 ret = CKR_GENERAL_ERROR;
1671 goto out;
1672 }
1673 ret = CKR_OK;
1674
1675 out:
1676 return ret;
1677 }
1678
1679
1680 CK_RV
C_VerifyUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)1681 C_VerifyUpdate(CK_SESSION_HANDLE hSession,
1682 CK_BYTE_PTR pPart,
1683 CK_ULONG ulPartLen)
1684 {
1685 INIT_CONTEXT();
1686 st_logf("VerifyUpdate\n");
1687 VERIFY_SESSION_HANDLE(hSession, NULL);
1688 return CKR_FUNCTION_NOT_SUPPORTED;
1689 }
1690
1691 CK_RV
C_VerifyFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)1692 C_VerifyFinal(CK_SESSION_HANDLE hSession,
1693 CK_BYTE_PTR pSignature,
1694 CK_ULONG ulSignatureLen)
1695 {
1696 INIT_CONTEXT();
1697 st_logf("VerifyFinal\n");
1698 VERIFY_SESSION_HANDLE(hSession, NULL);
1699 return CKR_FUNCTION_NOT_SUPPORTED;
1700 }
1701
1702 CK_RV
C_GenerateRandom(CK_SESSION_HANDLE hSession,CK_BYTE_PTR RandomData,CK_ULONG ulRandomLen)1703 C_GenerateRandom(CK_SESSION_HANDLE hSession,
1704 CK_BYTE_PTR RandomData,
1705 CK_ULONG ulRandomLen)
1706 {
1707 INIT_CONTEXT();
1708 st_logf("GenerateRandom\n");
1709 VERIFY_SESSION_HANDLE(hSession, NULL);
1710 return CKR_FUNCTION_NOT_SUPPORTED;
1711 }
1712
1713
1714 CK_FUNCTION_LIST funcs = {
1715 { 2, 11 },
1716 C_Initialize,
1717 C_Finalize,
1718 C_GetInfo,
1719 C_GetFunctionList,
1720 C_GetSlotList,
1721 C_GetSlotInfo,
1722 C_GetTokenInfo,
1723 C_GetMechanismList,
1724 C_GetMechanismInfo,
1725 C_InitToken,
1726 (void *)func_not_supported, /* C_InitPIN */
1727 (void *)func_not_supported, /* C_SetPIN */
1728 C_OpenSession,
1729 C_CloseSession,
1730 C_CloseAllSessions,
1731 C_GetSessionInfo,
1732 (void *)func_not_supported, /* C_GetOperationState */
1733 (void *)func_not_supported, /* C_SetOperationState */
1734 C_Login,
1735 C_Logout,
1736 (void *)func_not_supported, /* C_CreateObject */
1737 (void *)func_not_supported, /* C_CopyObject */
1738 (void *)func_not_supported, /* C_DestroyObject */
1739 (void *)func_not_supported, /* C_GetObjectSize */
1740 C_GetAttributeValue,
1741 (void *)func_not_supported, /* C_SetAttributeValue */
1742 C_FindObjectsInit,
1743 C_FindObjects,
1744 C_FindObjectsFinal,
1745 (void *)func_not_supported, /* C_EncryptInit, */
1746 (void *)func_not_supported, /* C_Encrypt, */
1747 (void *)func_not_supported, /* C_EncryptUpdate, */
1748 (void *)func_not_supported, /* C_EncryptFinal, */
1749 (void *)func_not_supported, /* C_DecryptInit, */
1750 (void *)func_not_supported, /* C_Decrypt, */
1751 (void *)func_not_supported, /* C_DecryptUpdate, */
1752 (void *)func_not_supported, /* C_DecryptFinal, */
1753 C_DigestInit,
1754 (void *)func_not_supported, /* C_Digest */
1755 (void *)func_not_supported, /* C_DigestUpdate */
1756 (void *)func_not_supported, /* C_DigestKey */
1757 (void *)func_not_supported, /* C_DigestFinal */
1758 C_SignInit,
1759 C_Sign,
1760 C_SignUpdate,
1761 C_SignFinal,
1762 (void *)func_not_supported, /* C_SignRecoverInit */
1763 (void *)func_not_supported, /* C_SignRecover */
1764 C_VerifyInit,
1765 C_Verify,
1766 C_VerifyUpdate,
1767 C_VerifyFinal,
1768 (void *)func_not_supported, /* C_VerifyRecoverInit */
1769 (void *)func_not_supported, /* C_VerifyRecover */
1770 (void *)func_not_supported, /* C_DigestEncryptUpdate */
1771 (void *)func_not_supported, /* C_DecryptDigestUpdate */
1772 (void *)func_not_supported, /* C_SignEncryptUpdate */
1773 (void *)func_not_supported, /* C_DecryptVerifyUpdate */
1774 (void *)func_not_supported, /* C_GenerateKey */
1775 (void *)func_not_supported, /* C_GenerateKeyPair */
1776 (void *)func_not_supported, /* C_WrapKey */
1777 (void *)func_not_supported, /* C_UnwrapKey */
1778 (void *)func_not_supported, /* C_DeriveKey */
1779 (void *)func_not_supported, /* C_SeedRandom */
1780 C_GenerateRandom,
1781 (void *)func_not_supported, /* C_GetFunctionStatus */
1782 (void *)func_not_supported, /* C_CancelFunction */
1783 (void *)func_not_supported /* C_WaitForSlotEvent */
1784 };
1785