2 * Copyright (c) 2004 - 2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #define CRYPTOKI_EXPORTS 1
37 #include "ref/pkcs11.h"
39 #define OBJECT_ID_MASK 0xfff
40 #define HANDLE_OBJECT_ID(h) ((h) & OBJECT_ID_MASK)
41 #define OBJECT_ID(obj) HANDLE_OBJECT_ID((obj)->object_handle)
44 #define random() rand()
45 #define srandom(s) srand(s)
53 CK_ATTRIBUTE attribute
;
58 CK_OBJECT_HANDLE object_handle
;
59 struct st_attr
*attrs
;
64 static struct soft_token
{
65 CK_VOID_PTR application
;
70 struct st_object
**objs
;
79 struct session_state
{
80 CK_SESSION_HANDLE session_handle
;
83 CK_ATTRIBUTE
*attributes
;
84 CK_ULONG num_attributes
;
89 CK_MECHANISM_PTR sign_mechanism
;
91 CK_MECHANISM_PTR verify_mechanism
;
93 #define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0]))
97 static hx509_context context
;
100 application_error(const char *fmt
, ...)
106 if (soft_token
.flags
.app_error_fatal
)
111 st_logf(const char *fmt
, ...)
114 if (soft_token
.logfile
== NULL
)
117 vfprintf(soft_token
.logfile
, fmt
, ap
);
119 fflush(soft_token
.logfile
);
125 if (context
== NULL
) {
126 int ret
= hx509_context_init(&context
);
128 return CKR_GENERAL_ERROR
;
133 #define INIT_CONTEXT() { CK_RV icret = init_context(); if (icret) return icret; }
136 snprintf_fill(char *str
, size_t size
, char fillchar
, const char *fmt
, ...)
141 len
= vsnprintf(str
, size
, fmt
, ap
);
143 if (len
< 0 || (size_t)len
> size
)
145 while ((size_t)len
< size
)
146 str
[len
++] = fillchar
;
150 #define printf error_use_st_logf
153 #define VERIFY_SESSION_HANDLE(s, state) \
156 xret = verify_session_handle(s, state); \
157 if (xret != CKR_OK) { \
158 /* return CKR_OK */; \
163 verify_session_handle(CK_SESSION_HANDLE hSession
,
164 struct session_state
**state
)
168 for (i
= 0; i
< MAX_NUM_SESSION
; i
++){
169 if (soft_token
.state
[i
].session_handle
== hSession
)
172 if (i
== MAX_NUM_SESSION
) {
173 application_error("use of invalid handle: 0x%08lx\n",
174 (unsigned long)hSession
);
175 return CKR_SESSION_HANDLE_INVALID
;
178 *state
= &soft_token
.state
[i
];
183 object_handle_to_object(CK_OBJECT_HANDLE handle
,
184 struct st_object
**object
)
186 int i
= HANDLE_OBJECT_ID(handle
);
189 if (i
>= soft_token
.object
.num_objs
)
190 return CKR_ARGUMENTS_BAD
;
191 if (soft_token
.object
.objs
[i
] == NULL
)
192 return CKR_ARGUMENTS_BAD
;
193 if (soft_token
.object
.objs
[i
]->object_handle
!= handle
)
194 return CKR_ARGUMENTS_BAD
;
195 *object
= soft_token
.object
.objs
[i
];
200 attributes_match(const struct st_object
*obj
,
201 const CK_ATTRIBUTE
*attributes
,
202 CK_ULONG num_attributes
)
207 st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj
));
209 for (i
= 0; i
< num_attributes
; i
++) {
211 for (j
= 0; j
< obj
->num_attributes
; j
++) {
212 if (attributes
[i
].type
== obj
->attrs
[j
].attribute
.type
&&
213 attributes
[i
].ulValueLen
== obj
->attrs
[j
].attribute
.ulValueLen
&&
214 memcmp(attributes
[i
].pValue
, obj
->attrs
[j
].attribute
.pValue
,
215 attributes
[i
].ulValueLen
) == 0) {
221 st_logf("type %d attribute have no match\n", attributes
[i
].type
);
225 st_logf("attribute matches\n");
230 print_attributes(const CK_ATTRIBUTE
*attributes
,
231 CK_ULONG num_attributes
)
235 st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes
);
237 for (i
= 0; i
< num_attributes
; i
++) {
239 switch (attributes
[i
].type
) {
242 if (attributes
[i
].ulValueLen
!= sizeof(CK_BBOOL
)) {
243 application_error("token attribute wrong length\n");
246 ck_true
= attributes
[i
].pValue
;
247 st_logf("token: %s", *ck_true
? "TRUE" : "FALSE");
251 CK_OBJECT_CLASS
*class;
252 if (attributes
[i
].ulValueLen
!= sizeof(CK_ULONG
)) {
253 application_error("class attribute wrong length\n");
256 class = attributes
[i
].pValue
;
259 case CKO_CERTIFICATE
:
260 st_logf("certificate");
263 st_logf("public key");
265 case CKO_PRIVATE_KEY
:
266 st_logf("private key");
269 st_logf("secret key");
271 case CKO_DOMAIN_PARAMETERS
:
272 st_logf("domain parameters");
275 st_logf("[class %lx]", (long unsigned)*class);
286 case CKA_APPLICATION
:
287 st_logf("application");
296 st_logf("[unknown 0x%08lx]", (unsigned long)attributes
[i
].type
);
303 static struct st_object
*
306 struct st_object
*o
, **objs
;
309 o
= calloc(1, sizeof(*o
));
313 for (i
= 0; i
< soft_token
.object
.num_objs
; i
++) {
314 if (soft_token
.object
.objs
[i
] == NULL
) {
315 soft_token
.object
.objs
[i
] = o
;
319 if (i
== soft_token
.object
.num_objs
) {
320 objs
= realloc(soft_token
.object
.objs
,
321 (soft_token
.object
.num_objs
+ 1) * sizeof(soft_token
.object
.objs
[0]));
326 soft_token
.object
.objs
= objs
;
327 soft_token
.object
.objs
[soft_token
.object
.num_objs
++] = o
;
329 soft_token
.object
.objs
[i
]->object_handle
=
330 (random() & (~OBJECT_ID_MASK
)) | i
;
336 add_object_attribute(struct st_object
*o
,
338 CK_ATTRIBUTE_TYPE type
,
345 if (pValue
== NULL
&& ulValueLen
)
346 return CKR_ARGUMENTS_BAD
;
348 i
= o
->num_attributes
;
349 a
= realloc(o
->attrs
, (i
+ 1) * sizeof(o
->attrs
[0]));
351 return CKR_DEVICE_MEMORY
;
353 o
->attrs
[i
].secret
= secret
;
354 o
->attrs
[i
].attribute
.type
= type
;
355 o
->attrs
[i
].attribute
.pValue
= malloc(ulValueLen
);
356 if (o
->attrs
[i
].attribute
.pValue
== NULL
&& ulValueLen
!= 0)
357 return CKR_DEVICE_MEMORY
;
359 memcpy(o
->attrs
[i
].attribute
.pValue
, pValue
, ulValueLen
);
360 o
->attrs
[i
].attribute
.ulValueLen
= ulValueLen
;
367 add_pubkey_info(hx509_context hxctx
, struct st_object
*o
,
368 CK_KEY_TYPE key_type
, hx509_cert cert
)
371 CK_BYTE
*modulus
= NULL
;
372 size_t modulus_len
= 0;
373 CK_ULONG modulus_bits
= 0;
374 CK_BYTE
*exponent
= NULL
;
375 size_t exponent_len
= 0;
377 if (key_type
!= CKK_RSA
)
379 if (_hx509_cert_private_key(cert
) == NULL
)
382 num
= _hx509_private_key_get_internal(context
,
383 _hx509_cert_private_key(cert
),
386 return CKR_GENERAL_ERROR
;
387 modulus_bits
= BN_num_bits(num
);
389 modulus_len
= BN_num_bytes(num
);
390 modulus
= malloc(modulus_len
);
391 BN_bn2bin(num
, modulus
);
394 add_object_attribute(o
, 0, CKA_MODULUS
, modulus
, modulus_len
);
395 add_object_attribute(o
, 0, CKA_MODULUS_BITS
,
396 &modulus_bits
, sizeof(modulus_bits
));
400 num
= _hx509_private_key_get_internal(context
,
401 _hx509_cert_private_key(cert
),
404 return CKR_GENERAL_ERROR
;
406 exponent_len
= BN_num_bytes(num
);
407 exponent
= malloc(exponent_len
);
408 BN_bn2bin(num
, exponent
);
411 add_object_attribute(o
, 0, CKA_PUBLIC_EXPONENT
,
412 exponent
, exponent_len
);
425 static int HX509_LIB_CALL
426 add_cert(hx509_context hxctx
, void *ctx
, hx509_cert cert
)
428 static char empty
[] = "";
429 struct foo
*foo
= (struct foo
*)ctx
;
430 struct st_object
*o
= NULL
;
431 CK_OBJECT_CLASS type
;
432 CK_BBOOL bool_true
= CK_TRUE
;
433 CK_BBOOL bool_false
= CK_FALSE
;
434 CK_CERTIFICATE_TYPE cert_type
= CKC_X_509
;
435 CK_KEY_TYPE key_type
;
436 CK_MECHANISM_TYPE mech_type
;
437 CK_RV ret
= CKR_GENERAL_ERROR
;
439 heim_octet_string cert_data
, subject_data
, issuer_data
, serial_data
;
441 st_logf("adding certificate\n");
443 serial_data
.data
= NULL
;
444 serial_data
.length
= 0;
445 cert_data
= subject_data
= issuer_data
= serial_data
;
447 hret
= hx509_cert_binary(hxctx
, cert
, &cert_data
);
454 hret
= hx509_cert_get_issuer(cert
, &name
);
457 hret
= hx509_name_binary(name
, &issuer_data
);
458 hx509_name_free(&name
);
462 hret
= hx509_cert_get_subject(cert
, &name
);
465 hret
= hx509_name_binary(name
, &subject_data
);
466 hx509_name_free(&name
);
472 AlgorithmIdentifier alg
;
474 hret
= hx509_cert_get_SPKI_AlgorithmIdentifier(context
, cert
, &alg
);
476 ret
= CKR_DEVICE_MEMORY
;
480 key_type
= CKK_RSA
; /* XXX */
482 free_AlgorithmIdentifier(&alg
);
486 type
= CKO_CERTIFICATE
;
489 ret
= CKR_DEVICE_MEMORY
;
493 o
->cert
= hx509_cert_ref(cert
);
495 add_object_attribute(o
, 0, CKA_CLASS
, &type
, sizeof(type
));
496 add_object_attribute(o
, 0, CKA_TOKEN
, &bool_true
, sizeof(bool_true
));
497 add_object_attribute(o
, 0, CKA_PRIVATE
, &bool_false
, sizeof(bool_false
));
498 add_object_attribute(o
, 0, CKA_MODIFIABLE
, &bool_false
, sizeof(bool_false
));
499 add_object_attribute(o
, 0, CKA_LABEL
, foo
->label
, strlen(foo
->label
));
501 add_object_attribute(o
, 0, CKA_CERTIFICATE_TYPE
, &cert_type
, sizeof(cert_type
));
502 add_object_attribute(o
, 0, CKA_ID
, foo
->id
, strlen(foo
->id
));
504 add_object_attribute(o
, 0, CKA_SUBJECT
, subject_data
.data
, subject_data
.length
);
505 add_object_attribute(o
, 0, CKA_ISSUER
, issuer_data
.data
, issuer_data
.length
);
506 add_object_attribute(o
, 0, CKA_SERIAL_NUMBER
, serial_data
.data
, serial_data
.length
);
507 add_object_attribute(o
, 0, CKA_VALUE
, cert_data
.data
, cert_data
.length
);
508 add_object_attribute(o
, 0, CKA_TRUSTED
, &bool_false
, sizeof(bool_false
));
510 st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o
));
512 type
= CKO_PUBLIC_KEY
;
515 ret
= CKR_DEVICE_MEMORY
;
518 o
->cert
= hx509_cert_ref(cert
);
520 add_object_attribute(o
, 0, CKA_CLASS
, &type
, sizeof(type
));
521 add_object_attribute(o
, 0, CKA_TOKEN
, &bool_true
, sizeof(bool_true
));
522 add_object_attribute(o
, 0, CKA_PRIVATE
, &bool_false
, sizeof(bool_false
));
523 add_object_attribute(o
, 0, CKA_MODIFIABLE
, &bool_false
, sizeof(bool_false
));
524 add_object_attribute(o
, 0, CKA_LABEL
, foo
->label
, strlen(foo
->label
));
526 add_object_attribute(o
, 0, CKA_KEY_TYPE
, &key_type
, sizeof(key_type
));
527 add_object_attribute(o
, 0, CKA_ID
, foo
->id
, strlen(foo
->id
));
528 add_object_attribute(o
, 0, CKA_START_DATE
, empty
, 1); /* XXX */
529 add_object_attribute(o
, 0, CKA_END_DATE
, empty
, 1); /* XXX */
530 add_object_attribute(o
, 0, CKA_DERIVE
, &bool_false
, sizeof(bool_false
));
531 add_object_attribute(o
, 0, CKA_LOCAL
, &bool_false
, sizeof(bool_false
));
532 mech_type
= CKM_RSA_X_509
;
533 add_object_attribute(o
, 0, CKA_KEY_GEN_MECHANISM
, &mech_type
, sizeof(mech_type
));
535 add_object_attribute(o
, 0, CKA_SUBJECT
, subject_data
.data
, subject_data
.length
);
536 add_object_attribute(o
, 0, CKA_ENCRYPT
, &bool_true
, sizeof(bool_true
));
537 add_object_attribute(o
, 0, CKA_VERIFY
, &bool_true
, sizeof(bool_true
));
538 add_object_attribute(o
, 0, CKA_VERIFY_RECOVER
, &bool_false
, sizeof(bool_false
));
539 add_object_attribute(o
, 0, CKA_WRAP
, &bool_true
, sizeof(bool_true
));
540 add_object_attribute(o
, 0, CKA_TRUSTED
, &bool_true
, sizeof(bool_true
));
542 add_pubkey_info(hxctx
, o
, key_type
, cert
);
544 st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o
));
546 if (hx509_cert_have_private_key(cert
)) {
549 type
= CKO_PRIVATE_KEY
;
551 /* Note to static analyzers: `o' is still referred to via globals */
554 ret
= CKR_DEVICE_MEMORY
;
557 o
->cert
= hx509_cert_ref(cert
);
559 add_object_attribute(o
, 0, CKA_CLASS
, &type
, sizeof(type
));
560 add_object_attribute(o
, 0, CKA_TOKEN
, &bool_true
, sizeof(bool_true
));
561 add_object_attribute(o
, 0, CKA_PRIVATE
, &bool_true
, sizeof(bool_false
));
562 add_object_attribute(o
, 0, CKA_MODIFIABLE
, &bool_false
, sizeof(bool_false
));
563 add_object_attribute(o
, 0, CKA_LABEL
, foo
->label
, strlen(foo
->label
));
565 add_object_attribute(o
, 0, CKA_KEY_TYPE
, &key_type
, sizeof(key_type
));
566 add_object_attribute(o
, 0, CKA_ID
, foo
->id
, strlen(foo
->id
));
567 add_object_attribute(o
, 0, CKA_START_DATE
, empty
, 1); /* XXX */
568 add_object_attribute(o
, 0, CKA_END_DATE
, empty
, 1); /* XXX */
569 add_object_attribute(o
, 0, CKA_DERIVE
, &bool_false
, sizeof(bool_false
));
570 add_object_attribute(o
, 0, CKA_LOCAL
, &bool_false
, sizeof(bool_false
));
571 mech_type
= CKM_RSA_X_509
;
572 add_object_attribute(o
, 0, CKA_KEY_GEN_MECHANISM
, &mech_type
, sizeof(mech_type
));
574 add_object_attribute(o
, 0, CKA_SUBJECT
, subject_data
.data
, subject_data
.length
);
575 add_object_attribute(o
, 0, CKA_SENSITIVE
, &bool_true
, sizeof(bool_true
));
576 add_object_attribute(o
, 0, CKA_SECONDARY_AUTH
, &bool_false
, sizeof(bool_true
));
578 add_object_attribute(o
, 0, CKA_AUTH_PIN_FLAGS
, &flags
, sizeof(flags
));
580 add_object_attribute(o
, 0, CKA_DECRYPT
, &bool_true
, sizeof(bool_true
));
581 add_object_attribute(o
, 0, CKA_SIGN
, &bool_true
, sizeof(bool_true
));
582 add_object_attribute(o
, 0, CKA_SIGN_RECOVER
, &bool_false
, sizeof(bool_false
));
583 add_object_attribute(o
, 0, CKA_UNWRAP
, &bool_true
, sizeof(bool_true
));
584 add_object_attribute(o
, 0, CKA_EXTRACTABLE
, &bool_true
, sizeof(bool_true
));
585 add_object_attribute(o
, 0, CKA_NEVER_EXTRACTABLE
, &bool_false
, sizeof(bool_false
));
587 add_pubkey_info(hxctx
, o
, key_type
, cert
);
593 st_logf("something went wrong when adding cert!\n");
597 hx509_xfree(cert_data
.data
);
598 hx509_xfree(serial_data
.data
);
599 hx509_xfree(issuer_data
.data
);
600 hx509_xfree(subject_data
.data
);
602 /* Note to static analyzers: `o' is still referred to via globals */
607 add_certificate(const char *cert_file
,
613 hx509_lock lock
= NULL
;
621 flags
|= HX509_CERTS_UNPROTECT_ALL
;
625 ret
= asprintf(&str
, "PASS:%s", pin
);
626 if (ret
== -1 || !str
) {
627 st_logf("failed to allocate memory\n");
628 return CKR_GENERAL_ERROR
;
631 hx509_lock_init(context
, &lock
);
632 hx509_lock_command_string(lock
, str
);
634 memset(str
, 0, strlen(str
));
638 ret
= hx509_certs_init(context
, cert_file
, flags
, lock
, &certs
);
640 st_logf("failed to open file %s\n", cert_file
);
641 return CKR_GENERAL_ERROR
;
644 ret
= hx509_certs_iter_f(context
, certs
, add_cert
, &foo
);
645 hx509_certs_free(&certs
);
647 st_logf("failed adding certs from file %s\n", cert_file
);
648 return CKR_GENERAL_ERROR
;
655 find_object_final(struct session_state
*state
)
657 if (state
->find
.attributes
) {
660 for (i
= 0; i
< state
->find
.num_attributes
; i
++) {
661 if (state
->find
.attributes
[i
].pValue
)
662 free(state
->find
.attributes
[i
].pValue
);
664 free(state
->find
.attributes
);
665 state
->find
.attributes
= NULL
;
666 state
->find
.num_attributes
= 0;
667 state
->find
.next_object
= -1;
672 reset_crypto_state(struct session_state
*state
)
674 state
->sign_object
= -1;
675 if (state
->sign_mechanism
)
676 free(state
->sign_mechanism
);
677 state
->sign_mechanism
= NULL_PTR
;
678 state
->verify_object
= -1;
679 if (state
->verify_mechanism
)
680 free(state
->verify_mechanism
);
681 state
->verify_mechanism
= NULL_PTR
;
685 close_session(struct session_state
*state
)
687 if (state
->find
.attributes
) {
688 application_error("application didn't do C_FindObjectsFinal\n");
689 find_object_final(state
);
692 state
->session_handle
= CK_INVALID_HANDLE
;
693 soft_token
.application
= NULL_PTR
;
694 soft_token
.notify
= NULL_PTR
;
695 reset_crypto_state(state
);
701 return soft_token
.open_sessions
> 0 ? "yes" : "no";
705 read_conf_file(const char *fn
, CK_USER_TYPE userType
, const char *pin
)
707 char buf
[1024], *type
, *s
, *p
;
710 CK_RV failed
= CKR_OK
;
713 st_logf("Can't open configuration file. No file specified\n");
714 return CKR_GENERAL_ERROR
;
719 st_logf("can't open configuration file %s\n", fn
);
720 return CKR_GENERAL_ERROR
;
724 while(fgets(buf
, sizeof(buf
), f
) != NULL
) {
725 buf
[strcspn(buf
, "\n")] = '\0';
727 st_logf("line: %s\n", buf
);
730 while (isspace((unsigned char)*p
))
734 while (isspace((unsigned char)*p
))
738 type
= strtok_r(p
, "\t", &s
);
742 if (strcasecmp("certificate", type
) == 0) {
743 char *cert
, *id
, *label
;
745 id
= strtok_r(NULL
, "\t", &s
);
750 st_logf("id: %s\n", id
);
751 label
= strtok_r(NULL
, "\t", &s
);
753 st_logf("no label\n");
756 cert
= strtok_r(NULL
, "\t", &s
);
758 st_logf("no certfiicate store\n");
762 st_logf("adding: %s: %s in file %s\n", id
, label
, cert
);
764 ret
= add_certificate(cert
, pin
, id
, label
);
767 } else if (strcasecmp("debug", type
) == 0) {
770 name
= strtok_r(NULL
, "\t", &s
);
772 st_logf("no filename\n");
776 if (soft_token
.logfile
)
777 fclose(soft_token
.logfile
);
779 if (strcasecmp(name
, "stdout") == 0)
780 soft_token
.logfile
= stdout
;
782 soft_token
.logfile
= fopen(name
, "a");
783 if (soft_token
.logfile
)
784 rk_cloexec_file(soft_token
.logfile
);
786 if (soft_token
.logfile
== NULL
)
787 st_logf("failed to open file: %s\n", name
);
789 } else if (strcasecmp("app-fatal", type
) == 0) {
792 name
= strtok_r(NULL
, "\t", &s
);
794 st_logf("argument to app-fatal\n");
798 if (strcmp(name
, "true") == 0 || strcmp(name
, "on") == 0)
799 soft_token
.flags
.app_error_fatal
= 1;
800 else if (strcmp(name
, "false") == 0 || strcmp(name
, "off") == 0)
801 soft_token
.flags
.app_error_fatal
= 0;
803 st_logf("unknown app-fatal: %s\n", name
);
806 st_logf("unknown type: %s\n", type
);
816 func_not_supported(void)
818 st_logf("function not supported\n");
819 return CKR_FUNCTION_NOT_SUPPORTED
;
823 get_config_file_for_user(void)
828 fn
= secure_getenv("SOFTPKCS11RC");
832 char homebuf
[MAX_PATH
];
833 const char *home
= roken_get_appdatadir(homebuf
, sizeof(homebuf
));
836 ret
= asprintf(&fn
, "%s/.soft-token.rc", home
);
841 fn
= strdup("/etc/soft-token.rc");
851 C_Initialize(CK_VOID_PTR a
)
853 CK_C_INITIALIZE_ARGS_PTR args
= a
;
857 st_logf("Initialize\n");
861 OpenSSL_add_all_algorithms();
863 srandom(getpid() ^ (int) time(NULL
));
865 for (i
= 0; i
< MAX_NUM_SESSION
; i
++) {
866 soft_token
.state
[i
].session_handle
= CK_INVALID_HANDLE
;
867 soft_token
.state
[i
].find
.attributes
= NULL
;
868 soft_token
.state
[i
].find
.num_attributes
= 0;
869 soft_token
.state
[i
].find
.next_object
= -1;
870 reset_crypto_state(&soft_token
.state
[i
]);
873 soft_token
.flags
.hardware_slot
= 1;
874 soft_token
.flags
.app_error_fatal
= 0;
875 soft_token
.flags
.login_done
= 0;
877 soft_token
.object
.objs
= NULL
;
878 soft_token
.object
.num_objs
= 0;
880 soft_token
.logfile
= NULL
;
882 soft_token
.logfile
= stdout
;
885 soft_token
.logfile
= fopen("/tmp/log-pkcs11.txt", "a");
889 st_logf("\tCreateMutex:\t%p\n", args
->CreateMutex
);
890 st_logf("\tDestroyMutext\t%p\n", args
->DestroyMutex
);
891 st_logf("\tLockMutext\t%p\n", args
->LockMutex
);
892 st_logf("\tUnlockMutext\t%p\n", args
->UnlockMutex
);
893 st_logf("\tFlags\t%04x\n", (unsigned int)args
->flags
);
896 soft_token
.config_file
= get_config_file_for_user();
899 * This operations doesn't return CKR_OK if any of the
900 * certificates failes to be unparsed (ie password protected).
902 ret
= read_conf_file(soft_token
.config_file
, CKU_USER
, NULL
);
904 soft_token
.flags
.login_done
= 1;
910 C_Finalize(CK_VOID_PTR args
)
916 st_logf("Finalize\n");
918 for (i
= 0; i
< MAX_NUM_SESSION
; i
++) {
919 if (soft_token
.state
[i
].session_handle
!= CK_INVALID_HANDLE
) {
920 application_error("application finalized without "
921 "closing session\n");
922 close_session(&soft_token
.state
[i
]);
930 C_GetInfo(CK_INFO_PTR args
)
934 st_logf("GetInfo\n");
936 memset(args
, 17, sizeof(*args
));
937 args
->cryptokiVersion
.major
= 2;
938 args
->cryptokiVersion
.minor
= 10;
939 snprintf_fill((char *)args
->manufacturerID
,
940 sizeof(args
->manufacturerID
),
942 "Heimdal hx509 SoftToken");
943 snprintf_fill((char *)args
->libraryDescription
,
944 sizeof(args
->libraryDescription
), ' ',
945 "Heimdal hx509 SoftToken");
946 args
->libraryVersion
.major
= 2;
947 args
->libraryVersion
.minor
= 0;
952 extern CK_FUNCTION_LIST funcs
;
955 C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList
)
959 *ppFunctionList
= &funcs
;
964 C_GetSlotList(CK_BBOOL tokenPresent
,
965 CK_SLOT_ID_PTR pSlotList
,
966 CK_ULONG_PTR pulCount
)
969 st_logf("GetSlotList: %s\n",
970 tokenPresent
? "tokenPresent" : "token not Present");
978 C_GetSlotInfo(CK_SLOT_ID slotID
,
979 CK_SLOT_INFO_PTR pInfo
)
982 st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID
, has_session());
984 memset(pInfo
, 18, sizeof(*pInfo
));
987 return CKR_ARGUMENTS_BAD
;
989 snprintf_fill((char *)pInfo
->slotDescription
,
990 sizeof(pInfo
->slotDescription
),
992 "Heimdal hx509 SoftToken (slot)");
993 snprintf_fill((char *)pInfo
->manufacturerID
,
994 sizeof(pInfo
->manufacturerID
),
996 "Heimdal hx509 SoftToken (slot)");
997 pInfo
->flags
= CKF_TOKEN_PRESENT
;
998 if (soft_token
.flags
.hardware_slot
)
999 pInfo
->flags
|= CKF_HW_SLOT
;
1000 pInfo
->hardwareVersion
.major
= 1;
1001 pInfo
->hardwareVersion
.minor
= 0;
1002 pInfo
->firmwareVersion
.major
= 1;
1003 pInfo
->firmwareVersion
.minor
= 0;
1009 C_GetTokenInfo(CK_SLOT_ID slotID
,
1010 CK_TOKEN_INFO_PTR pInfo
)
1013 st_logf("GetTokenInfo: %s\n", has_session());
1015 memset(pInfo
, 19, sizeof(*pInfo
));
1017 snprintf_fill((char *)pInfo
->label
,
1018 sizeof(pInfo
->label
),
1020 "Heimdal hx509 SoftToken (token)");
1021 snprintf_fill((char *)pInfo
->manufacturerID
,
1022 sizeof(pInfo
->manufacturerID
),
1024 "Heimdal hx509 SoftToken (token)");
1025 snprintf_fill((char *)pInfo
->model
,
1026 sizeof(pInfo
->model
),
1028 "Heimdal hx509 SoftToken (token)");
1029 snprintf_fill((char *)pInfo
->serialNumber
,
1030 sizeof(pInfo
->serialNumber
),
1034 CKF_TOKEN_INITIALIZED
|
1035 CKF_USER_PIN_INITIALIZED
;
1037 if (soft_token
.flags
.login_done
== 0)
1038 pInfo
->flags
|= CKF_LOGIN_REQUIRED
;
1041 CKF_RESTORE_KEY_NOT_NEEDED |
1043 pInfo
->ulMaxSessionCount
= MAX_NUM_SESSION
;
1044 pInfo
->ulSessionCount
= soft_token
.open_sessions
;
1045 pInfo
->ulMaxRwSessionCount
= MAX_NUM_SESSION
;
1046 pInfo
->ulRwSessionCount
= soft_token
.open_sessions
;
1047 pInfo
->ulMaxPinLen
= 1024;
1048 pInfo
->ulMinPinLen
= 0;
1049 pInfo
->ulTotalPublicMemory
= 4711;
1050 pInfo
->ulFreePublicMemory
= 4712;
1051 pInfo
->ulTotalPrivateMemory
= 4713;
1052 pInfo
->ulFreePrivateMemory
= 4714;
1053 pInfo
->hardwareVersion
.major
= 2;
1054 pInfo
->hardwareVersion
.minor
= 0;
1055 pInfo
->firmwareVersion
.major
= 2;
1056 pInfo
->firmwareVersion
.minor
= 0;
1062 C_GetMechanismList(CK_SLOT_ID slotID
,
1063 CK_MECHANISM_TYPE_PTR pMechanismList
,
1064 CK_ULONG_PTR pulCount
)
1067 st_logf("GetMechanismList\n");
1070 if (pMechanismList
== NULL_PTR
)
1072 pMechanismList
[0] = CKM_RSA_PKCS
;
1078 C_GetMechanismInfo(CK_SLOT_ID slotID
,
1079 CK_MECHANISM_TYPE type
,
1080 CK_MECHANISM_INFO_PTR pInfo
)
1083 st_logf("GetMechanismInfo: slot %d type: %d\n",
1084 (int)slotID
, (int)type
);
1085 memset(pInfo
, 0, sizeof(*pInfo
));
1091 C_InitToken(CK_SLOT_ID slotID
,
1092 CK_UTF8CHAR_PTR pPin
,
1094 CK_UTF8CHAR_PTR pLabel
)
1097 st_logf("InitToken: slot %d\n", (int)slotID
);
1098 return CKR_FUNCTION_NOT_SUPPORTED
;
1102 C_OpenSession(CK_SLOT_ID slotID
,
1104 CK_VOID_PTR pApplication
,
1106 CK_SESSION_HANDLE_PTR phSession
)
1110 st_logf("OpenSession: slot: %d\n", (int)slotID
);
1112 if (soft_token
.open_sessions
== MAX_NUM_SESSION
)
1113 return CKR_SESSION_COUNT
;
1115 soft_token
.application
= pApplication
;
1116 soft_token
.notify
= Notify
;
1118 for (i
= 0; i
< MAX_NUM_SESSION
; i
++)
1119 if (soft_token
.state
[i
].session_handle
== CK_INVALID_HANDLE
)
1121 if (i
== MAX_NUM_SESSION
)
1124 soft_token
.open_sessions
++;
1126 soft_token
.state
[i
].session_handle
=
1127 (CK_SESSION_HANDLE
)(random() & 0xfffff);
1128 *phSession
= soft_token
.state
[i
].session_handle
;
1134 C_CloseSession(CK_SESSION_HANDLE hSession
)
1136 struct session_state
*state
;
1138 st_logf("CloseSession\n");
1140 if (verify_session_handle(hSession
, &state
) != CKR_OK
)
1141 application_error("closed session not open");
1143 close_session(state
);
1149 C_CloseAllSessions(CK_SLOT_ID slotID
)
1154 st_logf("CloseAllSessions\n");
1156 for (i
= 0; i
< MAX_NUM_SESSION
; i
++)
1157 if (soft_token
.state
[i
].session_handle
!= CK_INVALID_HANDLE
)
1158 close_session(&soft_token
.state
[i
]);
1164 C_GetSessionInfo(CK_SESSION_HANDLE hSession
,
1165 CK_SESSION_INFO_PTR pInfo
)
1167 st_logf("GetSessionInfo\n");
1170 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1172 memset(pInfo
, 20, sizeof(*pInfo
));
1175 if (soft_token
.flags
.login_done
)
1176 pInfo
->state
= CKS_RO_USER_FUNCTIONS
;
1178 pInfo
->state
= CKS_RO_PUBLIC_SESSION
;
1179 pInfo
->flags
= CKF_SERIAL_SESSION
;
1180 pInfo
->ulDeviceError
= 0;
1186 C_Login(CK_SESSION_HANDLE hSession
,
1187 CK_USER_TYPE userType
,
1188 CK_UTF8CHAR_PTR pPin
,
1197 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1199 if (pPin
!= NULL_PTR
) {
1202 aret
= asprintf(&pin
, "%.*s", (int)ulPinLen
, pPin
);
1203 if (aret
!= -1 && pin
)
1204 st_logf("type: %d password: %s\n", (int)userType
, pin
);
1206 st_logf("memory error: asprintf failed\n");
1213 ret
= read_conf_file(soft_token
.config_file
, userType
, pin
);
1215 soft_token
.flags
.login_done
= 1;
1219 return soft_token
.flags
.login_done
? CKR_OK
: CKR_PIN_INCORRECT
;
1223 C_Logout(CK_SESSION_HANDLE hSession
)
1225 st_logf("Logout\n");
1228 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1229 return CKR_FUNCTION_NOT_SUPPORTED
;
1233 C_GetObjectSize(CK_SESSION_HANDLE hSession
,
1234 CK_OBJECT_HANDLE hObject
,
1235 CK_ULONG_PTR pulSize
)
1237 st_logf("GetObjectSize\n");
1240 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1241 return CKR_FUNCTION_NOT_SUPPORTED
;
1245 C_GetAttributeValue(CK_SESSION_HANDLE hSession
,
1246 CK_OBJECT_HANDLE hObject
,
1247 CK_ATTRIBUTE_PTR pTemplate
,
1250 struct session_state
*state
;
1251 struct st_object
*obj
;
1258 st_logf("GetAttributeValue: %lx\n",
1259 (unsigned long)HANDLE_OBJECT_ID(hObject
));
1260 VERIFY_SESSION_HANDLE(hSession
, &state
);
1262 if ((ret
= object_handle_to_object(hObject
, &obj
)) != CKR_OK
) {
1263 st_logf("object not found: %lx\n",
1264 (unsigned long)HANDLE_OBJECT_ID(hObject
));
1268 for (i
= 0; i
< ulCount
; i
++) {
1269 st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate
[i
].type
);
1270 for (j
= 0; j
< obj
->num_attributes
; j
++) {
1271 if (obj
->attrs
[j
].secret
) {
1272 pTemplate
[i
].ulValueLen
= (CK_ULONG
)-1;
1275 if (pTemplate
[i
].type
== obj
->attrs
[j
].attribute
.type
) {
1276 if (pTemplate
[i
].pValue
!= NULL_PTR
&& obj
->attrs
[j
].secret
== 0) {
1277 if (pTemplate
[i
].ulValueLen
>= obj
->attrs
[j
].attribute
.ulValueLen
)
1278 memcpy(pTemplate
[i
].pValue
, obj
->attrs
[j
].attribute
.pValue
,
1279 obj
->attrs
[j
].attribute
.ulValueLen
);
1281 pTemplate
[i
].ulValueLen
= obj
->attrs
[j
].attribute
.ulValueLen
;
1285 if (j
== obj
->num_attributes
) {
1286 st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate
[i
].type
);
1287 pTemplate
[i
].ulValueLen
= (CK_ULONG
)-1;
1295 C_FindObjectsInit(CK_SESSION_HANDLE hSession
,
1296 CK_ATTRIBUTE_PTR pTemplate
,
1299 struct session_state
*state
;
1301 st_logf("FindObjectsInit\n");
1305 VERIFY_SESSION_HANDLE(hSession
, &state
);
1307 if (state
->find
.next_object
!= -1) {
1308 application_error("application didn't do C_FindObjectsFinal\n");
1309 find_object_final(state
);
1314 print_attributes(pTemplate
, ulCount
);
1316 state
->find
.attributes
=
1317 calloc(1, ulCount
* sizeof(state
->find
.attributes
[0]));
1318 if (state
->find
.attributes
== NULL
)
1319 return CKR_DEVICE_MEMORY
;
1320 for (i
= 0; i
< ulCount
; i
++) {
1321 state
->find
.attributes
[i
].pValue
=
1322 malloc(pTemplate
[i
].ulValueLen
);
1323 if (state
->find
.attributes
[i
].pValue
== NULL
) {
1324 find_object_final(state
);
1325 return CKR_DEVICE_MEMORY
;
1327 memcpy(state
->find
.attributes
[i
].pValue
,
1328 pTemplate
[i
].pValue
, pTemplate
[i
].ulValueLen
);
1329 state
->find
.attributes
[i
].type
= pTemplate
[i
].type
;
1330 state
->find
.attributes
[i
].ulValueLen
= pTemplate
[i
].ulValueLen
;
1332 state
->find
.num_attributes
= ulCount
;
1333 state
->find
.next_object
= 0;
1335 st_logf("find all objects\n");
1336 state
->find
.attributes
= NULL
;
1337 state
->find
.num_attributes
= 0;
1338 state
->find
.next_object
= 0;
1345 C_FindObjects(CK_SESSION_HANDLE hSession
,
1346 CK_OBJECT_HANDLE_PTR phObject
,
1347 CK_ULONG ulMaxObjectCount
,
1348 CK_ULONG_PTR pulObjectCount
)
1350 struct session_state
*state
;
1355 st_logf("FindObjects\n");
1357 VERIFY_SESSION_HANDLE(hSession
, &state
);
1359 if (state
->find
.next_object
== -1) {
1360 application_error("application didn't do C_FindObjectsInit\n");
1361 return CKR_ARGUMENTS_BAD
;
1363 if (ulMaxObjectCount
== 0) {
1364 application_error("application asked for 0 objects\n");
1365 return CKR_ARGUMENTS_BAD
;
1367 *pulObjectCount
= 0;
1368 for (i
= state
->find
.next_object
; i
< soft_token
.object
.num_objs
; i
++) {
1369 st_logf("FindObjects: %d\n", i
);
1370 state
->find
.next_object
= i
+ 1;
1371 if (attributes_match(soft_token
.object
.objs
[i
],
1372 state
->find
.attributes
,
1373 state
->find
.num_attributes
)) {
1374 *phObject
++ = soft_token
.object
.objs
[i
]->object_handle
;
1376 (*pulObjectCount
)++;
1377 if (ulMaxObjectCount
== 0)
1385 C_FindObjectsFinal(CK_SESSION_HANDLE hSession
)
1387 struct session_state
*state
;
1391 st_logf("FindObjectsFinal\n");
1392 VERIFY_SESSION_HANDLE(hSession
, &state
);
1393 find_object_final(state
);
1398 commonInit(CK_ATTRIBUTE
*attr_match
, int attr_match_len
,
1399 const CK_MECHANISM_TYPE
*mechs
, int mechs_len
,
1400 const CK_MECHANISM_PTR pMechanism
, CK_OBJECT_HANDLE hKey
,
1401 struct st_object
**o
)
1407 if ((ret
= object_handle_to_object(hKey
, o
)) != CKR_OK
)
1410 ret
= attributes_match(*o
, attr_match
, attr_match_len
);
1412 application_error("called commonInit on key that doesn't "
1413 "support required attr");
1414 return CKR_ARGUMENTS_BAD
;
1417 for (i
= 0; i
< mechs_len
; i
++)
1418 if (mechs
[i
] == pMechanism
->mechanism
)
1420 if (i
== mechs_len
) {
1421 application_error("called mech (%08lx) not supported\n",
1422 pMechanism
->mechanism
);
1423 return CKR_ARGUMENTS_BAD
;
1430 dup_mechanism(CK_MECHANISM_PTR
*dp
, const CK_MECHANISM_PTR pMechanism
)
1434 p
= malloc(sizeof(*p
));
1436 return CKR_DEVICE_MEMORY
;
1441 memcpy(p
, pMechanism
, sizeof(*p
));
1447 C_DigestInit(CK_SESSION_HANDLE hSession
,
1448 CK_MECHANISM_PTR pMechanism
)
1450 st_logf("DigestInit\n");
1452 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1453 return CKR_FUNCTION_NOT_SUPPORTED
;
1457 C_SignInit(CK_SESSION_HANDLE hSession
,
1458 CK_MECHANISM_PTR pMechanism
,
1459 CK_OBJECT_HANDLE hKey
)
1461 struct session_state
*state
;
1462 CK_MECHANISM_TYPE mechs
[] = { CKM_RSA_PKCS
};
1463 CK_BBOOL bool_true
= CK_TRUE
;
1464 CK_ATTRIBUTE attr
[] = {
1465 { CKA_SIGN
, &bool_true
, sizeof(bool_true
) }
1467 struct st_object
*o
;
1471 st_logf("SignInit\n");
1472 VERIFY_SESSION_HANDLE(hSession
, &state
);
1474 ret
= commonInit(attr
, sizeof(attr
)/sizeof(attr
[0]),
1475 mechs
, sizeof(mechs
)/sizeof(mechs
[0]),
1476 pMechanism
, hKey
, &o
);
1480 ret
= dup_mechanism(&state
->sign_mechanism
, pMechanism
);
1482 state
->sign_object
= OBJECT_ID(o
);
1488 C_Sign(CK_SESSION_HANDLE hSession
,
1491 CK_BYTE_PTR pSignature
,
1492 CK_ULONG_PTR pulSignatureLen
)
1494 struct session_state
*state
;
1495 struct st_object
*o
;
1498 const AlgorithmIdentifier
*alg
;
1499 heim_octet_string sig
, data
;
1503 VERIFY_SESSION_HANDLE(hSession
, &state
);
1508 if (state
->sign_object
== -1)
1509 return CKR_ARGUMENTS_BAD
;
1511 if (pulSignatureLen
== NULL
) {
1512 st_logf("signature len NULL\n");
1513 ret
= CKR_ARGUMENTS_BAD
;
1517 if (pData
== NULL_PTR
) {
1518 st_logf("data NULL\n");
1519 ret
= CKR_ARGUMENTS_BAD
;
1523 o
= soft_token
.object
.objs
[state
->sign_object
];
1525 if (hx509_cert_have_private_key(o
->cert
) == 0) {
1526 st_logf("private key NULL\n");
1527 return CKR_ARGUMENTS_BAD
;
1530 switch(state
->sign_mechanism
->mechanism
) {
1532 alg
= hx509_signature_rsa_pkcs1_x509();
1535 ret
= CKR_FUNCTION_NOT_SUPPORTED
;
1540 data
.length
= ulDataLen
;
1542 hret
= _hx509_create_signature(context
,
1543 _hx509_cert_private_key(o
->cert
),
1549 ret
= CKR_DEVICE_ERROR
;
1552 *pulSignatureLen
= sig
.length
;
1554 if (pSignature
!= NULL_PTR
)
1555 memcpy(pSignature
, sig
.data
, sig
.length
);
1560 memset(sig
.data
, 0, sig
.length
);
1561 der_free_octet_string(&sig
);
1567 C_SignUpdate(CK_SESSION_HANDLE hSession
,
1572 st_logf("SignUpdate\n");
1573 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1574 return CKR_FUNCTION_NOT_SUPPORTED
;
1579 C_SignFinal(CK_SESSION_HANDLE hSession
,
1580 CK_BYTE_PTR pSignature
,
1581 CK_ULONG_PTR pulSignatureLen
)
1584 st_logf("SignUpdate\n");
1585 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1586 return CKR_FUNCTION_NOT_SUPPORTED
;
1590 C_VerifyInit(CK_SESSION_HANDLE hSession
,
1591 CK_MECHANISM_PTR pMechanism
,
1592 CK_OBJECT_HANDLE hKey
)
1594 struct session_state
*state
;
1595 CK_MECHANISM_TYPE mechs
[] = { CKM_RSA_PKCS
};
1596 CK_BBOOL bool_true
= CK_TRUE
;
1597 CK_ATTRIBUTE attr
[] = {
1598 { CKA_VERIFY
, &bool_true
, sizeof(bool_true
) }
1600 struct st_object
*o
;
1604 st_logf("VerifyInit\n");
1605 VERIFY_SESSION_HANDLE(hSession
, &state
);
1607 ret
= commonInit(attr
, sizeof(attr
)/sizeof(attr
[0]),
1608 mechs
, sizeof(mechs
)/sizeof(mechs
[0]),
1609 pMechanism
, hKey
, &o
);
1613 ret
= dup_mechanism(&state
->verify_mechanism
, pMechanism
);
1615 state
->verify_object
= OBJECT_ID(o
);
1621 C_Verify(CK_SESSION_HANDLE hSession
,
1624 CK_BYTE_PTR pSignature
,
1625 CK_ULONG ulSignatureLen
)
1627 struct session_state
*state
;
1628 struct st_object
*o
;
1629 const AlgorithmIdentifier
*alg
;
1632 heim_octet_string data
, sig
;
1635 st_logf("Verify\n");
1636 VERIFY_SESSION_HANDLE(hSession
, &state
);
1638 if (state
->verify_object
== -1)
1639 return CKR_ARGUMENTS_BAD
;
1641 o
= soft_token
.object
.objs
[state
->verify_object
];
1643 switch(state
->verify_mechanism
->mechanism
) {
1645 alg
= hx509_signature_rsa_pkcs1_x509();
1648 ret
= CKR_FUNCTION_NOT_SUPPORTED
;
1653 sig
.length
= ulDataLen
;
1654 data
.data
= pSignature
;
1655 data
.length
= ulSignatureLen
;
1657 hret
= _hx509_verify_signature(context
,
1663 ret
= CKR_GENERAL_ERROR
;
1674 C_VerifyUpdate(CK_SESSION_HANDLE hSession
,
1679 st_logf("VerifyUpdate\n");
1680 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1681 return CKR_FUNCTION_NOT_SUPPORTED
;
1685 C_VerifyFinal(CK_SESSION_HANDLE hSession
,
1686 CK_BYTE_PTR pSignature
,
1687 CK_ULONG ulSignatureLen
)
1690 st_logf("VerifyFinal\n");
1691 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1692 return CKR_FUNCTION_NOT_SUPPORTED
;
1696 C_GenerateRandom(CK_SESSION_HANDLE hSession
,
1697 CK_BYTE_PTR RandomData
,
1698 CK_ULONG ulRandomLen
)
1701 st_logf("GenerateRandom\n");
1702 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1703 return CKR_FUNCTION_NOT_SUPPORTED
;
1707 CK_FUNCTION_LIST funcs
= {
1719 (void *)func_not_supported
, /* C_InitPIN */
1720 (void *)func_not_supported
, /* C_SetPIN */
1725 (void *)func_not_supported
, /* C_GetOperationState */
1726 (void *)func_not_supported
, /* C_SetOperationState */
1729 (void *)func_not_supported
, /* C_CreateObject */
1730 (void *)func_not_supported
, /* C_CopyObject */
1731 (void *)func_not_supported
, /* C_DestroyObject */
1732 (void *)func_not_supported
, /* C_GetObjectSize */
1733 C_GetAttributeValue
,
1734 (void *)func_not_supported
, /* C_SetAttributeValue */
1738 (void *)func_not_supported
, /* C_EncryptInit, */
1739 (void *)func_not_supported
, /* C_Encrypt, */
1740 (void *)func_not_supported
, /* C_EncryptUpdate, */
1741 (void *)func_not_supported
, /* C_EncryptFinal, */
1742 (void *)func_not_supported
, /* C_DecryptInit, */
1743 (void *)func_not_supported
, /* C_Decrypt, */
1744 (void *)func_not_supported
, /* C_DecryptUpdate, */
1745 (void *)func_not_supported
, /* C_DecryptFinal, */
1747 (void *)func_not_supported
, /* C_Digest */
1748 (void *)func_not_supported
, /* C_DigestUpdate */
1749 (void *)func_not_supported
, /* C_DigestKey */
1750 (void *)func_not_supported
, /* C_DigestFinal */
1755 (void *)func_not_supported
, /* C_SignRecoverInit */
1756 (void *)func_not_supported
, /* C_SignRecover */
1761 (void *)func_not_supported
, /* C_VerifyRecoverInit */
1762 (void *)func_not_supported
, /* C_VerifyRecover */
1763 (void *)func_not_supported
, /* C_DigestEncryptUpdate */
1764 (void *)func_not_supported
, /* C_DecryptDigestUpdate */
1765 (void *)func_not_supported
, /* C_SignEncryptUpdate */
1766 (void *)func_not_supported
, /* C_DecryptVerifyUpdate */
1767 (void *)func_not_supported
, /* C_GenerateKey */
1768 (void *)func_not_supported
, /* C_GenerateKeyPair */
1769 (void *)func_not_supported
, /* C_WrapKey */
1770 (void *)func_not_supported
, /* C_UnwrapKey */
1771 (void *)func_not_supported
, /* C_DeriveKey */
1772 (void *)func_not_supported
, /* C_SeedRandom */
1774 (void *)func_not_supported
, /* C_GetFunctionStatus */
1775 (void *)func_not_supported
, /* C_CancelFunction */
1776 (void *)func_not_supported
/* C_WaitForSlotEvent */