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