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
37 #define OBJECT_ID_MASK 0xfff
38 #define HANDLE_OBJECT_ID(h) ((h) & OBJECT_ID_MASK)
39 #define OBJECT_ID(obj) HANDLE_OBJECT_ID((obj)->object_handle)
43 CK_ATTRIBUTE attribute
;
48 CK_OBJECT_HANDLE object_handle
;
49 struct st_attr
*attrs
;
54 static struct soft_token
{
55 CK_VOID_PTR application
;
60 struct st_object
**objs
;
69 struct session_state
{
70 CK_SESSION_HANDLE session_handle
;
73 CK_ATTRIBUTE
*attributes
;
74 CK_ULONG num_attributes
;
79 CK_MECHANISM_PTR sign_mechanism
;
81 CK_MECHANISM_PTR verify_mechanism
;
83 #define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0]))
87 static hx509_context context
;
90 application_error(const char *fmt
, ...)
96 if (soft_token
.flags
.app_error_fatal
)
101 st_logf(const char *fmt
, ...)
104 if (soft_token
.logfile
== NULL
)
107 vfprintf(soft_token
.logfile
, fmt
, ap
);
109 fflush(soft_token
.logfile
);
115 if (context
== NULL
) {
116 int ret
= hx509_context_init(&context
);
118 return CKR_GENERAL_ERROR
;
123 #define INIT_CONTEXT() { CK_RV icret = init_context(); if (icret) return icret; }
126 snprintf_fill(char *str
, size_t size
, char fillchar
, const char *fmt
, ...)
131 len
= vsnprintf(str
, size
, fmt
, ap
);
133 if (len
< 0 || len
> size
)
136 str
[len
++] = fillchar
;
140 #define printf error_use_st_logf
143 #define VERIFY_SESSION_HANDLE(s, state) \
146 ret = verify_session_handle(s, state); \
147 if (ret != CKR_OK) { \
148 /* return CKR_OK */; \
153 verify_session_handle(CK_SESSION_HANDLE hSession
,
154 struct session_state
**state
)
158 for (i
= 0; i
< MAX_NUM_SESSION
; i
++){
159 if (soft_token
.state
[i
].session_handle
== hSession
)
162 if (i
== MAX_NUM_SESSION
) {
163 application_error("use of invalid handle: 0x%08lx\n",
164 (unsigned long)hSession
);
165 return CKR_SESSION_HANDLE_INVALID
;
168 *state
= &soft_token
.state
[i
];
173 object_handle_to_object(CK_OBJECT_HANDLE handle
,
174 struct st_object
**object
)
176 int i
= HANDLE_OBJECT_ID(handle
);
179 if (i
>= soft_token
.object
.num_objs
)
180 return CKR_ARGUMENTS_BAD
;
181 if (soft_token
.object
.objs
[i
] == NULL
)
182 return CKR_ARGUMENTS_BAD
;
183 if (soft_token
.object
.objs
[i
]->object_handle
!= handle
)
184 return CKR_ARGUMENTS_BAD
;
185 *object
= soft_token
.object
.objs
[i
];
190 attributes_match(const struct st_object
*obj
,
191 const CK_ATTRIBUTE
*attributes
,
192 CK_ULONG num_attributes
)
197 st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj
));
199 for (i
= 0; i
< num_attributes
; i
++) {
201 for (j
= 0; j
< obj
->num_attributes
; j
++) {
202 if (attributes
[i
].type
== obj
->attrs
[j
].attribute
.type
&&
203 attributes
[i
].ulValueLen
== obj
->attrs
[j
].attribute
.ulValueLen
&&
204 memcmp(attributes
[i
].pValue
, obj
->attrs
[j
].attribute
.pValue
,
205 attributes
[i
].ulValueLen
) == 0) {
211 st_logf("type %d attribute have no match\n", attributes
[i
].type
);
215 st_logf("attribute matches\n");
220 print_attributes(const CK_ATTRIBUTE
*attributes
,
221 CK_ULONG num_attributes
)
225 st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes
);
227 for (i
= 0; i
< num_attributes
; i
++) {
229 switch (attributes
[i
].type
) {
232 if (attributes
[i
].ulValueLen
!= sizeof(CK_BBOOL
)) {
233 application_error("token attribute wrong length\n");
236 ck_true
= attributes
[i
].pValue
;
237 st_logf("token: %s", *ck_true
? "TRUE" : "FALSE");
241 CK_OBJECT_CLASS
*class;
242 if (attributes
[i
].ulValueLen
!= sizeof(CK_ULONG
)) {
243 application_error("class attribute wrong length\n");
246 class = attributes
[i
].pValue
;
249 case CKO_CERTIFICATE
:
250 st_logf("certificate");
253 st_logf("public key");
255 case CKO_PRIVATE_KEY
:
256 st_logf("private key");
259 st_logf("secret key");
261 case CKO_DOMAIN_PARAMETERS
:
262 st_logf("domain parameters");
265 st_logf("[class %lx]", (long unsigned)*class);
276 case CKA_APPLICATION
:
277 st_logf("application");
286 st_logf("[unknown 0x%08lx]", (unsigned long)attributes
[i
].type
);
293 static struct st_object
*
296 struct st_object
*o
, **objs
;
299 o
= calloc(1, sizeof(*o
));
303 for (i
= 0; i
< soft_token
.object
.num_objs
; i
++) {
304 if (soft_token
.object
.objs
== NULL
) {
305 soft_token
.object
.objs
[i
] = o
;
309 if (i
== soft_token
.object
.num_objs
) {
310 objs
= realloc(soft_token
.object
.objs
,
311 (soft_token
.object
.num_objs
+ 1) * sizeof(soft_token
.object
.objs
[0]));
316 soft_token
.object
.objs
= objs
;
317 soft_token
.object
.objs
[soft_token
.object
.num_objs
++] = o
;
319 soft_token
.object
.objs
[i
]->object_handle
=
320 (random() & (~OBJECT_ID_MASK
)) | i
;
326 add_object_attribute(struct st_object
*o
,
328 CK_ATTRIBUTE_TYPE type
,
335 i
= o
->num_attributes
;
336 a
= realloc(o
->attrs
, (i
+ 1) * sizeof(o
->attrs
[0]));
338 return CKR_DEVICE_MEMORY
;
340 o
->attrs
[i
].secret
= secret
;
341 o
->attrs
[i
].attribute
.type
= type
;
342 o
->attrs
[i
].attribute
.pValue
= malloc(ulValueLen
);
343 if (o
->attrs
[i
].attribute
.pValue
== NULL
&& ulValueLen
!= 0)
344 return CKR_DEVICE_MEMORY
;
345 memcpy(o
->attrs
[i
].attribute
.pValue
, pValue
, ulValueLen
);
346 o
->attrs
[i
].attribute
.ulValueLen
= ulValueLen
;
353 add_pubkey_info(hx509_context hxctx
, struct st_object
*o
,
354 CK_KEY_TYPE key_type
, hx509_cert cert
)
357 CK_BYTE
*modulus
= NULL
;
358 size_t modulus_len
= 0;
359 CK_ULONG modulus_bits
= 0;
360 CK_BYTE
*exponent
= NULL
;
361 size_t exponent_len
= 0;
363 if (key_type
!= CKK_RSA
)
365 if (_hx509_cert_private_key(cert
) == NULL
)
368 num
= _hx509_private_key_get_internal(context
,
369 _hx509_cert_private_key(cert
),
372 return CKR_GENERAL_ERROR
;
373 modulus_bits
= BN_num_bits(num
);
375 modulus_len
= BN_num_bytes(num
);
376 modulus
= malloc(modulus_len
);
377 BN_bn2bin(num
, modulus
);
380 add_object_attribute(o
, 0, CKA_MODULUS
, modulus
, modulus_len
);
381 add_object_attribute(o
, 0, CKA_MODULUS_BITS
,
382 &modulus_bits
, sizeof(modulus_bits
));
386 num
= _hx509_private_key_get_internal(context
,
387 _hx509_cert_private_key(cert
),
390 return CKR_GENERAL_ERROR
;
392 exponent_len
= BN_num_bytes(num
);
393 exponent
= malloc(exponent_len
);
394 BN_bn2bin(num
, exponent
);
397 add_object_attribute(o
, 0, CKA_PUBLIC_EXPONENT
,
398 exponent
, exponent_len
);
412 add_cert(hx509_context hxctx
, void *ctx
, hx509_cert cert
)
414 struct foo
*foo
= (struct foo
*)ctx
;
415 struct st_object
*o
= NULL
;
416 CK_OBJECT_CLASS type
;
417 CK_BBOOL bool_true
= CK_TRUE
;
418 CK_BBOOL bool_false
= CK_FALSE
;
419 CK_CERTIFICATE_TYPE cert_type
= CKC_X_509
;
420 CK_KEY_TYPE key_type
;
421 CK_MECHANISM_TYPE mech_type
;
422 CK_RV ret
= CKR_GENERAL_ERROR
;
424 heim_octet_string cert_data
, subject_data
, issuer_data
, serial_data
;
426 st_logf("adding certificate\n");
428 serial_data
.data
= NULL
;
429 serial_data
.length
= 0;
430 cert_data
= subject_data
= issuer_data
= serial_data
;
432 hret
= hx509_cert_binary(hxctx
, cert
, &cert_data
);
439 hret
= hx509_cert_get_issuer(cert
, &name
);
442 hret
= hx509_name_binary(name
, &issuer_data
);
443 hx509_name_free(&name
);
447 hret
= hx509_cert_get_subject(cert
, &name
);
450 hret
= hx509_name_binary(name
, &subject_data
);
451 hx509_name_free(&name
);
457 AlgorithmIdentifier alg
;
459 hret
= hx509_cert_get_SPKI_AlgorithmIdentifier(context
, cert
, &alg
);
461 ret
= CKR_DEVICE_MEMORY
;
465 key_type
= CKK_RSA
; /* XXX */
467 free_AlgorithmIdentifier(&alg
);
471 type
= CKO_CERTIFICATE
;
474 ret
= CKR_DEVICE_MEMORY
;
478 o
->cert
= hx509_cert_ref(cert
);
480 add_object_attribute(o
, 0, CKA_CLASS
, &type
, sizeof(type
));
481 add_object_attribute(o
, 0, CKA_TOKEN
, &bool_true
, sizeof(bool_true
));
482 add_object_attribute(o
, 0, CKA_PRIVATE
, &bool_false
, sizeof(bool_false
));
483 add_object_attribute(o
, 0, CKA_MODIFIABLE
, &bool_false
, sizeof(bool_false
));
484 add_object_attribute(o
, 0, CKA_LABEL
, foo
->label
, strlen(foo
->label
));
486 add_object_attribute(o
, 0, CKA_CERTIFICATE_TYPE
, &cert_type
, sizeof(cert_type
));
487 add_object_attribute(o
, 0, CKA_ID
, foo
->id
, strlen(foo
->id
));
489 add_object_attribute(o
, 0, CKA_SUBJECT
, subject_data
.data
, subject_data
.length
);
490 add_object_attribute(o
, 0, CKA_ISSUER
, issuer_data
.data
, issuer_data
.length
);
491 add_object_attribute(o
, 0, CKA_SERIAL_NUMBER
, serial_data
.data
, serial_data
.length
);
492 add_object_attribute(o
, 0, CKA_VALUE
, cert_data
.data
, cert_data
.length
);
493 add_object_attribute(o
, 0, CKA_TRUSTED
, &bool_false
, sizeof(bool_false
));
495 st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o
));
497 type
= CKO_PUBLIC_KEY
;
500 ret
= CKR_DEVICE_MEMORY
;
503 o
->cert
= hx509_cert_ref(cert
);
505 add_object_attribute(o
, 0, CKA_CLASS
, &type
, sizeof(type
));
506 add_object_attribute(o
, 0, CKA_TOKEN
, &bool_true
, sizeof(bool_true
));
507 add_object_attribute(o
, 0, CKA_PRIVATE
, &bool_false
, sizeof(bool_false
));
508 add_object_attribute(o
, 0, CKA_MODIFIABLE
, &bool_false
, sizeof(bool_false
));
509 add_object_attribute(o
, 0, CKA_LABEL
, foo
->label
, strlen(foo
->label
));
511 add_object_attribute(o
, 0, CKA_KEY_TYPE
, &key_type
, sizeof(key_type
));
512 add_object_attribute(o
, 0, CKA_ID
, foo
->id
, strlen(foo
->id
));
513 add_object_attribute(o
, 0, CKA_START_DATE
, "", 1); /* XXX */
514 add_object_attribute(o
, 0, CKA_END_DATE
, "", 1); /* XXX */
515 add_object_attribute(o
, 0, CKA_DERIVE
, &bool_false
, sizeof(bool_false
));
516 add_object_attribute(o
, 0, CKA_LOCAL
, &bool_false
, sizeof(bool_false
));
517 mech_type
= CKM_RSA_X_509
;
518 add_object_attribute(o
, 0, CKA_KEY_GEN_MECHANISM
, &mech_type
, sizeof(mech_type
));
520 add_object_attribute(o
, 0, CKA_SUBJECT
, subject_data
.data
, subject_data
.length
);
521 add_object_attribute(o
, 0, CKA_ENCRYPT
, &bool_true
, sizeof(bool_true
));
522 add_object_attribute(o
, 0, CKA_VERIFY
, &bool_true
, sizeof(bool_true
));
523 add_object_attribute(o
, 0, CKA_VERIFY_RECOVER
, &bool_false
, sizeof(bool_false
));
524 add_object_attribute(o
, 0, CKA_WRAP
, &bool_true
, sizeof(bool_true
));
525 add_object_attribute(o
, 0, CKA_TRUSTED
, &bool_true
, sizeof(bool_true
));
527 add_pubkey_info(hxctx
, o
, key_type
, cert
);
529 st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o
));
531 if (hx509_cert_have_private_key(cert
)) {
534 type
= CKO_PRIVATE_KEY
;
537 ret
= CKR_DEVICE_MEMORY
;
540 o
->cert
= hx509_cert_ref(cert
);
542 add_object_attribute(o
, 0, CKA_CLASS
, &type
, sizeof(type
));
543 add_object_attribute(o
, 0, CKA_TOKEN
, &bool_true
, sizeof(bool_true
));
544 add_object_attribute(o
, 0, CKA_PRIVATE
, &bool_true
, sizeof(bool_false
));
545 add_object_attribute(o
, 0, CKA_MODIFIABLE
, &bool_false
, sizeof(bool_false
));
546 add_object_attribute(o
, 0, CKA_LABEL
, foo
->label
, strlen(foo
->label
));
548 add_object_attribute(o
, 0, CKA_KEY_TYPE
, &key_type
, sizeof(key_type
));
549 add_object_attribute(o
, 0, CKA_ID
, foo
->id
, strlen(foo
->id
));
550 add_object_attribute(o
, 0, CKA_START_DATE
, "", 1); /* XXX */
551 add_object_attribute(o
, 0, CKA_END_DATE
, "", 1); /* XXX */
552 add_object_attribute(o
, 0, CKA_DERIVE
, &bool_false
, sizeof(bool_false
));
553 add_object_attribute(o
, 0, CKA_LOCAL
, &bool_false
, sizeof(bool_false
));
554 mech_type
= CKM_RSA_X_509
;
555 add_object_attribute(o
, 0, CKA_KEY_GEN_MECHANISM
, &mech_type
, sizeof(mech_type
));
557 add_object_attribute(o
, 0, CKA_SUBJECT
, subject_data
.data
, subject_data
.length
);
558 add_object_attribute(o
, 0, CKA_SENSITIVE
, &bool_true
, sizeof(bool_true
));
559 add_object_attribute(o
, 0, CKA_SECONDARY_AUTH
, &bool_false
, sizeof(bool_true
));
561 add_object_attribute(o
, 0, CKA_AUTH_PIN_FLAGS
, &flags
, sizeof(flags
));
563 add_object_attribute(o
, 0, CKA_DECRYPT
, &bool_true
, sizeof(bool_true
));
564 add_object_attribute(o
, 0, CKA_SIGN
, &bool_true
, sizeof(bool_true
));
565 add_object_attribute(o
, 0, CKA_SIGN_RECOVER
, &bool_false
, sizeof(bool_false
));
566 add_object_attribute(o
, 0, CKA_UNWRAP
, &bool_true
, sizeof(bool_true
));
567 add_object_attribute(o
, 0, CKA_EXTRACTABLE
, &bool_true
, sizeof(bool_true
));
568 add_object_attribute(o
, 0, CKA_NEVER_EXTRACTABLE
, &bool_false
, sizeof(bool_false
));
570 add_pubkey_info(hxctx
, o
, key_type
, cert
);
576 st_logf("something went wrong when adding cert!\n");
580 hx509_xfree(cert_data
.data
);
581 hx509_xfree(serial_data
.data
);
582 hx509_xfree(issuer_data
.data
);
583 hx509_xfree(subject_data
.data
);
589 add_certificate(const char *cert_file
,
595 hx509_lock lock
= NULL
;
603 flags
|= HX509_CERTS_UNPROTECT_ALL
;
607 asprintf(&str
, "PASS:%s", pin
);
609 hx509_lock_init(context
, &lock
);
610 hx509_lock_command_string(lock
, str
);
612 memset(str
, 0, strlen(str
));
616 ret
= hx509_certs_init(context
, cert_file
, flags
, lock
, &certs
);
618 st_logf("failed to open file %s\n", cert_file
);
619 return CKR_GENERAL_ERROR
;
622 ret
= hx509_certs_iter(context
, certs
, add_cert
, &foo
);
623 hx509_certs_free(&certs
);
625 st_logf("failed adding certs from file %s\n", cert_file
);
626 return CKR_GENERAL_ERROR
;
633 find_object_final(struct session_state
*state
)
635 if (state
->find
.attributes
) {
638 for (i
= 0; i
< state
->find
.num_attributes
; i
++) {
639 if (state
->find
.attributes
[i
].pValue
)
640 free(state
->find
.attributes
[i
].pValue
);
642 free(state
->find
.attributes
);
643 state
->find
.attributes
= NULL
;
644 state
->find
.num_attributes
= 0;
645 state
->find
.next_object
= -1;
650 reset_crypto_state(struct session_state
*state
)
652 state
->sign_object
= -1;
653 if (state
->sign_mechanism
)
654 free(state
->sign_mechanism
);
655 state
->sign_mechanism
= NULL_PTR
;
656 state
->verify_object
= -1;
657 if (state
->verify_mechanism
)
658 free(state
->verify_mechanism
);
659 state
->verify_mechanism
= NULL_PTR
;
663 close_session(struct session_state
*state
)
665 if (state
->find
.attributes
) {
666 application_error("application didn't do C_FindObjectsFinal\n");
667 find_object_final(state
);
670 state
->session_handle
= CK_INVALID_HANDLE
;
671 soft_token
.application
= NULL_PTR
;
672 soft_token
.notify
= NULL_PTR
;
673 reset_crypto_state(state
);
679 return soft_token
.open_sessions
> 0 ? "yes" : "no";
683 read_conf_file(const char *fn
, CK_USER_TYPE userType
, const char *pin
)
685 char buf
[1024], *type
, *s
, *p
;
688 CK_RV failed
= CKR_OK
;
692 st_logf("can't open configuration file %s\n", fn
);
693 return CKR_GENERAL_ERROR
;
697 while(fgets(buf
, sizeof(buf
), f
) != NULL
) {
698 buf
[strcspn(buf
, "\n")] = '\0';
700 st_logf("line: %s\n", buf
);
703 while (isspace((unsigned char)*p
))
707 while (isspace((unsigned char)*p
))
711 type
= strtok_r(p
, "\t", &s
);
715 if (strcasecmp("certificate", type
) == 0) {
716 char *cert
, *id
, *label
;
718 id
= strtok_r(NULL
, "\t", &s
);
723 st_logf("id: %s\n", id
);
724 label
= strtok_r(NULL
, "\t", &s
);
726 st_logf("no label\n");
729 cert
= strtok_r(NULL
, "\t", &s
);
731 st_logf("no certfiicate store\n");
735 st_logf("adding: %s: %s in file %s\n", id
, label
, cert
);
737 ret
= add_certificate(cert
, pin
, id
, label
);
740 } else if (strcasecmp("debug", type
) == 0) {
743 name
= strtok_r(NULL
, "\t", &s
);
745 st_logf("no filename\n");
749 if (soft_token
.logfile
)
750 fclose(soft_token
.logfile
);
752 if (strcasecmp(name
, "stdout") == 0)
753 soft_token
.logfile
= stdout
;
755 soft_token
.logfile
= fopen(name
, "a");
756 if (soft_token
.logfile
)
757 rk_cloexec_file(soft_token
.logfile
);
759 if (soft_token
.logfile
== NULL
)
760 st_logf("failed to open file: %s\n", name
);
762 } else if (strcasecmp("app-fatal", type
) == 0) {
765 name
= strtok_r(NULL
, "\t", &s
);
767 st_logf("argument to app-fatal\n");
771 if (strcmp(name
, "true") == 0 || strcmp(name
, "on") == 0)
772 soft_token
.flags
.app_error_fatal
= 1;
773 else if (strcmp(name
, "false") == 0 || strcmp(name
, "off") == 0)
774 soft_token
.flags
.app_error_fatal
= 0;
776 st_logf("unknown app-fatal: %s\n", name
);
779 st_logf("unknown type: %s\n", type
);
789 func_not_supported(void)
791 st_logf("function not supported\n");
792 return CKR_FUNCTION_NOT_SUPPORTED
;
796 C_Initialize(CK_VOID_PTR a
)
798 CK_C_INITIALIZE_ARGS_PTR args
= a
;
802 st_logf("Initialize\n");
806 OpenSSL_add_all_algorithms();
808 srandom(getpid() ^ time(NULL
));
810 for (i
= 0; i
< MAX_NUM_SESSION
; i
++) {
811 soft_token
.state
[i
].session_handle
= CK_INVALID_HANDLE
;
812 soft_token
.state
[i
].find
.attributes
= NULL
;
813 soft_token
.state
[i
].find
.num_attributes
= 0;
814 soft_token
.state
[i
].find
.next_object
= -1;
815 reset_crypto_state(&soft_token
.state
[i
]);
818 soft_token
.flags
.hardware_slot
= 1;
819 soft_token
.flags
.app_error_fatal
= 0;
820 soft_token
.flags
.login_done
= 0;
822 soft_token
.object
.objs
= NULL
;
823 soft_token
.object
.num_objs
= 0;
825 soft_token
.logfile
= NULL
;
827 soft_token
.logfile
= stdout
;
830 soft_token
.logfile
= fopen("/tmp/log-pkcs11.txt", "a");
834 st_logf("\tCreateMutex:\t%p\n", args
->CreateMutex
);
835 st_logf("\tDestroyMutext\t%p\n", args
->DestroyMutex
);
836 st_logf("\tLockMutext\t%p\n", args
->LockMutex
);
837 st_logf("\tUnlockMutext\t%p\n", args
->UnlockMutex
);
838 st_logf("\tFlags\t%04x\n", (unsigned int)args
->flags
);
842 char *fn
= NULL
, *home
= NULL
;
844 if (getuid() == geteuid()) {
845 fn
= getenv("SOFTPKCS11RC");
848 home
= getenv("HOME");
850 if (fn
== NULL
&& home
== NULL
) {
851 struct passwd
*pw
= getpwuid(getuid());
857 asprintf(&fn
, "%s/.soft-token.rc", home
);
859 fn
= strdup("/etc/soft-token.rc");
862 soft_token
.config_file
= fn
;
866 * This operations doesn't return CKR_OK if any of the
867 * certificates failes to be unparsed (ie password protected).
869 ret
= read_conf_file(soft_token
.config_file
, CKU_USER
, NULL
);
871 soft_token
.flags
.login_done
= 1;
877 C_Finalize(CK_VOID_PTR args
)
883 st_logf("Finalize\n");
885 for (i
= 0; i
< MAX_NUM_SESSION
; i
++) {
886 if (soft_token
.state
[i
].session_handle
!= CK_INVALID_HANDLE
) {
887 application_error("application finalized without "
888 "closing session\n");
889 close_session(&soft_token
.state
[i
]);
897 C_GetInfo(CK_INFO_PTR args
)
901 st_logf("GetInfo\n");
903 memset(args
, 17, sizeof(*args
));
904 args
->cryptokiVersion
.major
= 2;
905 args
->cryptokiVersion
.minor
= 10;
906 snprintf_fill((char *)args
->manufacturerID
,
907 sizeof(args
->manufacturerID
),
909 "Heimdal hx509 SoftToken");
910 snprintf_fill((char *)args
->libraryDescription
,
911 sizeof(args
->libraryDescription
), ' ',
912 "Heimdal hx509 SoftToken");
913 args
->libraryVersion
.major
= 2;
914 args
->libraryVersion
.minor
= 0;
919 extern CK_FUNCTION_LIST funcs
;
922 C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList
)
926 *ppFunctionList
= &funcs
;
931 C_GetSlotList(CK_BBOOL tokenPresent
,
932 CK_SLOT_ID_PTR pSlotList
,
933 CK_ULONG_PTR pulCount
)
936 st_logf("GetSlotList: %s\n",
937 tokenPresent
? "tokenPresent" : "token not Present");
945 C_GetSlotInfo(CK_SLOT_ID slotID
,
946 CK_SLOT_INFO_PTR pInfo
)
949 st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID
, has_session());
951 memset(pInfo
, 18, sizeof(*pInfo
));
954 return CKR_ARGUMENTS_BAD
;
956 snprintf_fill((char *)pInfo
->slotDescription
,
957 sizeof(pInfo
->slotDescription
),
959 "Heimdal hx509 SoftToken (slot)");
960 snprintf_fill((char *)pInfo
->manufacturerID
,
961 sizeof(pInfo
->manufacturerID
),
963 "Heimdal hx509 SoftToken (slot)");
964 pInfo
->flags
= CKF_TOKEN_PRESENT
;
965 if (soft_token
.flags
.hardware_slot
)
966 pInfo
->flags
|= CKF_HW_SLOT
;
967 pInfo
->hardwareVersion
.major
= 1;
968 pInfo
->hardwareVersion
.minor
= 0;
969 pInfo
->firmwareVersion
.major
= 1;
970 pInfo
->firmwareVersion
.minor
= 0;
976 C_GetTokenInfo(CK_SLOT_ID slotID
,
977 CK_TOKEN_INFO_PTR pInfo
)
980 st_logf("GetTokenInfo: %s\n", has_session());
982 memset(pInfo
, 19, sizeof(*pInfo
));
984 snprintf_fill((char *)pInfo
->label
,
985 sizeof(pInfo
->label
),
987 "Heimdal hx509 SoftToken (token)");
988 snprintf_fill((char *)pInfo
->manufacturerID
,
989 sizeof(pInfo
->manufacturerID
),
991 "Heimdal hx509 SoftToken (token)");
992 snprintf_fill((char *)pInfo
->model
,
993 sizeof(pInfo
->model
),
995 "Heimdal hx509 SoftToken (token)");
996 snprintf_fill((char *)pInfo
->serialNumber
,
997 sizeof(pInfo
->serialNumber
),
1001 CKF_TOKEN_INITIALIZED
|
1002 CKF_USER_PIN_INITIALIZED
;
1004 if (soft_token
.flags
.login_done
== 0)
1005 pInfo
->flags
|= CKF_LOGIN_REQUIRED
;
1008 CKF_RESTORE_KEY_NOT_NEEDED |
1010 pInfo
->ulMaxSessionCount
= MAX_NUM_SESSION
;
1011 pInfo
->ulSessionCount
= soft_token
.open_sessions
;
1012 pInfo
->ulMaxRwSessionCount
= MAX_NUM_SESSION
;
1013 pInfo
->ulRwSessionCount
= soft_token
.open_sessions
;
1014 pInfo
->ulMaxPinLen
= 1024;
1015 pInfo
->ulMinPinLen
= 0;
1016 pInfo
->ulTotalPublicMemory
= 4711;
1017 pInfo
->ulFreePublicMemory
= 4712;
1018 pInfo
->ulTotalPrivateMemory
= 4713;
1019 pInfo
->ulFreePrivateMemory
= 4714;
1020 pInfo
->hardwareVersion
.major
= 2;
1021 pInfo
->hardwareVersion
.minor
= 0;
1022 pInfo
->firmwareVersion
.major
= 2;
1023 pInfo
->firmwareVersion
.minor
= 0;
1029 C_GetMechanismList(CK_SLOT_ID slotID
,
1030 CK_MECHANISM_TYPE_PTR pMechanismList
,
1031 CK_ULONG_PTR pulCount
)
1034 st_logf("GetMechanismList\n");
1037 if (pMechanismList
== NULL_PTR
)
1039 pMechanismList
[1] = CKM_RSA_PKCS
;
1045 C_GetMechanismInfo(CK_SLOT_ID slotID
,
1046 CK_MECHANISM_TYPE type
,
1047 CK_MECHANISM_INFO_PTR pInfo
)
1050 st_logf("GetMechanismInfo: slot %d type: %d\n",
1051 (int)slotID
, (int)type
);
1052 memset(pInfo
, 0, sizeof(*pInfo
));
1058 C_InitToken(CK_SLOT_ID slotID
,
1059 CK_UTF8CHAR_PTR pPin
,
1061 CK_UTF8CHAR_PTR pLabel
)
1064 st_logf("InitToken: slot %d\n", (int)slotID
);
1065 return CKR_FUNCTION_NOT_SUPPORTED
;
1069 C_OpenSession(CK_SLOT_ID slotID
,
1071 CK_VOID_PTR pApplication
,
1073 CK_SESSION_HANDLE_PTR phSession
)
1077 st_logf("OpenSession: slot: %d\n", (int)slotID
);
1079 if (soft_token
.open_sessions
== MAX_NUM_SESSION
)
1080 return CKR_SESSION_COUNT
;
1082 soft_token
.application
= pApplication
;
1083 soft_token
.notify
= Notify
;
1085 for (i
= 0; i
< MAX_NUM_SESSION
; i
++)
1086 if (soft_token
.state
[i
].session_handle
== CK_INVALID_HANDLE
)
1088 if (i
== MAX_NUM_SESSION
)
1091 soft_token
.open_sessions
++;
1093 soft_token
.state
[i
].session_handle
=
1094 (CK_SESSION_HANDLE
)(random() & 0xfffff);
1095 *phSession
= soft_token
.state
[i
].session_handle
;
1101 C_CloseSession(CK_SESSION_HANDLE hSession
)
1103 struct session_state
*state
;
1105 st_logf("CloseSession\n");
1107 if (verify_session_handle(hSession
, &state
) != CKR_OK
)
1108 application_error("closed session not open");
1110 close_session(state
);
1116 C_CloseAllSessions(CK_SLOT_ID slotID
)
1121 st_logf("CloseAllSessions\n");
1123 for (i
= 0; i
< MAX_NUM_SESSION
; i
++)
1124 if (soft_token
.state
[i
].session_handle
!= CK_INVALID_HANDLE
)
1125 close_session(&soft_token
.state
[i
]);
1131 C_GetSessionInfo(CK_SESSION_HANDLE hSession
,
1132 CK_SESSION_INFO_PTR pInfo
)
1134 st_logf("GetSessionInfo\n");
1137 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1139 memset(pInfo
, 20, sizeof(*pInfo
));
1142 if (soft_token
.flags
.login_done
)
1143 pInfo
->state
= CKS_RO_USER_FUNCTIONS
;
1145 pInfo
->state
= CKS_RO_PUBLIC_SESSION
;
1146 pInfo
->flags
= CKF_SERIAL_SESSION
;
1147 pInfo
->ulDeviceError
= 0;
1153 C_Login(CK_SESSION_HANDLE hSession
,
1154 CK_USER_TYPE userType
,
1155 CK_UTF8CHAR_PTR pPin
,
1164 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1166 if (pPin
!= NULL_PTR
) {
1167 asprintf(&pin
, "%.*s", (int)ulPinLen
, pPin
);
1168 st_logf("type: %d password: %s\n", (int)userType
, pin
);
1175 ret
= read_conf_file(soft_token
.config_file
, userType
, pin
);
1177 soft_token
.flags
.login_done
= 1;
1181 return soft_token
.flags
.login_done
? CKR_OK
: CKR_PIN_INCORRECT
;
1185 C_Logout(CK_SESSION_HANDLE hSession
)
1187 st_logf("Logout\n");
1190 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1191 return CKR_FUNCTION_NOT_SUPPORTED
;
1195 C_GetObjectSize(CK_SESSION_HANDLE hSession
,
1196 CK_OBJECT_HANDLE hObject
,
1197 CK_ULONG_PTR pulSize
)
1199 st_logf("GetObjectSize\n");
1202 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1203 return CKR_FUNCTION_NOT_SUPPORTED
;
1207 C_GetAttributeValue(CK_SESSION_HANDLE hSession
,
1208 CK_OBJECT_HANDLE hObject
,
1209 CK_ATTRIBUTE_PTR pTemplate
,
1212 struct session_state
*state
;
1213 struct st_object
*obj
;
1220 st_logf("GetAttributeValue: %lx\n",
1221 (unsigned long)HANDLE_OBJECT_ID(hObject
));
1222 VERIFY_SESSION_HANDLE(hSession
, &state
);
1224 if ((ret
= object_handle_to_object(hObject
, &obj
)) != CKR_OK
) {
1225 st_logf("object not found: %lx\n",
1226 (unsigned long)HANDLE_OBJECT_ID(hObject
));
1230 for (i
= 0; i
< ulCount
; i
++) {
1231 st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate
[i
].type
);
1232 for (j
= 0; j
< obj
->num_attributes
; j
++) {
1233 if (obj
->attrs
[j
].secret
) {
1234 pTemplate
[i
].ulValueLen
= (CK_ULONG
)-1;
1237 if (pTemplate
[i
].type
== obj
->attrs
[j
].attribute
.type
) {
1238 if (pTemplate
[i
].pValue
!= NULL_PTR
&& obj
->attrs
[j
].secret
== 0) {
1239 if (pTemplate
[i
].ulValueLen
>= obj
->attrs
[j
].attribute
.ulValueLen
)
1240 memcpy(pTemplate
[i
].pValue
, obj
->attrs
[j
].attribute
.pValue
,
1241 obj
->attrs
[j
].attribute
.ulValueLen
);
1243 pTemplate
[i
].ulValueLen
= obj
->attrs
[j
].attribute
.ulValueLen
;
1247 if (j
== obj
->num_attributes
) {
1248 st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate
[i
].type
);
1249 pTemplate
[i
].ulValueLen
= (CK_ULONG
)-1;
1257 C_FindObjectsInit(CK_SESSION_HANDLE hSession
,
1258 CK_ATTRIBUTE_PTR pTemplate
,
1261 struct session_state
*state
;
1263 st_logf("FindObjectsInit\n");
1267 VERIFY_SESSION_HANDLE(hSession
, &state
);
1269 if (state
->find
.next_object
!= -1) {
1270 application_error("application didn't do C_FindObjectsFinal\n");
1271 find_object_final(state
);
1276 print_attributes(pTemplate
, ulCount
);
1278 state
->find
.attributes
=
1279 calloc(1, ulCount
* sizeof(state
->find
.attributes
[0]));
1280 if (state
->find
.attributes
== NULL
)
1281 return CKR_DEVICE_MEMORY
;
1282 for (i
= 0; i
< ulCount
; i
++) {
1283 state
->find
.attributes
[i
].pValue
=
1284 malloc(pTemplate
[i
].ulValueLen
);
1285 if (state
->find
.attributes
[i
].pValue
== NULL
) {
1286 find_object_final(state
);
1287 return CKR_DEVICE_MEMORY
;
1289 memcpy(state
->find
.attributes
[i
].pValue
,
1290 pTemplate
[i
].pValue
, pTemplate
[i
].ulValueLen
);
1291 state
->find
.attributes
[i
].type
= pTemplate
[i
].type
;
1292 state
->find
.attributes
[i
].ulValueLen
= pTemplate
[i
].ulValueLen
;
1294 state
->find
.num_attributes
= ulCount
;
1295 state
->find
.next_object
= 0;
1297 st_logf("find all objects\n");
1298 state
->find
.attributes
= NULL
;
1299 state
->find
.num_attributes
= 0;
1300 state
->find
.next_object
= 0;
1307 C_FindObjects(CK_SESSION_HANDLE hSession
,
1308 CK_OBJECT_HANDLE_PTR phObject
,
1309 CK_ULONG ulMaxObjectCount
,
1310 CK_ULONG_PTR pulObjectCount
)
1312 struct session_state
*state
;
1317 st_logf("FindObjects\n");
1319 VERIFY_SESSION_HANDLE(hSession
, &state
);
1321 if (state
->find
.next_object
== -1) {
1322 application_error("application didn't do C_FindObjectsInit\n");
1323 return CKR_ARGUMENTS_BAD
;
1325 if (ulMaxObjectCount
== 0) {
1326 application_error("application asked for 0 objects\n");
1327 return CKR_ARGUMENTS_BAD
;
1329 *pulObjectCount
= 0;
1330 for (i
= state
->find
.next_object
; i
< soft_token
.object
.num_objs
; i
++) {
1331 st_logf("FindObjects: %d\n", i
);
1332 state
->find
.next_object
= i
+ 1;
1333 if (attributes_match(soft_token
.object
.objs
[i
],
1334 state
->find
.attributes
,
1335 state
->find
.num_attributes
)) {
1336 *phObject
++ = soft_token
.object
.objs
[i
]->object_handle
;
1338 (*pulObjectCount
)++;
1339 if (ulMaxObjectCount
== 0)
1347 C_FindObjectsFinal(CK_SESSION_HANDLE hSession
)
1349 struct session_state
*state
;
1353 st_logf("FindObjectsFinal\n");
1354 VERIFY_SESSION_HANDLE(hSession
, &state
);
1355 find_object_final(state
);
1360 commonInit(CK_ATTRIBUTE
*attr_match
, int attr_match_len
,
1361 const CK_MECHANISM_TYPE
*mechs
, int mechs_len
,
1362 const CK_MECHANISM_PTR pMechanism
, CK_OBJECT_HANDLE hKey
,
1363 struct st_object
**o
)
1369 if ((ret
= object_handle_to_object(hKey
, o
)) != CKR_OK
)
1372 ret
= attributes_match(*o
, attr_match
, attr_match_len
);
1374 application_error("called commonInit on key that doesn't "
1375 "support required attr");
1376 return CKR_ARGUMENTS_BAD
;
1379 for (i
= 0; i
< mechs_len
; i
++)
1380 if (mechs
[i
] == pMechanism
->mechanism
)
1382 if (i
== mechs_len
) {
1383 application_error("called mech (%08lx) not supported\n",
1384 pMechanism
->mechanism
);
1385 return CKR_ARGUMENTS_BAD
;
1392 dup_mechanism(CK_MECHANISM_PTR
*dup
, const CK_MECHANISM_PTR pMechanism
)
1396 p
= malloc(sizeof(*p
));
1398 return CKR_DEVICE_MEMORY
;
1403 memcpy(p
, pMechanism
, sizeof(*p
));
1409 C_DigestInit(CK_SESSION_HANDLE hSession
,
1410 CK_MECHANISM_PTR pMechanism
)
1412 st_logf("DigestInit\n");
1414 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1415 return CKR_FUNCTION_NOT_SUPPORTED
;
1419 C_SignInit(CK_SESSION_HANDLE hSession
,
1420 CK_MECHANISM_PTR pMechanism
,
1421 CK_OBJECT_HANDLE hKey
)
1423 struct session_state
*state
;
1424 CK_MECHANISM_TYPE mechs
[] = { CKM_RSA_PKCS
};
1425 CK_BBOOL bool_true
= CK_TRUE
;
1426 CK_ATTRIBUTE attr
[] = {
1427 { CKA_SIGN
, &bool_true
, sizeof(bool_true
) }
1429 struct st_object
*o
;
1433 st_logf("SignInit\n");
1434 VERIFY_SESSION_HANDLE(hSession
, &state
);
1436 ret
= commonInit(attr
, sizeof(attr
)/sizeof(attr
[0]),
1437 mechs
, sizeof(mechs
)/sizeof(mechs
[0]),
1438 pMechanism
, hKey
, &o
);
1442 ret
= dup_mechanism(&state
->sign_mechanism
, pMechanism
);
1444 state
->sign_object
= OBJECT_ID(o
);
1450 C_Sign(CK_SESSION_HANDLE hSession
,
1453 CK_BYTE_PTR pSignature
,
1454 CK_ULONG_PTR pulSignatureLen
)
1456 struct session_state
*state
;
1457 struct st_object
*o
;
1460 const AlgorithmIdentifier
*alg
;
1461 heim_octet_string sig
, data
;
1465 VERIFY_SESSION_HANDLE(hSession
, &state
);
1470 if (state
->sign_object
== -1)
1471 return CKR_ARGUMENTS_BAD
;
1473 if (pulSignatureLen
== NULL
) {
1474 st_logf("signature len NULL\n");
1475 ret
= CKR_ARGUMENTS_BAD
;
1479 if (pData
== NULL_PTR
) {
1480 st_logf("data NULL\n");
1481 ret
= CKR_ARGUMENTS_BAD
;
1485 o
= soft_token
.object
.objs
[state
->sign_object
];
1487 if (hx509_cert_have_private_key(o
->cert
) == 0) {
1488 st_logf("private key NULL\n");
1489 return CKR_ARGUMENTS_BAD
;
1492 switch(state
->sign_mechanism
->mechanism
) {
1494 alg
= hx509_signature_rsa_pkcs1_x509();
1497 ret
= CKR_FUNCTION_NOT_SUPPORTED
;
1502 data
.length
= ulDataLen
;
1504 hret
= _hx509_create_signature(context
,
1505 _hx509_cert_private_key(o
->cert
),
1511 ret
= CKR_DEVICE_ERROR
;
1514 *pulSignatureLen
= sig
.length
;
1516 if (pSignature
!= NULL_PTR
)
1517 memcpy(pSignature
, sig
.data
, sig
.length
);
1522 memset(sig
.data
, 0, sig
.length
);
1523 der_free_octet_string(&sig
);
1529 C_SignUpdate(CK_SESSION_HANDLE hSession
,
1534 st_logf("SignUpdate\n");
1535 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1536 return CKR_FUNCTION_NOT_SUPPORTED
;
1541 C_SignFinal(CK_SESSION_HANDLE hSession
,
1542 CK_BYTE_PTR pSignature
,
1543 CK_ULONG_PTR pulSignatureLen
)
1546 st_logf("SignUpdate\n");
1547 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1548 return CKR_FUNCTION_NOT_SUPPORTED
;
1552 C_VerifyInit(CK_SESSION_HANDLE hSession
,
1553 CK_MECHANISM_PTR pMechanism
,
1554 CK_OBJECT_HANDLE hKey
)
1556 struct session_state
*state
;
1557 CK_MECHANISM_TYPE mechs
[] = { CKM_RSA_PKCS
};
1558 CK_BBOOL bool_true
= CK_TRUE
;
1559 CK_ATTRIBUTE attr
[] = {
1560 { CKA_VERIFY
, &bool_true
, sizeof(bool_true
) }
1562 struct st_object
*o
;
1566 st_logf("VerifyInit\n");
1567 VERIFY_SESSION_HANDLE(hSession
, &state
);
1569 ret
= commonInit(attr
, sizeof(attr
)/sizeof(attr
[0]),
1570 mechs
, sizeof(mechs
)/sizeof(mechs
[0]),
1571 pMechanism
, hKey
, &o
);
1575 ret
= dup_mechanism(&state
->verify_mechanism
, pMechanism
);
1577 state
->verify_object
= OBJECT_ID(o
);
1583 C_Verify(CK_SESSION_HANDLE hSession
,
1586 CK_BYTE_PTR pSignature
,
1587 CK_ULONG ulSignatureLen
)
1589 struct session_state
*state
;
1590 struct st_object
*o
;
1591 const AlgorithmIdentifier
*alg
;
1594 heim_octet_string data
, sig
;
1597 st_logf("Verify\n");
1598 VERIFY_SESSION_HANDLE(hSession
, &state
);
1600 if (state
->verify_object
== -1)
1601 return CKR_ARGUMENTS_BAD
;
1603 o
= soft_token
.object
.objs
[state
->verify_object
];
1605 switch(state
->verify_mechanism
->mechanism
) {
1607 alg
= hx509_signature_rsa_pkcs1_x509();
1610 ret
= CKR_FUNCTION_NOT_SUPPORTED
;
1615 sig
.length
= ulDataLen
;
1616 data
.data
= pSignature
;
1617 data
.length
= ulSignatureLen
;
1619 hret
= _hx509_verify_signature(context
,
1625 ret
= CKR_GENERAL_ERROR
;
1636 C_VerifyUpdate(CK_SESSION_HANDLE hSession
,
1641 st_logf("VerifyUpdate\n");
1642 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1643 return CKR_FUNCTION_NOT_SUPPORTED
;
1647 C_VerifyFinal(CK_SESSION_HANDLE hSession
,
1648 CK_BYTE_PTR pSignature
,
1649 CK_ULONG ulSignatureLen
)
1652 st_logf("VerifyFinal\n");
1653 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1654 return CKR_FUNCTION_NOT_SUPPORTED
;
1658 C_GenerateRandom(CK_SESSION_HANDLE hSession
,
1659 CK_BYTE_PTR RandomData
,
1660 CK_ULONG ulRandomLen
)
1663 st_logf("GenerateRandom\n");
1664 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1665 return CKR_FUNCTION_NOT_SUPPORTED
;
1669 CK_FUNCTION_LIST funcs
= {
1681 (void *)func_not_supported
, /* C_InitPIN */
1682 (void *)func_not_supported
, /* C_SetPIN */
1687 (void *)func_not_supported
, /* C_GetOperationState */
1688 (void *)func_not_supported
, /* C_SetOperationState */
1691 (void *)func_not_supported
, /* C_CreateObject */
1692 (void *)func_not_supported
, /* C_CopyObject */
1693 (void *)func_not_supported
, /* C_DestroyObject */
1694 (void *)func_not_supported
, /* C_GetObjectSize */
1695 C_GetAttributeValue
,
1696 (void *)func_not_supported
, /* C_SetAttributeValue */
1700 (void *)func_not_supported
, /* C_EncryptInit, */
1701 (void *)func_not_supported
, /* C_Encrypt, */
1702 (void *)func_not_supported
, /* C_EncryptUpdate, */
1703 (void *)func_not_supported
, /* C_EncryptFinal, */
1704 (void *)func_not_supported
, /* C_DecryptInit, */
1705 (void *)func_not_supported
, /* C_Decrypt, */
1706 (void *)func_not_supported
, /* C_DecryptUpdate, */
1707 (void *)func_not_supported
, /* C_DecryptFinal, */
1709 (void *)func_not_supported
, /* C_Digest */
1710 (void *)func_not_supported
, /* C_DigestUpdate */
1711 (void *)func_not_supported
, /* C_DigestKey */
1712 (void *)func_not_supported
, /* C_DigestFinal */
1717 (void *)func_not_supported
, /* C_SignRecoverInit */
1718 (void *)func_not_supported
, /* C_SignRecover */
1723 (void *)func_not_supported
, /* C_VerifyRecoverInit */
1724 (void *)func_not_supported
, /* C_VerifyRecover */
1725 (void *)func_not_supported
, /* C_DigestEncryptUpdate */
1726 (void *)func_not_supported
, /* C_DecryptDigestUpdate */
1727 (void *)func_not_supported
, /* C_SignEncryptUpdate */
1728 (void *)func_not_supported
, /* C_DecryptVerifyUpdate */
1729 (void *)func_not_supported
, /* C_GenerateKey */
1730 (void *)func_not_supported
, /* C_GenerateKeyPair */
1731 (void *)func_not_supported
, /* C_WrapKey */
1732 (void *)func_not_supported
, /* C_UnwrapKey */
1733 (void *)func_not_supported
, /* C_DeriveKey */
1734 (void *)func_not_supported
, /* C_SeedRandom */
1736 (void *)func_not_supported
, /* C_GetFunctionStatus */
1737 (void *)func_not_supported
, /* C_CancelFunction */
1738 (void *)func_not_supported
/* C_WaitForSlotEvent */