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
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
);
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
;
548 ret
= CKR_DEVICE_MEMORY
;
551 o
->cert
= hx509_cert_ref(cert
);
553 add_object_attribute(o
, 0, CKA_CLASS
, &type
, sizeof(type
));
554 add_object_attribute(o
, 0, CKA_TOKEN
, &bool_true
, sizeof(bool_true
));
555 add_object_attribute(o
, 0, CKA_PRIVATE
, &bool_true
, sizeof(bool_false
));
556 add_object_attribute(o
, 0, CKA_MODIFIABLE
, &bool_false
, sizeof(bool_false
));
557 add_object_attribute(o
, 0, CKA_LABEL
, foo
->label
, strlen(foo
->label
));
559 add_object_attribute(o
, 0, CKA_KEY_TYPE
, &key_type
, sizeof(key_type
));
560 add_object_attribute(o
, 0, CKA_ID
, foo
->id
, strlen(foo
->id
));
561 add_object_attribute(o
, 0, CKA_START_DATE
, empty
, 1); /* XXX */
562 add_object_attribute(o
, 0, CKA_END_DATE
, empty
, 1); /* XXX */
563 add_object_attribute(o
, 0, CKA_DERIVE
, &bool_false
, sizeof(bool_false
));
564 add_object_attribute(o
, 0, CKA_LOCAL
, &bool_false
, sizeof(bool_false
));
565 mech_type
= CKM_RSA_X_509
;
566 add_object_attribute(o
, 0, CKA_KEY_GEN_MECHANISM
, &mech_type
, sizeof(mech_type
));
568 add_object_attribute(o
, 0, CKA_SUBJECT
, subject_data
.data
, subject_data
.length
);
569 add_object_attribute(o
, 0, CKA_SENSITIVE
, &bool_true
, sizeof(bool_true
));
570 add_object_attribute(o
, 0, CKA_SECONDARY_AUTH
, &bool_false
, sizeof(bool_true
));
572 add_object_attribute(o
, 0, CKA_AUTH_PIN_FLAGS
, &flags
, sizeof(flags
));
574 add_object_attribute(o
, 0, CKA_DECRYPT
, &bool_true
, sizeof(bool_true
));
575 add_object_attribute(o
, 0, CKA_SIGN
, &bool_true
, sizeof(bool_true
));
576 add_object_attribute(o
, 0, CKA_SIGN_RECOVER
, &bool_false
, sizeof(bool_false
));
577 add_object_attribute(o
, 0, CKA_UNWRAP
, &bool_true
, sizeof(bool_true
));
578 add_object_attribute(o
, 0, CKA_EXTRACTABLE
, &bool_true
, sizeof(bool_true
));
579 add_object_attribute(o
, 0, CKA_NEVER_EXTRACTABLE
, &bool_false
, sizeof(bool_false
));
581 add_pubkey_info(hxctx
, o
, key_type
, cert
);
587 st_logf("something went wrong when adding cert!\n");
591 hx509_xfree(cert_data
.data
);
592 hx509_xfree(serial_data
.data
);
593 hx509_xfree(issuer_data
.data
);
594 hx509_xfree(subject_data
.data
);
600 add_certificate(const char *cert_file
,
606 hx509_lock lock
= NULL
;
614 flags
|= HX509_CERTS_UNPROTECT_ALL
;
618 asprintf(&str
, "PASS:%s", pin
);
620 hx509_lock_init(context
, &lock
);
621 hx509_lock_command_string(lock
, str
);
623 memset(str
, 0, strlen(str
));
627 ret
= hx509_certs_init(context
, cert_file
, flags
, lock
, &certs
);
629 st_logf("failed to open file %s\n", cert_file
);
630 return CKR_GENERAL_ERROR
;
633 ret
= hx509_certs_iter_f(context
, certs
, add_cert
, &foo
);
634 hx509_certs_free(&certs
);
636 st_logf("failed adding certs from file %s\n", cert_file
);
637 return CKR_GENERAL_ERROR
;
644 find_object_final(struct session_state
*state
)
646 if (state
->find
.attributes
) {
649 for (i
= 0; i
< state
->find
.num_attributes
; i
++) {
650 if (state
->find
.attributes
[i
].pValue
)
651 free(state
->find
.attributes
[i
].pValue
);
653 free(state
->find
.attributes
);
654 state
->find
.attributes
= NULL
;
655 state
->find
.num_attributes
= 0;
656 state
->find
.next_object
= -1;
661 reset_crypto_state(struct session_state
*state
)
663 state
->sign_object
= -1;
664 if (state
->sign_mechanism
)
665 free(state
->sign_mechanism
);
666 state
->sign_mechanism
= NULL_PTR
;
667 state
->verify_object
= -1;
668 if (state
->verify_mechanism
)
669 free(state
->verify_mechanism
);
670 state
->verify_mechanism
= NULL_PTR
;
674 close_session(struct session_state
*state
)
676 if (state
->find
.attributes
) {
677 application_error("application didn't do C_FindObjectsFinal\n");
678 find_object_final(state
);
681 state
->session_handle
= CK_INVALID_HANDLE
;
682 soft_token
.application
= NULL_PTR
;
683 soft_token
.notify
= NULL_PTR
;
684 reset_crypto_state(state
);
690 return soft_token
.open_sessions
> 0 ? "yes" : "no";
694 read_conf_file(const char *fn
, CK_USER_TYPE userType
, const char *pin
)
696 char buf
[1024], *type
, *s
, *p
;
699 CK_RV failed
= CKR_OK
;
702 st_logf("Can't open configuration file. No file specified\n");
703 return CKR_GENERAL_ERROR
;
708 st_logf("can't open configuration file %s\n", fn
);
709 return CKR_GENERAL_ERROR
;
713 while(fgets(buf
, sizeof(buf
), f
) != NULL
) {
714 buf
[strcspn(buf
, "\n")] = '\0';
716 st_logf("line: %s\n", buf
);
719 while (isspace((unsigned char)*p
))
723 while (isspace((unsigned char)*p
))
727 type
= strtok_r(p
, "\t", &s
);
731 if (strcasecmp("certificate", type
) == 0) {
732 char *cert
, *id
, *label
;
734 id
= strtok_r(NULL
, "\t", &s
);
739 st_logf("id: %s\n", id
);
740 label
= strtok_r(NULL
, "\t", &s
);
742 st_logf("no label\n");
745 cert
= strtok_r(NULL
, "\t", &s
);
747 st_logf("no certfiicate store\n");
751 st_logf("adding: %s: %s in file %s\n", id
, label
, cert
);
753 ret
= add_certificate(cert
, pin
, id
, label
);
756 } else if (strcasecmp("debug", type
) == 0) {
759 name
= strtok_r(NULL
, "\t", &s
);
761 st_logf("no filename\n");
765 if (soft_token
.logfile
)
766 fclose(soft_token
.logfile
);
768 if (strcasecmp(name
, "stdout") == 0)
769 soft_token
.logfile
= stdout
;
771 soft_token
.logfile
= fopen(name
, "a");
772 if (soft_token
.logfile
)
773 rk_cloexec_file(soft_token
.logfile
);
775 if (soft_token
.logfile
== NULL
)
776 st_logf("failed to open file: %s\n", name
);
778 } else if (strcasecmp("app-fatal", type
) == 0) {
781 name
= strtok_r(NULL
, "\t", &s
);
783 st_logf("argument to app-fatal\n");
787 if (strcmp(name
, "true") == 0 || strcmp(name
, "on") == 0)
788 soft_token
.flags
.app_error_fatal
= 1;
789 else if (strcmp(name
, "false") == 0 || strcmp(name
, "off") == 0)
790 soft_token
.flags
.app_error_fatal
= 0;
792 st_logf("unknown app-fatal: %s\n", name
);
795 st_logf("unknown type: %s\n", type
);
805 func_not_supported(void)
807 st_logf("function not supported\n");
808 return CKR_FUNCTION_NOT_SUPPORTED
;
812 get_config_file_for_user(void)
820 fn
= getenv("SOFTPKCS11RC");
823 home
= getenv("HOME");
825 if (fn
== NULL
&& home
== NULL
) {
826 struct passwd
*pw
= getpwuid(getuid());
832 asprintf(&fn
, "%s/.soft-token.rc", home
);
834 fn
= strdup("/etc/soft-token.rc");
838 char appdatafolder
[MAX_PATH
];
840 fn
= getenv("SOFTPKCS11RC");
842 /* Retrieve the roaming AppData folder for the current user. The
843 current user is the user account represented by the current
847 SUCCEEDED(SHGetFolderPath(NULL
, CSIDL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, appdatafolder
))) {
849 asprintf(&fn
, "%s\\.soft-token.rc", appdatafolder
);
859 C_Initialize(CK_VOID_PTR a
)
861 CK_C_INITIALIZE_ARGS_PTR args
= a
;
865 st_logf("Initialize\n");
869 OpenSSL_add_all_algorithms();
871 srandom(getpid() ^ (int) time(NULL
));
873 for (i
= 0; i
< MAX_NUM_SESSION
; i
++) {
874 soft_token
.state
[i
].session_handle
= CK_INVALID_HANDLE
;
875 soft_token
.state
[i
].find
.attributes
= NULL
;
876 soft_token
.state
[i
].find
.num_attributes
= 0;
877 soft_token
.state
[i
].find
.next_object
= -1;
878 reset_crypto_state(&soft_token
.state
[i
]);
881 soft_token
.flags
.hardware_slot
= 1;
882 soft_token
.flags
.app_error_fatal
= 0;
883 soft_token
.flags
.login_done
= 0;
885 soft_token
.object
.objs
= NULL
;
886 soft_token
.object
.num_objs
= 0;
888 soft_token
.logfile
= NULL
;
890 soft_token
.logfile
= stdout
;
893 soft_token
.logfile
= fopen("/tmp/log-pkcs11.txt", "a");
897 st_logf("\tCreateMutex:\t%p\n", args
->CreateMutex
);
898 st_logf("\tDestroyMutext\t%p\n", args
->DestroyMutex
);
899 st_logf("\tLockMutext\t%p\n", args
->LockMutex
);
900 st_logf("\tUnlockMutext\t%p\n", args
->UnlockMutex
);
901 st_logf("\tFlags\t%04x\n", (unsigned int)args
->flags
);
904 soft_token
.config_file
= get_config_file_for_user();
907 * This operations doesn't return CKR_OK if any of the
908 * certificates failes to be unparsed (ie password protected).
910 ret
= read_conf_file(soft_token
.config_file
, CKU_USER
, NULL
);
912 soft_token
.flags
.login_done
= 1;
918 C_Finalize(CK_VOID_PTR args
)
924 st_logf("Finalize\n");
926 for (i
= 0; i
< MAX_NUM_SESSION
; i
++) {
927 if (soft_token
.state
[i
].session_handle
!= CK_INVALID_HANDLE
) {
928 application_error("application finalized without "
929 "closing session\n");
930 close_session(&soft_token
.state
[i
]);
938 C_GetInfo(CK_INFO_PTR args
)
942 st_logf("GetInfo\n");
944 memset(args
, 17, sizeof(*args
));
945 args
->cryptokiVersion
.major
= 2;
946 args
->cryptokiVersion
.minor
= 10;
947 snprintf_fill((char *)args
->manufacturerID
,
948 sizeof(args
->manufacturerID
),
950 "Heimdal hx509 SoftToken");
951 snprintf_fill((char *)args
->libraryDescription
,
952 sizeof(args
->libraryDescription
), ' ',
953 "Heimdal hx509 SoftToken");
954 args
->libraryVersion
.major
= 2;
955 args
->libraryVersion
.minor
= 0;
960 extern CK_FUNCTION_LIST funcs
;
963 C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList
)
967 *ppFunctionList
= &funcs
;
972 C_GetSlotList(CK_BBOOL tokenPresent
,
973 CK_SLOT_ID_PTR pSlotList
,
974 CK_ULONG_PTR pulCount
)
977 st_logf("GetSlotList: %s\n",
978 tokenPresent
? "tokenPresent" : "token not Present");
986 C_GetSlotInfo(CK_SLOT_ID slotID
,
987 CK_SLOT_INFO_PTR pInfo
)
990 st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID
, has_session());
992 memset(pInfo
, 18, sizeof(*pInfo
));
995 return CKR_ARGUMENTS_BAD
;
997 snprintf_fill((char *)pInfo
->slotDescription
,
998 sizeof(pInfo
->slotDescription
),
1000 "Heimdal hx509 SoftToken (slot)");
1001 snprintf_fill((char *)pInfo
->manufacturerID
,
1002 sizeof(pInfo
->manufacturerID
),
1004 "Heimdal hx509 SoftToken (slot)");
1005 pInfo
->flags
= CKF_TOKEN_PRESENT
;
1006 if (soft_token
.flags
.hardware_slot
)
1007 pInfo
->flags
|= CKF_HW_SLOT
;
1008 pInfo
->hardwareVersion
.major
= 1;
1009 pInfo
->hardwareVersion
.minor
= 0;
1010 pInfo
->firmwareVersion
.major
= 1;
1011 pInfo
->firmwareVersion
.minor
= 0;
1017 C_GetTokenInfo(CK_SLOT_ID slotID
,
1018 CK_TOKEN_INFO_PTR pInfo
)
1021 st_logf("GetTokenInfo: %s\n", has_session());
1023 memset(pInfo
, 19, sizeof(*pInfo
));
1025 snprintf_fill((char *)pInfo
->label
,
1026 sizeof(pInfo
->label
),
1028 "Heimdal hx509 SoftToken (token)");
1029 snprintf_fill((char *)pInfo
->manufacturerID
,
1030 sizeof(pInfo
->manufacturerID
),
1032 "Heimdal hx509 SoftToken (token)");
1033 snprintf_fill((char *)pInfo
->model
,
1034 sizeof(pInfo
->model
),
1036 "Heimdal hx509 SoftToken (token)");
1037 snprintf_fill((char *)pInfo
->serialNumber
,
1038 sizeof(pInfo
->serialNumber
),
1042 CKF_TOKEN_INITIALIZED
|
1043 CKF_USER_PIN_INITIALIZED
;
1045 if (soft_token
.flags
.login_done
== 0)
1046 pInfo
->flags
|= CKF_LOGIN_REQUIRED
;
1049 CKF_RESTORE_KEY_NOT_NEEDED |
1051 pInfo
->ulMaxSessionCount
= MAX_NUM_SESSION
;
1052 pInfo
->ulSessionCount
= soft_token
.open_sessions
;
1053 pInfo
->ulMaxRwSessionCount
= MAX_NUM_SESSION
;
1054 pInfo
->ulRwSessionCount
= soft_token
.open_sessions
;
1055 pInfo
->ulMaxPinLen
= 1024;
1056 pInfo
->ulMinPinLen
= 0;
1057 pInfo
->ulTotalPublicMemory
= 4711;
1058 pInfo
->ulFreePublicMemory
= 4712;
1059 pInfo
->ulTotalPrivateMemory
= 4713;
1060 pInfo
->ulFreePrivateMemory
= 4714;
1061 pInfo
->hardwareVersion
.major
= 2;
1062 pInfo
->hardwareVersion
.minor
= 0;
1063 pInfo
->firmwareVersion
.major
= 2;
1064 pInfo
->firmwareVersion
.minor
= 0;
1070 C_GetMechanismList(CK_SLOT_ID slotID
,
1071 CK_MECHANISM_TYPE_PTR pMechanismList
,
1072 CK_ULONG_PTR pulCount
)
1075 st_logf("GetMechanismList\n");
1078 if (pMechanismList
== NULL_PTR
)
1080 pMechanismList
[1] = CKM_RSA_PKCS
;
1086 C_GetMechanismInfo(CK_SLOT_ID slotID
,
1087 CK_MECHANISM_TYPE type
,
1088 CK_MECHANISM_INFO_PTR pInfo
)
1091 st_logf("GetMechanismInfo: slot %d type: %d\n",
1092 (int)slotID
, (int)type
);
1093 memset(pInfo
, 0, sizeof(*pInfo
));
1099 C_InitToken(CK_SLOT_ID slotID
,
1100 CK_UTF8CHAR_PTR pPin
,
1102 CK_UTF8CHAR_PTR pLabel
)
1105 st_logf("InitToken: slot %d\n", (int)slotID
);
1106 return CKR_FUNCTION_NOT_SUPPORTED
;
1110 C_OpenSession(CK_SLOT_ID slotID
,
1112 CK_VOID_PTR pApplication
,
1114 CK_SESSION_HANDLE_PTR phSession
)
1118 st_logf("OpenSession: slot: %d\n", (int)slotID
);
1120 if (soft_token
.open_sessions
== MAX_NUM_SESSION
)
1121 return CKR_SESSION_COUNT
;
1123 soft_token
.application
= pApplication
;
1124 soft_token
.notify
= Notify
;
1126 for (i
= 0; i
< MAX_NUM_SESSION
; i
++)
1127 if (soft_token
.state
[i
].session_handle
== CK_INVALID_HANDLE
)
1129 if (i
== MAX_NUM_SESSION
)
1132 soft_token
.open_sessions
++;
1134 soft_token
.state
[i
].session_handle
=
1135 (CK_SESSION_HANDLE
)(random() & 0xfffff);
1136 *phSession
= soft_token
.state
[i
].session_handle
;
1142 C_CloseSession(CK_SESSION_HANDLE hSession
)
1144 struct session_state
*state
;
1146 st_logf("CloseSession\n");
1148 if (verify_session_handle(hSession
, &state
) != CKR_OK
)
1149 application_error("closed session not open");
1151 close_session(state
);
1157 C_CloseAllSessions(CK_SLOT_ID slotID
)
1162 st_logf("CloseAllSessions\n");
1164 for (i
= 0; i
< MAX_NUM_SESSION
; i
++)
1165 if (soft_token
.state
[i
].session_handle
!= CK_INVALID_HANDLE
)
1166 close_session(&soft_token
.state
[i
]);
1172 C_GetSessionInfo(CK_SESSION_HANDLE hSession
,
1173 CK_SESSION_INFO_PTR pInfo
)
1175 st_logf("GetSessionInfo\n");
1178 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1180 memset(pInfo
, 20, sizeof(*pInfo
));
1183 if (soft_token
.flags
.login_done
)
1184 pInfo
->state
= CKS_RO_USER_FUNCTIONS
;
1186 pInfo
->state
= CKS_RO_PUBLIC_SESSION
;
1187 pInfo
->flags
= CKF_SERIAL_SESSION
;
1188 pInfo
->ulDeviceError
= 0;
1194 C_Login(CK_SESSION_HANDLE hSession
,
1195 CK_USER_TYPE userType
,
1196 CK_UTF8CHAR_PTR pPin
,
1205 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1207 if (pPin
!= NULL_PTR
) {
1208 asprintf(&pin
, "%.*s", (int)ulPinLen
, pPin
);
1209 st_logf("type: %d password: %s\n", (int)userType
, pin
);
1216 ret
= read_conf_file(soft_token
.config_file
, userType
, pin
);
1218 soft_token
.flags
.login_done
= 1;
1222 return soft_token
.flags
.login_done
? CKR_OK
: CKR_PIN_INCORRECT
;
1226 C_Logout(CK_SESSION_HANDLE hSession
)
1228 st_logf("Logout\n");
1231 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1232 return CKR_FUNCTION_NOT_SUPPORTED
;
1236 C_GetObjectSize(CK_SESSION_HANDLE hSession
,
1237 CK_OBJECT_HANDLE hObject
,
1238 CK_ULONG_PTR pulSize
)
1240 st_logf("GetObjectSize\n");
1243 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1244 return CKR_FUNCTION_NOT_SUPPORTED
;
1248 C_GetAttributeValue(CK_SESSION_HANDLE hSession
,
1249 CK_OBJECT_HANDLE hObject
,
1250 CK_ATTRIBUTE_PTR pTemplate
,
1253 struct session_state
*state
;
1254 struct st_object
*obj
;
1261 st_logf("GetAttributeValue: %lx\n",
1262 (unsigned long)HANDLE_OBJECT_ID(hObject
));
1263 VERIFY_SESSION_HANDLE(hSession
, &state
);
1265 if ((ret
= object_handle_to_object(hObject
, &obj
)) != CKR_OK
) {
1266 st_logf("object not found: %lx\n",
1267 (unsigned long)HANDLE_OBJECT_ID(hObject
));
1271 for (i
= 0; i
< ulCount
; i
++) {
1272 st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate
[i
].type
);
1273 for (j
= 0; j
< obj
->num_attributes
; j
++) {
1274 if (obj
->attrs
[j
].secret
) {
1275 pTemplate
[i
].ulValueLen
= (CK_ULONG
)-1;
1278 if (pTemplate
[i
].type
== obj
->attrs
[j
].attribute
.type
) {
1279 if (pTemplate
[i
].pValue
!= NULL_PTR
&& obj
->attrs
[j
].secret
== 0) {
1280 if (pTemplate
[i
].ulValueLen
>= obj
->attrs
[j
].attribute
.ulValueLen
)
1281 memcpy(pTemplate
[i
].pValue
, obj
->attrs
[j
].attribute
.pValue
,
1282 obj
->attrs
[j
].attribute
.ulValueLen
);
1284 pTemplate
[i
].ulValueLen
= obj
->attrs
[j
].attribute
.ulValueLen
;
1288 if (j
== obj
->num_attributes
) {
1289 st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate
[i
].type
);
1290 pTemplate
[i
].ulValueLen
= (CK_ULONG
)-1;
1298 C_FindObjectsInit(CK_SESSION_HANDLE hSession
,
1299 CK_ATTRIBUTE_PTR pTemplate
,
1302 struct session_state
*state
;
1304 st_logf("FindObjectsInit\n");
1308 VERIFY_SESSION_HANDLE(hSession
, &state
);
1310 if (state
->find
.next_object
!= -1) {
1311 application_error("application didn't do C_FindObjectsFinal\n");
1312 find_object_final(state
);
1317 print_attributes(pTemplate
, ulCount
);
1319 state
->find
.attributes
=
1320 calloc(1, ulCount
* sizeof(state
->find
.attributes
[0]));
1321 if (state
->find
.attributes
== NULL
)
1322 return CKR_DEVICE_MEMORY
;
1323 for (i
= 0; i
< ulCount
; i
++) {
1324 state
->find
.attributes
[i
].pValue
=
1325 malloc(pTemplate
[i
].ulValueLen
);
1326 if (state
->find
.attributes
[i
].pValue
== NULL
) {
1327 find_object_final(state
);
1328 return CKR_DEVICE_MEMORY
;
1330 memcpy(state
->find
.attributes
[i
].pValue
,
1331 pTemplate
[i
].pValue
, pTemplate
[i
].ulValueLen
);
1332 state
->find
.attributes
[i
].type
= pTemplate
[i
].type
;
1333 state
->find
.attributes
[i
].ulValueLen
= pTemplate
[i
].ulValueLen
;
1335 state
->find
.num_attributes
= ulCount
;
1336 state
->find
.next_object
= 0;
1338 st_logf("find all objects\n");
1339 state
->find
.attributes
= NULL
;
1340 state
->find
.num_attributes
= 0;
1341 state
->find
.next_object
= 0;
1348 C_FindObjects(CK_SESSION_HANDLE hSession
,
1349 CK_OBJECT_HANDLE_PTR phObject
,
1350 CK_ULONG ulMaxObjectCount
,
1351 CK_ULONG_PTR pulObjectCount
)
1353 struct session_state
*state
;
1358 st_logf("FindObjects\n");
1360 VERIFY_SESSION_HANDLE(hSession
, &state
);
1362 if (state
->find
.next_object
== -1) {
1363 application_error("application didn't do C_FindObjectsInit\n");
1364 return CKR_ARGUMENTS_BAD
;
1366 if (ulMaxObjectCount
== 0) {
1367 application_error("application asked for 0 objects\n");
1368 return CKR_ARGUMENTS_BAD
;
1370 *pulObjectCount
= 0;
1371 for (i
= state
->find
.next_object
; i
< soft_token
.object
.num_objs
; i
++) {
1372 st_logf("FindObjects: %d\n", i
);
1373 state
->find
.next_object
= i
+ 1;
1374 if (attributes_match(soft_token
.object
.objs
[i
],
1375 state
->find
.attributes
,
1376 state
->find
.num_attributes
)) {
1377 *phObject
++ = soft_token
.object
.objs
[i
]->object_handle
;
1379 (*pulObjectCount
)++;
1380 if (ulMaxObjectCount
== 0)
1388 C_FindObjectsFinal(CK_SESSION_HANDLE hSession
)
1390 struct session_state
*state
;
1394 st_logf("FindObjectsFinal\n");
1395 VERIFY_SESSION_HANDLE(hSession
, &state
);
1396 find_object_final(state
);
1401 commonInit(CK_ATTRIBUTE
*attr_match
, int attr_match_len
,
1402 const CK_MECHANISM_TYPE
*mechs
, int mechs_len
,
1403 const CK_MECHANISM_PTR pMechanism
, CK_OBJECT_HANDLE hKey
,
1404 struct st_object
**o
)
1410 if ((ret
= object_handle_to_object(hKey
, o
)) != CKR_OK
)
1413 ret
= attributes_match(*o
, attr_match
, attr_match_len
);
1415 application_error("called commonInit on key that doesn't "
1416 "support required attr");
1417 return CKR_ARGUMENTS_BAD
;
1420 for (i
= 0; i
< mechs_len
; i
++)
1421 if (mechs
[i
] == pMechanism
->mechanism
)
1423 if (i
== mechs_len
) {
1424 application_error("called mech (%08lx) not supported\n",
1425 pMechanism
->mechanism
);
1426 return CKR_ARGUMENTS_BAD
;
1433 dup_mechanism(CK_MECHANISM_PTR
*dp
, const CK_MECHANISM_PTR pMechanism
)
1437 p
= malloc(sizeof(*p
));
1439 return CKR_DEVICE_MEMORY
;
1444 memcpy(p
, pMechanism
, sizeof(*p
));
1450 C_DigestInit(CK_SESSION_HANDLE hSession
,
1451 CK_MECHANISM_PTR pMechanism
)
1453 st_logf("DigestInit\n");
1455 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1456 return CKR_FUNCTION_NOT_SUPPORTED
;
1460 C_SignInit(CK_SESSION_HANDLE hSession
,
1461 CK_MECHANISM_PTR pMechanism
,
1462 CK_OBJECT_HANDLE hKey
)
1464 struct session_state
*state
;
1465 CK_MECHANISM_TYPE mechs
[] = { CKM_RSA_PKCS
};
1466 CK_BBOOL bool_true
= CK_TRUE
;
1467 CK_ATTRIBUTE attr
[] = {
1468 { CKA_SIGN
, &bool_true
, sizeof(bool_true
) }
1470 struct st_object
*o
;
1474 st_logf("SignInit\n");
1475 VERIFY_SESSION_HANDLE(hSession
, &state
);
1477 ret
= commonInit(attr
, sizeof(attr
)/sizeof(attr
[0]),
1478 mechs
, sizeof(mechs
)/sizeof(mechs
[0]),
1479 pMechanism
, hKey
, &o
);
1483 ret
= dup_mechanism(&state
->sign_mechanism
, pMechanism
);
1485 state
->sign_object
= OBJECT_ID(o
);
1491 C_Sign(CK_SESSION_HANDLE hSession
,
1494 CK_BYTE_PTR pSignature
,
1495 CK_ULONG_PTR pulSignatureLen
)
1497 struct session_state
*state
;
1498 struct st_object
*o
;
1501 const AlgorithmIdentifier
*alg
;
1502 heim_octet_string sig
, data
;
1506 VERIFY_SESSION_HANDLE(hSession
, &state
);
1511 if (state
->sign_object
== -1)
1512 return CKR_ARGUMENTS_BAD
;
1514 if (pulSignatureLen
== NULL
) {
1515 st_logf("signature len NULL\n");
1516 ret
= CKR_ARGUMENTS_BAD
;
1520 if (pData
== NULL_PTR
) {
1521 st_logf("data NULL\n");
1522 ret
= CKR_ARGUMENTS_BAD
;
1526 o
= soft_token
.object
.objs
[state
->sign_object
];
1528 if (hx509_cert_have_private_key(o
->cert
) == 0) {
1529 st_logf("private key NULL\n");
1530 return CKR_ARGUMENTS_BAD
;
1533 switch(state
->sign_mechanism
->mechanism
) {
1535 alg
= hx509_signature_rsa_pkcs1_x509();
1538 ret
= CKR_FUNCTION_NOT_SUPPORTED
;
1543 data
.length
= ulDataLen
;
1545 hret
= _hx509_create_signature(context
,
1546 _hx509_cert_private_key(o
->cert
),
1552 ret
= CKR_DEVICE_ERROR
;
1555 *pulSignatureLen
= sig
.length
;
1557 if (pSignature
!= NULL_PTR
)
1558 memcpy(pSignature
, sig
.data
, sig
.length
);
1563 memset(sig
.data
, 0, sig
.length
);
1564 der_free_octet_string(&sig
);
1570 C_SignUpdate(CK_SESSION_HANDLE hSession
,
1575 st_logf("SignUpdate\n");
1576 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1577 return CKR_FUNCTION_NOT_SUPPORTED
;
1582 C_SignFinal(CK_SESSION_HANDLE hSession
,
1583 CK_BYTE_PTR pSignature
,
1584 CK_ULONG_PTR pulSignatureLen
)
1587 st_logf("SignUpdate\n");
1588 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1589 return CKR_FUNCTION_NOT_SUPPORTED
;
1593 C_VerifyInit(CK_SESSION_HANDLE hSession
,
1594 CK_MECHANISM_PTR pMechanism
,
1595 CK_OBJECT_HANDLE hKey
)
1597 struct session_state
*state
;
1598 CK_MECHANISM_TYPE mechs
[] = { CKM_RSA_PKCS
};
1599 CK_BBOOL bool_true
= CK_TRUE
;
1600 CK_ATTRIBUTE attr
[] = {
1601 { CKA_VERIFY
, &bool_true
, sizeof(bool_true
) }
1603 struct st_object
*o
;
1607 st_logf("VerifyInit\n");
1608 VERIFY_SESSION_HANDLE(hSession
, &state
);
1610 ret
= commonInit(attr
, sizeof(attr
)/sizeof(attr
[0]),
1611 mechs
, sizeof(mechs
)/sizeof(mechs
[0]),
1612 pMechanism
, hKey
, &o
);
1616 ret
= dup_mechanism(&state
->verify_mechanism
, pMechanism
);
1618 state
->verify_object
= OBJECT_ID(o
);
1624 C_Verify(CK_SESSION_HANDLE hSession
,
1627 CK_BYTE_PTR pSignature
,
1628 CK_ULONG ulSignatureLen
)
1630 struct session_state
*state
;
1631 struct st_object
*o
;
1632 const AlgorithmIdentifier
*alg
;
1635 heim_octet_string data
, sig
;
1638 st_logf("Verify\n");
1639 VERIFY_SESSION_HANDLE(hSession
, &state
);
1641 if (state
->verify_object
== -1)
1642 return CKR_ARGUMENTS_BAD
;
1644 o
= soft_token
.object
.objs
[state
->verify_object
];
1646 switch(state
->verify_mechanism
->mechanism
) {
1648 alg
= hx509_signature_rsa_pkcs1_x509();
1651 ret
= CKR_FUNCTION_NOT_SUPPORTED
;
1656 sig
.length
= ulDataLen
;
1657 data
.data
= pSignature
;
1658 data
.length
= ulSignatureLen
;
1660 hret
= _hx509_verify_signature(context
,
1666 ret
= CKR_GENERAL_ERROR
;
1677 C_VerifyUpdate(CK_SESSION_HANDLE hSession
,
1682 st_logf("VerifyUpdate\n");
1683 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1684 return CKR_FUNCTION_NOT_SUPPORTED
;
1688 C_VerifyFinal(CK_SESSION_HANDLE hSession
,
1689 CK_BYTE_PTR pSignature
,
1690 CK_ULONG ulSignatureLen
)
1693 st_logf("VerifyFinal\n");
1694 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1695 return CKR_FUNCTION_NOT_SUPPORTED
;
1699 C_GenerateRandom(CK_SESSION_HANDLE hSession
,
1700 CK_BYTE_PTR RandomData
,
1701 CK_ULONG ulRandomLen
)
1704 st_logf("GenerateRandom\n");
1705 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1706 return CKR_FUNCTION_NOT_SUPPORTED
;
1710 CK_FUNCTION_LIST funcs
= {
1722 (void *)func_not_supported
, /* C_InitPIN */
1723 (void *)func_not_supported
, /* C_SetPIN */
1728 (void *)func_not_supported
, /* C_GetOperationState */
1729 (void *)func_not_supported
, /* C_SetOperationState */
1732 (void *)func_not_supported
, /* C_CreateObject */
1733 (void *)func_not_supported
, /* C_CopyObject */
1734 (void *)func_not_supported
, /* C_DestroyObject */
1735 (void *)func_not_supported
, /* C_GetObjectSize */
1736 C_GetAttributeValue
,
1737 (void *)func_not_supported
, /* C_SetAttributeValue */
1741 (void *)func_not_supported
, /* C_EncryptInit, */
1742 (void *)func_not_supported
, /* C_Encrypt, */
1743 (void *)func_not_supported
, /* C_EncryptUpdate, */
1744 (void *)func_not_supported
, /* C_EncryptFinal, */
1745 (void *)func_not_supported
, /* C_DecryptInit, */
1746 (void *)func_not_supported
, /* C_Decrypt, */
1747 (void *)func_not_supported
, /* C_DecryptUpdate, */
1748 (void *)func_not_supported
, /* C_DecryptFinal, */
1750 (void *)func_not_supported
, /* C_Digest */
1751 (void *)func_not_supported
, /* C_DigestUpdate */
1752 (void *)func_not_supported
, /* C_DigestKey */
1753 (void *)func_not_supported
, /* C_DigestFinal */
1758 (void *)func_not_supported
, /* C_SignRecoverInit */
1759 (void *)func_not_supported
, /* C_SignRecover */
1764 (void *)func_not_supported
, /* C_VerifyRecoverInit */
1765 (void *)func_not_supported
, /* C_VerifyRecover */
1766 (void *)func_not_supported
, /* C_DigestEncryptUpdate */
1767 (void *)func_not_supported
, /* C_DecryptDigestUpdate */
1768 (void *)func_not_supported
, /* C_SignEncryptUpdate */
1769 (void *)func_not_supported
, /* C_DecryptVerifyUpdate */
1770 (void *)func_not_supported
, /* C_GenerateKey */
1771 (void *)func_not_supported
, /* C_GenerateKeyPair */
1772 (void *)func_not_supported
, /* C_WrapKey */
1773 (void *)func_not_supported
, /* C_UnwrapKey */
1774 (void *)func_not_supported
, /* C_DeriveKey */
1775 (void *)func_not_supported
, /* C_SeedRandom */
1777 (void *)func_not_supported
, /* C_GetFunctionStatus */
1778 (void *)func_not_supported
, /* C_CancelFunction */
1779 (void *)func_not_supported
/* C_WaitForSlotEvent */