Imported Upstream version 1.20.1
[platform/upstream/krb5.git] / src / tests / softpkcs11 / main.c
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  * Copyright (c) 2004-2006, Stockholms universitet
4  * (Stockholm University, Stockholm Sweden)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * 3. Neither the name of the university nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 #include "k5-platform.h"
36
37 #include <openssl/err.h>
38 #include <openssl/evp.h>
39 #include <openssl/pem.h>
40 #include <openssl/rand.h>
41 #include <openssl/x509.h>
42
43 #include <ctype.h>
44 #include <pwd.h>
45
46 #include <pkcs11.h>
47
48 #if OPENSSL_VERSION_NUMBER < 0x10100000L
49 #define EVP_PKEY_get0_RSA(key) ((key)->pkey.rsa)
50 #define RSA_PKCS1_OpenSSL RSA_PKCS1_SSLeay
51 #define RSA_get0_key compat_rsa_get0_key
52 static void
53 compat_rsa_get0_key(const RSA *rsa, const BIGNUM **n, const BIGNUM **e,
54                     const BIGNUM **d)
55 {
56     if (n != NULL)
57         *n = rsa->n;
58     if (e != NULL)
59         *e = rsa->e;
60     if (d != NULL)
61         *d = rsa->d;
62 }
63 #endif
64
65 #define OPENSSL_ASN1_MALLOC_ENCODE(T, B, BL, S, R)      \
66     {                                                   \
67         unsigned char *p;                               \
68         (BL) = i2d_##T((S), NULL);                      \
69         if ((BL) <= 0) {                                \
70             (R) = EINVAL;                               \
71         } else {                                        \
72             (B) = malloc((BL));                         \
73             if ((B) == NULL) {                          \
74                 (R) = ENOMEM;                           \
75             } else {                                    \
76                 p = (B);                                \
77                 (R) = 0;                                \
78                 (BL) = i2d_##T((S), &p);                \
79                 if ((BL) <= 0) {                        \
80                     free((B));                          \
81                     (B) = NULL;                         \
82                     (R) = EINVAL;                       \
83                 }                                       \
84             }                                           \
85         }                                               \
86     }
87
88 /* RCSID("$Id: main.c,v 1.24 2006/01/11 12:42:53 lha Exp $"); */
89
90 #define OBJECT_ID_MASK          0xfff
91 #define HANDLE_OBJECT_ID(h)     ((h) & OBJECT_ID_MASK)
92 #define OBJECT_ID(obj)          HANDLE_OBJECT_ID((obj)->object_handle)
93
94 struct st_attr {
95     CK_ATTRIBUTE attribute;
96     int secret;
97 };
98
99 struct st_object {
100     CK_OBJECT_HANDLE object_handle;
101     struct st_attr *attrs;
102     int num_attributes;
103     enum {
104         STO_T_CERTIFICATE,
105         STO_T_PRIVATE_KEY,
106         STO_T_PUBLIC_KEY
107     } type;
108     union {
109         X509 *cert;
110         EVP_PKEY *public_key;
111         struct {
112             char *file;
113             EVP_PKEY *key;
114             X509 *cert;
115         } private_key;
116     } u;
117 };
118
119 static struct soft_token {
120     CK_VOID_PTR application;
121     CK_NOTIFY notify;
122     struct {
123         struct st_object **objs;
124         int num_objs;
125     } object;
126     struct {
127         int hardware_slot;
128         int app_error_fatal;
129         int login_done;
130     } flags;
131     int open_sessions;
132     struct session_state {
133         CK_SESSION_HANDLE session_handle;
134
135         struct {
136             CK_ATTRIBUTE *attributes;
137             CK_ULONG num_attributes;
138             int next_object;
139         } find;
140
141         int encrypt_object;
142         CK_MECHANISM_PTR encrypt_mechanism;
143         int decrypt_object;
144         CK_MECHANISM_PTR decrypt_mechanism;
145         int sign_object;
146         CK_MECHANISM_PTR sign_mechanism;
147         int verify_object;
148         CK_MECHANISM_PTR verify_mechanism;
149         int digest_object;
150     } state[10];
151 #define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0]))
152     FILE *logfile;
153     CK_SESSION_HANDLE next_session_handle;
154 } soft_token;
155
156 static void
157 application_error(const char *fmt, ...)
158 {
159     va_list ap;
160     va_start(ap, fmt);
161     vprintf(fmt, ap);
162     va_end(ap);
163     if (soft_token.flags.app_error_fatal)
164         abort();
165 }
166
167 static void
168 st_logf(const char *fmt, ...)
169 {
170     va_list ap;
171     if (soft_token.logfile == NULL)
172         return;
173     va_start(ap, fmt);
174     vfprintf(soft_token.logfile, fmt, ap);
175     va_end(ap);
176     fflush(soft_token.logfile);
177 }
178
179 static void
180 snprintf_fill(char *str, int size, char fillchar, const char *fmt, ...)
181 {
182     int len;
183     va_list ap;
184     va_start(ap, fmt);
185     len = vsnprintf(str, size, fmt, ap);
186     va_end(ap);
187     if (len < 0 || len > size)
188         return;
189     while(len < size)
190         str[len++] = fillchar;
191 }
192
193 #ifndef TEST_APP
194 #define printf error_use_st_logf
195 #endif
196
197 #define VERIFY_SESSION_HANDLE(s, state)                 \
198     {                                                   \
199         CK_RV vshret;                                   \
200         vshret = verify_session_handle(s, state);       \
201         if (vshret != CKR_OK) {                         \
202             /* return CKR_OK */;                        \
203         }                                               \
204     }
205
206 static CK_RV
207 verify_session_handle(CK_SESSION_HANDLE hSession,
208                       struct session_state **state)
209 {
210     size_t i;
211
212     for (i = 0; i < MAX_NUM_SESSION; i++){
213         if (soft_token.state[i].session_handle == hSession)
214             break;
215     }
216     if (i == MAX_NUM_SESSION) {
217         application_error("use of invalid handle: 0x%08lx\n",
218                           (unsigned long)hSession);
219         return CKR_SESSION_HANDLE_INVALID;
220     }
221     if (state)
222         *state = &soft_token.state[i];
223     return CKR_OK;
224 }
225
226 static CK_RV
227 object_handle_to_object(CK_OBJECT_HANDLE handle,
228                         struct st_object **object)
229 {
230     int i = HANDLE_OBJECT_ID(handle);
231
232     *object = NULL;
233     if (i >= soft_token.object.num_objs)
234         return CKR_ARGUMENTS_BAD;
235     if (soft_token.object.objs[i] == NULL)
236         return CKR_ARGUMENTS_BAD;
237     if (soft_token.object.objs[i]->object_handle != handle)
238         return CKR_ARGUMENTS_BAD;
239     *object = soft_token.object.objs[i];
240     return CKR_OK;
241 }
242
243 static int
244 attributes_match(const struct st_object *obj,
245                  const CK_ATTRIBUTE *attributes,
246                  CK_ULONG num_attributes)
247 {
248     CK_ULONG i;
249     int j;
250     st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj));
251
252     for (i = 0; i < num_attributes; i++) {
253         int match = 0;
254         for (j = 0; j < obj->num_attributes; j++) {
255             if (attributes[i].type == obj->attrs[j].attribute.type &&
256                 attributes[i].ulValueLen == obj->attrs[j].attribute.ulValueLen &&
257                 memcmp(attributes[i].pValue, obj->attrs[j].attribute.pValue,
258                        attributes[i].ulValueLen) == 0) {
259                 match = 1;
260                 break;
261             }
262         }
263         if (match == 0) {
264             st_logf("type %lu attribute have no match\n", attributes[i].type);
265             return 0;
266         }
267     }
268     st_logf("attribute matches\n");
269     return 1;
270 }
271
272 static void
273 print_attributes(const CK_ATTRIBUTE *attributes,
274                  CK_ULONG num_attributes)
275 {
276     CK_ULONG i;
277
278     st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes);
279
280     for (i = 0; i < num_attributes; i++) {
281         st_logf("  type: ");
282         switch (attributes[i].type) {
283         case CKA_TOKEN: {
284             CK_BBOOL *ck_true;
285             if (attributes[i].ulValueLen != sizeof(CK_BBOOL)) {
286                 application_error("token attribute wrong length\n");
287                 break;
288             }
289             ck_true = attributes[i].pValue;
290             st_logf("token: %s", *ck_true ? "TRUE" : "FALSE");
291             break;
292         }
293         case CKA_CLASS: {
294             CK_OBJECT_CLASS *class;
295             if (attributes[i].ulValueLen != sizeof(CK_ULONG)) {
296                 application_error("class attribute wrong length\n");
297                 break;
298             }
299             class = attributes[i].pValue;
300             st_logf("class ");
301             switch (*class) {
302             case CKO_CERTIFICATE:
303                 st_logf("certificate");
304                 break;
305             case CKO_PUBLIC_KEY:
306                 st_logf("public key");
307                 break;
308             case CKO_PRIVATE_KEY:
309                 st_logf("private key");
310                 break;
311             case CKO_SECRET_KEY:
312                 st_logf("secret key");
313                 break;
314             case CKO_DOMAIN_PARAMETERS:
315                 st_logf("domain parameters");
316                 break;
317             default:
318                 st_logf("[class %lx]", (long unsigned)*class);
319                 break;
320             }
321             break;
322         }
323         case CKA_PRIVATE:
324             st_logf("private");
325             break;
326         case CKA_LABEL:
327             st_logf("label");
328             break;
329         case CKA_APPLICATION:
330             st_logf("application");
331             break;
332         case CKA_VALUE:
333             st_logf("value");
334             break;
335         case CKA_ID:
336             st_logf("id");
337             break;
338         default:
339             st_logf("[unknown 0x%08lx]", (unsigned long)attributes[i].type);
340             break;
341         }
342         st_logf("\n");
343     }
344 }
345
346 static void
347 free_st_object(struct st_object *o)
348 {
349     int i;
350
351     for (i = 0; i < o->num_attributes; i++)
352         free(o->attrs[i].attribute.pValue);
353     free(o->attrs);
354     if (o->type == STO_T_CERTIFICATE) {
355         X509_free(o->u.cert);
356     } else if (o->type == STO_T_PRIVATE_KEY) {
357         free(o->u.private_key.file);
358         EVP_PKEY_free(o->u.private_key.key);
359         X509_free(o->u.private_key.cert);
360     } else if (o->type == STO_T_PUBLIC_KEY) {
361         EVP_PKEY_free(o->u.public_key);
362     }
363     free(o);
364 }
365
366 static struct st_object *
367 add_st_object(void)
368 {
369     struct st_object *o, **objs;
370
371     objs = realloc(soft_token.object.objs,
372                    (soft_token.object.num_objs + 1) *
373                    sizeof(soft_token.object.objs[0]));
374     if (objs == NULL)
375         return NULL;
376     soft_token.object.objs = objs;
377
378     o = calloc(1, sizeof(*o));
379     if (o == NULL)
380         return NULL;
381     o->attrs = NULL;
382     o->num_attributes = 0;
383     o->object_handle = soft_token.object.num_objs;
384
385     soft_token.object.objs[soft_token.object.num_objs++] = o;
386     return o;
387 }
388
389 static CK_RV
390 add_object_attribute(struct st_object *o,
391                      int secret,
392                      CK_ATTRIBUTE_TYPE type,
393                      CK_VOID_PTR pValue,
394                      CK_ULONG ulValueLen)
395 {
396     struct st_attr *a;
397     int i;
398
399     i = o->num_attributes;
400     a = realloc(o->attrs, (i + 1) * sizeof(o->attrs[0]));
401     if (a == NULL)
402         return CKR_DEVICE_MEMORY;
403     o->attrs = a;
404     o->attrs[i].secret = secret;
405     o->attrs[i].attribute.type = type;
406     o->attrs[i].attribute.pValue = malloc(ulValueLen);
407     if (o->attrs[i].attribute.pValue == NULL && ulValueLen != 0)
408         return CKR_DEVICE_MEMORY;
409     memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen);
410     o->attrs[i].attribute.ulValueLen = ulValueLen;
411     o->num_attributes++;
412
413     return CKR_OK;
414 }
415
416 #ifdef HAVE_EVP_PKEY_GET_BN_PARAM
417
418 /* Declare owner pointers since EVP_PKEY_get_bn_param() gives us copies. */
419 #define DECLARE_BIGNUM(name) BIGNUM *name = NULL
420 #define RELEASE_BIGNUM(bn) BN_clear_free(bn)
421 static CK_RV
422 get_bignums(EVP_PKEY *key, BIGNUM **n, BIGNUM **e)
423 {
424     if (EVP_PKEY_get_bn_param(key, "n", n) == 0 ||
425         EVP_PKEY_get_bn_param(key, "e", e) == 0)
426         return CKR_DEVICE_ERROR;
427
428     return CKR_OK;
429 }
430
431 #else
432
433 /* Declare const pointers since the old API gives us aliases. */
434 #define DECLARE_BIGNUM(name) const BIGNUM *name
435 #define RELEASE_BIGNUM(bn)
436 static CK_RV
437 get_bignums(EVP_PKEY *key, const BIGNUM **n, const BIGNUM **e)
438 {
439     const RSA *rsa;
440
441     rsa = EVP_PKEY_get0_RSA(key);
442     RSA_get0_key(rsa, n, e, NULL);
443
444     return CKR_OK;
445 }
446
447 #endif
448
449 static CK_RV
450 add_pubkey_info(struct st_object *o, CK_KEY_TYPE key_type, EVP_PKEY *key)
451 {
452     CK_BYTE *modulus = NULL, *exponent = 0;
453     size_t modulus_len = 0, exponent_len = 0;
454     CK_ULONG modulus_bits = 0;
455     CK_RV ret;
456     DECLARE_BIGNUM(n);
457     DECLARE_BIGNUM(e);
458
459     if (key_type != CKK_RSA)
460         abort();
461
462     ret = get_bignums(key, &n, &e);
463     if (ret != CKR_OK)
464         goto done;
465
466     modulus_bits = BN_num_bits(n);
467     modulus_len = BN_num_bytes(n);
468     exponent_len = BN_num_bytes(e);
469
470     modulus = malloc(modulus_len);
471     exponent = malloc(exponent_len);
472     if (modulus == NULL || exponent == NULL) {
473         ret = CKR_DEVICE_MEMORY;
474         goto done;
475     }
476
477     BN_bn2bin(n, modulus);
478     BN_bn2bin(e, exponent);
479
480     add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len);
481     add_object_attribute(o, 0, CKA_MODULUS_BITS, &modulus_bits,
482                          sizeof(modulus_bits));
483     add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT, exponent, exponent_len);
484
485     ret = CKR_OK;
486 done:
487     free(modulus);
488     free(exponent);
489     RELEASE_BIGNUM(n);
490     RELEASE_BIGNUM(e);
491     return ret;
492 }
493
494 static int
495 pem_callback(char *buf, int num, int w, void *key)
496 {
497     return -1;
498 }
499
500
501 static CK_RV
502 add_certificate(char *label,
503                 const char *cert_file,
504                 const char *private_key_file,
505                 char *id,
506                 int anchor)
507 {
508     struct st_object *o = NULL;
509     CK_BBOOL bool_true = CK_TRUE;
510     CK_BBOOL bool_false = CK_FALSE;
511     CK_OBJECT_CLASS c;
512     CK_CERTIFICATE_TYPE cert_type = CKC_X_509;
513     CK_KEY_TYPE key_type;
514     CK_MECHANISM_TYPE mech_type;
515     void *cert_data = NULL;
516     size_t cert_length;
517     void *subject_data = NULL;
518     size_t subject_length;
519     void *issuer_data = NULL;
520     size_t issuer_length;
521     void *serial_data = NULL;
522     size_t serial_length;
523     CK_RV ret = CKR_GENERAL_ERROR;
524     X509 *cert;
525     EVP_PKEY *public_key;
526
527     size_t id_len = strlen(id);
528
529     {
530         FILE *f;
531
532         f = fopen(cert_file, "r");
533         if (f == NULL) {
534             st_logf("failed to open file %s\n", cert_file);
535             return CKR_GENERAL_ERROR;
536         }
537
538         cert = PEM_read_X509(f, NULL, NULL, NULL);
539         fclose(f);
540         if (cert == NULL) {
541             st_logf("failed reading PEM cert\n");
542             return CKR_GENERAL_ERROR;
543         }
544
545         OPENSSL_ASN1_MALLOC_ENCODE(X509, cert_data, cert_length, cert, ret);
546         if (ret)
547             goto out;
548
549         OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, issuer_data, issuer_length,
550                                    X509_get_issuer_name(cert), ret);
551         if (ret)
552             goto out;
553
554         OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, subject_data, subject_length,
555                                    X509_get_subject_name(cert), ret);
556         if (ret)
557             goto out;
558
559         OPENSSL_ASN1_MALLOC_ENCODE(ASN1_INTEGER, serial_data, serial_length,
560                                    X509_get_serialNumber(cert), ret);
561         if (ret)
562             goto out;
563
564     }
565
566     st_logf("done parsing, adding to internal structure\n");
567
568     o = add_st_object();
569     if (o == NULL) {
570         ret = CKR_DEVICE_MEMORY;
571         goto out;
572     }
573     o->type = STO_T_CERTIFICATE;
574     o->u.cert = X509_dup(cert);
575     if (o->u.cert == NULL) {
576         ret = CKR_DEVICE_MEMORY;
577         goto out;
578     }
579     public_key = X509_get_pubkey(o->u.cert);
580
581     switch (EVP_PKEY_base_id(public_key)) {
582     case EVP_PKEY_RSA:
583         key_type = CKK_RSA;
584         break;
585     case EVP_PKEY_DSA:
586         key_type = CKK_DSA;
587         break;
588     default:
589         st_logf("invalid key_type\n");
590         ret = CKR_GENERAL_ERROR;
591         goto out;
592     }
593
594     c = CKO_CERTIFICATE;
595     add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c));
596     add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
597     add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
598     add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
599     add_object_attribute(o, 0, CKA_LABEL, label, strlen(label));
600
601     add_object_attribute(o, 0, CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type));
602     add_object_attribute(o, 0, CKA_ID, id, id_len);
603
604     add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length);
605     add_object_attribute(o, 0, CKA_ISSUER, issuer_data, issuer_length);
606     add_object_attribute(o, 0, CKA_SERIAL_NUMBER, serial_data, serial_length);
607     add_object_attribute(o, 0, CKA_VALUE, cert_data, cert_length);
608     if (anchor)
609         add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true));
610     else
611         add_object_attribute(o, 0, CKA_TRUSTED, &bool_false, sizeof(bool_false));
612
613     st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o));
614
615     o = add_st_object();
616     if (o == NULL) {
617         ret = CKR_DEVICE_MEMORY;
618         goto out;
619     }
620     o->type = STO_T_PUBLIC_KEY;
621     o->u.public_key = public_key;
622
623     c = CKO_PUBLIC_KEY;
624     add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c));
625     add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
626     add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
627     add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
628     add_object_attribute(o, 0, CKA_LABEL, label, strlen(label));
629
630     add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
631     add_object_attribute(o, 0, CKA_ID, id, id_len);
632     add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */
633     add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */
634     add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
635     add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
636     mech_type = CKM_RSA_X_509;
637     add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
638
639     add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length);
640     add_object_attribute(o, 0, CKA_ENCRYPT, &bool_true, sizeof(bool_true));
641     add_object_attribute(o, 0, CKA_VERIFY, &bool_true, sizeof(bool_true));
642     add_object_attribute(o, 0, CKA_VERIFY_RECOVER, &bool_false, sizeof(bool_false));
643     add_object_attribute(o, 0, CKA_WRAP, &bool_true, sizeof(bool_true));
644     add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true));
645
646     add_pubkey_info(o, key_type, public_key);
647
648     st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o));
649
650     if (private_key_file) {
651         CK_FLAGS flags;
652         FILE *f;
653
654         o = add_st_object();
655         if (o == NULL) {
656             ret = CKR_DEVICE_MEMORY;
657             goto out;
658         }
659         o->type = STO_T_PRIVATE_KEY;
660         o->u.private_key.file = strdup(private_key_file);
661         o->u.private_key.key = NULL;
662
663         o->u.private_key.cert = X509_dup(cert);
664         if (o->u.private_key.cert == NULL) {
665             ret = CKR_DEVICE_MEMORY;
666             goto out;
667         }
668
669         c = CKO_PRIVATE_KEY;
670         add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c));
671         add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
672         add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false));
673         add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
674         add_object_attribute(o, 0, CKA_LABEL, label, strlen(label));
675
676         add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
677         add_object_attribute(o, 0, CKA_ID, id, id_len);
678         add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */
679         add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */
680         add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
681         add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
682         mech_type = CKM_RSA_X_509;
683         add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));
684
685         add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length);
686         add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true));
687         add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true));
688         flags = 0;
689         add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags));
690
691         add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true));
692         add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true));
693         add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false));
694         add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true));
695         add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true));
696         add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false));
697
698         add_pubkey_info(o, key_type, public_key);
699
700         f = fopen(private_key_file, "r");
701         if (f == NULL) {
702             st_logf("failed to open private key\n");
703             return CKR_GENERAL_ERROR;
704         }
705
706         o->u.private_key.key = PEM_read_PrivateKey(f, NULL, pem_callback, NULL);
707         fclose(f);
708         if (o->u.private_key.key == NULL) {
709             st_logf("failed to read private key a startup\n");
710             /* don't bother with this failure for now,
711                fix it at C_Login time */;
712         } else {
713             /* XXX verify keytype */
714
715             if (X509_check_private_key(cert, o->u.private_key.key) != 1) {
716                 EVP_PKEY_free(o->u.private_key.key);
717                 o->u.private_key.key = NULL;
718                 st_logf("private key doesn't verify\n");
719             } else {
720                 st_logf("private key usable\n");
721                 soft_token.flags.login_done = 1;
722             }
723         }
724     }
725
726     ret = CKR_OK;
727 out:
728     if (ret != CKR_OK) {
729         st_logf("something went wrong when adding cert!\n");
730
731         /* XXX wack o */;
732     }
733     free(cert_data);
734     free(serial_data);
735     free(issuer_data);
736     free(subject_data);
737     X509_free(cert);
738
739     return ret;
740 }
741
742 static void
743 find_object_final(struct session_state *state)
744 {
745     if (state->find.attributes) {
746         CK_ULONG i;
747
748         for (i = 0; i < state->find.num_attributes; i++) {
749             if (state->find.attributes[i].pValue)
750                 free(state->find.attributes[i].pValue);
751         }
752         free(state->find.attributes);
753         state->find.attributes = NULL;
754         state->find.num_attributes = 0;
755         state->find.next_object = -1;
756     }
757 }
758
759 static void
760 reset_crypto_state(struct session_state *state)
761 {
762     state->encrypt_object = -1;
763     if (state->encrypt_mechanism)
764         free(state->encrypt_mechanism);
765     state->encrypt_mechanism = NULL_PTR;
766     state->decrypt_object = -1;
767     if (state->decrypt_mechanism)
768         free(state->decrypt_mechanism);
769     state->decrypt_mechanism = NULL_PTR;
770     state->sign_object = -1;
771     if (state->sign_mechanism)
772         free(state->sign_mechanism);
773     state->sign_mechanism = NULL_PTR;
774     state->verify_object = -1;
775     if (state->verify_mechanism)
776         free(state->verify_mechanism);
777     state->verify_mechanism = NULL_PTR;
778     state->digest_object = -1;
779 }
780
781 static void
782 close_session(struct session_state *state)
783 {
784     if (state->find.attributes) {
785         application_error("application didn't do C_FindObjectsFinal\n");
786         find_object_final(state);
787     }
788
789     state->session_handle = CK_INVALID_HANDLE;
790     soft_token.application = NULL_PTR;
791     soft_token.notify = NULL_PTR;
792     reset_crypto_state(state);
793 }
794
795 static const char *
796 has_session(void)
797 {
798     return soft_token.open_sessions > 0 ? "yes" : "no";
799 }
800
801 static void
802 read_conf_file(const char *fn)
803 {
804     char buf[1024], *cert, *key, *id, *label, *s, *p;
805     int anchor;
806     FILE *f;
807
808     f = fopen(fn, "r");
809     if (f == NULL) {
810         st_logf("can't open configuration file %s\n", fn);
811         return;
812     }
813
814     while(fgets(buf, sizeof(buf), f) != NULL) {
815         buf[strcspn(buf, "\n")] = '\0';
816
817         anchor = 0;
818
819         st_logf("line: %s\n", buf);
820
821         p = buf;
822         while (isspace(*p))
823             p++;
824         if (*p == '#')
825             continue;
826         while (isspace(*p))
827             p++;
828
829         s = NULL;
830         id = strtok_r(p, "\t", &s);
831         if (id == NULL)
832             continue;
833         label = strtok_r(NULL, "\t", &s);
834         if (label == NULL)
835             continue;
836         cert = strtok_r(NULL, "\t", &s);
837         if (cert == NULL)
838             continue;
839         key = strtok_r(NULL, "\t", &s);
840
841         /* XXX */
842         if (strcmp(id, "anchor") == 0) {
843             id = "\x00\x00";
844             anchor = 1;
845         }
846
847         st_logf("adding: %s\n", label);
848
849         add_certificate(label, cert, key, id, anchor);
850     }
851
852     fclose(f);
853 }
854
855 static CK_RV
856 func_not_supported(void)
857 {
858     st_logf("function not supported\n");
859     return CKR_FUNCTION_NOT_SUPPORTED;
860 }
861
862 static char *
863 get_rcfilename()
864 {
865     struct passwd *pw;
866     const char *home = NULL;
867     char *fn;
868
869     if (getuid() == geteuid()) {
870         fn = getenv("SOFTPKCS11RC");
871         if (fn != NULL)
872             return strdup(fn);
873
874         home = getenv("HOME");
875     }
876
877     if (home == NULL) {
878         pw = getpwuid(getuid());
879         if (pw != NULL)
880             home = pw->pw_dir;
881     }
882
883     if (home == NULL)
884         return strdup("/etc/soft-token.rc");
885
886     if (asprintf(&fn, "%s/.soft-token.rc", home) < 0)
887         return NULL;
888     return fn;
889 }
890
891 CK_RV
892 C_Initialize(CK_VOID_PTR a)
893 {
894     CK_C_INITIALIZE_ARGS_PTR args = a;
895     size_t i;
896     char *fn;
897
898     st_logf("Initialize\n");
899
900     OpenSSL_add_all_algorithms();
901     ERR_load_crypto_strings();
902
903     for (i = 0; i < MAX_NUM_SESSION; i++) {
904         soft_token.state[i].session_handle = CK_INVALID_HANDLE;
905         soft_token.state[i].find.attributes = NULL;
906         soft_token.state[i].find.num_attributes = 0;
907         soft_token.state[i].find.next_object = -1;
908         reset_crypto_state(&soft_token.state[i]);
909     }
910
911     soft_token.flags.hardware_slot = 1;
912     soft_token.flags.app_error_fatal = 0;
913     soft_token.flags.login_done = 0;
914
915     soft_token.object.objs = NULL;
916     soft_token.object.num_objs = 0;
917
918     soft_token.logfile = NULL;
919 #if 0
920     soft_token.logfile = stdout;
921 #endif
922 #if 0
923     soft_token.logfile = fopen("/tmp/log-pkcs11.txt", "a");
924 #endif
925
926     if (a != NULL_PTR) {
927         st_logf("\tCreateMutex:\t%p\n", args->CreateMutex);
928         st_logf("\tDestroyMutext\t%p\n", args->DestroyMutex);
929         st_logf("\tLockMutext\t%p\n", args->LockMutex);
930         st_logf("\tUnlockMutext\t%p\n", args->UnlockMutex);
931         st_logf("\tFlags\t%04x\n", (unsigned int)args->flags);
932     }
933
934     soft_token.next_session_handle = 1;
935
936     fn = get_rcfilename();
937     if (fn == NULL)
938         return CKR_DEVICE_MEMORY;
939     read_conf_file(fn);
940     free(fn);
941     return CKR_OK;
942 }
943
944 CK_RV
945 C_Finalize(CK_VOID_PTR args)
946 {
947     size_t i;
948     int j;
949
950     st_logf("Finalize\n");
951
952     for (i = 0; i < MAX_NUM_SESSION; i++) {
953         if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) {
954             application_error("application finalized without "
955                               "closing session\n");
956             close_session(&soft_token.state[i]);
957         }
958     }
959
960     for (j = 0; j < soft_token.object.num_objs; j++)
961         free_st_object(soft_token.object.objs[j]);
962     free(soft_token.object.objs);
963     soft_token.object.objs = NULL;
964     soft_token.object.num_objs = 0;
965
966     return CKR_OK;
967 }
968
969 CK_RV
970 C_GetInfo(CK_INFO_PTR args)
971 {
972     st_logf("GetInfo\n");
973
974     memset(args, 17, sizeof(*args));
975     args->cryptokiVersion.major = 2;
976     args->cryptokiVersion.minor = 10;
977     snprintf_fill((char *)args->manufacturerID,
978                   sizeof(args->manufacturerID),
979                   ' ',
980                   "SoftToken");
981     snprintf_fill((char *)args->libraryDescription,
982                   sizeof(args->libraryDescription), ' ',
983                   "SoftToken");
984     args->libraryVersion.major = 1;
985     args->libraryVersion.minor = 8;
986
987     return CKR_OK;
988 }
989
990 extern CK_FUNCTION_LIST funcs;
991
992 CK_RV
993 C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList)
994 {
995     *ppFunctionList = &funcs;
996     return CKR_OK;
997 }
998
999 CK_RV
1000 C_GetSlotList(CK_BBOOL tokenPresent,
1001               CK_SLOT_ID_PTR pSlotList,
1002               CK_ULONG_PTR   pulCount)
1003 {
1004     st_logf("GetSlotList: %s\n",
1005             tokenPresent ? "tokenPresent" : "token not Present");
1006     if (pSlotList)
1007         pSlotList[0] = 1;
1008     *pulCount = 1;
1009     return CKR_OK;
1010 }
1011
1012 CK_RV
1013 C_GetSlotInfo(CK_SLOT_ID slotID,
1014               CK_SLOT_INFO_PTR pInfo)
1015 {
1016     st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID, has_session());
1017
1018     memset(pInfo, 18, sizeof(*pInfo));
1019
1020     if (slotID != 1)
1021         return CKR_ARGUMENTS_BAD;
1022
1023     snprintf_fill((char *)pInfo->slotDescription,
1024                   sizeof(pInfo->slotDescription),
1025                   ' ',
1026                   "SoftToken (slot)");
1027     snprintf_fill((char *)pInfo->manufacturerID,
1028                   sizeof(pInfo->manufacturerID),
1029                   ' ',
1030                   "SoftToken (slot)");
1031     pInfo->flags = CKF_TOKEN_PRESENT;
1032     if (soft_token.flags.hardware_slot)
1033         pInfo->flags |= CKF_HW_SLOT;
1034     pInfo->hardwareVersion.major = 1;
1035     pInfo->hardwareVersion.minor = 0;
1036     pInfo->firmwareVersion.major = 1;
1037     pInfo->firmwareVersion.minor = 0;
1038
1039     return CKR_OK;
1040 }
1041
1042 CK_RV
1043 C_GetTokenInfo(CK_SLOT_ID slotID,
1044                CK_TOKEN_INFO_PTR pInfo)
1045 {
1046     st_logf("GetTokenInfo: %s\n", has_session());
1047
1048     memset(pInfo, 19, sizeof(*pInfo));
1049
1050     snprintf_fill((char *)pInfo->label,
1051                   sizeof(pInfo->label),
1052                   ' ',
1053                   "SoftToken (token)");
1054     snprintf_fill((char *)pInfo->manufacturerID,
1055                   sizeof(pInfo->manufacturerID),
1056                   ' ',
1057                   "SoftToken (token)");
1058     snprintf_fill((char *)pInfo->model,
1059                   sizeof(pInfo->model),
1060                   ' ',
1061                   "SoftToken (token)");
1062     snprintf_fill((char *)pInfo->serialNumber,
1063                   sizeof(pInfo->serialNumber),
1064                   ' ',
1065                   "4711");
1066     pInfo->flags =
1067         CKF_TOKEN_INITIALIZED |
1068         CKF_USER_PIN_INITIALIZED;
1069
1070     if (soft_token.flags.login_done == 0)
1071         pInfo->flags |= CKF_LOGIN_REQUIRED;
1072
1073     /* CFK_RNG |
1074        CKF_RESTORE_KEY_NOT_NEEDED |
1075     */
1076     pInfo->ulMaxSessionCount = MAX_NUM_SESSION;
1077     pInfo->ulSessionCount = soft_token.open_sessions;
1078     pInfo->ulMaxRwSessionCount = MAX_NUM_SESSION;
1079     pInfo->ulRwSessionCount = soft_token.open_sessions;
1080     pInfo->ulMaxPinLen = 1024;
1081     pInfo->ulMinPinLen = 0;
1082     pInfo->ulTotalPublicMemory = 4711;
1083     pInfo->ulFreePublicMemory = 4712;
1084     pInfo->ulTotalPrivateMemory = 4713;
1085     pInfo->ulFreePrivateMemory = 4714;
1086     pInfo->hardwareVersion.major = 2;
1087     pInfo->hardwareVersion.minor = 0;
1088     pInfo->firmwareVersion.major = 2;
1089     pInfo->firmwareVersion.minor = 0;
1090
1091     return CKR_OK;
1092 }
1093
1094 CK_RV
1095 C_GetMechanismList(CK_SLOT_ID slotID,
1096                    CK_MECHANISM_TYPE_PTR pMechanismList,
1097                    CK_ULONG_PTR pulCount)
1098 {
1099     st_logf("GetMechanismList\n");
1100
1101     *pulCount = 2;
1102     if (pMechanismList == NULL_PTR)
1103         return CKR_OK;
1104     pMechanismList[0] = CKM_RSA_X_509;
1105     pMechanismList[1] = CKM_RSA_PKCS;
1106
1107     return CKR_OK;
1108 }
1109
1110 CK_RV
1111 C_GetMechanismInfo(CK_SLOT_ID slotID,
1112                    CK_MECHANISM_TYPE type,
1113                    CK_MECHANISM_INFO_PTR pInfo)
1114 {
1115     st_logf("GetMechanismInfo: slot %d type: %d\n",
1116             (int)slotID, (int)type);
1117     return CKR_FUNCTION_NOT_SUPPORTED;
1118 }
1119
1120 CK_RV
1121 C_InitToken(CK_SLOT_ID slotID,
1122             CK_UTF8CHAR_PTR pPin,
1123             CK_ULONG ulPinLen,
1124             CK_UTF8CHAR_PTR pLabel)
1125 {
1126     st_logf("InitToken: slot %d\n", (int)slotID);
1127     return CKR_FUNCTION_NOT_SUPPORTED;
1128 }
1129
1130 CK_RV
1131 C_OpenSession(CK_SLOT_ID slotID,
1132               CK_FLAGS flags,
1133               CK_VOID_PTR pApplication,
1134               CK_NOTIFY Notify,
1135               CK_SESSION_HANDLE_PTR phSession)
1136 {
1137     size_t i;
1138
1139     st_logf("OpenSession: slot: %d\n", (int)slotID);
1140
1141     if (soft_token.open_sessions == MAX_NUM_SESSION)
1142         return CKR_SESSION_COUNT;
1143
1144     soft_token.application = pApplication;
1145     soft_token.notify = Notify;
1146
1147     for (i = 0; i < MAX_NUM_SESSION; i++)
1148         if (soft_token.state[i].session_handle == CK_INVALID_HANDLE)
1149             break;
1150     if (i == MAX_NUM_SESSION)
1151         abort();
1152
1153     soft_token.open_sessions++;
1154
1155     soft_token.state[i].session_handle = soft_token.next_session_handle++;
1156     *phSession = soft_token.state[i].session_handle;
1157
1158     return CKR_OK;
1159 }
1160
1161 CK_RV
1162 C_CloseSession(CK_SESSION_HANDLE hSession)
1163 {
1164     struct session_state *state;
1165     st_logf("CloseSession\n");
1166
1167     if (verify_session_handle(hSession, &state) != CKR_OK)
1168         application_error("closed session not open");
1169     else
1170         close_session(state);
1171
1172     return CKR_OK;
1173 }
1174
1175 CK_RV
1176 C_CloseAllSessions(CK_SLOT_ID slotID)
1177 {
1178     size_t i;
1179
1180     st_logf("CloseAllSessions\n");
1181
1182     for (i = 0; i < MAX_NUM_SESSION; i++)
1183         if (soft_token.state[i].session_handle != CK_INVALID_HANDLE)
1184             close_session(&soft_token.state[i]);
1185
1186     return CKR_OK;
1187 }
1188
1189 CK_RV
1190 C_GetSessionInfo(CK_SESSION_HANDLE hSession,
1191                  CK_SESSION_INFO_PTR pInfo)
1192 {
1193     st_logf("GetSessionInfo\n");
1194
1195     VERIFY_SESSION_HANDLE(hSession, NULL);
1196
1197     memset(pInfo, 20, sizeof(*pInfo));
1198
1199     pInfo->slotID = 1;
1200     if (soft_token.flags.login_done)
1201         pInfo->state = CKS_RO_USER_FUNCTIONS;
1202     else
1203         pInfo->state = CKS_RO_PUBLIC_SESSION;
1204     pInfo->flags = CKF_SERIAL_SESSION;
1205     pInfo->ulDeviceError = 0;
1206
1207     return CKR_OK;
1208 }
1209
1210 CK_RV
1211 C_Login(CK_SESSION_HANDLE hSession,
1212         CK_USER_TYPE userType,
1213         CK_UTF8CHAR_PTR pPin,
1214         CK_ULONG ulPinLen)
1215 {
1216     char *pin = NULL;
1217     int i;
1218
1219     st_logf("Login\n");
1220
1221     VERIFY_SESSION_HANDLE(hSession, NULL);
1222
1223     if (pPin != NULL_PTR) {
1224         if (asprintf(&pin, "%.*s", (int)ulPinLen, pPin) < 0)
1225             return CKR_DEVICE_MEMORY;
1226         st_logf("type: %d password: %s\n", (int)userType, pin);
1227     }
1228
1229     for (i = 0; i < soft_token.object.num_objs; i++) {
1230         struct st_object *o = soft_token.object.objs[i];
1231         FILE *f;
1232
1233         if (o->type != STO_T_PRIVATE_KEY)
1234             continue;
1235
1236         if (o->u.private_key.key)
1237             continue;
1238
1239         f = fopen(o->u.private_key.file, "r");
1240         if (f == NULL) {
1241             st_logf("can't open private file: %s\n", o->u.private_key.file);
1242             continue;
1243         }
1244
1245         o->u.private_key.key = PEM_read_PrivateKey(f, NULL, NULL, pin);
1246         fclose(f);
1247         if (o->u.private_key.key == NULL) {
1248             st_logf("failed to read key: %s error: %s\n",
1249                     o->u.private_key.file,
1250                     ERR_error_string(ERR_get_error(), NULL));
1251             /* just ignore failure */;
1252             continue;
1253         }
1254
1255         /* XXX check keytype */
1256
1257         if (X509_check_private_key(o->u.private_key.cert, o->u.private_key.key) != 1) {
1258             EVP_PKEY_free(o->u.private_key.key);
1259             o->u.private_key.key = NULL;
1260             st_logf("private key %s doesn't verify\n", o->u.private_key.file);
1261             continue;
1262         }
1263
1264         soft_token.flags.login_done = 1;
1265     }
1266     free(pin);
1267
1268     return soft_token.flags.login_done ? CKR_OK : CKR_PIN_INCORRECT;
1269 }
1270
1271 CK_RV
1272 C_Logout(CK_SESSION_HANDLE hSession)
1273 {
1274     st_logf("Logout\n");
1275     VERIFY_SESSION_HANDLE(hSession, NULL);
1276     return CKR_FUNCTION_NOT_SUPPORTED;
1277 }
1278
1279 CK_RV
1280 C_GetObjectSize(CK_SESSION_HANDLE hSession,
1281                 CK_OBJECT_HANDLE hObject,
1282                 CK_ULONG_PTR pulSize)
1283 {
1284     st_logf("GetObjectSize\n");
1285     VERIFY_SESSION_HANDLE(hSession, NULL);
1286     return CKR_FUNCTION_NOT_SUPPORTED;
1287 }
1288
1289 CK_RV
1290 C_GetAttributeValue(CK_SESSION_HANDLE hSession,
1291                     CK_OBJECT_HANDLE hObject,
1292                     CK_ATTRIBUTE_PTR pTemplate,
1293                     CK_ULONG ulCount)
1294 {
1295     struct session_state *state;
1296     struct st_object *obj;
1297     CK_ULONG i;
1298     CK_RV ret;
1299     int j;
1300
1301     st_logf("GetAttributeValue: %lx\n",
1302             (unsigned long)HANDLE_OBJECT_ID(hObject));
1303     VERIFY_SESSION_HANDLE(hSession, &state);
1304
1305     if ((ret = object_handle_to_object(hObject, &obj)) != CKR_OK) {
1306         st_logf("object not found: %lx\n",
1307                 (unsigned long)HANDLE_OBJECT_ID(hObject));
1308         return ret;
1309     }
1310
1311     for (i = 0; i < ulCount; i++) {
1312         st_logf("       getting 0x%08lx\n", (unsigned long)pTemplate[i].type);
1313         for (j = 0; j < obj->num_attributes; j++) {
1314             if (obj->attrs[j].secret) {
1315                 pTemplate[i].ulValueLen = (CK_ULONG)-1;
1316                 break;
1317             }
1318             if (pTemplate[i].type == obj->attrs[j].attribute.type) {
1319                 if (pTemplate[i].pValue != NULL_PTR && obj->attrs[j].secret == 0) {
1320                     if (pTemplate[i].ulValueLen >= obj->attrs[j].attribute.ulValueLen)
1321                         memcpy(pTemplate[i].pValue, obj->attrs[j].attribute.pValue,
1322                                obj->attrs[j].attribute.ulValueLen);
1323                 }
1324                 pTemplate[i].ulValueLen = obj->attrs[j].attribute.ulValueLen;
1325                 break;
1326             }
1327         }
1328         if (j == obj->num_attributes) {
1329             st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate[i].type);
1330             pTemplate[i].ulValueLen = (CK_ULONG)-1;
1331         }
1332
1333     }
1334     return CKR_OK;
1335 }
1336
1337 CK_RV
1338 C_FindObjectsInit(CK_SESSION_HANDLE hSession,
1339                   CK_ATTRIBUTE_PTR pTemplate,
1340                   CK_ULONG ulCount)
1341 {
1342     struct session_state *state;
1343
1344     st_logf("FindObjectsInit\n");
1345
1346     VERIFY_SESSION_HANDLE(hSession, &state);
1347
1348     if (state->find.next_object != -1) {
1349         application_error("application didn't do C_FindObjectsFinal\n");
1350         find_object_final(state);
1351     }
1352     if (ulCount) {
1353         CK_ULONG i;
1354
1355         print_attributes(pTemplate, ulCount);
1356
1357         state->find.attributes =
1358             calloc(1, ulCount * sizeof(state->find.attributes[0]));
1359         if (state->find.attributes == NULL)
1360             return CKR_DEVICE_MEMORY;
1361         for (i = 0; i < ulCount; i++) {
1362             state->find.attributes[i].pValue =
1363                 malloc(pTemplate[i].ulValueLen);
1364             if (state->find.attributes[i].pValue == NULL) {
1365                 find_object_final(state);
1366                 return CKR_DEVICE_MEMORY;
1367             }
1368             memcpy(state->find.attributes[i].pValue,
1369                    pTemplate[i].pValue, pTemplate[i].ulValueLen);
1370             state->find.attributes[i].type = pTemplate[i].type;
1371             state->find.attributes[i].ulValueLen = pTemplate[i].ulValueLen;
1372         }
1373         state->find.num_attributes = ulCount;
1374         state->find.next_object = 0;
1375     } else {
1376         st_logf("find all objects\n");
1377         state->find.attributes = NULL;
1378         state->find.num_attributes = 0;
1379         state->find.next_object = 0;
1380     }
1381
1382     return CKR_OK;
1383 }
1384
1385 CK_RV
1386 C_FindObjects(CK_SESSION_HANDLE hSession,
1387               CK_OBJECT_HANDLE_PTR phObject,
1388               CK_ULONG ulMaxObjectCount,
1389               CK_ULONG_PTR pulObjectCount)
1390 {
1391     struct session_state *state;
1392     int i;
1393
1394     st_logf("FindObjects\n");
1395
1396     VERIFY_SESSION_HANDLE(hSession, &state);
1397
1398     if (state->find.next_object == -1) {
1399         application_error("application didn't do C_FindObjectsInit\n");
1400         return CKR_ARGUMENTS_BAD;
1401     }
1402     if (ulMaxObjectCount == 0) {
1403         application_error("application asked for 0 objects\n");
1404         return CKR_ARGUMENTS_BAD;
1405     }
1406     *pulObjectCount = 0;
1407     for (i = state->find.next_object; i < soft_token.object.num_objs; i++) {
1408         st_logf("FindObjects: %d\n", i);
1409         state->find.next_object = i + 1;
1410         if (attributes_match(soft_token.object.objs[i],
1411                              state->find.attributes,
1412                              state->find.num_attributes)) {
1413             *phObject++ = soft_token.object.objs[i]->object_handle;
1414             ulMaxObjectCount--;
1415             (*pulObjectCount)++;
1416             if (ulMaxObjectCount == 0)
1417                 break;
1418         }
1419     }
1420     return CKR_OK;
1421 }
1422
1423 CK_RV
1424 C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
1425 {
1426     struct session_state *state;
1427
1428     st_logf("FindObjectsFinal\n");
1429     VERIFY_SESSION_HANDLE(hSession, &state);
1430     find_object_final(state);
1431     return CKR_OK;
1432 }
1433
1434 static CK_RV
1435 commonInit(CK_ATTRIBUTE *attr_match, int attr_match_len,
1436            const CK_MECHANISM_TYPE *mechs, int mechs_len,
1437            const CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey,
1438            struct st_object **o)
1439 {
1440     CK_RV ret;
1441     int i;
1442
1443     *o = NULL;
1444     if ((ret = object_handle_to_object(hKey, o)) != CKR_OK)
1445         return ret;
1446
1447     ret = attributes_match(*o, attr_match, attr_match_len);
1448     if (!ret) {
1449         application_error("called commonInit on key that doesn't "
1450                           "support required attr");
1451         return CKR_ARGUMENTS_BAD;
1452     }
1453
1454     for (i = 0; i < mechs_len; i++)
1455         if (mechs[i] == pMechanism->mechanism)
1456             break;
1457     if (i == mechs_len) {
1458         application_error("called mech (%08lx) not supported\n",
1459                           pMechanism->mechanism);
1460         return CKR_ARGUMENTS_BAD;
1461     }
1462     return CKR_OK;
1463 }
1464
1465
1466 static CK_RV
1467 dup_mechanism(CK_MECHANISM_PTR *dup, const CK_MECHANISM_PTR pMechanism)
1468 {
1469     CK_MECHANISM_PTR p;
1470
1471     p = malloc(sizeof(*p));
1472     if (p == NULL)
1473         return CKR_DEVICE_MEMORY;
1474
1475     if (*dup)
1476         free(*dup);
1477     *dup = p;
1478     memcpy(p, pMechanism, sizeof(*p));
1479
1480     return CKR_OK;
1481 }
1482
1483
1484 CK_RV
1485 C_EncryptInit(CK_SESSION_HANDLE hSession,
1486               CK_MECHANISM_PTR pMechanism,
1487               CK_OBJECT_HANDLE hKey)
1488 {
1489     struct session_state *state;
1490     CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 };
1491     CK_BBOOL bool_true = CK_TRUE;
1492     CK_ATTRIBUTE attr[] = {
1493         { CKA_ENCRYPT, &bool_true, sizeof(bool_true) }
1494     };
1495     struct st_object *o;
1496     CK_RV ret;
1497
1498     st_logf("EncryptInit\n");
1499     VERIFY_SESSION_HANDLE(hSession, &state);
1500
1501     ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1502                      mechs, sizeof(mechs)/sizeof(mechs[0]),
1503                      pMechanism, hKey, &o);
1504     if (ret)
1505         return ret;
1506
1507     ret = dup_mechanism(&state->encrypt_mechanism, pMechanism);
1508     if (ret == CKR_OK)
1509         state->encrypt_object = OBJECT_ID(o);
1510
1511     return ret;
1512 }
1513
1514 CK_RV
1515 C_Encrypt(CK_SESSION_HANDLE hSession,
1516           CK_BYTE_PTR pData,
1517           CK_ULONG ulDataLen,
1518           CK_BYTE_PTR pEncryptedData,
1519           CK_ULONG_PTR pulEncryptedDataLen)
1520 {
1521     struct session_state *state;
1522     struct st_object *o;
1523     void *buffer = NULL;
1524     CK_RV ret;
1525     size_t buffer_len = 0;
1526     int padding;
1527     EVP_PKEY_CTX *ctx = NULL;
1528
1529     st_logf("Encrypt\n");
1530
1531     VERIFY_SESSION_HANDLE(hSession, &state);
1532
1533     if (state->encrypt_object == -1)
1534         return CKR_ARGUMENTS_BAD;
1535
1536     o = soft_token.object.objs[state->encrypt_object];
1537
1538     if (o->u.public_key == NULL) {
1539         st_logf("public key NULL\n");
1540         return CKR_ARGUMENTS_BAD;
1541     }
1542
1543     if (pulEncryptedDataLen == NULL) {
1544         st_logf("pulEncryptedDataLen NULL\n");
1545         ret = CKR_ARGUMENTS_BAD;
1546         goto out;
1547     }
1548
1549     if (pData == NULL) {
1550         st_logf("data NULL\n");
1551         ret = CKR_ARGUMENTS_BAD;
1552         goto out;
1553     }
1554
1555     switch(state->encrypt_mechanism->mechanism) {
1556     case CKM_RSA_PKCS:
1557         padding = RSA_PKCS1_PADDING;
1558         break;
1559     case CKM_RSA_X_509:
1560         padding = RSA_NO_PADDING;
1561         break;
1562     default:
1563         ret = CKR_FUNCTION_NOT_SUPPORTED;
1564         goto out;
1565     }
1566
1567     ctx = EVP_PKEY_CTX_new(o->u.public_key, NULL);
1568     if (ctx == NULL || EVP_PKEY_encrypt_init(ctx) <= 0 ||
1569         EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
1570         EVP_PKEY_encrypt(ctx, NULL, &buffer_len, pData, ulDataLen) <= 0) {
1571         ret = CKR_DEVICE_ERROR;
1572         goto out;
1573     }
1574
1575     buffer = OPENSSL_malloc(buffer_len);
1576     if (buffer == NULL) {
1577         ret = CKR_DEVICE_MEMORY;
1578         goto out;
1579     }
1580
1581     if (EVP_PKEY_encrypt(ctx, buffer, &buffer_len, pData, ulDataLen) <= 0) {
1582         ret = CKR_DEVICE_ERROR;
1583         goto out;
1584     }
1585     st_logf("Encrypt done\n");
1586
1587     if (pEncryptedData != NULL)
1588         memcpy(pEncryptedData, buffer, buffer_len);
1589     *pulEncryptedDataLen = buffer_len;
1590
1591     ret = CKR_OK;
1592 out:
1593     OPENSSL_cleanse(buffer, buffer_len);
1594     OPENSSL_free(buffer);
1595     EVP_PKEY_CTX_free(ctx);
1596     return ret;
1597 }
1598
1599 CK_RV
1600 C_EncryptUpdate(CK_SESSION_HANDLE hSession,
1601                 CK_BYTE_PTR pPart,
1602                 CK_ULONG ulPartLen,
1603                 CK_BYTE_PTR pEncryptedPart,
1604                 CK_ULONG_PTR pulEncryptedPartLen)
1605 {
1606     st_logf("EncryptUpdate\n");
1607     VERIFY_SESSION_HANDLE(hSession, NULL);
1608     return CKR_FUNCTION_NOT_SUPPORTED;
1609 }
1610
1611
1612 CK_RV
1613 C_EncryptFinal(CK_SESSION_HANDLE hSession,
1614                CK_BYTE_PTR pLastEncryptedPart,
1615                CK_ULONG_PTR pulLastEncryptedPartLen)
1616 {
1617     st_logf("EncryptFinal\n");
1618     VERIFY_SESSION_HANDLE(hSession, NULL);
1619     return CKR_FUNCTION_NOT_SUPPORTED;
1620 }
1621
1622
1623 /* C_DecryptInit initializes a decryption operation. */
1624 CK_RV
1625 C_DecryptInit(CK_SESSION_HANDLE hSession,
1626               CK_MECHANISM_PTR pMechanism,
1627               CK_OBJECT_HANDLE hKey)
1628 {
1629     struct session_state *state;
1630     CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 };
1631     CK_BBOOL bool_true = CK_TRUE;
1632     CK_ATTRIBUTE attr[] = {
1633         { CKA_DECRYPT, &bool_true, sizeof(bool_true) }
1634     };
1635     struct st_object *o;
1636     CK_RV ret;
1637
1638     st_logf("DecryptInit\n");
1639     VERIFY_SESSION_HANDLE(hSession, &state);
1640
1641     ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1642                      mechs, sizeof(mechs)/sizeof(mechs[0]),
1643                      pMechanism, hKey, &o);
1644     if (ret)
1645         return ret;
1646
1647     ret = dup_mechanism(&state->decrypt_mechanism, pMechanism);
1648     if (ret == CKR_OK)
1649         state->decrypt_object = OBJECT_ID(o);
1650
1651     return CKR_OK;
1652 }
1653
1654
1655 CK_RV
1656 C_Decrypt(CK_SESSION_HANDLE hSession,
1657           CK_BYTE_PTR       pEncryptedData,
1658           CK_ULONG          ulEncryptedDataLen,
1659           CK_BYTE_PTR       pData,
1660           CK_ULONG_PTR      pulDataLen)
1661 {
1662     struct session_state *state;
1663     struct st_object *o;
1664     void *buffer = NULL;
1665     CK_RV ret;
1666     size_t buffer_len = 0;
1667     int padding;
1668     EVP_PKEY_CTX *ctx = NULL;
1669
1670     st_logf("Decrypt\n");
1671
1672     VERIFY_SESSION_HANDLE(hSession, &state);
1673
1674     if (state->decrypt_object == -1)
1675         return CKR_ARGUMENTS_BAD;
1676
1677     o = soft_token.object.objs[state->decrypt_object];
1678
1679     if (o->u.private_key.key == NULL) {
1680         st_logf("private key NULL\n");
1681         return CKR_ARGUMENTS_BAD;
1682     }
1683
1684     if (pulDataLen == NULL) {
1685         st_logf("pulDataLen NULL\n");
1686         ret = CKR_ARGUMENTS_BAD;
1687         goto out;
1688     }
1689
1690     if (pEncryptedData == NULL_PTR) {
1691         st_logf("data NULL\n");
1692         ret = CKR_ARGUMENTS_BAD;
1693         goto out;
1694     }
1695
1696     switch(state->decrypt_mechanism->mechanism) {
1697     case CKM_RSA_PKCS:
1698         padding = RSA_PKCS1_PADDING;
1699         break;
1700     case CKM_RSA_X_509:
1701         padding = RSA_NO_PADDING;
1702         break;
1703     default:
1704         ret = CKR_FUNCTION_NOT_SUPPORTED;
1705         goto out;
1706     }
1707
1708     ctx = EVP_PKEY_CTX_new(o->u.private_key.key, NULL);
1709     if (ctx == NULL || EVP_PKEY_decrypt_init(ctx) <= 0 ||
1710         EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
1711         EVP_PKEY_decrypt(ctx, NULL, &buffer_len, pEncryptedData,
1712                          ulEncryptedDataLen) <= 0) {
1713         ret = CKR_DEVICE_ERROR;
1714         goto out;
1715     }
1716
1717     buffer = OPENSSL_malloc(buffer_len);
1718     if (buffer == NULL) {
1719         ret = CKR_DEVICE_MEMORY;
1720         goto out;
1721     }
1722
1723     if (EVP_PKEY_decrypt(ctx, buffer, &buffer_len, pEncryptedData,
1724                          ulEncryptedDataLen) <= 0) {
1725         ret = CKR_DEVICE_ERROR;
1726         goto out;
1727     }
1728     st_logf("Decrypt done\n");
1729
1730     if (pData != NULL_PTR)
1731         memcpy(pData, buffer, buffer_len);
1732     *pulDataLen = buffer_len;
1733
1734     ret = CKR_OK;
1735 out:
1736     OPENSSL_cleanse(buffer, buffer_len);
1737     OPENSSL_free(buffer);
1738     EVP_PKEY_CTX_free(ctx);
1739     return ret;
1740 }
1741
1742
1743 CK_RV
1744 C_DecryptUpdate(CK_SESSION_HANDLE hSession,
1745                 CK_BYTE_PTR pEncryptedPart,
1746                 CK_ULONG ulEncryptedPartLen,
1747                 CK_BYTE_PTR pPart,
1748                 CK_ULONG_PTR pulPartLen)
1749
1750 {
1751     st_logf("DecryptUpdate\n");
1752     VERIFY_SESSION_HANDLE(hSession, NULL);
1753     return CKR_FUNCTION_NOT_SUPPORTED;
1754 }
1755
1756
1757 CK_RV
1758 C_DecryptFinal(CK_SESSION_HANDLE hSession,
1759                CK_BYTE_PTR pLastPart,
1760                CK_ULONG_PTR pulLastPartLen)
1761 {
1762     st_logf("DecryptFinal\n");
1763     VERIFY_SESSION_HANDLE(hSession, NULL);
1764     return CKR_FUNCTION_NOT_SUPPORTED;
1765 }
1766
1767 CK_RV
1768 C_DigestInit(CK_SESSION_HANDLE hSession,
1769              CK_MECHANISM_PTR pMechanism)
1770 {
1771     st_logf("DigestInit\n");
1772     VERIFY_SESSION_HANDLE(hSession, NULL);
1773     return CKR_FUNCTION_NOT_SUPPORTED;
1774 }
1775
1776 CK_RV
1777 C_SignInit(CK_SESSION_HANDLE hSession,
1778            CK_MECHANISM_PTR pMechanism,
1779            CK_OBJECT_HANDLE hKey)
1780 {
1781     struct session_state *state;
1782     CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 };
1783     CK_BBOOL bool_true = CK_TRUE;
1784     CK_ATTRIBUTE attr[] = {
1785         { CKA_SIGN, &bool_true, sizeof(bool_true) }
1786     };
1787     struct st_object *o;
1788     CK_RV ret;
1789
1790     st_logf("SignInit\n");
1791     VERIFY_SESSION_HANDLE(hSession, &state);
1792
1793     ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1794                      mechs, sizeof(mechs)/sizeof(mechs[0]),
1795                      pMechanism, hKey, &o);
1796     if (ret)
1797         return ret;
1798
1799     ret = dup_mechanism(&state->sign_mechanism, pMechanism);
1800     if (ret == CKR_OK)
1801         state->sign_object = OBJECT_ID(o);
1802
1803     return CKR_OK;
1804 }
1805
1806 CK_RV
1807 C_Sign(CK_SESSION_HANDLE hSession,
1808        CK_BYTE_PTR pData,
1809        CK_ULONG ulDataLen,
1810        CK_BYTE_PTR pSignature,
1811        CK_ULONG_PTR pulSignatureLen)
1812 {
1813     struct session_state *state;
1814     struct st_object *o;
1815     void *buffer = NULL;
1816     CK_RV ret;
1817     int padding;
1818     size_t buffer_len = 0;
1819     EVP_PKEY_CTX *ctx = NULL;
1820
1821     st_logf("Sign\n");
1822     VERIFY_SESSION_HANDLE(hSession, &state);
1823
1824     if (state->sign_object == -1)
1825         return CKR_ARGUMENTS_BAD;
1826
1827     o = soft_token.object.objs[state->sign_object];
1828
1829     if (o->u.private_key.key == NULL) {
1830         st_logf("private key NULL\n");
1831         return CKR_ARGUMENTS_BAD;
1832     }
1833
1834     if (pulSignatureLen == NULL) {
1835         st_logf("signature len NULL\n");
1836         ret = CKR_ARGUMENTS_BAD;
1837         goto out;
1838     }
1839
1840     if (pData == NULL_PTR) {
1841         st_logf("data NULL\n");
1842         ret = CKR_ARGUMENTS_BAD;
1843         goto out;
1844     }
1845
1846     switch(state->sign_mechanism->mechanism) {
1847     case CKM_RSA_PKCS:
1848         padding = RSA_PKCS1_PADDING;
1849         break;
1850     case CKM_RSA_X_509:
1851         padding = RSA_NO_PADDING;
1852         break;
1853     default:
1854         ret = CKR_FUNCTION_NOT_SUPPORTED;
1855         goto out;
1856     }
1857
1858     ctx = EVP_PKEY_CTX_new(o->u.private_key.key, NULL);
1859     if (ctx == NULL || EVP_PKEY_sign_init(ctx) <= 0 ||
1860         EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
1861         EVP_PKEY_sign(ctx, NULL, &buffer_len, pData, ulDataLen) <= 0) {
1862         ret = CKR_DEVICE_ERROR;
1863         goto out;
1864     }
1865
1866     buffer = OPENSSL_malloc(buffer_len);
1867     if (buffer == NULL) {
1868         ret = CKR_DEVICE_MEMORY;
1869         goto out;
1870     }
1871
1872     if (EVP_PKEY_sign(ctx, buffer, &buffer_len, pData, ulDataLen) <= 0) {
1873         ret = CKR_DEVICE_ERROR;
1874         goto out;
1875     }
1876     st_logf("Sign done\n");
1877
1878     if (pSignature != NULL)
1879         memcpy(pSignature, buffer, buffer_len);
1880     *pulSignatureLen = buffer_len;
1881
1882     ret = CKR_OK;
1883 out:
1884     OPENSSL_cleanse(buffer, buffer_len);
1885     OPENSSL_free(buffer);
1886     EVP_PKEY_CTX_free(ctx);
1887     return ret;
1888 }
1889
1890 CK_RV
1891 C_SignUpdate(CK_SESSION_HANDLE hSession,
1892              CK_BYTE_PTR pPart,
1893              CK_ULONG ulPartLen)
1894 {
1895     st_logf("SignUpdate\n");
1896     VERIFY_SESSION_HANDLE(hSession, NULL);
1897     return CKR_FUNCTION_NOT_SUPPORTED;
1898 }
1899
1900
1901 CK_RV
1902 C_SignFinal(CK_SESSION_HANDLE hSession,
1903             CK_BYTE_PTR pSignature,
1904             CK_ULONG_PTR pulSignatureLen)
1905 {
1906     st_logf("SignUpdate\n");
1907     VERIFY_SESSION_HANDLE(hSession, NULL);
1908     return CKR_FUNCTION_NOT_SUPPORTED;
1909 }
1910
1911 CK_RV
1912 C_VerifyInit(CK_SESSION_HANDLE hSession,
1913              CK_MECHANISM_PTR pMechanism,
1914              CK_OBJECT_HANDLE hKey)
1915 {
1916     struct session_state *state;
1917     CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 };
1918     CK_BBOOL bool_true = CK_TRUE;
1919     CK_ATTRIBUTE attr[] = {
1920         { CKA_VERIFY, &bool_true, sizeof(bool_true) }
1921     };
1922     struct st_object *o;
1923     CK_RV ret;
1924
1925     st_logf("VerifyInit\n");
1926     VERIFY_SESSION_HANDLE(hSession, &state);
1927
1928     ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]),
1929                      mechs, sizeof(mechs)/sizeof(mechs[0]),
1930                      pMechanism, hKey, &o);
1931     if (ret)
1932         return ret;
1933
1934     ret = dup_mechanism(&state->verify_mechanism, pMechanism);
1935     if (ret == CKR_OK)
1936         state->verify_object = OBJECT_ID(o);
1937
1938     return ret;
1939 }
1940
1941 CK_RV
1942 C_Verify(CK_SESSION_HANDLE hSession,
1943          CK_BYTE_PTR pData,
1944          CK_ULONG ulDataLen,
1945          CK_BYTE_PTR pSignature,
1946          CK_ULONG ulSignatureLen)
1947 {
1948     struct session_state *state;
1949     struct st_object *o;
1950     CK_RV ret;
1951     int padding;
1952     EVP_PKEY_CTX *ctx = NULL;
1953
1954     st_logf("Verify\n");
1955     VERIFY_SESSION_HANDLE(hSession, &state);
1956
1957     if (state->verify_object == -1)
1958         return CKR_ARGUMENTS_BAD;
1959
1960     o = soft_token.object.objs[state->verify_object];
1961
1962     if (o->u.public_key == NULL) {
1963         st_logf("public key NULL\n");
1964         return CKR_ARGUMENTS_BAD;
1965     }
1966
1967     if (pSignature == NULL) {
1968         st_logf("signature NULL\n");
1969         ret = CKR_ARGUMENTS_BAD;
1970         goto out;
1971     }
1972
1973     if (pData == NULL_PTR) {
1974         st_logf("data NULL\n");
1975         ret = CKR_ARGUMENTS_BAD;
1976         goto out;
1977     }
1978
1979     switch(state->verify_mechanism->mechanism) {
1980     case CKM_RSA_PKCS:
1981         padding = RSA_PKCS1_PADDING;
1982         break;
1983     case CKM_RSA_X_509:
1984         padding = RSA_NO_PADDING;
1985         break;
1986     default:
1987         ret = CKR_FUNCTION_NOT_SUPPORTED;
1988         goto out;
1989     }
1990
1991     ctx = EVP_PKEY_CTX_new(o->u.public_key, NULL);
1992     if (ctx == NULL || EVP_PKEY_verify_init(ctx) <= 0 ||
1993         EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0 ||
1994         EVP_PKEY_verify(ctx, pSignature, ulSignatureLen, pData,
1995                         ulDataLen) <= 0) {
1996         ret = CKR_DEVICE_ERROR;
1997         goto out;
1998     }
1999     st_logf("Verify done\n");
2000
2001     ret = CKR_OK;
2002 out:
2003     EVP_PKEY_CTX_free(ctx);
2004     return ret;
2005 }
2006
2007 CK_RV
2008 C_VerifyUpdate(CK_SESSION_HANDLE hSession,
2009                CK_BYTE_PTR pPart,
2010                CK_ULONG ulPartLen)
2011 {
2012     st_logf("VerifyUpdate\n");
2013     VERIFY_SESSION_HANDLE(hSession, NULL);
2014     return CKR_FUNCTION_NOT_SUPPORTED;
2015 }
2016
2017 CK_RV
2018 C_VerifyFinal(CK_SESSION_HANDLE hSession,
2019               CK_BYTE_PTR pSignature,
2020               CK_ULONG ulSignatureLen)
2021 {
2022     st_logf("VerifyFinal\n");
2023     VERIFY_SESSION_HANDLE(hSession, NULL);
2024     return CKR_FUNCTION_NOT_SUPPORTED;
2025 }
2026
2027 CK_RV
2028 C_GenerateRandom(CK_SESSION_HANDLE hSession,
2029                  CK_BYTE_PTR RandomData,
2030                  CK_ULONG ulRandomLen)
2031 {
2032     st_logf("GenerateRandom\n");
2033     VERIFY_SESSION_HANDLE(hSession, NULL);
2034     return CKR_FUNCTION_NOT_SUPPORTED;
2035 }
2036
2037 CK_FUNCTION_LIST funcs = {
2038     { 2, 11 },
2039     C_Initialize,
2040     C_Finalize,
2041     C_GetInfo,
2042     C_GetFunctionList,
2043     C_GetSlotList,
2044     C_GetSlotInfo,
2045     C_GetTokenInfo,
2046     C_GetMechanismList,
2047     C_GetMechanismInfo,
2048     C_InitToken,
2049     (void *)func_not_supported, /* C_InitPIN */
2050     (void *)func_not_supported, /* C_SetPIN */
2051     C_OpenSession,
2052     C_CloseSession,
2053     C_CloseAllSessions,
2054     C_GetSessionInfo,
2055     (void *)func_not_supported, /* C_GetOperationState */
2056     (void *)func_not_supported, /* C_SetOperationState */
2057     C_Login,
2058     C_Logout,
2059     (void *)func_not_supported, /* C_CreateObject */
2060     (void *)func_not_supported, /* C_CopyObject */
2061     (void *)func_not_supported, /* C_DestroyObject */
2062     (void *)func_not_supported, /* C_GetObjectSize */
2063     C_GetAttributeValue,
2064     (void *)func_not_supported, /* C_SetAttributeValue */
2065     C_FindObjectsInit,
2066     C_FindObjects,
2067     C_FindObjectsFinal,
2068     C_EncryptInit,
2069     C_Encrypt,
2070     C_EncryptUpdate,
2071     C_EncryptFinal,
2072     C_DecryptInit,
2073     C_Decrypt,
2074     C_DecryptUpdate,
2075     C_DecryptFinal,
2076     C_DigestInit,
2077     (void *)func_not_supported, /* C_Digest */
2078     (void *)func_not_supported, /* C_DigestUpdate */
2079     (void *)func_not_supported, /* C_DigestKey */
2080     (void *)func_not_supported, /* C_DigestFinal */
2081     C_SignInit,
2082     C_Sign,
2083     C_SignUpdate,
2084     C_SignFinal,
2085     (void *)func_not_supported, /* C_SignRecoverInit */
2086     (void *)func_not_supported, /* C_SignRecover */
2087     C_VerifyInit,
2088     C_Verify,
2089     C_VerifyUpdate,
2090     C_VerifyFinal,
2091     (void *)func_not_supported, /* C_VerifyRecoverInit */
2092     (void *)func_not_supported, /* C_VerifyRecover */
2093     (void *)func_not_supported, /* C_DigestEncryptUpdate */
2094     (void *)func_not_supported, /* C_DecryptDigestUpdate */
2095     (void *)func_not_supported, /* C_SignEncryptUpdate */
2096     (void *)func_not_supported, /* C_DecryptVerifyUpdate */
2097     (void *)func_not_supported, /* C_GenerateKey */
2098     (void *)func_not_supported, /* C_GenerateKeyPair */
2099     (void *)func_not_supported, /* C_WrapKey */
2100     (void *)func_not_supported, /* C_UnwrapKey */
2101     (void *)func_not_supported, /* C_DeriveKey */
2102     (void *)func_not_supported, /* C_SeedRandom */
2103     C_GenerateRandom,
2104     (void *)func_not_supported, /* C_GetFunctionStatus */
2105     (void *)func_not_supported, /* C_CancelFunction */
2106     (void *)func_not_supported  /* C_WaitForSlotEvent */
2107 };