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