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