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