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