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
== 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 i
= o
->num_attributes
;
346 a
= realloc(o
->attrs
, (i
+ 1) * sizeof(o
->attrs
[0]));
348 return CKR_DEVICE_MEMORY
;
350 o
->attrs
[i
].secret
= secret
;
351 o
->attrs
[i
].attribute
.type
= type
;
352 o
->attrs
[i
].attribute
.pValue
= malloc(ulValueLen
);
353 if (o
->attrs
[i
].attribute
.pValue
== NULL
&& ulValueLen
!= 0)
354 return CKR_DEVICE_MEMORY
;
355 memcpy(o
->attrs
[i
].attribute
.pValue
, pValue
, ulValueLen
);
356 o
->attrs
[i
].attribute
.ulValueLen
= ulValueLen
;
363 add_pubkey_info(hx509_context hxctx
, struct st_object
*o
,
364 CK_KEY_TYPE key_type
, hx509_cert cert
)
367 CK_BYTE
*modulus
= NULL
;
368 size_t modulus_len
= 0;
369 CK_ULONG modulus_bits
= 0;
370 CK_BYTE
*exponent
= NULL
;
371 size_t exponent_len
= 0;
373 if (key_type
!= CKK_RSA
)
375 if (_hx509_cert_private_key(cert
) == NULL
)
378 num
= _hx509_private_key_get_internal(context
,
379 _hx509_cert_private_key(cert
),
382 return CKR_GENERAL_ERROR
;
383 modulus_bits
= BN_num_bits(num
);
385 modulus_len
= BN_num_bytes(num
);
386 modulus
= malloc(modulus_len
);
387 BN_bn2bin(num
, modulus
);
390 add_object_attribute(o
, 0, CKA_MODULUS
, modulus
, modulus_len
);
391 add_object_attribute(o
, 0, CKA_MODULUS_BITS
,
392 &modulus_bits
, sizeof(modulus_bits
));
396 num
= _hx509_private_key_get_internal(context
,
397 _hx509_cert_private_key(cert
),
400 return CKR_GENERAL_ERROR
;
402 exponent_len
= BN_num_bytes(num
);
403 exponent
= malloc(exponent_len
);
404 BN_bn2bin(num
, exponent
);
407 add_object_attribute(o
, 0, CKA_PUBLIC_EXPONENT
,
408 exponent
, exponent_len
);
421 static int HX509_LIB_CALL
422 add_cert(hx509_context hxctx
, void *ctx
, hx509_cert cert
)
424 static char empty
[] = "";
425 struct foo
*foo
= (struct foo
*)ctx
;
426 struct st_object
*o
= NULL
;
427 CK_OBJECT_CLASS type
;
428 CK_BBOOL bool_true
= CK_TRUE
;
429 CK_BBOOL bool_false
= CK_FALSE
;
430 CK_CERTIFICATE_TYPE cert_type
= CKC_X_509
;
431 CK_KEY_TYPE key_type
;
432 CK_MECHANISM_TYPE mech_type
;
433 CK_RV ret
= CKR_GENERAL_ERROR
;
435 heim_octet_string cert_data
, subject_data
, issuer_data
, serial_data
;
437 st_logf("adding certificate\n");
439 serial_data
.data
= NULL
;
440 serial_data
.length
= 0;
441 cert_data
= subject_data
= issuer_data
= serial_data
;
443 hret
= hx509_cert_binary(hxctx
, cert
, &cert_data
);
450 hret
= hx509_cert_get_issuer(cert
, &name
);
453 hret
= hx509_name_binary(name
, &issuer_data
);
454 hx509_name_free(&name
);
458 hret
= hx509_cert_get_subject(cert
, &name
);
461 hret
= hx509_name_binary(name
, &subject_data
);
462 hx509_name_free(&name
);
468 AlgorithmIdentifier alg
;
470 hret
= hx509_cert_get_SPKI_AlgorithmIdentifier(context
, cert
, &alg
);
472 ret
= CKR_DEVICE_MEMORY
;
476 key_type
= CKK_RSA
; /* XXX */
478 free_AlgorithmIdentifier(&alg
);
482 type
= CKO_CERTIFICATE
;
485 ret
= CKR_DEVICE_MEMORY
;
489 o
->cert
= hx509_cert_ref(cert
);
491 add_object_attribute(o
, 0, CKA_CLASS
, &type
, sizeof(type
));
492 add_object_attribute(o
, 0, CKA_TOKEN
, &bool_true
, sizeof(bool_true
));
493 add_object_attribute(o
, 0, CKA_PRIVATE
, &bool_false
, sizeof(bool_false
));
494 add_object_attribute(o
, 0, CKA_MODIFIABLE
, &bool_false
, sizeof(bool_false
));
495 add_object_attribute(o
, 0, CKA_LABEL
, foo
->label
, strlen(foo
->label
));
497 add_object_attribute(o
, 0, CKA_CERTIFICATE_TYPE
, &cert_type
, sizeof(cert_type
));
498 add_object_attribute(o
, 0, CKA_ID
, foo
->id
, strlen(foo
->id
));
500 add_object_attribute(o
, 0, CKA_SUBJECT
, subject_data
.data
, subject_data
.length
);
501 add_object_attribute(o
, 0, CKA_ISSUER
, issuer_data
.data
, issuer_data
.length
);
502 add_object_attribute(o
, 0, CKA_SERIAL_NUMBER
, serial_data
.data
, serial_data
.length
);
503 add_object_attribute(o
, 0, CKA_VALUE
, cert_data
.data
, cert_data
.length
);
504 add_object_attribute(o
, 0, CKA_TRUSTED
, &bool_false
, sizeof(bool_false
));
506 st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o
));
508 type
= CKO_PUBLIC_KEY
;
511 ret
= CKR_DEVICE_MEMORY
;
514 o
->cert
= hx509_cert_ref(cert
);
516 add_object_attribute(o
, 0, CKA_CLASS
, &type
, sizeof(type
));
517 add_object_attribute(o
, 0, CKA_TOKEN
, &bool_true
, sizeof(bool_true
));
518 add_object_attribute(o
, 0, CKA_PRIVATE
, &bool_false
, sizeof(bool_false
));
519 add_object_attribute(o
, 0, CKA_MODIFIABLE
, &bool_false
, sizeof(bool_false
));
520 add_object_attribute(o
, 0, CKA_LABEL
, foo
->label
, strlen(foo
->label
));
522 add_object_attribute(o
, 0, CKA_KEY_TYPE
, &key_type
, sizeof(key_type
));
523 add_object_attribute(o
, 0, CKA_ID
, foo
->id
, strlen(foo
->id
));
524 add_object_attribute(o
, 0, CKA_START_DATE
, empty
, 1); /* XXX */
525 add_object_attribute(o
, 0, CKA_END_DATE
, empty
, 1); /* XXX */
526 add_object_attribute(o
, 0, CKA_DERIVE
, &bool_false
, sizeof(bool_false
));
527 add_object_attribute(o
, 0, CKA_LOCAL
, &bool_false
, sizeof(bool_false
));
528 mech_type
= CKM_RSA_X_509
;
529 add_object_attribute(o
, 0, CKA_KEY_GEN_MECHANISM
, &mech_type
, sizeof(mech_type
));
531 add_object_attribute(o
, 0, CKA_SUBJECT
, subject_data
.data
, subject_data
.length
);
532 add_object_attribute(o
, 0, CKA_ENCRYPT
, &bool_true
, sizeof(bool_true
));
533 add_object_attribute(o
, 0, CKA_VERIFY
, &bool_true
, sizeof(bool_true
));
534 add_object_attribute(o
, 0, CKA_VERIFY_RECOVER
, &bool_false
, sizeof(bool_false
));
535 add_object_attribute(o
, 0, CKA_WRAP
, &bool_true
, sizeof(bool_true
));
536 add_object_attribute(o
, 0, CKA_TRUSTED
, &bool_true
, sizeof(bool_true
));
538 add_pubkey_info(hxctx
, o
, key_type
, cert
);
540 st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o
));
542 if (hx509_cert_have_private_key(cert
)) {
545 type
= CKO_PRIVATE_KEY
;
547 /* Note to static analyzers: `o' is still referred to via globals */
550 ret
= CKR_DEVICE_MEMORY
;
553 o
->cert
= hx509_cert_ref(cert
);
555 add_object_attribute(o
, 0, CKA_CLASS
, &type
, sizeof(type
));
556 add_object_attribute(o
, 0, CKA_TOKEN
, &bool_true
, sizeof(bool_true
));
557 add_object_attribute(o
, 0, CKA_PRIVATE
, &bool_true
, sizeof(bool_false
));
558 add_object_attribute(o
, 0, CKA_MODIFIABLE
, &bool_false
, sizeof(bool_false
));
559 add_object_attribute(o
, 0, CKA_LABEL
, foo
->label
, strlen(foo
->label
));
561 add_object_attribute(o
, 0, CKA_KEY_TYPE
, &key_type
, sizeof(key_type
));
562 add_object_attribute(o
, 0, CKA_ID
, foo
->id
, strlen(foo
->id
));
563 add_object_attribute(o
, 0, CKA_START_DATE
, empty
, 1); /* XXX */
564 add_object_attribute(o
, 0, CKA_END_DATE
, empty
, 1); /* XXX */
565 add_object_attribute(o
, 0, CKA_DERIVE
, &bool_false
, sizeof(bool_false
));
566 add_object_attribute(o
, 0, CKA_LOCAL
, &bool_false
, sizeof(bool_false
));
567 mech_type
= CKM_RSA_X_509
;
568 add_object_attribute(o
, 0, CKA_KEY_GEN_MECHANISM
, &mech_type
, sizeof(mech_type
));
570 add_object_attribute(o
, 0, CKA_SUBJECT
, subject_data
.data
, subject_data
.length
);
571 add_object_attribute(o
, 0, CKA_SENSITIVE
, &bool_true
, sizeof(bool_true
));
572 add_object_attribute(o
, 0, CKA_SECONDARY_AUTH
, &bool_false
, sizeof(bool_true
));
574 add_object_attribute(o
, 0, CKA_AUTH_PIN_FLAGS
, &flags
, sizeof(flags
));
576 add_object_attribute(o
, 0, CKA_DECRYPT
, &bool_true
, sizeof(bool_true
));
577 add_object_attribute(o
, 0, CKA_SIGN
, &bool_true
, sizeof(bool_true
));
578 add_object_attribute(o
, 0, CKA_SIGN_RECOVER
, &bool_false
, sizeof(bool_false
));
579 add_object_attribute(o
, 0, CKA_UNWRAP
, &bool_true
, sizeof(bool_true
));
580 add_object_attribute(o
, 0, CKA_EXTRACTABLE
, &bool_true
, sizeof(bool_true
));
581 add_object_attribute(o
, 0, CKA_NEVER_EXTRACTABLE
, &bool_false
, sizeof(bool_false
));
583 add_pubkey_info(hxctx
, o
, key_type
, cert
);
589 st_logf("something went wrong when adding cert!\n");
593 hx509_xfree(cert_data
.data
);
594 hx509_xfree(serial_data
.data
);
595 hx509_xfree(issuer_data
.data
);
596 hx509_xfree(subject_data
.data
);
598 /* Note to static analyzers: `o' is still referred to via globals */
603 add_certificate(const char *cert_file
,
609 hx509_lock lock
= NULL
;
617 flags
|= HX509_CERTS_UNPROTECT_ALL
;
621 ret
= asprintf(&str
, "PASS:%s", pin
);
622 if (ret
== -1 || !str
) {
623 st_logf("failed to allocate memory\n");
624 return CKR_GENERAL_ERROR
;
627 hx509_lock_init(context
, &lock
);
628 hx509_lock_command_string(lock
, str
);
630 memset(str
, 0, strlen(str
));
634 ret
= hx509_certs_init(context
, cert_file
, flags
, lock
, &certs
);
636 st_logf("failed to open file %s\n", cert_file
);
637 return CKR_GENERAL_ERROR
;
640 ret
= hx509_certs_iter_f(context
, certs
, add_cert
, &foo
);
641 hx509_certs_free(&certs
);
643 st_logf("failed adding certs from file %s\n", cert_file
);
644 return CKR_GENERAL_ERROR
;
651 find_object_final(struct session_state
*state
)
653 if (state
->find
.attributes
) {
656 for (i
= 0; i
< state
->find
.num_attributes
; i
++) {
657 if (state
->find
.attributes
[i
].pValue
)
658 free(state
->find
.attributes
[i
].pValue
);
660 free(state
->find
.attributes
);
661 state
->find
.attributes
= NULL
;
662 state
->find
.num_attributes
= 0;
663 state
->find
.next_object
= -1;
668 reset_crypto_state(struct session_state
*state
)
670 state
->sign_object
= -1;
671 if (state
->sign_mechanism
)
672 free(state
->sign_mechanism
);
673 state
->sign_mechanism
= NULL_PTR
;
674 state
->verify_object
= -1;
675 if (state
->verify_mechanism
)
676 free(state
->verify_mechanism
);
677 state
->verify_mechanism
= NULL_PTR
;
681 close_session(struct session_state
*state
)
683 if (state
->find
.attributes
) {
684 application_error("application didn't do C_FindObjectsFinal\n");
685 find_object_final(state
);
688 state
->session_handle
= CK_INVALID_HANDLE
;
689 soft_token
.application
= NULL_PTR
;
690 soft_token
.notify
= NULL_PTR
;
691 reset_crypto_state(state
);
697 return soft_token
.open_sessions
> 0 ? "yes" : "no";
701 read_conf_file(const char *fn
, CK_USER_TYPE userType
, const char *pin
)
703 char buf
[1024], *type
, *s
, *p
;
706 CK_RV failed
= CKR_OK
;
709 st_logf("Can't open configuration file. No file specified\n");
710 return CKR_GENERAL_ERROR
;
715 st_logf("can't open configuration file %s\n", fn
);
716 return CKR_GENERAL_ERROR
;
720 while(fgets(buf
, sizeof(buf
), f
) != NULL
) {
721 buf
[strcspn(buf
, "\n")] = '\0';
723 st_logf("line: %s\n", buf
);
726 while (isspace((unsigned char)*p
))
730 while (isspace((unsigned char)*p
))
734 type
= strtok_r(p
, "\t", &s
);
738 if (strcasecmp("certificate", type
) == 0) {
739 char *cert
, *id
, *label
;
741 id
= strtok_r(NULL
, "\t", &s
);
746 st_logf("id: %s\n", id
);
747 label
= strtok_r(NULL
, "\t", &s
);
749 st_logf("no label\n");
752 cert
= strtok_r(NULL
, "\t", &s
);
754 st_logf("no certfiicate store\n");
758 st_logf("adding: %s: %s in file %s\n", id
, label
, cert
);
760 ret
= add_certificate(cert
, pin
, id
, label
);
763 } else if (strcasecmp("debug", type
) == 0) {
766 name
= strtok_r(NULL
, "\t", &s
);
768 st_logf("no filename\n");
772 if (soft_token
.logfile
)
773 fclose(soft_token
.logfile
);
775 if (strcasecmp(name
, "stdout") == 0)
776 soft_token
.logfile
= stdout
;
778 soft_token
.logfile
= fopen(name
, "a");
779 if (soft_token
.logfile
)
780 rk_cloexec_file(soft_token
.logfile
);
782 if (soft_token
.logfile
== NULL
)
783 st_logf("failed to open file: %s\n", name
);
785 } else if (strcasecmp("app-fatal", type
) == 0) {
788 name
= strtok_r(NULL
, "\t", &s
);
790 st_logf("argument to app-fatal\n");
794 if (strcmp(name
, "true") == 0 || strcmp(name
, "on") == 0)
795 soft_token
.flags
.app_error_fatal
= 1;
796 else if (strcmp(name
, "false") == 0 || strcmp(name
, "off") == 0)
797 soft_token
.flags
.app_error_fatal
= 0;
799 st_logf("unknown app-fatal: %s\n", name
);
802 st_logf("unknown type: %s\n", type
);
812 func_not_supported(void)
814 st_logf("function not supported\n");
815 return CKR_FUNCTION_NOT_SUPPORTED
;
819 get_config_file_for_user(void)
824 fn
= secure_getenv("SOFTPKCS11RC");
828 char homebuf
[MAX_PATH
];
829 const char *home
= roken_get_appdatadir(homebuf
, sizeof(homebuf
));
832 ret
= asprintf(&fn
, "%s/.soft-token.rc", home
);
837 fn
= strdup("/etc/soft-token.rc");
847 C_Initialize(CK_VOID_PTR a
)
849 CK_C_INITIALIZE_ARGS_PTR args
= a
;
853 st_logf("Initialize\n");
857 OpenSSL_add_all_algorithms();
859 srandom(getpid() ^ (int) time(NULL
));
861 for (i
= 0; i
< MAX_NUM_SESSION
; i
++) {
862 soft_token
.state
[i
].session_handle
= CK_INVALID_HANDLE
;
863 soft_token
.state
[i
].find
.attributes
= NULL
;
864 soft_token
.state
[i
].find
.num_attributes
= 0;
865 soft_token
.state
[i
].find
.next_object
= -1;
866 reset_crypto_state(&soft_token
.state
[i
]);
869 soft_token
.flags
.hardware_slot
= 1;
870 soft_token
.flags
.app_error_fatal
= 0;
871 soft_token
.flags
.login_done
= 0;
873 soft_token
.object
.objs
= NULL
;
874 soft_token
.object
.num_objs
= 0;
876 soft_token
.logfile
= NULL
;
878 soft_token
.logfile
= stdout
;
881 soft_token
.logfile
= fopen("/tmp/log-pkcs11.txt", "a");
885 st_logf("\tCreateMutex:\t%p\n", args
->CreateMutex
);
886 st_logf("\tDestroyMutext\t%p\n", args
->DestroyMutex
);
887 st_logf("\tLockMutext\t%p\n", args
->LockMutex
);
888 st_logf("\tUnlockMutext\t%p\n", args
->UnlockMutex
);
889 st_logf("\tFlags\t%04x\n", (unsigned int)args
->flags
);
892 soft_token
.config_file
= get_config_file_for_user();
895 * This operations doesn't return CKR_OK if any of the
896 * certificates failes to be unparsed (ie password protected).
898 ret
= read_conf_file(soft_token
.config_file
, CKU_USER
, NULL
);
900 soft_token
.flags
.login_done
= 1;
906 C_Finalize(CK_VOID_PTR args
)
912 st_logf("Finalize\n");
914 for (i
= 0; i
< MAX_NUM_SESSION
; i
++) {
915 if (soft_token
.state
[i
].session_handle
!= CK_INVALID_HANDLE
) {
916 application_error("application finalized without "
917 "closing session\n");
918 close_session(&soft_token
.state
[i
]);
926 C_GetInfo(CK_INFO_PTR args
)
930 st_logf("GetInfo\n");
932 memset(args
, 17, sizeof(*args
));
933 args
->cryptokiVersion
.major
= 2;
934 args
->cryptokiVersion
.minor
= 10;
935 snprintf_fill((char *)args
->manufacturerID
,
936 sizeof(args
->manufacturerID
),
938 "Heimdal hx509 SoftToken");
939 snprintf_fill((char *)args
->libraryDescription
,
940 sizeof(args
->libraryDescription
), ' ',
941 "Heimdal hx509 SoftToken");
942 args
->libraryVersion
.major
= 2;
943 args
->libraryVersion
.minor
= 0;
948 extern CK_FUNCTION_LIST funcs
;
951 C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList
)
955 *ppFunctionList
= &funcs
;
960 C_GetSlotList(CK_BBOOL tokenPresent
,
961 CK_SLOT_ID_PTR pSlotList
,
962 CK_ULONG_PTR pulCount
)
965 st_logf("GetSlotList: %s\n",
966 tokenPresent
? "tokenPresent" : "token not Present");
974 C_GetSlotInfo(CK_SLOT_ID slotID
,
975 CK_SLOT_INFO_PTR pInfo
)
978 st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID
, has_session());
980 memset(pInfo
, 18, sizeof(*pInfo
));
983 return CKR_ARGUMENTS_BAD
;
985 snprintf_fill((char *)pInfo
->slotDescription
,
986 sizeof(pInfo
->slotDescription
),
988 "Heimdal hx509 SoftToken (slot)");
989 snprintf_fill((char *)pInfo
->manufacturerID
,
990 sizeof(pInfo
->manufacturerID
),
992 "Heimdal hx509 SoftToken (slot)");
993 pInfo
->flags
= CKF_TOKEN_PRESENT
;
994 if (soft_token
.flags
.hardware_slot
)
995 pInfo
->flags
|= CKF_HW_SLOT
;
996 pInfo
->hardwareVersion
.major
= 1;
997 pInfo
->hardwareVersion
.minor
= 0;
998 pInfo
->firmwareVersion
.major
= 1;
999 pInfo
->firmwareVersion
.minor
= 0;
1005 C_GetTokenInfo(CK_SLOT_ID slotID
,
1006 CK_TOKEN_INFO_PTR pInfo
)
1009 st_logf("GetTokenInfo: %s\n", has_session());
1011 memset(pInfo
, 19, sizeof(*pInfo
));
1013 snprintf_fill((char *)pInfo
->label
,
1014 sizeof(pInfo
->label
),
1016 "Heimdal hx509 SoftToken (token)");
1017 snprintf_fill((char *)pInfo
->manufacturerID
,
1018 sizeof(pInfo
->manufacturerID
),
1020 "Heimdal hx509 SoftToken (token)");
1021 snprintf_fill((char *)pInfo
->model
,
1022 sizeof(pInfo
->model
),
1024 "Heimdal hx509 SoftToken (token)");
1025 snprintf_fill((char *)pInfo
->serialNumber
,
1026 sizeof(pInfo
->serialNumber
),
1030 CKF_TOKEN_INITIALIZED
|
1031 CKF_USER_PIN_INITIALIZED
;
1033 if (soft_token
.flags
.login_done
== 0)
1034 pInfo
->flags
|= CKF_LOGIN_REQUIRED
;
1037 CKF_RESTORE_KEY_NOT_NEEDED |
1039 pInfo
->ulMaxSessionCount
= MAX_NUM_SESSION
;
1040 pInfo
->ulSessionCount
= soft_token
.open_sessions
;
1041 pInfo
->ulMaxRwSessionCount
= MAX_NUM_SESSION
;
1042 pInfo
->ulRwSessionCount
= soft_token
.open_sessions
;
1043 pInfo
->ulMaxPinLen
= 1024;
1044 pInfo
->ulMinPinLen
= 0;
1045 pInfo
->ulTotalPublicMemory
= 4711;
1046 pInfo
->ulFreePublicMemory
= 4712;
1047 pInfo
->ulTotalPrivateMemory
= 4713;
1048 pInfo
->ulFreePrivateMemory
= 4714;
1049 pInfo
->hardwareVersion
.major
= 2;
1050 pInfo
->hardwareVersion
.minor
= 0;
1051 pInfo
->firmwareVersion
.major
= 2;
1052 pInfo
->firmwareVersion
.minor
= 0;
1058 C_GetMechanismList(CK_SLOT_ID slotID
,
1059 CK_MECHANISM_TYPE_PTR pMechanismList
,
1060 CK_ULONG_PTR pulCount
)
1063 st_logf("GetMechanismList\n");
1066 if (pMechanismList
== NULL_PTR
)
1068 pMechanismList
[0] = CKM_RSA_PKCS
;
1074 C_GetMechanismInfo(CK_SLOT_ID slotID
,
1075 CK_MECHANISM_TYPE type
,
1076 CK_MECHANISM_INFO_PTR pInfo
)
1079 st_logf("GetMechanismInfo: slot %d type: %d\n",
1080 (int)slotID
, (int)type
);
1081 memset(pInfo
, 0, sizeof(*pInfo
));
1087 C_InitToken(CK_SLOT_ID slotID
,
1088 CK_UTF8CHAR_PTR pPin
,
1090 CK_UTF8CHAR_PTR pLabel
)
1093 st_logf("InitToken: slot %d\n", (int)slotID
);
1094 return CKR_FUNCTION_NOT_SUPPORTED
;
1098 C_OpenSession(CK_SLOT_ID slotID
,
1100 CK_VOID_PTR pApplication
,
1102 CK_SESSION_HANDLE_PTR phSession
)
1106 st_logf("OpenSession: slot: %d\n", (int)slotID
);
1108 if (soft_token
.open_sessions
== MAX_NUM_SESSION
)
1109 return CKR_SESSION_COUNT
;
1111 soft_token
.application
= pApplication
;
1112 soft_token
.notify
= Notify
;
1114 for (i
= 0; i
< MAX_NUM_SESSION
; i
++)
1115 if (soft_token
.state
[i
].session_handle
== CK_INVALID_HANDLE
)
1117 if (i
== MAX_NUM_SESSION
)
1120 soft_token
.open_sessions
++;
1122 soft_token
.state
[i
].session_handle
=
1123 (CK_SESSION_HANDLE
)(random() & 0xfffff);
1124 *phSession
= soft_token
.state
[i
].session_handle
;
1130 C_CloseSession(CK_SESSION_HANDLE hSession
)
1132 struct session_state
*state
;
1134 st_logf("CloseSession\n");
1136 if (verify_session_handle(hSession
, &state
) != CKR_OK
)
1137 application_error("closed session not open");
1139 close_session(state
);
1145 C_CloseAllSessions(CK_SLOT_ID slotID
)
1150 st_logf("CloseAllSessions\n");
1152 for (i
= 0; i
< MAX_NUM_SESSION
; i
++)
1153 if (soft_token
.state
[i
].session_handle
!= CK_INVALID_HANDLE
)
1154 close_session(&soft_token
.state
[i
]);
1160 C_GetSessionInfo(CK_SESSION_HANDLE hSession
,
1161 CK_SESSION_INFO_PTR pInfo
)
1163 st_logf("GetSessionInfo\n");
1166 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1168 memset(pInfo
, 20, sizeof(*pInfo
));
1171 if (soft_token
.flags
.login_done
)
1172 pInfo
->state
= CKS_RO_USER_FUNCTIONS
;
1174 pInfo
->state
= CKS_RO_PUBLIC_SESSION
;
1175 pInfo
->flags
= CKF_SERIAL_SESSION
;
1176 pInfo
->ulDeviceError
= 0;
1182 C_Login(CK_SESSION_HANDLE hSession
,
1183 CK_USER_TYPE userType
,
1184 CK_UTF8CHAR_PTR pPin
,
1193 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1195 if (pPin
!= NULL_PTR
) {
1198 aret
= asprintf(&pin
, "%.*s", (int)ulPinLen
, pPin
);
1199 if (aret
!= -1 && pin
)
1200 st_logf("type: %d password: %s\n", (int)userType
, pin
);
1202 st_logf("memory error: asprintf failed\n");
1209 ret
= read_conf_file(soft_token
.config_file
, userType
, pin
);
1211 soft_token
.flags
.login_done
= 1;
1215 return soft_token
.flags
.login_done
? CKR_OK
: CKR_PIN_INCORRECT
;
1219 C_Logout(CK_SESSION_HANDLE hSession
)
1221 st_logf("Logout\n");
1224 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1225 return CKR_FUNCTION_NOT_SUPPORTED
;
1229 C_GetObjectSize(CK_SESSION_HANDLE hSession
,
1230 CK_OBJECT_HANDLE hObject
,
1231 CK_ULONG_PTR pulSize
)
1233 st_logf("GetObjectSize\n");
1236 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1237 return CKR_FUNCTION_NOT_SUPPORTED
;
1241 C_GetAttributeValue(CK_SESSION_HANDLE hSession
,
1242 CK_OBJECT_HANDLE hObject
,
1243 CK_ATTRIBUTE_PTR pTemplate
,
1246 struct session_state
*state
;
1247 struct st_object
*obj
;
1254 st_logf("GetAttributeValue: %lx\n",
1255 (unsigned long)HANDLE_OBJECT_ID(hObject
));
1256 VERIFY_SESSION_HANDLE(hSession
, &state
);
1258 if ((ret
= object_handle_to_object(hObject
, &obj
)) != CKR_OK
) {
1259 st_logf("object not found: %lx\n",
1260 (unsigned long)HANDLE_OBJECT_ID(hObject
));
1264 for (i
= 0; i
< ulCount
; i
++) {
1265 st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate
[i
].type
);
1266 for (j
= 0; j
< obj
->num_attributes
; j
++) {
1267 if (obj
->attrs
[j
].secret
) {
1268 pTemplate
[i
].ulValueLen
= (CK_ULONG
)-1;
1271 if (pTemplate
[i
].type
== obj
->attrs
[j
].attribute
.type
) {
1272 if (pTemplate
[i
].pValue
!= NULL_PTR
&& obj
->attrs
[j
].secret
== 0) {
1273 if (pTemplate
[i
].ulValueLen
>= obj
->attrs
[j
].attribute
.ulValueLen
)
1274 memcpy(pTemplate
[i
].pValue
, obj
->attrs
[j
].attribute
.pValue
,
1275 obj
->attrs
[j
].attribute
.ulValueLen
);
1277 pTemplate
[i
].ulValueLen
= obj
->attrs
[j
].attribute
.ulValueLen
;
1281 if (j
== obj
->num_attributes
) {
1282 st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate
[i
].type
);
1283 pTemplate
[i
].ulValueLen
= (CK_ULONG
)-1;
1291 C_FindObjectsInit(CK_SESSION_HANDLE hSession
,
1292 CK_ATTRIBUTE_PTR pTemplate
,
1295 struct session_state
*state
;
1297 st_logf("FindObjectsInit\n");
1301 VERIFY_SESSION_HANDLE(hSession
, &state
);
1303 if (state
->find
.next_object
!= -1) {
1304 application_error("application didn't do C_FindObjectsFinal\n");
1305 find_object_final(state
);
1310 print_attributes(pTemplate
, ulCount
);
1312 state
->find
.attributes
=
1313 calloc(1, ulCount
* sizeof(state
->find
.attributes
[0]));
1314 if (state
->find
.attributes
== NULL
)
1315 return CKR_DEVICE_MEMORY
;
1316 for (i
= 0; i
< ulCount
; i
++) {
1317 state
->find
.attributes
[i
].pValue
=
1318 malloc(pTemplate
[i
].ulValueLen
);
1319 if (state
->find
.attributes
[i
].pValue
== NULL
) {
1320 find_object_final(state
);
1321 return CKR_DEVICE_MEMORY
;
1323 memcpy(state
->find
.attributes
[i
].pValue
,
1324 pTemplate
[i
].pValue
, pTemplate
[i
].ulValueLen
);
1325 state
->find
.attributes
[i
].type
= pTemplate
[i
].type
;
1326 state
->find
.attributes
[i
].ulValueLen
= pTemplate
[i
].ulValueLen
;
1328 state
->find
.num_attributes
= ulCount
;
1329 state
->find
.next_object
= 0;
1331 st_logf("find all objects\n");
1332 state
->find
.attributes
= NULL
;
1333 state
->find
.num_attributes
= 0;
1334 state
->find
.next_object
= 0;
1341 C_FindObjects(CK_SESSION_HANDLE hSession
,
1342 CK_OBJECT_HANDLE_PTR phObject
,
1343 CK_ULONG ulMaxObjectCount
,
1344 CK_ULONG_PTR pulObjectCount
)
1346 struct session_state
*state
;
1351 st_logf("FindObjects\n");
1353 VERIFY_SESSION_HANDLE(hSession
, &state
);
1355 if (state
->find
.next_object
== -1) {
1356 application_error("application didn't do C_FindObjectsInit\n");
1357 return CKR_ARGUMENTS_BAD
;
1359 if (ulMaxObjectCount
== 0) {
1360 application_error("application asked for 0 objects\n");
1361 return CKR_ARGUMENTS_BAD
;
1363 *pulObjectCount
= 0;
1364 for (i
= state
->find
.next_object
; i
< soft_token
.object
.num_objs
; i
++) {
1365 st_logf("FindObjects: %d\n", i
);
1366 state
->find
.next_object
= i
+ 1;
1367 if (attributes_match(soft_token
.object
.objs
[i
],
1368 state
->find
.attributes
,
1369 state
->find
.num_attributes
)) {
1370 *phObject
++ = soft_token
.object
.objs
[i
]->object_handle
;
1372 (*pulObjectCount
)++;
1373 if (ulMaxObjectCount
== 0)
1381 C_FindObjectsFinal(CK_SESSION_HANDLE hSession
)
1383 struct session_state
*state
;
1387 st_logf("FindObjectsFinal\n");
1388 VERIFY_SESSION_HANDLE(hSession
, &state
);
1389 find_object_final(state
);
1394 commonInit(CK_ATTRIBUTE
*attr_match
, int attr_match_len
,
1395 const CK_MECHANISM_TYPE
*mechs
, int mechs_len
,
1396 const CK_MECHANISM_PTR pMechanism
, CK_OBJECT_HANDLE hKey
,
1397 struct st_object
**o
)
1403 if ((ret
= object_handle_to_object(hKey
, o
)) != CKR_OK
)
1406 ret
= attributes_match(*o
, attr_match
, attr_match_len
);
1408 application_error("called commonInit on key that doesn't "
1409 "support required attr");
1410 return CKR_ARGUMENTS_BAD
;
1413 for (i
= 0; i
< mechs_len
; i
++)
1414 if (mechs
[i
] == pMechanism
->mechanism
)
1416 if (i
== mechs_len
) {
1417 application_error("called mech (%08lx) not supported\n",
1418 pMechanism
->mechanism
);
1419 return CKR_ARGUMENTS_BAD
;
1426 dup_mechanism(CK_MECHANISM_PTR
*dp
, const CK_MECHANISM_PTR pMechanism
)
1430 p
= malloc(sizeof(*p
));
1432 return CKR_DEVICE_MEMORY
;
1437 memcpy(p
, pMechanism
, sizeof(*p
));
1443 C_DigestInit(CK_SESSION_HANDLE hSession
,
1444 CK_MECHANISM_PTR pMechanism
)
1446 st_logf("DigestInit\n");
1448 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1449 return CKR_FUNCTION_NOT_SUPPORTED
;
1453 C_SignInit(CK_SESSION_HANDLE hSession
,
1454 CK_MECHANISM_PTR pMechanism
,
1455 CK_OBJECT_HANDLE hKey
)
1457 struct session_state
*state
;
1458 CK_MECHANISM_TYPE mechs
[] = { CKM_RSA_PKCS
};
1459 CK_BBOOL bool_true
= CK_TRUE
;
1460 CK_ATTRIBUTE attr
[] = {
1461 { CKA_SIGN
, &bool_true
, sizeof(bool_true
) }
1463 struct st_object
*o
;
1467 st_logf("SignInit\n");
1468 VERIFY_SESSION_HANDLE(hSession
, &state
);
1470 ret
= commonInit(attr
, sizeof(attr
)/sizeof(attr
[0]),
1471 mechs
, sizeof(mechs
)/sizeof(mechs
[0]),
1472 pMechanism
, hKey
, &o
);
1476 ret
= dup_mechanism(&state
->sign_mechanism
, pMechanism
);
1478 state
->sign_object
= OBJECT_ID(o
);
1484 C_Sign(CK_SESSION_HANDLE hSession
,
1487 CK_BYTE_PTR pSignature
,
1488 CK_ULONG_PTR pulSignatureLen
)
1490 struct session_state
*state
;
1491 struct st_object
*o
;
1494 const AlgorithmIdentifier
*alg
;
1495 heim_octet_string sig
, data
;
1499 VERIFY_SESSION_HANDLE(hSession
, &state
);
1504 if (state
->sign_object
== -1)
1505 return CKR_ARGUMENTS_BAD
;
1507 if (pulSignatureLen
== NULL
) {
1508 st_logf("signature len NULL\n");
1509 ret
= CKR_ARGUMENTS_BAD
;
1513 if (pData
== NULL_PTR
) {
1514 st_logf("data NULL\n");
1515 ret
= CKR_ARGUMENTS_BAD
;
1519 o
= soft_token
.object
.objs
[state
->sign_object
];
1521 if (hx509_cert_have_private_key(o
->cert
) == 0) {
1522 st_logf("private key NULL\n");
1523 return CKR_ARGUMENTS_BAD
;
1526 switch(state
->sign_mechanism
->mechanism
) {
1528 alg
= hx509_signature_rsa_pkcs1_x509();
1531 ret
= CKR_FUNCTION_NOT_SUPPORTED
;
1536 data
.length
= ulDataLen
;
1538 hret
= _hx509_create_signature(context
,
1539 _hx509_cert_private_key(o
->cert
),
1545 ret
= CKR_DEVICE_ERROR
;
1548 *pulSignatureLen
= sig
.length
;
1550 if (pSignature
!= NULL_PTR
)
1551 memcpy(pSignature
, sig
.data
, sig
.length
);
1556 memset(sig
.data
, 0, sig
.length
);
1557 der_free_octet_string(&sig
);
1563 C_SignUpdate(CK_SESSION_HANDLE hSession
,
1568 st_logf("SignUpdate\n");
1569 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1570 return CKR_FUNCTION_NOT_SUPPORTED
;
1575 C_SignFinal(CK_SESSION_HANDLE hSession
,
1576 CK_BYTE_PTR pSignature
,
1577 CK_ULONG_PTR pulSignatureLen
)
1580 st_logf("SignUpdate\n");
1581 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1582 return CKR_FUNCTION_NOT_SUPPORTED
;
1586 C_VerifyInit(CK_SESSION_HANDLE hSession
,
1587 CK_MECHANISM_PTR pMechanism
,
1588 CK_OBJECT_HANDLE hKey
)
1590 struct session_state
*state
;
1591 CK_MECHANISM_TYPE mechs
[] = { CKM_RSA_PKCS
};
1592 CK_BBOOL bool_true
= CK_TRUE
;
1593 CK_ATTRIBUTE attr
[] = {
1594 { CKA_VERIFY
, &bool_true
, sizeof(bool_true
) }
1596 struct st_object
*o
;
1600 st_logf("VerifyInit\n");
1601 VERIFY_SESSION_HANDLE(hSession
, &state
);
1603 ret
= commonInit(attr
, sizeof(attr
)/sizeof(attr
[0]),
1604 mechs
, sizeof(mechs
)/sizeof(mechs
[0]),
1605 pMechanism
, hKey
, &o
);
1609 ret
= dup_mechanism(&state
->verify_mechanism
, pMechanism
);
1611 state
->verify_object
= OBJECT_ID(o
);
1617 C_Verify(CK_SESSION_HANDLE hSession
,
1620 CK_BYTE_PTR pSignature
,
1621 CK_ULONG ulSignatureLen
)
1623 struct session_state
*state
;
1624 struct st_object
*o
;
1625 const AlgorithmIdentifier
*alg
;
1628 heim_octet_string data
, sig
;
1631 st_logf("Verify\n");
1632 VERIFY_SESSION_HANDLE(hSession
, &state
);
1634 if (state
->verify_object
== -1)
1635 return CKR_ARGUMENTS_BAD
;
1637 o
= soft_token
.object
.objs
[state
->verify_object
];
1639 switch(state
->verify_mechanism
->mechanism
) {
1641 alg
= hx509_signature_rsa_pkcs1_x509();
1644 ret
= CKR_FUNCTION_NOT_SUPPORTED
;
1649 sig
.length
= ulDataLen
;
1650 data
.data
= pSignature
;
1651 data
.length
= ulSignatureLen
;
1653 hret
= _hx509_verify_signature(context
,
1659 ret
= CKR_GENERAL_ERROR
;
1670 C_VerifyUpdate(CK_SESSION_HANDLE hSession
,
1675 st_logf("VerifyUpdate\n");
1676 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1677 return CKR_FUNCTION_NOT_SUPPORTED
;
1681 C_VerifyFinal(CK_SESSION_HANDLE hSession
,
1682 CK_BYTE_PTR pSignature
,
1683 CK_ULONG ulSignatureLen
)
1686 st_logf("VerifyFinal\n");
1687 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1688 return CKR_FUNCTION_NOT_SUPPORTED
;
1692 C_GenerateRandom(CK_SESSION_HANDLE hSession
,
1693 CK_BYTE_PTR RandomData
,
1694 CK_ULONG ulRandomLen
)
1697 st_logf("GenerateRandom\n");
1698 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1699 return CKR_FUNCTION_NOT_SUPPORTED
;
1703 CK_FUNCTION_LIST funcs
= {
1715 (void *)func_not_supported
, /* C_InitPIN */
1716 (void *)func_not_supported
, /* C_SetPIN */
1721 (void *)func_not_supported
, /* C_GetOperationState */
1722 (void *)func_not_supported
, /* C_SetOperationState */
1725 (void *)func_not_supported
, /* C_CreateObject */
1726 (void *)func_not_supported
, /* C_CopyObject */
1727 (void *)func_not_supported
, /* C_DestroyObject */
1728 (void *)func_not_supported
, /* C_GetObjectSize */
1729 C_GetAttributeValue
,
1730 (void *)func_not_supported
, /* C_SetAttributeValue */
1734 (void *)func_not_supported
, /* C_EncryptInit, */
1735 (void *)func_not_supported
, /* C_Encrypt, */
1736 (void *)func_not_supported
, /* C_EncryptUpdate, */
1737 (void *)func_not_supported
, /* C_EncryptFinal, */
1738 (void *)func_not_supported
, /* C_DecryptInit, */
1739 (void *)func_not_supported
, /* C_Decrypt, */
1740 (void *)func_not_supported
, /* C_DecryptUpdate, */
1741 (void *)func_not_supported
, /* C_DecryptFinal, */
1743 (void *)func_not_supported
, /* C_Digest */
1744 (void *)func_not_supported
, /* C_DigestUpdate */
1745 (void *)func_not_supported
, /* C_DigestKey */
1746 (void *)func_not_supported
, /* C_DigestFinal */
1751 (void *)func_not_supported
, /* C_SignRecoverInit */
1752 (void *)func_not_supported
, /* C_SignRecover */
1757 (void *)func_not_supported
, /* C_VerifyRecoverInit */
1758 (void *)func_not_supported
, /* C_VerifyRecover */
1759 (void *)func_not_supported
, /* C_DigestEncryptUpdate */
1760 (void *)func_not_supported
, /* C_DecryptDigestUpdate */
1761 (void *)func_not_supported
, /* C_SignEncryptUpdate */
1762 (void *)func_not_supported
, /* C_DecryptVerifyUpdate */
1763 (void *)func_not_supported
, /* C_GenerateKey */
1764 (void *)func_not_supported
, /* C_GenerateKeyPair */
1765 (void *)func_not_supported
, /* C_WrapKey */
1766 (void *)func_not_supported
, /* C_UnwrapKey */
1767 (void *)func_not_supported
, /* C_DeriveKey */
1768 (void *)func_not_supported
, /* C_SeedRandom */
1770 (void *)func_not_supported
, /* C_GetFunctionStatus */
1771 (void *)func_not_supported
, /* C_CancelFunction */
1772 (void *)func_not_supported
/* C_WaitForSlotEvent */