1178825Sdfr/*
2233294Sstas * Copyright (c) 2004 - 2008 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
5178825Sdfr *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
9178825Sdfr *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
12178825Sdfr *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
16178825Sdfr *
17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
18233294Sstas *    may be used to endorse or promote products derived from this software
19233294Sstas *    without specific prior written permission.
20178825Sdfr *
21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31233294Sstas * SUCH DAMAGE.
32178825Sdfr */
33178825Sdfr
34233294Sstas#define CRYPTOKI_EXPORTS 1
35233294Sstas
36178825Sdfr#include "hx_locl.h"
37178825Sdfr#include "pkcs11.h"
38178825Sdfr
39178825Sdfr#define OBJECT_ID_MASK		0xfff
40178825Sdfr#define HANDLE_OBJECT_ID(h)	((h) & OBJECT_ID_MASK)
41178825Sdfr#define OBJECT_ID(obj)		HANDLE_OBJECT_ID((obj)->object_handle)
42178825Sdfr
43233294Sstas#ifndef HAVE_RANDOM
44233294Sstas#define random() rand()
45233294Sstas#define srandom(s) srand(s)
46233294Sstas#endif
47178825Sdfr
48233294Sstas#ifdef _WIN32
49233294Sstas#include <shlobj.h>
50233294Sstas#endif
51233294Sstas
52178825Sdfrstruct st_attr {
53178825Sdfr    CK_ATTRIBUTE attribute;
54178825Sdfr    int secret;
55178825Sdfr};
56178825Sdfr
57178825Sdfrstruct st_object {
58178825Sdfr    CK_OBJECT_HANDLE object_handle;
59178825Sdfr    struct st_attr *attrs;
60178825Sdfr    int num_attributes;
61178825Sdfr    hx509_cert cert;
62178825Sdfr};
63178825Sdfr
64178825Sdfrstatic struct soft_token {
65178825Sdfr    CK_VOID_PTR application;
66178825Sdfr    CK_NOTIFY notify;
67178825Sdfr    char *config_file;
68178825Sdfr    hx509_certs certs;
69178825Sdfr    struct {
70178825Sdfr	struct st_object **objs;
71178825Sdfr	int num_objs;
72178825Sdfr    } object;
73178825Sdfr    struct {
74178825Sdfr	int hardware_slot;
75178825Sdfr	int app_error_fatal;
76178825Sdfr	int login_done;
77178825Sdfr    } flags;
78178825Sdfr    int open_sessions;
79178825Sdfr    struct session_state {
80178825Sdfr	CK_SESSION_HANDLE session_handle;
81178825Sdfr
82178825Sdfr	struct {
83178825Sdfr	    CK_ATTRIBUTE *attributes;
84178825Sdfr	    CK_ULONG num_attributes;
85178825Sdfr	    int next_object;
86178825Sdfr	} find;
87178825Sdfr
88178825Sdfr	int sign_object;
89178825Sdfr	CK_MECHANISM_PTR sign_mechanism;
90178825Sdfr	int verify_object;
91178825Sdfr	CK_MECHANISM_PTR verify_mechanism;
92178825Sdfr    } state[10];
93178825Sdfr#define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0]))
94178825Sdfr    FILE *logfile;
95178825Sdfr} soft_token;
96178825Sdfr
97178825Sdfrstatic hx509_context context;
98178825Sdfr
99178825Sdfrstatic void
100178825Sdfrapplication_error(const char *fmt, ...)
101178825Sdfr{
102178825Sdfr    va_list ap;
103178825Sdfr    va_start(ap, fmt);
104178825Sdfr    vprintf(fmt, ap);
105178825Sdfr    va_end(ap);
106178825Sdfr    if (soft_token.flags.app_error_fatal)
107178825Sdfr	abort();
108178825Sdfr}
109178825Sdfr
110178825Sdfrstatic void
111178825Sdfrst_logf(const char *fmt, ...)
112178825Sdfr{
113178825Sdfr    va_list ap;
114178825Sdfr    if (soft_token.logfile == NULL)
115178825Sdfr	return;
116178825Sdfr    va_start(ap, fmt);
117178825Sdfr    vfprintf(soft_token.logfile, fmt, ap);
118178825Sdfr    va_end(ap);
119178825Sdfr    fflush(soft_token.logfile);
120178825Sdfr}
121178825Sdfr
122178825Sdfrstatic CK_RV
123178825Sdfrinit_context(void)
124178825Sdfr{
125178825Sdfr    if (context == NULL) {
126178825Sdfr	int ret = hx509_context_init(&context);
127178825Sdfr	if (ret)
128178825Sdfr	    return CKR_GENERAL_ERROR;
129178825Sdfr    }
130178825Sdfr    return CKR_OK;
131178825Sdfr}
132178825Sdfr
133178825Sdfr#define INIT_CONTEXT() { CK_RV icret = init_context(); if (icret) return icret; }
134178825Sdfr
135178825Sdfrstatic void
136178825Sdfrsnprintf_fill(char *str, size_t size, char fillchar, const char *fmt, ...)
137178825Sdfr{
138178825Sdfr    int len;
139178825Sdfr    va_list ap;
140233294Sstas    va_start(ap, fmt);
141178825Sdfr    len = vsnprintf(str, size, fmt, ap);
142178825Sdfr    va_end(ap);
143233294Sstas    if (len < 0 || (size_t)len > size)
144178825Sdfr	return;
145233294Sstas    while ((size_t)len < size)
146178825Sdfr	str[len++] = fillchar;
147178825Sdfr}
148178825Sdfr
149178825Sdfr#ifndef TEST_APP
150178825Sdfr#define printf error_use_st_logf
151178825Sdfr#endif
152178825Sdfr
153178825Sdfr#define VERIFY_SESSION_HANDLE(s, state)			\
154178825Sdfr{							\
155233294Sstas    CK_RV xret;						\
156233294Sstas    xret = verify_session_handle(s, state);		\
157233294Sstas    if (xret != CKR_OK) {				\
158178825Sdfr	/* return CKR_OK */;				\
159178825Sdfr    }							\
160178825Sdfr}
161178825Sdfr
162178825Sdfrstatic CK_RV
163178825Sdfrverify_session_handle(CK_SESSION_HANDLE hSession,
164178825Sdfr		      struct session_state **state)
165178825Sdfr{
166233294Sstas    size_t i;
167178825Sdfr
168178825Sdfr    for (i = 0; i < MAX_NUM_SESSION; i++){
169178825Sdfr	if (soft_token.state[i].session_handle == hSession)
170178825Sdfr	    break;
171178825Sdfr    }
172178825Sdfr    if (i == MAX_NUM_SESSION) {
173178825Sdfr	application_error("use of invalid handle: 0x%08lx\n",
174178825Sdfr			  (unsigned long)hSession);
175178825Sdfr	return CKR_SESSION_HANDLE_INVALID;
176178825Sdfr    }
177178825Sdfr    if (state)
178178825Sdfr	*state = &soft_token.state[i];
179178825Sdfr    return CKR_OK;
180178825Sdfr}
181178825Sdfr
182178825Sdfrstatic CK_RV
183178825Sdfrobject_handle_to_object(CK_OBJECT_HANDLE handle,
184178825Sdfr			struct st_object **object)
185178825Sdfr{
186178825Sdfr    int i = HANDLE_OBJECT_ID(handle);
187178825Sdfr
188178825Sdfr    *object = NULL;
189178825Sdfr    if (i >= soft_token.object.num_objs)
190178825Sdfr	return CKR_ARGUMENTS_BAD;
191178825Sdfr    if (soft_token.object.objs[i] == NULL)
192178825Sdfr	return CKR_ARGUMENTS_BAD;
193178825Sdfr    if (soft_token.object.objs[i]->object_handle != handle)
194178825Sdfr	return CKR_ARGUMENTS_BAD;
195178825Sdfr    *object = soft_token.object.objs[i];
196178825Sdfr    return CKR_OK;
197178825Sdfr}
198178825Sdfr
199178825Sdfrstatic int
200178825Sdfrattributes_match(const struct st_object *obj,
201178825Sdfr		 const CK_ATTRIBUTE *attributes,
202178825Sdfr		 CK_ULONG num_attributes)
203178825Sdfr{
204178825Sdfr    CK_ULONG i;
205178825Sdfr    int j;
206178825Sdfr
207178825Sdfr    st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj));
208178825Sdfr
209178825Sdfr    for (i = 0; i < num_attributes; i++) {
210178825Sdfr	int match = 0;
211178825Sdfr	for (j = 0; j < obj->num_attributes; j++) {
212178825Sdfr	    if (attributes[i].type == obj->attrs[j].attribute.type &&
213178825Sdfr		attributes[i].ulValueLen == obj->attrs[j].attribute.ulValueLen &&
214178825Sdfr		memcmp(attributes[i].pValue, obj->attrs[j].attribute.pValue,
215178825Sdfr		       attributes[i].ulValueLen) == 0) {
216178825Sdfr		match = 1;
217178825Sdfr		break;
218178825Sdfr	    }
219178825Sdfr	}
220178825Sdfr	if (match == 0) {
221178825Sdfr	    st_logf("type %d attribute have no match\n", attributes[i].type);
222178825Sdfr	    return 0;
223178825Sdfr	}
224178825Sdfr    }
225178825Sdfr    st_logf("attribute matches\n");
226178825Sdfr    return 1;
227178825Sdfr}
228178825Sdfr
229178825Sdfrstatic void
230178825Sdfrprint_attributes(const CK_ATTRIBUTE *attributes,
231178825Sdfr		 CK_ULONG num_attributes)
232178825Sdfr{
233178825Sdfr    CK_ULONG i;
234178825Sdfr
235178825Sdfr    st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes);
236178825Sdfr
237178825Sdfr    for (i = 0; i < num_attributes; i++) {
238178825Sdfr	st_logf("  type: ");
239178825Sdfr	switch (attributes[i].type) {
240178825Sdfr	case CKA_TOKEN: {
241178825Sdfr	    CK_BBOOL *ck_true;
242178825Sdfr	    if (attributes[i].ulValueLen != sizeof(CK_BBOOL)) {
243178825Sdfr		application_error("token attribute wrong length\n");
244178825Sdfr		break;
245178825Sdfr	    }
246178825Sdfr	    ck_true = attributes[i].pValue;
247178825Sdfr	    st_logf("token: %s", *ck_true ? "TRUE" : "FALSE");
248178825Sdfr	    break;
249178825Sdfr	}
250178825Sdfr	case CKA_CLASS: {
251178825Sdfr	    CK_OBJECT_CLASS *class;
252178825Sdfr	    if (attributes[i].ulValueLen != sizeof(CK_ULONG)) {
253178825Sdfr		application_error("class attribute wrong length\n");
254178825Sdfr		break;
255178825Sdfr	    }
256178825Sdfr	    class = attributes[i].pValue;
257178825Sdfr	    st_logf("class ");
258178825Sdfr	    switch (*class) {
259178825Sdfr	    case CKO_CERTIFICATE:
260178825Sdfr		st_logf("certificate");
261178825Sdfr		break;
262178825Sdfr	    case CKO_PUBLIC_KEY:
263178825Sdfr		st_logf("public key");
264178825Sdfr		break;
265178825Sdfr	    case CKO_PRIVATE_KEY:
266178825Sdfr		st_logf("private key");
267178825Sdfr		break;
268178825Sdfr	    case CKO_SECRET_KEY:
269178825Sdfr		st_logf("secret key");
270178825Sdfr		break;
271178825Sdfr	    case CKO_DOMAIN_PARAMETERS:
272178825Sdfr		st_logf("domain parameters");
273178825Sdfr		break;
274178825Sdfr	    default:
275178825Sdfr		st_logf("[class %lx]", (long unsigned)*class);
276178825Sdfr		break;
277178825Sdfr	    }
278178825Sdfr	    break;
279178825Sdfr	}
280178825Sdfr	case CKA_PRIVATE:
281178825Sdfr	    st_logf("private");
282178825Sdfr	    break;
283178825Sdfr	case CKA_LABEL:
284178825Sdfr	    st_logf("label");
285178825Sdfr	    break;
286178825Sdfr	case CKA_APPLICATION:
287178825Sdfr	    st_logf("application");
288178825Sdfr	    break;
289178825Sdfr	case CKA_VALUE:
290178825Sdfr	    st_logf("value");
291178825Sdfr	    break;
292178825Sdfr	case CKA_ID:
293178825Sdfr	    st_logf("id");
294178825Sdfr	    break;
295178825Sdfr	default:
296178825Sdfr	    st_logf("[unknown 0x%08lx]", (unsigned long)attributes[i].type);
297178825Sdfr	    break;
298178825Sdfr	}
299178825Sdfr	st_logf("\n");
300178825Sdfr    }
301178825Sdfr}
302178825Sdfr
303178825Sdfrstatic struct st_object *
304178825Sdfradd_st_object(void)
305178825Sdfr{
306178825Sdfr    struct st_object *o, **objs;
307178825Sdfr    int i;
308178825Sdfr
309233294Sstas    o = calloc(1, sizeof(*o));
310178825Sdfr    if (o == NULL)
311178825Sdfr	return NULL;
312233294Sstas
313178825Sdfr    for (i = 0; i < soft_token.object.num_objs; i++) {
314178825Sdfr	if (soft_token.object.objs == NULL) {
315178825Sdfr	    soft_token.object.objs[i] = o;
316178825Sdfr	    break;
317178825Sdfr	}
318178825Sdfr    }
319178825Sdfr    if (i == soft_token.object.num_objs) {
320178825Sdfr	objs = realloc(soft_token.object.objs,
321178825Sdfr		       (soft_token.object.num_objs + 1) * sizeof(soft_token.object.objs[0]));
322178825Sdfr	if (objs == NULL) {
323178825Sdfr	    free(o);
324178825Sdfr	    return NULL;
325178825Sdfr	}
326178825Sdfr	soft_token.object.objs = objs;
327178825Sdfr	soft_token.object.objs[soft_token.object.num_objs++] = o;
328233294Sstas    }
329178825Sdfr    soft_token.object.objs[i]->object_handle =
330178825Sdfr	(random() & (~OBJECT_ID_MASK)) | i;
331178825Sdfr
332178825Sdfr    return o;
333178825Sdfr}
334178825Sdfr
335178825Sdfrstatic CK_RV
336233294Sstasadd_object_attribute(struct st_object *o,
337178825Sdfr		     int secret,
338178825Sdfr		     CK_ATTRIBUTE_TYPE type,
339178825Sdfr		     CK_VOID_PTR pValue,
340178825Sdfr		     CK_ULONG ulValueLen)
341178825Sdfr{
342178825Sdfr    struct st_attr *a;
343178825Sdfr    int i;
344178825Sdfr
345178825Sdfr    i = o->num_attributes;
346178825Sdfr    a = realloc(o->attrs, (i + 1) * sizeof(o->attrs[0]));
347178825Sdfr    if (a == NULL)
348178825Sdfr	return CKR_DEVICE_MEMORY;
349178825Sdfr    o->attrs = a;
350178825Sdfr    o->attrs[i].secret = secret;
351178825Sdfr    o->attrs[i].attribute.type = type;
352178825Sdfr    o->attrs[i].attribute.pValue = malloc(ulValueLen);
353178825Sdfr    if (o->attrs[i].attribute.pValue == NULL && ulValueLen != 0)
354178825Sdfr	return CKR_DEVICE_MEMORY;
355178825Sdfr    memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen);
356178825Sdfr    o->attrs[i].attribute.ulValueLen = ulValueLen;
357178825Sdfr    o->num_attributes++;
358178825Sdfr
359178825Sdfr    return CKR_OK;
360178825Sdfr}
361178825Sdfr
362178825Sdfrstatic CK_RV
363178825Sdfradd_pubkey_info(hx509_context hxctx, struct st_object *o,
364178825Sdfr		CK_KEY_TYPE key_type, hx509_cert cert)
365178825Sdfr{
366178825Sdfr    BIGNUM *num;
367178825Sdfr    CK_BYTE *modulus = NULL;
368178825Sdfr    size_t modulus_len = 0;
369178825Sdfr    CK_ULONG modulus_bits = 0;
370178825Sdfr    CK_BYTE *exponent = NULL;
371178825Sdfr    size_t exponent_len = 0;
372233294Sstas
373178825Sdfr    if (key_type != CKK_RSA)
374178825Sdfr	return CKR_OK;
375178825Sdfr    if (_hx509_cert_private_key(cert) == NULL)
376178825Sdfr	return CKR_OK;
377178825Sdfr
378233294Sstas    num = _hx509_private_key_get_internal(context,
379233294Sstas					  _hx509_cert_private_key(cert),
380178825Sdfr					  "rsa-modulus");
381178825Sdfr    if (num == NULL)
382178825Sdfr	return CKR_GENERAL_ERROR;
383178825Sdfr    modulus_bits = BN_num_bits(num);
384178825Sdfr
385178825Sdfr    modulus_len = BN_num_bytes(num);
386178825Sdfr    modulus = malloc(modulus_len);
387178825Sdfr    BN_bn2bin(num, modulus);
388178825Sdfr    BN_free(num);
389178825Sdfr
390178825Sdfr    add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len);
391178825Sdfr    add_object_attribute(o, 0, CKA_MODULUS_BITS,
392178825Sdfr			 &modulus_bits, sizeof(modulus_bits));
393178825Sdfr
394178825Sdfr    free(modulus);
395233294Sstas
396233294Sstas    num = _hx509_private_key_get_internal(context,
397233294Sstas					  _hx509_cert_private_key(cert),
398178825Sdfr					  "rsa-exponent");
399178825Sdfr    if (num == NULL)
400178825Sdfr	return CKR_GENERAL_ERROR;
401178825Sdfr
402178825Sdfr    exponent_len = BN_num_bytes(num);
403178825Sdfr    exponent = malloc(exponent_len);
404178825Sdfr    BN_bn2bin(num, exponent);
405178825Sdfr    BN_free(num);
406178825Sdfr
407178825Sdfr    add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT,
408178825Sdfr			 exponent, exponent_len);
409178825Sdfr
410178825Sdfr    free(exponent);
411178825Sdfr
412178825Sdfr    return CKR_OK;
413178825Sdfr}
414178825Sdfr
415178825Sdfr
416178825Sdfrstruct foo {
417178825Sdfr    char *label;
418178825Sdfr    char *id;
419178825Sdfr};
420178825Sdfr
421178825Sdfrstatic int
422178825Sdfradd_cert(hx509_context hxctx, void *ctx, hx509_cert cert)
423178825Sdfr{
424233294Sstas    static char empty[] = "";
425178825Sdfr    struct foo *foo = (struct foo *)ctx;
426178825Sdfr    struct st_object *o = NULL;
427178825Sdfr    CK_OBJECT_CLASS type;
428178825Sdfr    CK_BBOOL bool_true = CK_TRUE;
429178825Sdfr    CK_BBOOL bool_false = CK_FALSE;
430178825Sdfr    CK_CERTIFICATE_TYPE cert_type = CKC_X_509;
431178825Sdfr    CK_KEY_TYPE key_type;
432178825Sdfr    CK_MECHANISM_TYPE mech_type;
433178825Sdfr    CK_RV ret = CKR_GENERAL_ERROR;
434178825Sdfr    int hret;
435178825Sdfr    heim_octet_string cert_data, subject_data, issuer_data, serial_data;
436178825Sdfr
437178825Sdfr    st_logf("adding certificate\n");
438178825Sdfr
439178825Sdfr    serial_data.data = NULL;
440178825Sdfr    serial_data.length = 0;
441178825Sdfr    cert_data = subject_data = issuer_data = serial_data;
442178825Sdfr
443178825Sdfr    hret = hx509_cert_binary(hxctx, cert, &cert_data);
444178825Sdfr    if (hret)
445178825Sdfr	goto out;
446178825Sdfr
447178825Sdfr    {
448178825Sdfr	    hx509_name name;
449178825Sdfr
450178825Sdfr	    hret = hx509_cert_get_issuer(cert, &name);
451178825Sdfr	    if (hret)
452178825Sdfr		goto out;
453178825Sdfr	    hret = hx509_name_binary(name, &issuer_data);
454178825Sdfr	    hx509_name_free(&name);
455178825Sdfr	    if (hret)
456178825Sdfr		goto out;
457178825Sdfr
458178825Sdfr	    hret = hx509_cert_get_subject(cert, &name);
459178825Sdfr	    if (hret)
460178825Sdfr		goto out;
461178825Sdfr	    hret = hx509_name_binary(name, &subject_data);
462178825Sdfr	    hx509_name_free(&name);
463178825Sdfr	    if (hret)
464178825Sdfr		goto out;
465178825Sdfr    }
466178825Sdfr
467178825Sdfr    {
468178825Sdfr	AlgorithmIdentifier alg;
469178825Sdfr
470178825Sdfr	hret = hx509_cert_get_SPKI_AlgorithmIdentifier(context, cert, &alg);
471178825Sdfr	if (hret) {
472178825Sdfr	    ret = CKR_DEVICE_MEMORY;
473178825Sdfr	    goto out;
474178825Sdfr	}
475178825Sdfr
476178825Sdfr	key_type = CKK_RSA; /* XXX */
477178825Sdfr
478178825Sdfr	free_AlgorithmIdentifier(&alg);
479178825Sdfr    }
480178825Sdfr
481178825Sdfr
482178825Sdfr    type = CKO_CERTIFICATE;
483178825Sdfr    o = add_st_object();
484178825Sdfr    if (o == NULL) {
485178825Sdfr	ret = CKR_DEVICE_MEMORY;
486178825Sdfr	goto out;
487178825Sdfr    }
488178825Sdfr
489178825Sdfr    o->cert = hx509_cert_ref(cert);
490178825Sdfr
491178825Sdfr    add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
492178825Sdfr    add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
493178825Sdfr    add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
494178825Sdfr    add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
495178825Sdfr    add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
496178825Sdfr
497178825Sdfr    add_object_attribute(o, 0, CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type));
498178825Sdfr    add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
499178825Sdfr
500178825Sdfr    add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
501178825Sdfr    add_object_attribute(o, 0, CKA_ISSUER, issuer_data.data, issuer_data.length);
502178825Sdfr    add_object_attribute(o, 0, CKA_SERIAL_NUMBER, serial_data.data, serial_data.length);
503178825Sdfr    add_object_attribute(o, 0, CKA_VALUE, cert_data.data, cert_data.length);
504178825Sdfr    add_object_attribute(o, 0, CKA_TRUSTED, &bool_false, sizeof(bool_false));
505178825Sdfr
506178825Sdfr    st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o));
507178825Sdfr
508178825Sdfr    type = CKO_PUBLIC_KEY;
509178825Sdfr    o = add_st_object();
510178825Sdfr    if (o == NULL) {
511178825Sdfr	ret = CKR_DEVICE_MEMORY;
512178825Sdfr	goto out;
513178825Sdfr    }
514178825Sdfr    o->cert = hx509_cert_ref(cert);
515178825Sdfr
516178825Sdfr    add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
517178825Sdfr    add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
518178825Sdfr    add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
519178825Sdfr    add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
520178825Sdfr    add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
521178825Sdfr
522178825Sdfr    add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
523178825Sdfr    add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
524233294Sstas    add_object_attribute(o, 0, CKA_START_DATE, empty, 1); /* XXX */
525233294Sstas    add_object_attribute(o, 0, CKA_END_DATE, empty, 1); /* XXX */
526178825Sdfr    add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
527178825Sdfr    add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
528178825Sdfr    mech_type = CKM_RSA_X_509;
529178825Sdfr    add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
530178825Sdfr
531178825Sdfr    add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
532178825Sdfr    add_object_attribute(o, 0, CKA_ENCRYPT, &bool_true, sizeof(bool_true));
533178825Sdfr    add_object_attribute(o, 0, CKA_VERIFY, &bool_true, sizeof(bool_true));
534178825Sdfr    add_object_attribute(o, 0, CKA_VERIFY_RECOVER, &bool_false, sizeof(bool_false));
535178825Sdfr    add_object_attribute(o, 0, CKA_WRAP, &bool_true, sizeof(bool_true));
536178825Sdfr    add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true));
537178825Sdfr
538178825Sdfr    add_pubkey_info(hxctx, o, key_type, cert);
539178825Sdfr
540178825Sdfr    st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o));
541178825Sdfr
542178825Sdfr    if (hx509_cert_have_private_key(cert)) {
543178825Sdfr	CK_FLAGS flags;
544178825Sdfr
545178825Sdfr	type = CKO_PRIVATE_KEY;
546178825Sdfr	o = add_st_object();
547178825Sdfr	if (o == NULL) {
548178825Sdfr	    ret = CKR_DEVICE_MEMORY;
549178825Sdfr	    goto out;
550178825Sdfr	}
551178825Sdfr	o->cert = hx509_cert_ref(cert);
552178825Sdfr
553178825Sdfr	add_object_attribute(o, 0, CKA_CLASS, &type, sizeof(type));
554178825Sdfr	add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
555178825Sdfr	add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false));
556178825Sdfr	add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
557178825Sdfr	add_object_attribute(o, 0, CKA_LABEL, foo->label, strlen(foo->label));
558178825Sdfr
559178825Sdfr	add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
560178825Sdfr	add_object_attribute(o, 0, CKA_ID, foo->id, strlen(foo->id));
561233294Sstas	add_object_attribute(o, 0, CKA_START_DATE, empty, 1); /* XXX */
562233294Sstas	add_object_attribute(o, 0, CKA_END_DATE, empty, 1); /* XXX */
563178825Sdfr	add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
564178825Sdfr	add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
565178825Sdfr	mech_type = CKM_RSA_X_509;
566178825Sdfr	add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
567178825Sdfr
568178825Sdfr	add_object_attribute(o, 0, CKA_SUBJECT, subject_data.data, subject_data.length);
569178825Sdfr	add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true));
570178825Sdfr	add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true));
571178825Sdfr	flags = 0;
572178825Sdfr	add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags));
573178825Sdfr
574178825Sdfr	add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true));
575178825Sdfr	add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true));
576178825Sdfr	add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false));
577178825Sdfr	add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true));
578178825Sdfr	add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true));
579178825Sdfr	add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false));
580178825Sdfr
581178825Sdfr	add_pubkey_info(hxctx, o, key_type, cert);
582178825Sdfr    }
583178825Sdfr
584178825Sdfr    ret = CKR_OK;
585178825Sdfr out:
586178825Sdfr    if (ret != CKR_OK) {
587178825Sdfr	st_logf("something went wrong when adding cert!\n");
588178825Sdfr
589178825Sdfr	/* XXX wack o */;
590178825Sdfr    }
591178825Sdfr    hx509_xfree(cert_data.data);
592178825Sdfr    hx509_xfree(serial_data.data);
593178825Sdfr    hx509_xfree(issuer_data.data);
594178825Sdfr    hx509_xfree(subject_data.data);
595178825Sdfr
596178825Sdfr    return 0;
597178825Sdfr}
598178825Sdfr
599178825Sdfrstatic CK_RV
600178825Sdfradd_certificate(const char *cert_file,
601178825Sdfr		const char *pin,
602178825Sdfr		char *id,
603178825Sdfr		char *label)
604178825Sdfr{
605178825Sdfr    hx509_certs certs;
606178825Sdfr    hx509_lock lock = NULL;
607178825Sdfr    int ret, flags = 0;
608178825Sdfr
609178825Sdfr    struct foo foo;
610178825Sdfr    foo.id = id;
611178825Sdfr    foo.label = label;
612178825Sdfr
613178825Sdfr    if (pin == NULL)
614178825Sdfr	flags |= HX509_CERTS_UNPROTECT_ALL;
615178825Sdfr
616178825Sdfr    if (pin) {
617178825Sdfr	char *str;
618178825Sdfr	asprintf(&str, "PASS:%s", pin);
619178825Sdfr
620178825Sdfr	hx509_lock_init(context, &lock);
621178825Sdfr	hx509_lock_command_string(lock, str);
622178825Sdfr
623178825Sdfr	memset(str, 0, strlen(str));
624178825Sdfr	free(str);
625178825Sdfr    }
626178825Sdfr
627178825Sdfr    ret = hx509_certs_init(context, cert_file, flags, lock, &certs);
628178825Sdfr    if (ret) {
629178825Sdfr	st_logf("failed to open file %s\n", cert_file);
630178825Sdfr	return CKR_GENERAL_ERROR;
631178825Sdfr    }
632178825Sdfr
633233294Sstas    ret = hx509_certs_iter_f(context, certs, add_cert, &foo);
634178825Sdfr    hx509_certs_free(&certs);
635178825Sdfr    if (ret) {
636178825Sdfr	st_logf("failed adding certs from file %s\n", cert_file);
637178825Sdfr	return CKR_GENERAL_ERROR;
638178825Sdfr    }
639178825Sdfr
640178825Sdfr    return CKR_OK;
641178825Sdfr}
642178825Sdfr
643178825Sdfrstatic void
644178825Sdfrfind_object_final(struct session_state *state)
645178825Sdfr{
646178825Sdfr    if (state->find.attributes) {
647178825Sdfr	CK_ULONG i;
648178825Sdfr
649178825Sdfr	for (i = 0; i < state->find.num_attributes; i++) {
650178825Sdfr	    if (state->find.attributes[i].pValue)
651178825Sdfr		free(state->find.attributes[i].pValue);
652178825Sdfr	}
653178825Sdfr	free(state->find.attributes);
654178825Sdfr	state->find.attributes = NULL;
655178825Sdfr	state->find.num_attributes = 0;
656178825Sdfr	state->find.next_object = -1;
657178825Sdfr    }
658178825Sdfr}
659178825Sdfr
660178825Sdfrstatic void
661178825Sdfrreset_crypto_state(struct session_state *state)
662178825Sdfr{
663178825Sdfr    state->sign_object = -1;
664178825Sdfr    if (state->sign_mechanism)
665178825Sdfr	free(state->sign_mechanism);
666178825Sdfr    state->sign_mechanism = NULL_PTR;
667178825Sdfr    state->verify_object = -1;
668178825Sdfr    if (state->verify_mechanism)
669178825Sdfr	free(state->verify_mechanism);
670178825Sdfr    state->verify_mechanism = NULL_PTR;
671178825Sdfr}
672178825Sdfr
673178825Sdfrstatic void
674178825Sdfrclose_session(struct session_state *state)
675178825Sdfr{
676178825Sdfr    if (state->find.attributes) {
677178825Sdfr	application_error("application didn't do C_FindObjectsFinal\n");
678178825Sdfr	find_object_final(state);
679178825Sdfr    }
680178825Sdfr
681178825Sdfr    state->session_handle = CK_INVALID_HANDLE;
682178825Sdfr    soft_token.application = NULL_PTR;
683178825Sdfr    soft_token.notify = NULL_PTR;
684178825Sdfr    reset_crypto_state(state);
685178825Sdfr}
686178825Sdfr
687178825Sdfrstatic const char *
688178825Sdfrhas_session(void)
689178825Sdfr{
690178825Sdfr    return soft_token.open_sessions > 0 ? "yes" : "no";
691178825Sdfr}
692178825Sdfr
693178825Sdfrstatic CK_RV
694178825Sdfrread_conf_file(const char *fn, CK_USER_TYPE userType, const char *pin)
695178825Sdfr{
696178825Sdfr    char buf[1024], *type, *s, *p;
697178825Sdfr    FILE *f;
698178825Sdfr    CK_RV ret = CKR_OK;
699178825Sdfr    CK_RV failed = CKR_OK;
700178825Sdfr
701233294Sstas    if (fn == NULL) {
702233294Sstas        st_logf("Can't open configuration file.  No file specified\n");
703233294Sstas        return CKR_GENERAL_ERROR;
704233294Sstas    }
705233294Sstas
706178825Sdfr    f = fopen(fn, "r");
707178825Sdfr    if (f == NULL) {
708178825Sdfr	st_logf("can't open configuration file %s\n", fn);
709178825Sdfr	return CKR_GENERAL_ERROR;
710178825Sdfr    }
711233294Sstas    rk_cloexec_file(f);
712178825Sdfr
713178825Sdfr    while(fgets(buf, sizeof(buf), f) != NULL) {
714178825Sdfr	buf[strcspn(buf, "\n")] = '\0';
715178825Sdfr
716178825Sdfr	st_logf("line: %s\n", buf);
717178825Sdfr
718178825Sdfr	p = buf;
719233294Sstas	while (isspace((unsigned char)*p))
720178825Sdfr	    p++;
721178825Sdfr	if (*p == '#')
722178825Sdfr	    continue;
723233294Sstas	while (isspace((unsigned char)*p))
724178825Sdfr	    p++;
725178825Sdfr
726178825Sdfr	s = NULL;
727178825Sdfr	type = strtok_r(p, "\t", &s);
728178825Sdfr	if (type == NULL)
729178825Sdfr	    continue;
730233294Sstas
731178825Sdfr	if (strcasecmp("certificate", type) == 0) {
732178825Sdfr	    char *cert, *id, *label;
733233294Sstas
734178825Sdfr	    id = strtok_r(NULL, "\t", &s);
735178825Sdfr	    if (id == NULL) {
736178825Sdfr		st_logf("no id\n");
737178825Sdfr		continue;
738178825Sdfr	    }
739178825Sdfr	    st_logf("id: %s\n", id);
740178825Sdfr	    label = strtok_r(NULL, "\t", &s);
741178825Sdfr	    if (label == NULL) {
742178825Sdfr		st_logf("no label\n");
743178825Sdfr		continue;
744178825Sdfr	    }
745178825Sdfr	    cert = strtok_r(NULL, "\t", &s);
746178825Sdfr	    if (cert == NULL) {
747178825Sdfr		st_logf("no certfiicate store\n");
748178825Sdfr		continue;
749178825Sdfr	    }
750233294Sstas
751178825Sdfr	    st_logf("adding: %s: %s in file %s\n", id, label, cert);
752233294Sstas
753178825Sdfr	    ret = add_certificate(cert, pin, id, label);
754178825Sdfr	    if (ret)
755178825Sdfr		failed = ret;
756178825Sdfr	} else if (strcasecmp("debug", type) == 0) {
757178825Sdfr	    char *name;
758178825Sdfr
759178825Sdfr	    name = strtok_r(NULL, "\t", &s);
760178825Sdfr	    if (name == NULL) {
761178825Sdfr		st_logf("no filename\n");
762178825Sdfr		continue;
763178825Sdfr	    }
764178825Sdfr
765178825Sdfr	    if (soft_token.logfile)
766178825Sdfr		fclose(soft_token.logfile);
767178825Sdfr
768178825Sdfr	    if (strcasecmp(name, "stdout") == 0)
769178825Sdfr		soft_token.logfile = stdout;
770233294Sstas	    else {
771178825Sdfr		soft_token.logfile = fopen(name, "a");
772233294Sstas		if (soft_token.logfile)
773233294Sstas		    rk_cloexec_file(soft_token.logfile);
774233294Sstas	    }
775178825Sdfr	    if (soft_token.logfile == NULL)
776178825Sdfr		st_logf("failed to open file: %s\n", name);
777233294Sstas
778178825Sdfr	} else if (strcasecmp("app-fatal", type) == 0) {
779178825Sdfr	    char *name;
780178825Sdfr
781178825Sdfr	    name = strtok_r(NULL, "\t", &s);
782178825Sdfr	    if (name == NULL) {
783178825Sdfr		st_logf("argument to app-fatal\n");
784178825Sdfr		continue;
785178825Sdfr	    }
786178825Sdfr
787178825Sdfr	    if (strcmp(name, "true") == 0 || strcmp(name, "on") == 0)
788178825Sdfr		soft_token.flags.app_error_fatal = 1;
789178825Sdfr	    else if (strcmp(name, "false") == 0 || strcmp(name, "off") == 0)
790178825Sdfr		soft_token.flags.app_error_fatal = 0;
791178825Sdfr	    else
792178825Sdfr		st_logf("unknown app-fatal: %s\n", name);
793178825Sdfr
794178825Sdfr	} else {
795178825Sdfr	    st_logf("unknown type: %s\n", type);
796178825Sdfr	}
797178825Sdfr    }
798178825Sdfr
799178825Sdfr    fclose(f);
800178825Sdfr
801178825Sdfr    return failed;
802178825Sdfr}
803178825Sdfr
804178825Sdfrstatic CK_RV
805178825Sdfrfunc_not_supported(void)
806178825Sdfr{
807178825Sdfr    st_logf("function not supported\n");
808178825Sdfr    return CKR_FUNCTION_NOT_SUPPORTED;
809178825Sdfr}
810178825Sdfr
811233294Sstasstatic char *
812233294Sstasget_config_file_for_user(void)
813233294Sstas{
814233294Sstas    char *fn = NULL;
815233294Sstas
816233294Sstas#ifndef _WIN32
817233294Sstas    char *home = NULL;
818233294Sstas
819233294Sstas    if (!issuid()) {
820233294Sstas        fn = getenv("SOFTPKCS11RC");
821233294Sstas        if (fn)
822233294Sstas            fn = strdup(fn);
823233294Sstas        home = getenv("HOME");
824233294Sstas    }
825233294Sstas    if (fn == NULL && home == NULL) {
826233294Sstas        struct passwd *pw = getpwuid(getuid());
827233294Sstas        if(pw != NULL)
828233294Sstas            home = pw->pw_dir;
829233294Sstas    }
830233294Sstas    if (fn == NULL) {
831233294Sstas        if (home)
832233294Sstas            asprintf(&fn, "%s/.soft-token.rc", home);
833233294Sstas        else
834233294Sstas            fn = strdup("/etc/soft-token.rc");
835233294Sstas    }
836233294Sstas#else  /* Windows */
837233294Sstas
838233294Sstas    char appdatafolder[MAX_PATH];
839233294Sstas
840233294Sstas    fn = getenv("SOFTPKCS11RC");
841233294Sstas
842233294Sstas    /* Retrieve the roaming AppData folder for the current user.  The
843233294Sstas       current user is the user account represented by the current
844233294Sstas       thread token. */
845233294Sstas
846233294Sstas    if (fn == NULL &&
847233294Sstas        SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, appdatafolder))) {
848233294Sstas
849233294Sstas        asprintf(&fn, "%s\\.soft-token.rc", appdatafolder);
850233294Sstas    }
851233294Sstas
852233294Sstas#endif  /* _WIN32 */
853233294Sstas
854233294Sstas    return fn;
855233294Sstas}
856233294Sstas
857233294Sstas
858233294SstasCK_RV CK_SPEC
859178825SdfrC_Initialize(CK_VOID_PTR a)
860178825Sdfr{
861178825Sdfr    CK_C_INITIALIZE_ARGS_PTR args = a;
862178825Sdfr    CK_RV ret;
863233294Sstas    size_t i;
864178825Sdfr
865178825Sdfr    st_logf("Initialize\n");
866178825Sdfr
867178825Sdfr    INIT_CONTEXT();
868178825Sdfr
869178825Sdfr    OpenSSL_add_all_algorithms();
870178825Sdfr
871233294Sstas    srandom(getpid() ^ (int) time(NULL));
872178825Sdfr
873178825Sdfr    for (i = 0; i < MAX_NUM_SESSION; i++) {
874178825Sdfr	soft_token.state[i].session_handle = CK_INVALID_HANDLE;
875178825Sdfr	soft_token.state[i].find.attributes = NULL;
876178825Sdfr	soft_token.state[i].find.num_attributes = 0;
877178825Sdfr	soft_token.state[i].find.next_object = -1;
878178825Sdfr	reset_crypto_state(&soft_token.state[i]);
879178825Sdfr    }
880178825Sdfr
881178825Sdfr    soft_token.flags.hardware_slot = 1;
882178825Sdfr    soft_token.flags.app_error_fatal = 0;
883178825Sdfr    soft_token.flags.login_done = 0;
884178825Sdfr
885178825Sdfr    soft_token.object.objs = NULL;
886178825Sdfr    soft_token.object.num_objs = 0;
887233294Sstas
888178825Sdfr    soft_token.logfile = NULL;
889178825Sdfr#if 0
890178825Sdfr    soft_token.logfile = stdout;
891178825Sdfr#endif
892178825Sdfr#if 0
893178825Sdfr    soft_token.logfile = fopen("/tmp/log-pkcs11.txt", "a");
894178825Sdfr#endif
895178825Sdfr
896178825Sdfr    if (a != NULL_PTR) {
897178825Sdfr	st_logf("\tCreateMutex:\t%p\n", args->CreateMutex);
898178825Sdfr	st_logf("\tDestroyMutext\t%p\n", args->DestroyMutex);
899178825Sdfr	st_logf("\tLockMutext\t%p\n", args->LockMutex);
900178825Sdfr	st_logf("\tUnlockMutext\t%p\n", args->UnlockMutex);
901178825Sdfr	st_logf("\tFlags\t%04x\n", (unsigned int)args->flags);
902178825Sdfr    }
903178825Sdfr
904233294Sstas    soft_token.config_file = get_config_file_for_user();
905178825Sdfr
906178825Sdfr    /*
907178825Sdfr     * This operations doesn't return CKR_OK if any of the
908178825Sdfr     * certificates failes to be unparsed (ie password protected).
909178825Sdfr     */
910178825Sdfr    ret = read_conf_file(soft_token.config_file, CKU_USER, NULL);
911178825Sdfr    if (ret == CKR_OK)
912178825Sdfr	soft_token.flags.login_done = 1;
913178825Sdfr
914178825Sdfr    return CKR_OK;
915178825Sdfr}
916178825Sdfr
917178825SdfrCK_RV
918178825SdfrC_Finalize(CK_VOID_PTR args)
919178825Sdfr{
920233294Sstas    size_t i;
921178825Sdfr
922178825Sdfr    INIT_CONTEXT();
923178825Sdfr
924178825Sdfr    st_logf("Finalize\n");
925178825Sdfr
926178825Sdfr    for (i = 0; i < MAX_NUM_SESSION; i++) {
927178825Sdfr	if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) {
928178825Sdfr	    application_error("application finalized without "
929178825Sdfr			      "closing session\n");
930178825Sdfr	    close_session(&soft_token.state[i]);
931178825Sdfr	}
932178825Sdfr    }
933178825Sdfr
934178825Sdfr    return CKR_OK;
935178825Sdfr}
936178825Sdfr
937178825SdfrCK_RV
938178825SdfrC_GetInfo(CK_INFO_PTR args)
939178825Sdfr{
940178825Sdfr    INIT_CONTEXT();
941178825Sdfr
942178825Sdfr    st_logf("GetInfo\n");
943178825Sdfr
944178825Sdfr    memset(args, 17, sizeof(*args));
945178825Sdfr    args->cryptokiVersion.major = 2;
946178825Sdfr    args->cryptokiVersion.minor = 10;
947233294Sstas    snprintf_fill((char *)args->manufacturerID,
948178825Sdfr		  sizeof(args->manufacturerID),
949178825Sdfr		  ' ',
950178825Sdfr		  "Heimdal hx509 SoftToken");
951233294Sstas    snprintf_fill((char *)args->libraryDescription,
952178825Sdfr		  sizeof(args->libraryDescription), ' ',
953178825Sdfr		  "Heimdal hx509 SoftToken");
954178825Sdfr    args->libraryVersion.major = 2;
955178825Sdfr    args->libraryVersion.minor = 0;
956178825Sdfr
957178825Sdfr    return CKR_OK;
958178825Sdfr}
959178825Sdfr
960178825Sdfrextern CK_FUNCTION_LIST funcs;
961178825Sdfr
962178825SdfrCK_RV
963178825SdfrC_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
964178825Sdfr{
965178825Sdfr    INIT_CONTEXT();
966178825Sdfr
967178825Sdfr    *ppFunctionList = &funcs;
968178825Sdfr    return CKR_OK;
969178825Sdfr}
970178825Sdfr
971178825SdfrCK_RV
972178825SdfrC_GetSlotList(CK_BBOOL tokenPresent,
973178825Sdfr	      CK_SLOT_ID_PTR pSlotList,
974178825Sdfr	      CK_ULONG_PTR   pulCount)
975178825Sdfr{
976178825Sdfr    INIT_CONTEXT();
977178825Sdfr    st_logf("GetSlotList: %s\n",
978178825Sdfr	    tokenPresent ? "tokenPresent" : "token not Present");
979178825Sdfr    if (pSlotList)
980178825Sdfr	pSlotList[0] = 1;
981178825Sdfr    *pulCount = 1;
982178825Sdfr    return CKR_OK;
983178825Sdfr}
984178825Sdfr
985178825SdfrCK_RV
986178825SdfrC_GetSlotInfo(CK_SLOT_ID slotID,
987178825Sdfr	      CK_SLOT_INFO_PTR pInfo)
988178825Sdfr{
989178825Sdfr    INIT_CONTEXT();
990178825Sdfr    st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID, has_session());
991178825Sdfr
992178825Sdfr    memset(pInfo, 18, sizeof(*pInfo));
993178825Sdfr
994178825Sdfr    if (slotID != 1)
995178825Sdfr	return CKR_ARGUMENTS_BAD;
996178825Sdfr
997233294Sstas    snprintf_fill((char *)pInfo->slotDescription,
998178825Sdfr		  sizeof(pInfo->slotDescription),
999178825Sdfr		  ' ',
1000178825Sdfr		  "Heimdal hx509 SoftToken (slot)");
1001178825Sdfr    snprintf_fill((char *)pInfo->manufacturerID,
1002178825Sdfr		  sizeof(pInfo->manufacturerID),
1003178825Sdfr		  ' ',
1004178825Sdfr		  "Heimdal hx509 SoftToken (slot)");
1005178825Sdfr    pInfo->flags = CKF_TOKEN_PRESENT;
1006178825Sdfr    if (soft_token.flags.hardware_slot)
1007178825Sdfr	pInfo->flags |= CKF_HW_SLOT;
1008178825Sdfr    pInfo->hardwareVersion.major = 1;
1009178825Sdfr    pInfo->hardwareVersion.minor = 0;
1010178825Sdfr    pInfo->firmwareVersion.major = 1;
1011178825Sdfr    pInfo->firmwareVersion.minor = 0;
1012233294Sstas
1013178825Sdfr    return CKR_OK;
1014178825Sdfr}
1015178825Sdfr
1016178825SdfrCK_RV
1017178825SdfrC_GetTokenInfo(CK_SLOT_ID slotID,
1018178825Sdfr	       CK_TOKEN_INFO_PTR pInfo)
1019178825Sdfr{
1020178825Sdfr    INIT_CONTEXT();
1021233294Sstas    st_logf("GetTokenInfo: %s\n", has_session());
1022178825Sdfr
1023178825Sdfr    memset(pInfo, 19, sizeof(*pInfo));
1024178825Sdfr
1025233294Sstas    snprintf_fill((char *)pInfo->label,
1026178825Sdfr		  sizeof(pInfo->label),
1027178825Sdfr		  ' ',
1028178825Sdfr		  "Heimdal hx509 SoftToken (token)");
1029233294Sstas    snprintf_fill((char *)pInfo->manufacturerID,
1030178825Sdfr		  sizeof(pInfo->manufacturerID),
1031178825Sdfr		  ' ',
1032178825Sdfr		  "Heimdal hx509 SoftToken (token)");
1033178825Sdfr    snprintf_fill((char *)pInfo->model,
1034178825Sdfr		  sizeof(pInfo->model),
1035178825Sdfr		  ' ',
1036178825Sdfr		  "Heimdal hx509 SoftToken (token)");
1037233294Sstas    snprintf_fill((char *)pInfo->serialNumber,
1038178825Sdfr		  sizeof(pInfo->serialNumber),
1039178825Sdfr		  ' ',
1040178825Sdfr		  "4711");
1041233294Sstas    pInfo->flags =
1042233294Sstas	CKF_TOKEN_INITIALIZED |
1043178825Sdfr	CKF_USER_PIN_INITIALIZED;
1044178825Sdfr
1045178825Sdfr    if (soft_token.flags.login_done == 0)
1046178825Sdfr	pInfo->flags |= CKF_LOGIN_REQUIRED;
1047178825Sdfr
1048178825Sdfr    /* CFK_RNG |
1049178825Sdfr       CKF_RESTORE_KEY_NOT_NEEDED |
1050178825Sdfr    */
1051178825Sdfr    pInfo->ulMaxSessionCount = MAX_NUM_SESSION;
1052178825Sdfr    pInfo->ulSessionCount = soft_token.open_sessions;
1053178825Sdfr    pInfo->ulMaxRwSessionCount = MAX_NUM_SESSION;
1054178825Sdfr    pInfo->ulRwSessionCount = soft_token.open_sessions;
1055178825Sdfr    pInfo->ulMaxPinLen = 1024;
1056178825Sdfr    pInfo->ulMinPinLen = 0;
1057178825Sdfr    pInfo->ulTotalPublicMemory = 4711;
1058178825Sdfr    pInfo->ulFreePublicMemory = 4712;
1059178825Sdfr    pInfo->ulTotalPrivateMemory = 4713;
1060178825Sdfr    pInfo->ulFreePrivateMemory = 4714;
1061178825Sdfr    pInfo->hardwareVersion.major = 2;
1062178825Sdfr    pInfo->hardwareVersion.minor = 0;
1063178825Sdfr    pInfo->firmwareVersion.major = 2;
1064178825Sdfr    pInfo->firmwareVersion.minor = 0;
1065178825Sdfr
1066178825Sdfr    return CKR_OK;
1067178825Sdfr}
1068178825Sdfr
1069178825SdfrCK_RV
1070178825SdfrC_GetMechanismList(CK_SLOT_ID slotID,
1071178825Sdfr		   CK_MECHANISM_TYPE_PTR pMechanismList,
1072178825Sdfr		   CK_ULONG_PTR pulCount)
1073178825Sdfr{
1074178825Sdfr    INIT_CONTEXT();
1075178825Sdfr    st_logf("GetMechanismList\n");
1076178825Sdfr
1077178825Sdfr    *pulCount = 1;
1078178825Sdfr    if (pMechanismList == NULL_PTR)
1079178825Sdfr	return CKR_OK;
1080178825Sdfr    pMechanismList[1] = CKM_RSA_PKCS;
1081178825Sdfr
1082178825Sdfr    return CKR_OK;
1083178825Sdfr}
1084178825Sdfr
1085178825SdfrCK_RV
1086178825SdfrC_GetMechanismInfo(CK_SLOT_ID slotID,
1087178825Sdfr		   CK_MECHANISM_TYPE type,
1088178825Sdfr		   CK_MECHANISM_INFO_PTR pInfo)
1089178825Sdfr{
1090178825Sdfr    INIT_CONTEXT();
1091178825Sdfr    st_logf("GetMechanismInfo: slot %d type: %d\n",
1092178825Sdfr	    (int)slotID, (int)type);
1093178825Sdfr    memset(pInfo, 0, sizeof(*pInfo));
1094178825Sdfr
1095178825Sdfr    return CKR_OK;
1096178825Sdfr}
1097178825Sdfr
1098178825SdfrCK_RV
1099178825SdfrC_InitToken(CK_SLOT_ID slotID,
1100178825Sdfr	    CK_UTF8CHAR_PTR pPin,
1101178825Sdfr	    CK_ULONG ulPinLen,
1102178825Sdfr	    CK_UTF8CHAR_PTR pLabel)
1103178825Sdfr{
1104178825Sdfr    INIT_CONTEXT();
1105178825Sdfr    st_logf("InitToken: slot %d\n", (int)slotID);
1106178825Sdfr    return CKR_FUNCTION_NOT_SUPPORTED;
1107178825Sdfr}
1108178825Sdfr
1109178825SdfrCK_RV
1110178825SdfrC_OpenSession(CK_SLOT_ID slotID,
1111178825Sdfr	      CK_FLAGS flags,
1112178825Sdfr	      CK_VOID_PTR pApplication,
1113178825Sdfr	      CK_NOTIFY Notify,
1114178825Sdfr	      CK_SESSION_HANDLE_PTR phSession)
1115178825Sdfr{
1116233294Sstas    size_t i;
1117178825Sdfr    INIT_CONTEXT();
1118178825Sdfr    st_logf("OpenSession: slot: %d\n", (int)slotID);
1119233294Sstas
1120178825Sdfr    if (soft_token.open_sessions == MAX_NUM_SESSION)
1121178825Sdfr	return CKR_SESSION_COUNT;
1122178825Sdfr
1123178825Sdfr    soft_token.application = pApplication;
1124178825Sdfr    soft_token.notify = Notify;
1125178825Sdfr
1126178825Sdfr    for (i = 0; i < MAX_NUM_SESSION; i++)
1127178825Sdfr	if (soft_token.state[i].session_handle == CK_INVALID_HANDLE)
1128178825Sdfr	    break;
1129178825Sdfr    if (i == MAX_NUM_SESSION)
1130178825Sdfr	abort();
1131178825Sdfr
1132178825Sdfr    soft_token.open_sessions++;
1133178825Sdfr
1134178825Sdfr    soft_token.state[i].session_handle =
1135178825Sdfr	(CK_SESSION_HANDLE)(random() & 0xfffff);
1136178825Sdfr    *phSession = soft_token.state[i].session_handle;
1137178825Sdfr
1138178825Sdfr    return CKR_OK;
1139178825Sdfr}
1140178825Sdfr
1141178825SdfrCK_RV
1142178825SdfrC_CloseSession(CK_SESSION_HANDLE hSession)
1143178825Sdfr{
1144178825Sdfr    struct session_state *state;
1145178825Sdfr    INIT_CONTEXT();
1146178825Sdfr    st_logf("CloseSession\n");
1147178825Sdfr
1148178825Sdfr    if (verify_session_handle(hSession, &state) != CKR_OK)
1149178825Sdfr	application_error("closed session not open");
1150178825Sdfr    else
1151178825Sdfr	close_session(state);
1152178825Sdfr
1153178825Sdfr    return CKR_OK;
1154178825Sdfr}
1155178825Sdfr
1156178825SdfrCK_RV
1157178825SdfrC_CloseAllSessions(CK_SLOT_ID slotID)
1158178825Sdfr{
1159233294Sstas    size_t i;
1160178825Sdfr    INIT_CONTEXT();
1161178825Sdfr
1162178825Sdfr    st_logf("CloseAllSessions\n");
1163178825Sdfr
1164178825Sdfr    for (i = 0; i < MAX_NUM_SESSION; i++)
1165178825Sdfr	if (soft_token.state[i].session_handle != CK_INVALID_HANDLE)
1166178825Sdfr	    close_session(&soft_token.state[i]);
1167178825Sdfr
1168178825Sdfr    return CKR_OK;
1169178825Sdfr}
1170178825Sdfr
1171178825SdfrCK_RV
1172178825SdfrC_GetSessionInfo(CK_SESSION_HANDLE hSession,
1173178825Sdfr		 CK_SESSION_INFO_PTR pInfo)
1174178825Sdfr{
1175178825Sdfr    st_logf("GetSessionInfo\n");
1176178825Sdfr    INIT_CONTEXT();
1177233294Sstas
1178178825Sdfr    VERIFY_SESSION_HANDLE(hSession, NULL);
1179178825Sdfr
1180178825Sdfr    memset(pInfo, 20, sizeof(*pInfo));
1181178825Sdfr
1182178825Sdfr    pInfo->slotID = 1;
1183178825Sdfr    if (soft_token.flags.login_done)
1184178825Sdfr	pInfo->state = CKS_RO_USER_FUNCTIONS;
1185178825Sdfr    else
1186178825Sdfr	pInfo->state = CKS_RO_PUBLIC_SESSION;
1187178825Sdfr    pInfo->flags = CKF_SERIAL_SESSION;
1188178825Sdfr    pInfo->ulDeviceError = 0;
1189178825Sdfr
1190178825Sdfr    return CKR_OK;
1191178825Sdfr}
1192178825Sdfr
1193178825SdfrCK_RV
1194178825SdfrC_Login(CK_SESSION_HANDLE hSession,
1195178825Sdfr	CK_USER_TYPE userType,
1196178825Sdfr	CK_UTF8CHAR_PTR pPin,
1197178825Sdfr	CK_ULONG ulPinLen)
1198178825Sdfr{
1199178825Sdfr    char *pin = NULL;
1200178825Sdfr    CK_RV ret;
1201178825Sdfr    INIT_CONTEXT();
1202178825Sdfr
1203178825Sdfr    st_logf("Login\n");
1204178825Sdfr
1205178825Sdfr    VERIFY_SESSION_HANDLE(hSession, NULL);
1206178825Sdfr
1207178825Sdfr    if (pPin != NULL_PTR) {
1208178825Sdfr	asprintf(&pin, "%.*s", (int)ulPinLen, pPin);
1209178825Sdfr	st_logf("type: %d password: %s\n", (int)userType, pin);
1210178825Sdfr    }
1211178825Sdfr
1212178825Sdfr    /*
1213178825Sdfr     * Login
1214178825Sdfr     */
1215178825Sdfr
1216178825Sdfr    ret = read_conf_file(soft_token.config_file, userType, pin);
1217178825Sdfr    if (ret == CKR_OK)
1218178825Sdfr	soft_token.flags.login_done = 1;
1219178825Sdfr
1220178825Sdfr    free(pin);
1221233294Sstas
1222178825Sdfr    return soft_token.flags.login_done ? CKR_OK : CKR_PIN_INCORRECT;
1223178825Sdfr}
1224178825Sdfr
1225178825SdfrCK_RV
1226178825SdfrC_Logout(CK_SESSION_HANDLE hSession)
1227178825Sdfr{
1228178825Sdfr    st_logf("Logout\n");
1229178825Sdfr    INIT_CONTEXT();
1230178825Sdfr
1231178825Sdfr    VERIFY_SESSION_HANDLE(hSession, NULL);
1232178825Sdfr    return CKR_FUNCTION_NOT_SUPPORTED;
1233178825Sdfr}
1234178825Sdfr
1235178825SdfrCK_RV
1236178825SdfrC_GetObjectSize(CK_SESSION_HANDLE hSession,
1237178825Sdfr		CK_OBJECT_HANDLE hObject,
1238178825Sdfr		CK_ULONG_PTR pulSize)
1239178825Sdfr{
1240178825Sdfr    st_logf("GetObjectSize\n");
1241178825Sdfr    INIT_CONTEXT();
1242178825Sdfr
1243178825Sdfr    VERIFY_SESSION_HANDLE(hSession, NULL);
1244178825Sdfr    return CKR_FUNCTION_NOT_SUPPORTED;
1245178825Sdfr}
1246178825Sdfr
1247178825SdfrCK_RV
1248178825SdfrC_GetAttributeValue(CK_SESSION_HANDLE hSession,
1249178825Sdfr		    CK_OBJECT_HANDLE hObject,
1250178825Sdfr		    CK_ATTRIBUTE_PTR pTemplate,
1251178825Sdfr		    CK_ULONG ulCount)
1252178825Sdfr{
1253178825Sdfr    struct session_state *state;
1254178825Sdfr    struct st_object *obj;
1255178825Sdfr    CK_ULONG i;
1256178825Sdfr    CK_RV ret;
1257178825Sdfr    int j;
1258178825Sdfr
1259178825Sdfr    INIT_CONTEXT();
1260178825Sdfr
1261178825Sdfr    st_logf("GetAttributeValue: %lx\n",
1262178825Sdfr	    (unsigned long)HANDLE_OBJECT_ID(hObject));
1263178825Sdfr    VERIFY_SESSION_HANDLE(hSession, &state);
1264178825Sdfr
1265178825Sdfr    if ((ret = object_handle_to_object(hObject, &obj)) != CKR_OK) {
1266178825Sdfr	st_logf("object not found: %lx\n",
1267178825Sdfr		(unsigned long)HANDLE_OBJECT_ID(hObject));
1268178825Sdfr	return ret;
1269178825Sdfr    }
1270178825Sdfr
1271178825Sdfr    for (i = 0; i < ulCount; i++) {
1272178825Sdfr	st_logf("	getting 0x%08lx\n", (unsigned long)pTemplate[i].type);
1273178825Sdfr	for (j = 0; j < obj->num_attributes; j++) {
1274178825Sdfr	    if (obj->attrs[j].secret) {
1275178825Sdfr		pTemplate[i].ulValueLen = (CK_ULONG)-1;
1276178825Sdfr		break;
1277178825Sdfr	    }
1278178825Sdfr	    if (pTemplate[i].type == obj->attrs[j].attribute.type) {
1279178825Sdfr		if (pTemplate[i].pValue != NULL_PTR && obj->attrs[j].secret == 0) {
1280178825Sdfr		    if (pTemplate[i].ulValueLen >= obj->attrs[j].attribute.ulValueLen)
1281178825Sdfr			memcpy(pTemplate[i].pValue, obj->attrs[j].attribute.pValue,
1282178825Sdfr			       obj->attrs[j].attribute.ulValueLen);
1283178825Sdfr		}
1284178825Sdfr		pTemplate[i].ulValueLen = obj->attrs[j].attribute.ulValueLen;
1285178825Sdfr		break;
1286178825Sdfr	    }
1287178825Sdfr	}
1288178825Sdfr	if (j == obj->num_attributes) {
1289178825Sdfr	    st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate[i].type);
1290178825Sdfr	    pTemplate[i].ulValueLen = (CK_ULONG)-1;
1291178825Sdfr	}
1292178825Sdfr
1293178825Sdfr    }
1294178825Sdfr    return CKR_OK;
1295178825Sdfr}
1296178825Sdfr
1297178825SdfrCK_RV
1298178825SdfrC_FindObjectsInit(CK_SESSION_HANDLE hSession,
1299178825Sdfr		  CK_ATTRIBUTE_PTR pTemplate,
1300178825Sdfr		  CK_ULONG ulCount)
1301178825Sdfr{
1302178825Sdfr    struct session_state *state;
1303178825Sdfr
1304178825Sdfr    st_logf("FindObjectsInit\n");
1305178825Sdfr
1306178825Sdfr    INIT_CONTEXT();
1307178825Sdfr
1308178825Sdfr    VERIFY_SESSION_HANDLE(hSession, &state);
1309178825Sdfr
1310178825Sdfr    if (state->find.next_object != -1) {
1311178825Sdfr	application_error("application didn't do C_FindObjectsFinal\n");
1312178825Sdfr	find_object_final(state);
1313178825Sdfr    }
1314178825Sdfr    if (ulCount) {
1315178825Sdfr	CK_ULONG i;
1316178825Sdfr
1317178825Sdfr	print_attributes(pTemplate, ulCount);
1318178825Sdfr
1319233294Sstas	state->find.attributes =
1320178825Sdfr	    calloc(1, ulCount * sizeof(state->find.attributes[0]));
1321178825Sdfr	if (state->find.attributes == NULL)
1322178825Sdfr	    return CKR_DEVICE_MEMORY;
1323178825Sdfr	for (i = 0; i < ulCount; i++) {
1324233294Sstas	    state->find.attributes[i].pValue =
1325178825Sdfr		malloc(pTemplate[i].ulValueLen);
1326178825Sdfr	    if (state->find.attributes[i].pValue == NULL) {
1327178825Sdfr		find_object_final(state);
1328178825Sdfr		return CKR_DEVICE_MEMORY;
1329178825Sdfr	    }
1330178825Sdfr	    memcpy(state->find.attributes[i].pValue,
1331178825Sdfr		   pTemplate[i].pValue, pTemplate[i].ulValueLen);
1332178825Sdfr	    state->find.attributes[i].type = pTemplate[i].type;
1333178825Sdfr	    state->find.attributes[i].ulValueLen = pTemplate[i].ulValueLen;
1334178825Sdfr	}
1335178825Sdfr	state->find.num_attributes = ulCount;
1336178825Sdfr	state->find.next_object = 0;
1337178825Sdfr    } else {
1338178825Sdfr	st_logf("find all objects\n");
1339178825Sdfr	state->find.attributes = NULL;
1340178825Sdfr	state->find.num_attributes = 0;
1341178825Sdfr	state->find.next_object = 0;
1342178825Sdfr    }
1343178825Sdfr
1344178825Sdfr    return CKR_OK;
1345178825Sdfr}
1346178825Sdfr
1347178825SdfrCK_RV
1348178825SdfrC_FindObjects(CK_SESSION_HANDLE hSession,
1349178825Sdfr	      CK_OBJECT_HANDLE_PTR phObject,
1350178825Sdfr	      CK_ULONG ulMaxObjectCount,
1351178825Sdfr	      CK_ULONG_PTR pulObjectCount)
1352178825Sdfr{
1353178825Sdfr    struct session_state *state;
1354178825Sdfr    int i;
1355178825Sdfr
1356178825Sdfr    INIT_CONTEXT();
1357178825Sdfr
1358178825Sdfr    st_logf("FindObjects\n");
1359178825Sdfr
1360178825Sdfr    VERIFY_SESSION_HANDLE(hSession, &state);
1361178825Sdfr
1362178825Sdfr    if (state->find.next_object == -1) {
1363178825Sdfr	application_error("application didn't do C_FindObjectsInit\n");
1364178825Sdfr	return CKR_ARGUMENTS_BAD;
1365178825Sdfr    }
1366178825Sdfr    if (ulMaxObjectCount == 0) {
1367178825Sdfr	application_error("application asked for 0 objects\n");
1368178825Sdfr	return CKR_ARGUMENTS_BAD;
1369178825Sdfr    }
1370178825Sdfr    *pulObjectCount = 0;
1371178825Sdfr    for (i = state->find.next_object; i < soft_token.object.num_objs; i++) {
1372178825Sdfr	st_logf("FindObjects: %d\n", i);
1373178825Sdfr	state->find.next_object = i + 1;
1374178825Sdfr	if (attributes_match(soft_token.object.objs[i],
1375178825Sdfr			     state->find.attributes,
1376178825Sdfr			     state->find.num_attributes)) {
1377178825Sdfr	    *phObject++ = soft_token.object.objs[i]->object_handle;
1378178825Sdfr	    ulMaxObjectCount--;
1379178825Sdfr	    (*pulObjectCount)++;
1380178825Sdfr	    if (ulMaxObjectCount == 0)
1381178825Sdfr		break;
1382178825Sdfr	}
1383178825Sdfr    }
1384178825Sdfr    return CKR_OK;
1385178825Sdfr}
1386178825Sdfr
1387178825SdfrCK_RV
1388178825SdfrC_FindObjectsFinal(CK_SESSION_HANDLE hSession)
1389178825Sdfr{
1390178825Sdfr    struct session_state *state;
1391178825Sdfr
1392178825Sdfr    INIT_CONTEXT();
1393178825Sdfr
1394178825Sdfr    st_logf("FindObjectsFinal\n");
1395178825Sdfr    VERIFY_SESSION_HANDLE(hSession, &state);
1396178825Sdfr    find_object_final(state);
1397178825Sdfr    return CKR_OK;
1398178825Sdfr}
1399178825Sdfr
1400178825Sdfrstatic CK_RV
1401178825SdfrcommonInit(CK_ATTRIBUTE *attr_match, int attr_match_len,
1402178825Sdfr	   const CK_MECHANISM_TYPE *mechs, int mechs_len,
1403178825Sdfr	   const CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey,
1404178825Sdfr	   struct st_object **o)
1405178825Sdfr{
1406178825Sdfr    CK_RV ret;
1407178825Sdfr    int i;
1408178825Sdfr
1409178825Sdfr    *o = NULL;
1410178825Sdfr    if ((ret = object_handle_to_object(hKey, o)) != CKR_OK)
1411178825Sdfr	return ret;
1412178825Sdfr
1413178825Sdfr    ret = attributes_match(*o, attr_match, attr_match_len);
1414178825Sdfr    if (!ret) {
1415178825Sdfr	application_error("called commonInit on key that doesn't "
1416178825Sdfr			  "support required attr");
1417178825Sdfr	return CKR_ARGUMENTS_BAD;
1418178825Sdfr    }
1419178825Sdfr
1420178825Sdfr    for (i = 0; i < mechs_len; i++)
1421178825Sdfr	if (mechs[i] == pMechanism->mechanism)
1422178825Sdfr	    break;
1423178825Sdfr    if (i == mechs_len) {
1424178825Sdfr	application_error("called mech (%08lx) not supported\n",
1425178825Sdfr			  pMechanism->mechanism);
1426178825Sdfr	return CKR_ARGUMENTS_BAD;
1427178825Sdfr    }
1428178825Sdfr    return CKR_OK;
1429178825Sdfr}
1430178825Sdfr
1431178825Sdfr
1432178825Sdfrstatic CK_RV
1433233294Sstasdup_mechanism(CK_MECHANISM_PTR *dp, const CK_MECHANISM_PTR pMechanism)
1434178825Sdfr{
1435178825Sdfr    CK_MECHANISM_PTR p;
1436178825Sdfr
1437178825Sdfr    p = malloc(sizeof(*p));
1438178825Sdfr    if (p == NULL)
1439178825Sdfr	return CKR_DEVICE_MEMORY;
1440178825Sdfr
1441233294Sstas    if (*dp)
1442233294Sstas	free(*dp);
1443233294Sstas    *dp = p;
1444178825Sdfr    memcpy(p, pMechanism, sizeof(*p));
1445178825Sdfr
1446178825Sdfr    return CKR_OK;
1447178825Sdfr}
1448178825Sdfr
1449178825SdfrCK_RV
1450178825SdfrC_DigestInit(CK_SESSION_HANDLE hSession,
1451178825Sdfr	     CK_MECHANISM_PTR pMechanism)
1452178825Sdfr{
1453178825Sdfr    st_logf("DigestInit\n");
1454178825Sdfr    INIT_CONTEXT();
1455178825Sdfr    VERIFY_SESSION_HANDLE(hSession, NULL);
1456178825Sdfr    return CKR_FUNCTION_NOT_SUPPORTED;
1457178825Sdfr}
1458178825Sdfr
1459178825SdfrCK_RV
1460178825SdfrC_SignInit(CK_SESSION_HANDLE hSession,
1461178825Sdfr	   CK_MECHANISM_PTR pMechanism,
1462178825Sdfr	   CK_OBJECT_HANDLE hKey)
1463178825Sdfr{
1464178825Sdfr    struct session_state *state;
1465178825Sdfr    CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS };
1466178825Sdfr    CK_BBOOL bool_true = CK_TRUE;
1467178825Sdfr    CK_ATTRIBUTE attr[] = {
1468178825Sdfr	{ CKA_SIGN, &bool_true, sizeof(bool_true) }
1469178825Sdfr    };
1470178825Sdfr    struct st_object *o;
1471178825Sdfr    CK_RV ret;
1472178825Sdfr
1473178825Sdfr    INIT_CONTEXT();
1474178825Sdfr    st_logf("SignInit\n");
1475178825Sdfr    VERIFY_SESSION_HANDLE(hSession, &state);
1476233294Sstas
1477233294Sstas    ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1478178825Sdfr		     mechs, sizeof(mechs)/sizeof(mechs[0]),
1479178825Sdfr		     pMechanism, hKey, &o);
1480178825Sdfr    if (ret)
1481178825Sdfr	return ret;
1482178825Sdfr
1483178825Sdfr    ret = dup_mechanism(&state->sign_mechanism, pMechanism);
1484233294Sstas    if (ret == CKR_OK)
1485178825Sdfr	state->sign_object = OBJECT_ID(o);
1486178825Sdfr
1487178825Sdfr    return CKR_OK;
1488178825Sdfr}
1489178825Sdfr
1490178825SdfrCK_RV
1491178825SdfrC_Sign(CK_SESSION_HANDLE hSession,
1492178825Sdfr       CK_BYTE_PTR pData,
1493178825Sdfr       CK_ULONG ulDataLen,
1494178825Sdfr       CK_BYTE_PTR pSignature,
1495178825Sdfr       CK_ULONG_PTR pulSignatureLen)
1496178825Sdfr{
1497178825Sdfr    struct session_state *state;
1498178825Sdfr    struct st_object *o;
1499178825Sdfr    CK_RV ret;
1500233294Sstas    int hret;
1501178825Sdfr    const AlgorithmIdentifier *alg;
1502178825Sdfr    heim_octet_string sig, data;
1503178825Sdfr
1504178825Sdfr    INIT_CONTEXT();
1505178825Sdfr    st_logf("Sign\n");
1506178825Sdfr    VERIFY_SESSION_HANDLE(hSession, &state);
1507178825Sdfr
1508178825Sdfr    sig.data = NULL;
1509178825Sdfr    sig.length = 0;
1510178825Sdfr
1511178825Sdfr    if (state->sign_object == -1)
1512178825Sdfr	return CKR_ARGUMENTS_BAD;
1513178825Sdfr
1514178825Sdfr    if (pulSignatureLen == NULL) {
1515178825Sdfr	st_logf("signature len NULL\n");
1516178825Sdfr	ret = CKR_ARGUMENTS_BAD;
1517178825Sdfr	goto out;
1518178825Sdfr    }
1519178825Sdfr
1520178825Sdfr    if (pData == NULL_PTR) {
1521178825Sdfr	st_logf("data NULL\n");
1522178825Sdfr	ret = CKR_ARGUMENTS_BAD;
1523178825Sdfr	goto out;
1524178825Sdfr    }
1525178825Sdfr
1526178825Sdfr    o = soft_token.object.objs[state->sign_object];
1527178825Sdfr
1528178825Sdfr    if (hx509_cert_have_private_key(o->cert) == 0) {
1529178825Sdfr	st_logf("private key NULL\n");
1530178825Sdfr	return CKR_ARGUMENTS_BAD;
1531178825Sdfr    }
1532178825Sdfr
1533178825Sdfr    switch(state->sign_mechanism->mechanism) {
1534178825Sdfr    case CKM_RSA_PKCS:
1535178825Sdfr	alg = hx509_signature_rsa_pkcs1_x509();
1536178825Sdfr	break;
1537178825Sdfr    default:
1538178825Sdfr	ret = CKR_FUNCTION_NOT_SUPPORTED;
1539178825Sdfr	goto out;
1540178825Sdfr    }
1541233294Sstas
1542178825Sdfr    data.data = pData;
1543178825Sdfr    data.length = ulDataLen;
1544178825Sdfr
1545178825Sdfr    hret = _hx509_create_signature(context,
1546178825Sdfr				   _hx509_cert_private_key(o->cert),
1547178825Sdfr				   alg,
1548178825Sdfr				   &data,
1549178825Sdfr				   NULL,
1550178825Sdfr				   &sig);
1551178825Sdfr    if (hret) {
1552178825Sdfr	ret = CKR_DEVICE_ERROR;
1553178825Sdfr	goto out;
1554178825Sdfr    }
1555178825Sdfr    *pulSignatureLen = sig.length;
1556178825Sdfr
1557178825Sdfr    if (pSignature != NULL_PTR)
1558178825Sdfr	memcpy(pSignature, sig.data, sig.length);
1559178825Sdfr
1560178825Sdfr    ret = CKR_OK;
1561178825Sdfr out:
1562178825Sdfr    if (sig.data) {
1563178825Sdfr	memset(sig.data, 0, sig.length);
1564178825Sdfr	der_free_octet_string(&sig);
1565178825Sdfr    }
1566178825Sdfr    return ret;
1567178825Sdfr}
1568178825Sdfr
1569178825SdfrCK_RV
1570178825SdfrC_SignUpdate(CK_SESSION_HANDLE hSession,
1571178825Sdfr	     CK_BYTE_PTR pPart,
1572178825Sdfr	     CK_ULONG ulPartLen)
1573178825Sdfr{
1574178825Sdfr    INIT_CONTEXT();
1575178825Sdfr    st_logf("SignUpdate\n");
1576178825Sdfr    VERIFY_SESSION_HANDLE(hSession, NULL);
1577178825Sdfr    return CKR_FUNCTION_NOT_SUPPORTED;
1578178825Sdfr}
1579178825Sdfr
1580178825Sdfr
1581178825SdfrCK_RV
1582178825SdfrC_SignFinal(CK_SESSION_HANDLE hSession,
1583178825Sdfr	    CK_BYTE_PTR pSignature,
1584178825Sdfr	    CK_ULONG_PTR pulSignatureLen)
1585178825Sdfr{
1586178825Sdfr    INIT_CONTEXT();
1587178825Sdfr    st_logf("SignUpdate\n");
1588178825Sdfr    VERIFY_SESSION_HANDLE(hSession, NULL);
1589178825Sdfr    return CKR_FUNCTION_NOT_SUPPORTED;
1590178825Sdfr}
1591178825Sdfr
1592178825SdfrCK_RV
1593178825SdfrC_VerifyInit(CK_SESSION_HANDLE hSession,
1594178825Sdfr	     CK_MECHANISM_PTR pMechanism,
1595178825Sdfr	     CK_OBJECT_HANDLE hKey)
1596178825Sdfr{
1597178825Sdfr    struct session_state *state;
1598178825Sdfr    CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS };
1599178825Sdfr    CK_BBOOL bool_true = CK_TRUE;
1600178825Sdfr    CK_ATTRIBUTE attr[] = {
1601178825Sdfr	{ CKA_VERIFY, &bool_true, sizeof(bool_true) }
1602178825Sdfr    };
1603178825Sdfr    struct st_object *o;
1604178825Sdfr    CK_RV ret;
1605178825Sdfr
1606178825Sdfr    INIT_CONTEXT();
1607178825Sdfr    st_logf("VerifyInit\n");
1608178825Sdfr    VERIFY_SESSION_HANDLE(hSession, &state);
1609233294Sstas
1610233294Sstas    ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1611178825Sdfr		     mechs, sizeof(mechs)/sizeof(mechs[0]),
1612178825Sdfr		     pMechanism, hKey, &o);
1613178825Sdfr    if (ret)
1614178825Sdfr	return ret;
1615178825Sdfr
1616178825Sdfr    ret = dup_mechanism(&state->verify_mechanism, pMechanism);
1617233294Sstas    if (ret == CKR_OK)
1618178825Sdfr	state->verify_object = OBJECT_ID(o);
1619233294Sstas
1620178825Sdfr    return ret;
1621178825Sdfr}
1622178825Sdfr
1623178825SdfrCK_RV
1624178825SdfrC_Verify(CK_SESSION_HANDLE hSession,
1625178825Sdfr	 CK_BYTE_PTR pData,
1626178825Sdfr	 CK_ULONG ulDataLen,
1627178825Sdfr	 CK_BYTE_PTR pSignature,
1628178825Sdfr	 CK_ULONG ulSignatureLen)
1629178825Sdfr{
1630178825Sdfr    struct session_state *state;
1631178825Sdfr    struct st_object *o;
1632178825Sdfr    const AlgorithmIdentifier *alg;
1633178825Sdfr    CK_RV ret;
1634178825Sdfr    int hret;
1635178825Sdfr    heim_octet_string data, sig;
1636178825Sdfr
1637178825Sdfr    INIT_CONTEXT();
1638178825Sdfr    st_logf("Verify\n");
1639178825Sdfr    VERIFY_SESSION_HANDLE(hSession, &state);
1640178825Sdfr
1641178825Sdfr    if (state->verify_object == -1)
1642178825Sdfr	return CKR_ARGUMENTS_BAD;
1643178825Sdfr
1644178825Sdfr    o = soft_token.object.objs[state->verify_object];
1645178825Sdfr
1646178825Sdfr    switch(state->verify_mechanism->mechanism) {
1647178825Sdfr    case CKM_RSA_PKCS:
1648178825Sdfr	alg = hx509_signature_rsa_pkcs1_x509();
1649178825Sdfr	break;
1650178825Sdfr    default:
1651178825Sdfr	ret = CKR_FUNCTION_NOT_SUPPORTED;
1652178825Sdfr	goto out;
1653178825Sdfr    }
1654178825Sdfr
1655178825Sdfr    sig.data = pData;
1656178825Sdfr    sig.length = ulDataLen;
1657178825Sdfr    data.data = pSignature;
1658178825Sdfr    data.length = ulSignatureLen;
1659178825Sdfr
1660178825Sdfr    hret = _hx509_verify_signature(context,
1661233294Sstas				   o->cert,
1662178825Sdfr				   alg,
1663178825Sdfr				   &data,
1664178825Sdfr				   &sig);
1665178825Sdfr    if (hret) {
1666178825Sdfr	ret = CKR_GENERAL_ERROR;
1667178825Sdfr	goto out;
1668178825Sdfr    }
1669178825Sdfr    ret = CKR_OK;
1670178825Sdfr
1671178825Sdfr out:
1672178825Sdfr    return ret;
1673178825Sdfr}
1674178825Sdfr
1675178825Sdfr
1676178825SdfrCK_RV
1677178825SdfrC_VerifyUpdate(CK_SESSION_HANDLE hSession,
1678178825Sdfr	       CK_BYTE_PTR pPart,
1679178825Sdfr	       CK_ULONG ulPartLen)
1680178825Sdfr{
1681178825Sdfr    INIT_CONTEXT();
1682178825Sdfr    st_logf("VerifyUpdate\n");
1683178825Sdfr    VERIFY_SESSION_HANDLE(hSession, NULL);
1684178825Sdfr    return CKR_FUNCTION_NOT_SUPPORTED;
1685178825Sdfr}
1686178825Sdfr
1687178825SdfrCK_RV
1688178825SdfrC_VerifyFinal(CK_SESSION_HANDLE hSession,
1689178825Sdfr	      CK_BYTE_PTR pSignature,
1690178825Sdfr	      CK_ULONG ulSignatureLen)
1691178825Sdfr{
1692178825Sdfr    INIT_CONTEXT();
1693178825Sdfr    st_logf("VerifyFinal\n");
1694178825Sdfr    VERIFY_SESSION_HANDLE(hSession, NULL);
1695178825Sdfr    return CKR_FUNCTION_NOT_SUPPORTED;
1696178825Sdfr}
1697178825Sdfr
1698178825SdfrCK_RV
1699178825SdfrC_GenerateRandom(CK_SESSION_HANDLE hSession,
1700178825Sdfr		 CK_BYTE_PTR RandomData,
1701178825Sdfr		 CK_ULONG ulRandomLen)
1702178825Sdfr{
1703178825Sdfr    INIT_CONTEXT();
1704178825Sdfr    st_logf("GenerateRandom\n");
1705178825Sdfr    VERIFY_SESSION_HANDLE(hSession, NULL);
1706178825Sdfr    return CKR_FUNCTION_NOT_SUPPORTED;
1707178825Sdfr}
1708178825Sdfr
1709178825Sdfr
1710178825SdfrCK_FUNCTION_LIST funcs = {
1711178825Sdfr    { 2, 11 },
1712178825Sdfr    C_Initialize,
1713178825Sdfr    C_Finalize,
1714178825Sdfr    C_GetInfo,
1715178825Sdfr    C_GetFunctionList,
1716178825Sdfr    C_GetSlotList,
1717178825Sdfr    C_GetSlotInfo,
1718178825Sdfr    C_GetTokenInfo,
1719178825Sdfr    C_GetMechanismList,
1720178825Sdfr    C_GetMechanismInfo,
1721178825Sdfr    C_InitToken,
1722178825Sdfr    (void *)func_not_supported, /* C_InitPIN */
1723178825Sdfr    (void *)func_not_supported, /* C_SetPIN */
1724178825Sdfr    C_OpenSession,
1725178825Sdfr    C_CloseSession,
1726178825Sdfr    C_CloseAllSessions,
1727178825Sdfr    C_GetSessionInfo,
1728178825Sdfr    (void *)func_not_supported, /* C_GetOperationState */
1729178825Sdfr    (void *)func_not_supported, /* C_SetOperationState */
1730178825Sdfr    C_Login,
1731178825Sdfr    C_Logout,
1732178825Sdfr    (void *)func_not_supported, /* C_CreateObject */
1733178825Sdfr    (void *)func_not_supported, /* C_CopyObject */
1734178825Sdfr    (void *)func_not_supported, /* C_DestroyObject */
1735178825Sdfr    (void *)func_not_supported, /* C_GetObjectSize */
1736178825Sdfr    C_GetAttributeValue,
1737178825Sdfr    (void *)func_not_supported, /* C_SetAttributeValue */
1738178825Sdfr    C_FindObjectsInit,
1739178825Sdfr    C_FindObjects,
1740178825Sdfr    C_FindObjectsFinal,
1741178825Sdfr    (void *)func_not_supported, /* C_EncryptInit, */
1742178825Sdfr    (void *)func_not_supported, /* C_Encrypt, */
1743178825Sdfr    (void *)func_not_supported, /* C_EncryptUpdate, */
1744178825Sdfr    (void *)func_not_supported, /* C_EncryptFinal, */
1745178825Sdfr    (void *)func_not_supported, /* C_DecryptInit, */
1746178825Sdfr    (void *)func_not_supported, /* C_Decrypt, */
1747178825Sdfr    (void *)func_not_supported, /* C_DecryptUpdate, */
1748178825Sdfr    (void *)func_not_supported, /* C_DecryptFinal, */
1749178825Sdfr    C_DigestInit,
1750178825Sdfr    (void *)func_not_supported, /* C_Digest */
1751178825Sdfr    (void *)func_not_supported, /* C_DigestUpdate */
1752178825Sdfr    (void *)func_not_supported, /* C_DigestKey */
1753178825Sdfr    (void *)func_not_supported, /* C_DigestFinal */
1754178825Sdfr    C_SignInit,
1755178825Sdfr    C_Sign,
1756178825Sdfr    C_SignUpdate,
1757178825Sdfr    C_SignFinal,
1758178825Sdfr    (void *)func_not_supported, /* C_SignRecoverInit */
1759178825Sdfr    (void *)func_not_supported, /* C_SignRecover */
1760178825Sdfr    C_VerifyInit,
1761178825Sdfr    C_Verify,
1762178825Sdfr    C_VerifyUpdate,
1763178825Sdfr    C_VerifyFinal,
1764178825Sdfr    (void *)func_not_supported, /* C_VerifyRecoverInit */
1765178825Sdfr    (void *)func_not_supported, /* C_VerifyRecover */
1766178825Sdfr    (void *)func_not_supported, /* C_DigestEncryptUpdate */
1767178825Sdfr    (void *)func_not_supported, /* C_DecryptDigestUpdate */
1768178825Sdfr    (void *)func_not_supported, /* C_SignEncryptUpdate */
1769178825Sdfr    (void *)func_not_supported, /* C_DecryptVerifyUpdate */
1770178825Sdfr    (void *)func_not_supported, /* C_GenerateKey */
1771178825Sdfr    (void *)func_not_supported, /* C_GenerateKeyPair */
1772178825Sdfr    (void *)func_not_supported, /* C_WrapKey */
1773178825Sdfr    (void *)func_not_supported, /* C_UnwrapKey */
1774178825Sdfr    (void *)func_not_supported, /* C_DeriveKey */
1775178825Sdfr    (void *)func_not_supported, /* C_SeedRandom */
1776178825Sdfr    C_GenerateRandom,
1777178825Sdfr    (void *)func_not_supported, /* C_GetFunctionStatus */
1778178825Sdfr    (void *)func_not_supported, /* C_CancelFunction */
1779178825Sdfr    (void *)func_not_supported  /* C_WaitForSlotEvent */
1780178825Sdfr};
1781