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
= malloc(sizeof(*o
));
302 memset(o
, 0, sizeof(*o
));
304 o
->num_attributes
= 0;
306 for (i
= 0; i
< soft_token
.object
.num_objs
; i
++) {
307 if (soft_token
.object
.objs
== NULL
) {
308 soft_token
.object
.objs
[i
] = o
;
312 if (i
== soft_token
.object
.num_objs
) {
313 objs
= realloc(soft_token
.object
.objs
,
314 (soft_token
.object
.num_objs
+ 1) * sizeof(soft_token
.object
.objs
[0]));
319 soft_token
.object
.objs
= objs
;
320 soft_token
.object
.objs
[soft_token
.object
.num_objs
++] = o
;
322 soft_token
.object
.objs
[i
]->object_handle
=
323 (random() & (~OBJECT_ID_MASK
)) | i
;
329 add_object_attribute(struct st_object
*o
,
331 CK_ATTRIBUTE_TYPE type
,
338 i
= o
->num_attributes
;
339 a
= realloc(o
->attrs
, (i
+ 1) * sizeof(o
->attrs
[0]));
341 return CKR_DEVICE_MEMORY
;
343 o
->attrs
[i
].secret
= secret
;
344 o
->attrs
[i
].attribute
.type
= type
;
345 o
->attrs
[i
].attribute
.pValue
= malloc(ulValueLen
);
346 if (o
->attrs
[i
].attribute
.pValue
== NULL
&& ulValueLen
!= 0)
347 return CKR_DEVICE_MEMORY
;
348 memcpy(o
->attrs
[i
].attribute
.pValue
, pValue
, ulValueLen
);
349 o
->attrs
[i
].attribute
.ulValueLen
= ulValueLen
;
356 add_pubkey_info(hx509_context hxctx
, struct st_object
*o
,
357 CK_KEY_TYPE key_type
, hx509_cert cert
)
360 CK_BYTE
*modulus
= NULL
;
361 size_t modulus_len
= 0;
362 CK_ULONG modulus_bits
= 0;
363 CK_BYTE
*exponent
= NULL
;
364 size_t exponent_len
= 0;
366 if (key_type
!= CKK_RSA
)
368 if (_hx509_cert_private_key(cert
) == NULL
)
371 num
= _hx509_private_key_get_internal(context
,
372 _hx509_cert_private_key(cert
),
375 return CKR_GENERAL_ERROR
;
376 modulus_bits
= BN_num_bits(num
);
378 modulus_len
= BN_num_bytes(num
);
379 modulus
= malloc(modulus_len
);
380 BN_bn2bin(num
, modulus
);
383 add_object_attribute(o
, 0, CKA_MODULUS
, modulus
, modulus_len
);
384 add_object_attribute(o
, 0, CKA_MODULUS_BITS
,
385 &modulus_bits
, sizeof(modulus_bits
));
389 num
= _hx509_private_key_get_internal(context
,
390 _hx509_cert_private_key(cert
),
393 return CKR_GENERAL_ERROR
;
395 exponent_len
= BN_num_bytes(num
);
396 exponent
= malloc(exponent_len
);
397 BN_bn2bin(num
, exponent
);
400 add_object_attribute(o
, 0, CKA_PUBLIC_EXPONENT
,
401 exponent
, exponent_len
);
415 add_cert(hx509_context hxctx
, void *ctx
, hx509_cert cert
)
417 struct foo
*foo
= (struct foo
*)ctx
;
418 struct st_object
*o
= NULL
;
419 CK_OBJECT_CLASS type
;
420 CK_BBOOL bool_true
= CK_TRUE
;
421 CK_BBOOL bool_false
= CK_FALSE
;
422 CK_CERTIFICATE_TYPE cert_type
= CKC_X_509
;
423 CK_KEY_TYPE key_type
;
424 CK_MECHANISM_TYPE mech_type
;
425 CK_RV ret
= CKR_GENERAL_ERROR
;
427 heim_octet_string cert_data
, subject_data
, issuer_data
, serial_data
;
429 st_logf("adding certificate\n");
431 serial_data
.data
= NULL
;
432 serial_data
.length
= 0;
433 cert_data
= subject_data
= issuer_data
= serial_data
;
435 hret
= hx509_cert_binary(hxctx
, cert
, &cert_data
);
442 hret
= hx509_cert_get_issuer(cert
, &name
);
445 hret
= hx509_name_binary(name
, &issuer_data
);
446 hx509_name_free(&name
);
450 hret
= hx509_cert_get_subject(cert
, &name
);
453 hret
= hx509_name_binary(name
, &subject_data
);
454 hx509_name_free(&name
);
460 AlgorithmIdentifier alg
;
462 hret
= hx509_cert_get_SPKI_AlgorithmIdentifier(context
, cert
, &alg
);
464 ret
= CKR_DEVICE_MEMORY
;
468 key_type
= CKK_RSA
; /* XXX */
470 free_AlgorithmIdentifier(&alg
);
474 type
= CKO_CERTIFICATE
;
477 ret
= CKR_DEVICE_MEMORY
;
481 o
->cert
= hx509_cert_ref(cert
);
483 add_object_attribute(o
, 0, CKA_CLASS
, &type
, sizeof(type
));
484 add_object_attribute(o
, 0, CKA_TOKEN
, &bool_true
, sizeof(bool_true
));
485 add_object_attribute(o
, 0, CKA_PRIVATE
, &bool_false
, sizeof(bool_false
));
486 add_object_attribute(o
, 0, CKA_MODIFIABLE
, &bool_false
, sizeof(bool_false
));
487 add_object_attribute(o
, 0, CKA_LABEL
, foo
->label
, strlen(foo
->label
));
489 add_object_attribute(o
, 0, CKA_CERTIFICATE_TYPE
, &cert_type
, sizeof(cert_type
));
490 add_object_attribute(o
, 0, CKA_ID
, foo
->id
, strlen(foo
->id
));
492 add_object_attribute(o
, 0, CKA_SUBJECT
, subject_data
.data
, subject_data
.length
);
493 add_object_attribute(o
, 0, CKA_ISSUER
, issuer_data
.data
, issuer_data
.length
);
494 add_object_attribute(o
, 0, CKA_SERIAL_NUMBER
, serial_data
.data
, serial_data
.length
);
495 add_object_attribute(o
, 0, CKA_VALUE
, cert_data
.data
, cert_data
.length
);
496 add_object_attribute(o
, 0, CKA_TRUSTED
, &bool_false
, sizeof(bool_false
));
498 st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o
));
500 type
= CKO_PUBLIC_KEY
;
503 ret
= CKR_DEVICE_MEMORY
;
506 o
->cert
= hx509_cert_ref(cert
);
508 add_object_attribute(o
, 0, CKA_CLASS
, &type
, sizeof(type
));
509 add_object_attribute(o
, 0, CKA_TOKEN
, &bool_true
, sizeof(bool_true
));
510 add_object_attribute(o
, 0, CKA_PRIVATE
, &bool_false
, sizeof(bool_false
));
511 add_object_attribute(o
, 0, CKA_MODIFIABLE
, &bool_false
, sizeof(bool_false
));
512 add_object_attribute(o
, 0, CKA_LABEL
, foo
->label
, strlen(foo
->label
));
514 add_object_attribute(o
, 0, CKA_KEY_TYPE
, &key_type
, sizeof(key_type
));
515 add_object_attribute(o
, 0, CKA_ID
, foo
->id
, strlen(foo
->id
));
516 add_object_attribute(o
, 0, CKA_START_DATE
, "", 1); /* XXX */
517 add_object_attribute(o
, 0, CKA_END_DATE
, "", 1); /* XXX */
518 add_object_attribute(o
, 0, CKA_DERIVE
, &bool_false
, sizeof(bool_false
));
519 add_object_attribute(o
, 0, CKA_LOCAL
, &bool_false
, sizeof(bool_false
));
520 mech_type
= CKM_RSA_X_509
;
521 add_object_attribute(o
, 0, CKA_KEY_GEN_MECHANISM
, &mech_type
, sizeof(mech_type
));
523 add_object_attribute(o
, 0, CKA_SUBJECT
, subject_data
.data
, subject_data
.length
);
524 add_object_attribute(o
, 0, CKA_ENCRYPT
, &bool_true
, sizeof(bool_true
));
525 add_object_attribute(o
, 0, CKA_VERIFY
, &bool_true
, sizeof(bool_true
));
526 add_object_attribute(o
, 0, CKA_VERIFY_RECOVER
, &bool_false
, sizeof(bool_false
));
527 add_object_attribute(o
, 0, CKA_WRAP
, &bool_true
, sizeof(bool_true
));
528 add_object_attribute(o
, 0, CKA_TRUSTED
, &bool_true
, sizeof(bool_true
));
530 add_pubkey_info(hxctx
, o
, key_type
, cert
);
532 st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o
));
534 if (hx509_cert_have_private_key(cert
)) {
537 type
= CKO_PRIVATE_KEY
;
540 ret
= CKR_DEVICE_MEMORY
;
543 o
->cert
= hx509_cert_ref(cert
);
545 add_object_attribute(o
, 0, CKA_CLASS
, &type
, sizeof(type
));
546 add_object_attribute(o
, 0, CKA_TOKEN
, &bool_true
, sizeof(bool_true
));
547 add_object_attribute(o
, 0, CKA_PRIVATE
, &bool_true
, sizeof(bool_false
));
548 add_object_attribute(o
, 0, CKA_MODIFIABLE
, &bool_false
, sizeof(bool_false
));
549 add_object_attribute(o
, 0, CKA_LABEL
, foo
->label
, strlen(foo
->label
));
551 add_object_attribute(o
, 0, CKA_KEY_TYPE
, &key_type
, sizeof(key_type
));
552 add_object_attribute(o
, 0, CKA_ID
, foo
->id
, strlen(foo
->id
));
553 add_object_attribute(o
, 0, CKA_START_DATE
, "", 1); /* XXX */
554 add_object_attribute(o
, 0, CKA_END_DATE
, "", 1); /* XXX */
555 add_object_attribute(o
, 0, CKA_DERIVE
, &bool_false
, sizeof(bool_false
));
556 add_object_attribute(o
, 0, CKA_LOCAL
, &bool_false
, sizeof(bool_false
));
557 mech_type
= CKM_RSA_X_509
;
558 add_object_attribute(o
, 0, CKA_KEY_GEN_MECHANISM
, &mech_type
, sizeof(mech_type
));
560 add_object_attribute(o
, 0, CKA_SUBJECT
, subject_data
.data
, subject_data
.length
);
561 add_object_attribute(o
, 0, CKA_SENSITIVE
, &bool_true
, sizeof(bool_true
));
562 add_object_attribute(o
, 0, CKA_SECONDARY_AUTH
, &bool_false
, sizeof(bool_true
));
564 add_object_attribute(o
, 0, CKA_AUTH_PIN_FLAGS
, &flags
, sizeof(flags
));
566 add_object_attribute(o
, 0, CKA_DECRYPT
, &bool_true
, sizeof(bool_true
));
567 add_object_attribute(o
, 0, CKA_SIGN
, &bool_true
, sizeof(bool_true
));
568 add_object_attribute(o
, 0, CKA_SIGN_RECOVER
, &bool_false
, sizeof(bool_false
));
569 add_object_attribute(o
, 0, CKA_UNWRAP
, &bool_true
, sizeof(bool_true
));
570 add_object_attribute(o
, 0, CKA_EXTRACTABLE
, &bool_true
, sizeof(bool_true
));
571 add_object_attribute(o
, 0, CKA_NEVER_EXTRACTABLE
, &bool_false
, sizeof(bool_false
));
573 add_pubkey_info(hxctx
, o
, key_type
, cert
);
579 st_logf("something went wrong when adding cert!\n");
583 hx509_xfree(cert_data
.data
);
584 hx509_xfree(serial_data
.data
);
585 hx509_xfree(issuer_data
.data
);
586 hx509_xfree(subject_data
.data
);
592 add_certificate(const char *cert_file
,
598 hx509_lock lock
= NULL
;
606 flags
|= HX509_CERTS_UNPROTECT_ALL
;
610 asprintf(&str
, "PASS:%s", pin
);
612 hx509_lock_init(context
, &lock
);
613 hx509_lock_command_string(lock
, str
);
615 memset(str
, 0, strlen(str
));
619 ret
= hx509_certs_init(context
, cert_file
, flags
, lock
, &certs
);
621 st_logf("failed to open file %s\n", cert_file
);
622 return CKR_GENERAL_ERROR
;
625 ret
= hx509_certs_iter(context
, certs
, add_cert
, &foo
);
626 hx509_certs_free(&certs
);
628 st_logf("failed adding certs from file %s\n", cert_file
);
629 return CKR_GENERAL_ERROR
;
636 find_object_final(struct session_state
*state
)
638 if (state
->find
.attributes
) {
641 for (i
= 0; i
< state
->find
.num_attributes
; i
++) {
642 if (state
->find
.attributes
[i
].pValue
)
643 free(state
->find
.attributes
[i
].pValue
);
645 free(state
->find
.attributes
);
646 state
->find
.attributes
= NULL
;
647 state
->find
.num_attributes
= 0;
648 state
->find
.next_object
= -1;
653 reset_crypto_state(struct session_state
*state
)
655 state
->sign_object
= -1;
656 if (state
->sign_mechanism
)
657 free(state
->sign_mechanism
);
658 state
->sign_mechanism
= NULL_PTR
;
659 state
->verify_object
= -1;
660 if (state
->verify_mechanism
)
661 free(state
->verify_mechanism
);
662 state
->verify_mechanism
= NULL_PTR
;
666 close_session(struct session_state
*state
)
668 if (state
->find
.attributes
) {
669 application_error("application didn't do C_FindObjectsFinal\n");
670 find_object_final(state
);
673 state
->session_handle
= CK_INVALID_HANDLE
;
674 soft_token
.application
= NULL_PTR
;
675 soft_token
.notify
= NULL_PTR
;
676 reset_crypto_state(state
);
682 return soft_token
.open_sessions
> 0 ? "yes" : "no";
686 read_conf_file(const char *fn
, CK_USER_TYPE userType
, const char *pin
)
688 char buf
[1024], *type
, *s
, *p
;
692 CK_RV failed
= CKR_OK
;
696 st_logf("can't open configuration file %s\n", fn
);
697 return CKR_GENERAL_ERROR
;
700 while(fgets(buf
, sizeof(buf
), f
) != NULL
) {
701 buf
[strcspn(buf
, "\n")] = '\0';
705 st_logf("line: %s\n", buf
);
708 while (isspace((unsigned char)*p
))
712 while (isspace((unsigned char)*p
))
716 type
= strtok_r(p
, "\t", &s
);
720 if (strcasecmp("certificate", type
) == 0) {
721 char *cert
, *id
, *label
;
723 id
= strtok_r(NULL
, "\t", &s
);
728 st_logf("id: %s\n", id
);
729 label
= strtok_r(NULL
, "\t", &s
);
731 st_logf("no label\n");
734 cert
= strtok_r(NULL
, "\t", &s
);
736 st_logf("no certfiicate store\n");
740 st_logf("adding: %s: %s in file %s\n", id
, label
, cert
);
742 ret
= add_certificate(cert
, pin
, id
, label
);
745 } else if (strcasecmp("debug", type
) == 0) {
748 name
= strtok_r(NULL
, "\t", &s
);
750 st_logf("no filename\n");
754 if (soft_token
.logfile
)
755 fclose(soft_token
.logfile
);
757 if (strcasecmp(name
, "stdout") == 0)
758 soft_token
.logfile
= stdout
;
760 soft_token
.logfile
= fopen(name
, "a");
761 if (soft_token
.logfile
== NULL
)
762 st_logf("failed to open file: %s\n", name
);
764 } else if (strcasecmp("app-fatal", type
) == 0) {
767 name
= strtok_r(NULL
, "\t", &s
);
769 st_logf("argument to app-fatal\n");
773 if (strcmp(name
, "true") == 0 || strcmp(name
, "on") == 0)
774 soft_token
.flags
.app_error_fatal
= 1;
775 else if (strcmp(name
, "false") == 0 || strcmp(name
, "off") == 0)
776 soft_token
.flags
.app_error_fatal
= 0;
778 st_logf("unknown app-fatal: %s\n", name
);
781 st_logf("unknown type: %s\n", type
);
791 func_not_supported(void)
793 st_logf("function not supported\n");
794 return CKR_FUNCTION_NOT_SUPPORTED
;
798 C_Initialize(CK_VOID_PTR a
)
800 CK_C_INITIALIZE_ARGS_PTR args
= a
;
804 st_logf("Initialize\n");
808 OpenSSL_add_all_algorithms();
810 srandom(getpid() ^ time(NULL
));
812 for (i
= 0; i
< MAX_NUM_SESSION
; i
++) {
813 soft_token
.state
[i
].session_handle
= CK_INVALID_HANDLE
;
814 soft_token
.state
[i
].find
.attributes
= NULL
;
815 soft_token
.state
[i
].find
.num_attributes
= 0;
816 soft_token
.state
[i
].find
.next_object
= -1;
817 reset_crypto_state(&soft_token
.state
[i
]);
820 soft_token
.flags
.hardware_slot
= 1;
821 soft_token
.flags
.app_error_fatal
= 0;
822 soft_token
.flags
.login_done
= 0;
824 soft_token
.object
.objs
= NULL
;
825 soft_token
.object
.num_objs
= 0;
827 soft_token
.logfile
= NULL
;
829 soft_token
.logfile
= stdout
;
832 soft_token
.logfile
= fopen("/tmp/log-pkcs11.txt", "a");
836 st_logf("\tCreateMutex:\t%p\n", args
->CreateMutex
);
837 st_logf("\tDestroyMutext\t%p\n", args
->DestroyMutex
);
838 st_logf("\tLockMutext\t%p\n", args
->LockMutex
);
839 st_logf("\tUnlockMutext\t%p\n", args
->UnlockMutex
);
840 st_logf("\tFlags\t%04x\n", (unsigned int)args
->flags
);
844 char *fn
= NULL
, *home
= NULL
;
846 if (getuid() == geteuid()) {
847 fn
= getenv("SOFTPKCS11RC");
850 home
= getenv("HOME");
852 if (fn
== NULL
&& home
== NULL
) {
853 struct passwd
*pw
= getpwuid(getuid());
859 asprintf(&fn
, "%s/.soft-token.rc", home
);
861 fn
= strdup("/etc/soft-token.rc");
864 soft_token
.config_file
= fn
;
868 * This operations doesn't return CKR_OK if any of the
869 * certificates failes to be unparsed (ie password protected).
871 ret
= read_conf_file(soft_token
.config_file
, CKU_USER
, NULL
);
873 soft_token
.flags
.login_done
= 1;
879 C_Finalize(CK_VOID_PTR args
)
885 st_logf("Finalize\n");
887 for (i
= 0; i
< MAX_NUM_SESSION
; i
++) {
888 if (soft_token
.state
[i
].session_handle
!= CK_INVALID_HANDLE
) {
889 application_error("application finalized without "
890 "closing session\n");
891 close_session(&soft_token
.state
[i
]);
899 C_GetInfo(CK_INFO_PTR args
)
903 st_logf("GetInfo\n");
905 memset(args
, 17, sizeof(*args
));
906 args
->cryptokiVersion
.major
= 2;
907 args
->cryptokiVersion
.minor
= 10;
908 snprintf_fill((char *)args
->manufacturerID
,
909 sizeof(args
->manufacturerID
),
911 "Heimdal hx509 SoftToken");
912 snprintf_fill((char *)args
->libraryDescription
,
913 sizeof(args
->libraryDescription
), ' ',
914 "Heimdal hx509 SoftToken");
915 args
->libraryVersion
.major
= 2;
916 args
->libraryVersion
.minor
= 0;
921 extern CK_FUNCTION_LIST funcs
;
924 C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList
)
928 *ppFunctionList
= &funcs
;
933 C_GetSlotList(CK_BBOOL tokenPresent
,
934 CK_SLOT_ID_PTR pSlotList
,
935 CK_ULONG_PTR pulCount
)
938 st_logf("GetSlotList: %s\n",
939 tokenPresent
? "tokenPresent" : "token not Present");
947 C_GetSlotInfo(CK_SLOT_ID slotID
,
948 CK_SLOT_INFO_PTR pInfo
)
951 st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID
, has_session());
953 memset(pInfo
, 18, sizeof(*pInfo
));
956 return CKR_ARGUMENTS_BAD
;
958 snprintf_fill((char *)pInfo
->slotDescription
,
959 sizeof(pInfo
->slotDescription
),
961 "Heimdal hx509 SoftToken (slot)");
962 snprintf_fill((char *)pInfo
->manufacturerID
,
963 sizeof(pInfo
->manufacturerID
),
965 "Heimdal hx509 SoftToken (slot)");
966 pInfo
->flags
= CKF_TOKEN_PRESENT
;
967 if (soft_token
.flags
.hardware_slot
)
968 pInfo
->flags
|= CKF_HW_SLOT
;
969 pInfo
->hardwareVersion
.major
= 1;
970 pInfo
->hardwareVersion
.minor
= 0;
971 pInfo
->firmwareVersion
.major
= 1;
972 pInfo
->firmwareVersion
.minor
= 0;
978 C_GetTokenInfo(CK_SLOT_ID slotID
,
979 CK_TOKEN_INFO_PTR pInfo
)
982 st_logf("GetTokenInfo: %s\n", has_session());
984 memset(pInfo
, 19, sizeof(*pInfo
));
986 snprintf_fill((char *)pInfo
->label
,
987 sizeof(pInfo
->label
),
989 "Heimdal hx509 SoftToken (token)");
990 snprintf_fill((char *)pInfo
->manufacturerID
,
991 sizeof(pInfo
->manufacturerID
),
993 "Heimdal hx509 SoftToken (token)");
994 snprintf_fill((char *)pInfo
->model
,
995 sizeof(pInfo
->model
),
997 "Heimdal hx509 SoftToken (token)");
998 snprintf_fill((char *)pInfo
->serialNumber
,
999 sizeof(pInfo
->serialNumber
),
1003 CKF_TOKEN_INITIALIZED
|
1004 CKF_USER_PIN_INITIALIZED
;
1006 if (soft_token
.flags
.login_done
== 0)
1007 pInfo
->flags
|= CKF_LOGIN_REQUIRED
;
1010 CKF_RESTORE_KEY_NOT_NEEDED |
1012 pInfo
->ulMaxSessionCount
= MAX_NUM_SESSION
;
1013 pInfo
->ulSessionCount
= soft_token
.open_sessions
;
1014 pInfo
->ulMaxRwSessionCount
= MAX_NUM_SESSION
;
1015 pInfo
->ulRwSessionCount
= soft_token
.open_sessions
;
1016 pInfo
->ulMaxPinLen
= 1024;
1017 pInfo
->ulMinPinLen
= 0;
1018 pInfo
->ulTotalPublicMemory
= 4711;
1019 pInfo
->ulFreePublicMemory
= 4712;
1020 pInfo
->ulTotalPrivateMemory
= 4713;
1021 pInfo
->ulFreePrivateMemory
= 4714;
1022 pInfo
->hardwareVersion
.major
= 2;
1023 pInfo
->hardwareVersion
.minor
= 0;
1024 pInfo
->firmwareVersion
.major
= 2;
1025 pInfo
->firmwareVersion
.minor
= 0;
1031 C_GetMechanismList(CK_SLOT_ID slotID
,
1032 CK_MECHANISM_TYPE_PTR pMechanismList
,
1033 CK_ULONG_PTR pulCount
)
1036 st_logf("GetMechanismList\n");
1039 if (pMechanismList
== NULL_PTR
)
1041 pMechanismList
[1] = CKM_RSA_PKCS
;
1047 C_GetMechanismInfo(CK_SLOT_ID slotID
,
1048 CK_MECHANISM_TYPE type
,
1049 CK_MECHANISM_INFO_PTR pInfo
)
1052 st_logf("GetMechanismInfo: slot %d type: %d\n",
1053 (int)slotID
, (int)type
);
1054 memset(pInfo
, 0, sizeof(*pInfo
));
1060 C_InitToken(CK_SLOT_ID slotID
,
1061 CK_UTF8CHAR_PTR pPin
,
1063 CK_UTF8CHAR_PTR pLabel
)
1066 st_logf("InitToken: slot %d\n", (int)slotID
);
1067 return CKR_FUNCTION_NOT_SUPPORTED
;
1071 C_OpenSession(CK_SLOT_ID slotID
,
1073 CK_VOID_PTR pApplication
,
1075 CK_SESSION_HANDLE_PTR phSession
)
1079 st_logf("OpenSession: slot: %d\n", (int)slotID
);
1081 if (soft_token
.open_sessions
== MAX_NUM_SESSION
)
1082 return CKR_SESSION_COUNT
;
1084 soft_token
.application
= pApplication
;
1085 soft_token
.notify
= Notify
;
1087 for (i
= 0; i
< MAX_NUM_SESSION
; i
++)
1088 if (soft_token
.state
[i
].session_handle
== CK_INVALID_HANDLE
)
1090 if (i
== MAX_NUM_SESSION
)
1093 soft_token
.open_sessions
++;
1095 soft_token
.state
[i
].session_handle
=
1096 (CK_SESSION_HANDLE
)(random() & 0xfffff);
1097 *phSession
= soft_token
.state
[i
].session_handle
;
1103 C_CloseSession(CK_SESSION_HANDLE hSession
)
1105 struct session_state
*state
;
1107 st_logf("CloseSession\n");
1109 if (verify_session_handle(hSession
, &state
) != CKR_OK
)
1110 application_error("closed session not open");
1112 close_session(state
);
1118 C_CloseAllSessions(CK_SLOT_ID slotID
)
1123 st_logf("CloseAllSessions\n");
1125 for (i
= 0; i
< MAX_NUM_SESSION
; i
++)
1126 if (soft_token
.state
[i
].session_handle
!= CK_INVALID_HANDLE
)
1127 close_session(&soft_token
.state
[i
]);
1133 C_GetSessionInfo(CK_SESSION_HANDLE hSession
,
1134 CK_SESSION_INFO_PTR pInfo
)
1136 st_logf("GetSessionInfo\n");
1139 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1141 memset(pInfo
, 20, sizeof(*pInfo
));
1144 if (soft_token
.flags
.login_done
)
1145 pInfo
->state
= CKS_RO_USER_FUNCTIONS
;
1147 pInfo
->state
= CKS_RO_PUBLIC_SESSION
;
1148 pInfo
->flags
= CKF_SERIAL_SESSION
;
1149 pInfo
->ulDeviceError
= 0;
1155 C_Login(CK_SESSION_HANDLE hSession
,
1156 CK_USER_TYPE userType
,
1157 CK_UTF8CHAR_PTR pPin
,
1166 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1168 if (pPin
!= NULL_PTR
) {
1169 asprintf(&pin
, "%.*s", (int)ulPinLen
, pPin
);
1170 st_logf("type: %d password: %s\n", (int)userType
, pin
);
1177 ret
= read_conf_file(soft_token
.config_file
, userType
, pin
);
1179 soft_token
.flags
.login_done
= 1;
1183 return soft_token
.flags
.login_done
? CKR_OK
: CKR_PIN_INCORRECT
;
1187 C_Logout(CK_SESSION_HANDLE hSession
)
1189 st_logf("Logout\n");
1192 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1193 return CKR_FUNCTION_NOT_SUPPORTED
;
1197 C_GetObjectSize(CK_SESSION_HANDLE hSession
,
1198 CK_OBJECT_HANDLE hObject
,
1199 CK_ULONG_PTR pulSize
)
1201 st_logf("GetObjectSize\n");
1204 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1205 return CKR_FUNCTION_NOT_SUPPORTED
;
1209 C_GetAttributeValue(CK_SESSION_HANDLE hSession
,
1210 CK_OBJECT_HANDLE hObject
,
1211 CK_ATTRIBUTE_PTR pTemplate
,
1214 struct session_state
*state
;
1215 struct st_object
*obj
;
1222 st_logf("GetAttributeValue: %lx\n",
1223 (unsigned long)HANDLE_OBJECT_ID(hObject
));
1224 VERIFY_SESSION_HANDLE(hSession
, &state
);
1226 if ((ret
= object_handle_to_object(hObject
, &obj
)) != CKR_OK
) {
1227 st_logf("object not found: %lx\n",
1228 (unsigned long)HANDLE_OBJECT_ID(hObject
));
1232 for (i
= 0; i
< ulCount
; i
++) {
1233 st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate
[i
].type
);
1234 for (j
= 0; j
< obj
->num_attributes
; j
++) {
1235 if (obj
->attrs
[j
].secret
) {
1236 pTemplate
[i
].ulValueLen
= (CK_ULONG
)-1;
1239 if (pTemplate
[i
].type
== obj
->attrs
[j
].attribute
.type
) {
1240 if (pTemplate
[i
].pValue
!= NULL_PTR
&& obj
->attrs
[j
].secret
== 0) {
1241 if (pTemplate
[i
].ulValueLen
>= obj
->attrs
[j
].attribute
.ulValueLen
)
1242 memcpy(pTemplate
[i
].pValue
, obj
->attrs
[j
].attribute
.pValue
,
1243 obj
->attrs
[j
].attribute
.ulValueLen
);
1245 pTemplate
[i
].ulValueLen
= obj
->attrs
[j
].attribute
.ulValueLen
;
1249 if (j
== obj
->num_attributes
) {
1250 st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate
[i
].type
);
1251 pTemplate
[i
].ulValueLen
= (CK_ULONG
)-1;
1259 C_FindObjectsInit(CK_SESSION_HANDLE hSession
,
1260 CK_ATTRIBUTE_PTR pTemplate
,
1263 struct session_state
*state
;
1265 st_logf("FindObjectsInit\n");
1269 VERIFY_SESSION_HANDLE(hSession
, &state
);
1271 if (state
->find
.next_object
!= -1) {
1272 application_error("application didn't do C_FindObjectsFinal\n");
1273 find_object_final(state
);
1278 print_attributes(pTemplate
, ulCount
);
1280 state
->find
.attributes
=
1281 calloc(1, ulCount
* sizeof(state
->find
.attributes
[0]));
1282 if (state
->find
.attributes
== NULL
)
1283 return CKR_DEVICE_MEMORY
;
1284 for (i
= 0; i
< ulCount
; i
++) {
1285 state
->find
.attributes
[i
].pValue
=
1286 malloc(pTemplate
[i
].ulValueLen
);
1287 if (state
->find
.attributes
[i
].pValue
== NULL
) {
1288 find_object_final(state
);
1289 return CKR_DEVICE_MEMORY
;
1291 memcpy(state
->find
.attributes
[i
].pValue
,
1292 pTemplate
[i
].pValue
, pTemplate
[i
].ulValueLen
);
1293 state
->find
.attributes
[i
].type
= pTemplate
[i
].type
;
1294 state
->find
.attributes
[i
].ulValueLen
= pTemplate
[i
].ulValueLen
;
1296 state
->find
.num_attributes
= ulCount
;
1297 state
->find
.next_object
= 0;
1299 st_logf("find all objects\n");
1300 state
->find
.attributes
= NULL
;
1301 state
->find
.num_attributes
= 0;
1302 state
->find
.next_object
= 0;
1309 C_FindObjects(CK_SESSION_HANDLE hSession
,
1310 CK_OBJECT_HANDLE_PTR phObject
,
1311 CK_ULONG ulMaxObjectCount
,
1312 CK_ULONG_PTR pulObjectCount
)
1314 struct session_state
*state
;
1319 st_logf("FindObjects\n");
1321 VERIFY_SESSION_HANDLE(hSession
, &state
);
1323 if (state
->find
.next_object
== -1) {
1324 application_error("application didn't do C_FindObjectsInit\n");
1325 return CKR_ARGUMENTS_BAD
;
1327 if (ulMaxObjectCount
== 0) {
1328 application_error("application asked for 0 objects\n");
1329 return CKR_ARGUMENTS_BAD
;
1331 *pulObjectCount
= 0;
1332 for (i
= state
->find
.next_object
; i
< soft_token
.object
.num_objs
; i
++) {
1333 st_logf("FindObjects: %d\n", i
);
1334 state
->find
.next_object
= i
+ 1;
1335 if (attributes_match(soft_token
.object
.objs
[i
],
1336 state
->find
.attributes
,
1337 state
->find
.num_attributes
)) {
1338 *phObject
++ = soft_token
.object
.objs
[i
]->object_handle
;
1340 (*pulObjectCount
)++;
1341 if (ulMaxObjectCount
== 0)
1349 C_FindObjectsFinal(CK_SESSION_HANDLE hSession
)
1351 struct session_state
*state
;
1355 st_logf("FindObjectsFinal\n");
1356 VERIFY_SESSION_HANDLE(hSession
, &state
);
1357 find_object_final(state
);
1362 commonInit(CK_ATTRIBUTE
*attr_match
, int attr_match_len
,
1363 const CK_MECHANISM_TYPE
*mechs
, int mechs_len
,
1364 const CK_MECHANISM_PTR pMechanism
, CK_OBJECT_HANDLE hKey
,
1365 struct st_object
**o
)
1371 if ((ret
= object_handle_to_object(hKey
, o
)) != CKR_OK
)
1374 ret
= attributes_match(*o
, attr_match
, attr_match_len
);
1376 application_error("called commonInit on key that doesn't "
1377 "support required attr");
1378 return CKR_ARGUMENTS_BAD
;
1381 for (i
= 0; i
< mechs_len
; i
++)
1382 if (mechs
[i
] == pMechanism
->mechanism
)
1384 if (i
== mechs_len
) {
1385 application_error("called mech (%08lx) not supported\n",
1386 pMechanism
->mechanism
);
1387 return CKR_ARGUMENTS_BAD
;
1394 dup_mechanism(CK_MECHANISM_PTR
*dup
, const CK_MECHANISM_PTR pMechanism
)
1398 p
= malloc(sizeof(*p
));
1400 return CKR_DEVICE_MEMORY
;
1405 memcpy(p
, pMechanism
, sizeof(*p
));
1411 C_DigestInit(CK_SESSION_HANDLE hSession
,
1412 CK_MECHANISM_PTR pMechanism
)
1414 st_logf("DigestInit\n");
1416 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1417 return CKR_FUNCTION_NOT_SUPPORTED
;
1421 C_SignInit(CK_SESSION_HANDLE hSession
,
1422 CK_MECHANISM_PTR pMechanism
,
1423 CK_OBJECT_HANDLE hKey
)
1425 struct session_state
*state
;
1426 CK_MECHANISM_TYPE mechs
[] = { CKM_RSA_PKCS
};
1427 CK_BBOOL bool_true
= CK_TRUE
;
1428 CK_ATTRIBUTE attr
[] = {
1429 { CKA_SIGN
, &bool_true
, sizeof(bool_true
) }
1431 struct st_object
*o
;
1435 st_logf("SignInit\n");
1436 VERIFY_SESSION_HANDLE(hSession
, &state
);
1438 ret
= commonInit(attr
, sizeof(attr
)/sizeof(attr
[0]),
1439 mechs
, sizeof(mechs
)/sizeof(mechs
[0]),
1440 pMechanism
, hKey
, &o
);
1444 ret
= dup_mechanism(&state
->sign_mechanism
, pMechanism
);
1446 state
->sign_object
= OBJECT_ID(o
);
1452 C_Sign(CK_SESSION_HANDLE hSession
,
1455 CK_BYTE_PTR pSignature
,
1456 CK_ULONG_PTR pulSignatureLen
)
1458 struct session_state
*state
;
1459 struct st_object
*o
;
1462 const AlgorithmIdentifier
*alg
;
1463 heim_octet_string sig
, data
;
1467 VERIFY_SESSION_HANDLE(hSession
, &state
);
1472 if (state
->sign_object
== -1)
1473 return CKR_ARGUMENTS_BAD
;
1475 if (pulSignatureLen
== NULL
) {
1476 st_logf("signature len NULL\n");
1477 ret
= CKR_ARGUMENTS_BAD
;
1481 if (pData
== NULL_PTR
) {
1482 st_logf("data NULL\n");
1483 ret
= CKR_ARGUMENTS_BAD
;
1487 o
= soft_token
.object
.objs
[state
->sign_object
];
1489 if (hx509_cert_have_private_key(o
->cert
) == 0) {
1490 st_logf("private key NULL\n");
1491 return CKR_ARGUMENTS_BAD
;
1494 switch(state
->sign_mechanism
->mechanism
) {
1496 alg
= hx509_signature_rsa_pkcs1_x509();
1499 ret
= CKR_FUNCTION_NOT_SUPPORTED
;
1504 data
.length
= ulDataLen
;
1506 hret
= _hx509_create_signature(context
,
1507 _hx509_cert_private_key(o
->cert
),
1513 ret
= CKR_DEVICE_ERROR
;
1516 *pulSignatureLen
= sig
.length
;
1518 if (pSignature
!= NULL_PTR
)
1519 memcpy(pSignature
, sig
.data
, sig
.length
);
1524 memset(sig
.data
, 0, sig
.length
);
1525 der_free_octet_string(&sig
);
1531 C_SignUpdate(CK_SESSION_HANDLE hSession
,
1536 st_logf("SignUpdate\n");
1537 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1538 return CKR_FUNCTION_NOT_SUPPORTED
;
1543 C_SignFinal(CK_SESSION_HANDLE hSession
,
1544 CK_BYTE_PTR pSignature
,
1545 CK_ULONG_PTR pulSignatureLen
)
1548 st_logf("SignUpdate\n");
1549 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1550 return CKR_FUNCTION_NOT_SUPPORTED
;
1554 C_VerifyInit(CK_SESSION_HANDLE hSession
,
1555 CK_MECHANISM_PTR pMechanism
,
1556 CK_OBJECT_HANDLE hKey
)
1558 struct session_state
*state
;
1559 CK_MECHANISM_TYPE mechs
[] = { CKM_RSA_PKCS
};
1560 CK_BBOOL bool_true
= CK_TRUE
;
1561 CK_ATTRIBUTE attr
[] = {
1562 { CKA_VERIFY
, &bool_true
, sizeof(bool_true
) }
1564 struct st_object
*o
;
1568 st_logf("VerifyInit\n");
1569 VERIFY_SESSION_HANDLE(hSession
, &state
);
1571 ret
= commonInit(attr
, sizeof(attr
)/sizeof(attr
[0]),
1572 mechs
, sizeof(mechs
)/sizeof(mechs
[0]),
1573 pMechanism
, hKey
, &o
);
1577 ret
= dup_mechanism(&state
->verify_mechanism
, pMechanism
);
1579 state
->verify_object
= OBJECT_ID(o
);
1585 C_Verify(CK_SESSION_HANDLE hSession
,
1588 CK_BYTE_PTR pSignature
,
1589 CK_ULONG ulSignatureLen
)
1591 struct session_state
*state
;
1592 struct st_object
*o
;
1593 const AlgorithmIdentifier
*alg
;
1596 heim_octet_string data
, sig
;
1599 st_logf("Verify\n");
1600 VERIFY_SESSION_HANDLE(hSession
, &state
);
1602 if (state
->verify_object
== -1)
1603 return CKR_ARGUMENTS_BAD
;
1605 o
= soft_token
.object
.objs
[state
->verify_object
];
1607 switch(state
->verify_mechanism
->mechanism
) {
1609 alg
= hx509_signature_rsa_pkcs1_x509();
1612 ret
= CKR_FUNCTION_NOT_SUPPORTED
;
1617 sig
.length
= ulDataLen
;
1618 data
.data
= pSignature
;
1619 data
.length
= ulSignatureLen
;
1621 hret
= _hx509_verify_signature(context
,
1622 _hx509_get_cert(o
->cert
),
1627 ret
= CKR_GENERAL_ERROR
;
1638 C_VerifyUpdate(CK_SESSION_HANDLE hSession
,
1643 st_logf("VerifyUpdate\n");
1644 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1645 return CKR_FUNCTION_NOT_SUPPORTED
;
1649 C_VerifyFinal(CK_SESSION_HANDLE hSession
,
1650 CK_BYTE_PTR pSignature
,
1651 CK_ULONG ulSignatureLen
)
1654 st_logf("VerifyFinal\n");
1655 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1656 return CKR_FUNCTION_NOT_SUPPORTED
;
1660 C_GenerateRandom(CK_SESSION_HANDLE hSession
,
1661 CK_BYTE_PTR RandomData
,
1662 CK_ULONG ulRandomLen
)
1665 st_logf("GenerateRandom\n");
1666 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1667 return CKR_FUNCTION_NOT_SUPPORTED
;
1671 CK_FUNCTION_LIST funcs
= {
1683 (void *)func_not_supported
, /* C_InitPIN */
1684 (void *)func_not_supported
, /* C_SetPIN */
1689 (void *)func_not_supported
, /* C_GetOperationState */
1690 (void *)func_not_supported
, /* C_SetOperationState */
1693 (void *)func_not_supported
, /* C_CreateObject */
1694 (void *)func_not_supported
, /* C_CopyObject */
1695 (void *)func_not_supported
, /* C_DestroyObject */
1696 (void *)func_not_supported
, /* C_GetObjectSize */
1697 C_GetAttributeValue
,
1698 (void *)func_not_supported
, /* C_SetAttributeValue */
1702 (void *)func_not_supported
, /* C_EncryptInit, */
1703 (void *)func_not_supported
, /* C_Encrypt, */
1704 (void *)func_not_supported
, /* C_EncryptUpdate, */
1705 (void *)func_not_supported
, /* C_EncryptFinal, */
1706 (void *)func_not_supported
, /* C_DecryptInit, */
1707 (void *)func_not_supported
, /* C_Decrypt, */
1708 (void *)func_not_supported
, /* C_DecryptUpdate, */
1709 (void *)func_not_supported
, /* C_DecryptFinal, */
1711 (void *)func_not_supported
, /* C_Digest */
1712 (void *)func_not_supported
, /* C_DigestUpdate */
1713 (void *)func_not_supported
, /* C_DigestKey */
1714 (void *)func_not_supported
, /* C_DigestFinal */
1719 (void *)func_not_supported
, /* C_SignRecoverInit */
1720 (void *)func_not_supported
, /* C_SignRecover */
1725 (void *)func_not_supported
, /* C_VerifyRecoverInit */
1726 (void *)func_not_supported
, /* C_VerifyRecover */
1727 (void *)func_not_supported
, /* C_DigestEncryptUpdate */
1728 (void *)func_not_supported
, /* C_DecryptDigestUpdate */
1729 (void *)func_not_supported
, /* C_SignEncryptUpdate */
1730 (void *)func_not_supported
, /* C_DecryptVerifyUpdate */
1731 (void *)func_not_supported
, /* C_GenerateKey */
1732 (void *)func_not_supported
, /* C_GenerateKeyPair */
1733 (void *)func_not_supported
, /* C_WrapKey */
1734 (void *)func_not_supported
, /* C_UnwrapKey */
1735 (void *)func_not_supported
, /* C_DeriveKey */
1736 (void *)func_not_supported
, /* C_SeedRandom */
1738 (void *)func_not_supported
, /* C_GetFunctionStatus */
1739 (void *)func_not_supported
, /* C_CancelFunction */
1740 (void *)func_not_supported
/* C_WaitForSlotEvent */