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