1 /* $NetBSD: softp11.c,v 1.1.1.2 2014/04/24 12:45:42 pettai Exp $ */
4 * Copyright (c) 2004 - 2008 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #define CRYPTOKI_EXPORTS 1
41 #define OBJECT_ID_MASK 0xfff
42 #define HANDLE_OBJECT_ID(h) ((h) & OBJECT_ID_MASK)
43 #define OBJECT_ID(obj) HANDLE_OBJECT_ID((obj)->object_handle)
46 #define random() rand()
47 #define srandom(s) srand(s)
55 CK_ATTRIBUTE attribute
;
60 CK_OBJECT_HANDLE object_handle
;
61 struct st_attr
*attrs
;
66 static struct soft_token
{
67 CK_VOID_PTR application
;
72 struct st_object
**objs
;
81 struct session_state
{
82 CK_SESSION_HANDLE session_handle
;
85 CK_ATTRIBUTE
*attributes
;
86 CK_ULONG num_attributes
;
91 CK_MECHANISM_PTR sign_mechanism
;
93 CK_MECHANISM_PTR verify_mechanism
;
95 #define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0]))
99 static hx509_context context
;
102 application_error(const char *fmt
, ...)
108 if (soft_token
.flags
.app_error_fatal
)
113 st_logf(const char *fmt
, ...)
116 if (soft_token
.logfile
== NULL
)
119 vfprintf(soft_token
.logfile
, fmt
, ap
);
121 fflush(soft_token
.logfile
);
127 if (context
== NULL
) {
128 int ret
= hx509_context_init(&context
);
130 return CKR_GENERAL_ERROR
;
135 #define INIT_CONTEXT() { CK_RV icret = init_context(); if (icret) return icret; }
138 snprintf_fill(char *str
, size_t size
, char fillchar
, const char *fmt
, ...)
143 len
= vsnprintf(str
, size
, fmt
, ap
);
145 if (len
< 0 || (size_t)len
> size
)
147 while ((size_t)len
< size
)
148 str
[len
++] = fillchar
;
152 #define printf error_use_st_logf
155 #define VERIFY_SESSION_HANDLE(s, state) \
158 xret = verify_session_handle(s, state); \
159 if (xret != CKR_OK) { \
160 /* return CKR_OK */; \
165 verify_session_handle(CK_SESSION_HANDLE hSession
,
166 struct session_state
**state
)
170 for (i
= 0; i
< MAX_NUM_SESSION
; i
++){
171 if (soft_token
.state
[i
].session_handle
== hSession
)
174 if (i
== MAX_NUM_SESSION
) {
175 application_error("use of invalid handle: 0x%08lx\n",
176 (unsigned long)hSession
);
177 return CKR_SESSION_HANDLE_INVALID
;
180 *state
= &soft_token
.state
[i
];
185 object_handle_to_object(CK_OBJECT_HANDLE handle
,
186 struct st_object
**object
)
188 int i
= HANDLE_OBJECT_ID(handle
);
191 if (i
>= soft_token
.object
.num_objs
)
192 return CKR_ARGUMENTS_BAD
;
193 if (soft_token
.object
.objs
[i
] == NULL
)
194 return CKR_ARGUMENTS_BAD
;
195 if (soft_token
.object
.objs
[i
]->object_handle
!= handle
)
196 return CKR_ARGUMENTS_BAD
;
197 *object
= soft_token
.object
.objs
[i
];
202 attributes_match(const struct st_object
*obj
,
203 const CK_ATTRIBUTE
*attributes
,
204 CK_ULONG num_attributes
)
209 st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj
));
211 for (i
= 0; i
< num_attributes
; i
++) {
213 for (j
= 0; j
< obj
->num_attributes
; j
++) {
214 if (attributes
[i
].type
== obj
->attrs
[j
].attribute
.type
&&
215 attributes
[i
].ulValueLen
== obj
->attrs
[j
].attribute
.ulValueLen
&&
216 memcmp(attributes
[i
].pValue
, obj
->attrs
[j
].attribute
.pValue
,
217 attributes
[i
].ulValueLen
) == 0) {
223 st_logf("type %d attribute have no match\n", attributes
[i
].type
);
227 st_logf("attribute matches\n");
232 print_attributes(const CK_ATTRIBUTE
*attributes
,
233 CK_ULONG num_attributes
)
237 st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes
);
239 for (i
= 0; i
< num_attributes
; i
++) {
241 switch (attributes
[i
].type
) {
244 if (attributes
[i
].ulValueLen
!= sizeof(CK_BBOOL
)) {
245 application_error("token attribute wrong length\n");
248 ck_true
= attributes
[i
].pValue
;
249 st_logf("token: %s", *ck_true
? "TRUE" : "FALSE");
253 CK_OBJECT_CLASS
*class;
254 if (attributes
[i
].ulValueLen
!= sizeof(CK_ULONG
)) {
255 application_error("class attribute wrong length\n");
258 class = attributes
[i
].pValue
;
261 case CKO_CERTIFICATE
:
262 st_logf("certificate");
265 st_logf("public key");
267 case CKO_PRIVATE_KEY
:
268 st_logf("private key");
271 st_logf("secret key");
273 case CKO_DOMAIN_PARAMETERS
:
274 st_logf("domain parameters");
277 st_logf("[class %lx]", (long unsigned)*class);
288 case CKA_APPLICATION
:
289 st_logf("application");
298 st_logf("[unknown 0x%08lx]", (unsigned long)attributes
[i
].type
);
305 static struct st_object
*
308 struct st_object
*o
, **objs
;
311 o
= calloc(1, sizeof(*o
));
315 for (i
= 0; i
< soft_token
.object
.num_objs
; i
++) {
316 if (soft_token
.object
.objs
== NULL
) {
317 soft_token
.object
.objs
[i
] = o
;
321 if (i
== soft_token
.object
.num_objs
) {
322 objs
= realloc(soft_token
.object
.objs
,
323 (soft_token
.object
.num_objs
+ 1) * sizeof(soft_token
.object
.objs
[0]));
328 soft_token
.object
.objs
= objs
;
329 soft_token
.object
.objs
[soft_token
.object
.num_objs
++] = o
;
331 soft_token
.object
.objs
[i
]->object_handle
=
332 (random() & (~OBJECT_ID_MASK
)) | i
;
338 add_object_attribute(struct st_object
*o
,
340 CK_ATTRIBUTE_TYPE type
,
347 i
= o
->num_attributes
;
348 a
= realloc(o
->attrs
, (i
+ 1) * sizeof(o
->attrs
[0]));
350 return CKR_DEVICE_MEMORY
;
352 o
->attrs
[i
].secret
= secret
;
353 o
->attrs
[i
].attribute
.type
= type
;
354 o
->attrs
[i
].attribute
.pValue
= malloc(ulValueLen
);
355 if (o
->attrs
[i
].attribute
.pValue
== NULL
&& ulValueLen
!= 0)
356 return CKR_DEVICE_MEMORY
;
357 memcpy(o
->attrs
[i
].attribute
.pValue
, pValue
, ulValueLen
);
358 o
->attrs
[i
].attribute
.ulValueLen
= ulValueLen
;
365 add_pubkey_info(hx509_context hxctx
, struct st_object
*o
,
366 CK_KEY_TYPE key_type
, hx509_cert cert
)
369 CK_BYTE
*modulus
= NULL
;
370 size_t modulus_len
= 0;
371 CK_ULONG modulus_bits
= 0;
372 CK_BYTE
*exponent
= NULL
;
373 size_t exponent_len
= 0;
375 if (key_type
!= CKK_RSA
)
377 if (_hx509_cert_private_key(cert
) == NULL
)
380 num
= _hx509_private_key_get_internal(context
,
381 _hx509_cert_private_key(cert
),
384 return CKR_GENERAL_ERROR
;
385 modulus_bits
= BN_num_bits(num
);
387 modulus_len
= BN_num_bytes(num
);
388 modulus
= malloc(modulus_len
);
389 BN_bn2bin(num
, modulus
);
392 add_object_attribute(o
, 0, CKA_MODULUS
, modulus
, modulus_len
);
393 add_object_attribute(o
, 0, CKA_MODULUS_BITS
,
394 &modulus_bits
, sizeof(modulus_bits
));
398 num
= _hx509_private_key_get_internal(context
,
399 _hx509_cert_private_key(cert
),
402 return CKR_GENERAL_ERROR
;
404 exponent_len
= BN_num_bytes(num
);
405 exponent
= malloc(exponent_len
);
406 BN_bn2bin(num
, exponent
);
409 add_object_attribute(o
, 0, CKA_PUBLIC_EXPONENT
,
410 exponent
, exponent_len
);
424 add_cert(hx509_context hxctx
, void *ctx
, hx509_cert cert
)
426 static char empty
[] = "";
427 struct foo
*foo
= (struct foo
*)ctx
;
428 struct st_object
*o
= NULL
;
429 CK_OBJECT_CLASS type
;
430 CK_BBOOL bool_true
= CK_TRUE
;
431 CK_BBOOL bool_false
= CK_FALSE
;
432 CK_CERTIFICATE_TYPE cert_type
= CKC_X_509
;
433 CK_KEY_TYPE key_type
;
434 CK_MECHANISM_TYPE mech_type
;
435 CK_RV ret
= CKR_GENERAL_ERROR
;
437 heim_octet_string cert_data
, subject_data
, issuer_data
, serial_data
;
439 st_logf("adding certificate\n");
441 serial_data
.data
= NULL
;
442 serial_data
.length
= 0;
443 cert_data
= subject_data
= issuer_data
= serial_data
;
445 hret
= hx509_cert_binary(hxctx
, cert
, &cert_data
);
452 hret
= hx509_cert_get_issuer(cert
, &name
);
455 hret
= hx509_name_binary(name
, &issuer_data
);
456 hx509_name_free(&name
);
460 hret
= hx509_cert_get_subject(cert
, &name
);
463 hret
= hx509_name_binary(name
, &subject_data
);
464 hx509_name_free(&name
);
470 AlgorithmIdentifier alg
;
472 hret
= hx509_cert_get_SPKI_AlgorithmIdentifier(context
, cert
, &alg
);
474 ret
= CKR_DEVICE_MEMORY
;
478 key_type
= CKK_RSA
; /* XXX */
480 free_AlgorithmIdentifier(&alg
);
484 type
= CKO_CERTIFICATE
;
487 ret
= CKR_DEVICE_MEMORY
;
491 o
->cert
= hx509_cert_ref(cert
);
493 add_object_attribute(o
, 0, CKA_CLASS
, &type
, sizeof(type
));
494 add_object_attribute(o
, 0, CKA_TOKEN
, &bool_true
, sizeof(bool_true
));
495 add_object_attribute(o
, 0, CKA_PRIVATE
, &bool_false
, sizeof(bool_false
));
496 add_object_attribute(o
, 0, CKA_MODIFIABLE
, &bool_false
, sizeof(bool_false
));
497 add_object_attribute(o
, 0, CKA_LABEL
, foo
->label
, strlen(foo
->label
));
499 add_object_attribute(o
, 0, CKA_CERTIFICATE_TYPE
, &cert_type
, sizeof(cert_type
));
500 add_object_attribute(o
, 0, CKA_ID
, foo
->id
, strlen(foo
->id
));
502 add_object_attribute(o
, 0, CKA_SUBJECT
, subject_data
.data
, subject_data
.length
);
503 add_object_attribute(o
, 0, CKA_ISSUER
, issuer_data
.data
, issuer_data
.length
);
504 add_object_attribute(o
, 0, CKA_SERIAL_NUMBER
, serial_data
.data
, serial_data
.length
);
505 add_object_attribute(o
, 0, CKA_VALUE
, cert_data
.data
, cert_data
.length
);
506 add_object_attribute(o
, 0, CKA_TRUSTED
, &bool_false
, sizeof(bool_false
));
508 st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o
));
510 type
= CKO_PUBLIC_KEY
;
513 ret
= CKR_DEVICE_MEMORY
;
516 o
->cert
= hx509_cert_ref(cert
);
518 add_object_attribute(o
, 0, CKA_CLASS
, &type
, sizeof(type
));
519 add_object_attribute(o
, 0, CKA_TOKEN
, &bool_true
, sizeof(bool_true
));
520 add_object_attribute(o
, 0, CKA_PRIVATE
, &bool_false
, sizeof(bool_false
));
521 add_object_attribute(o
, 0, CKA_MODIFIABLE
, &bool_false
, sizeof(bool_false
));
522 add_object_attribute(o
, 0, CKA_LABEL
, foo
->label
, strlen(foo
->label
));
524 add_object_attribute(o
, 0, CKA_KEY_TYPE
, &key_type
, sizeof(key_type
));
525 add_object_attribute(o
, 0, CKA_ID
, foo
->id
, strlen(foo
->id
));
526 add_object_attribute(o
, 0, CKA_START_DATE
, empty
, 1); /* XXX */
527 add_object_attribute(o
, 0, CKA_END_DATE
, empty
, 1); /* XXX */
528 add_object_attribute(o
, 0, CKA_DERIVE
, &bool_false
, sizeof(bool_false
));
529 add_object_attribute(o
, 0, CKA_LOCAL
, &bool_false
, sizeof(bool_false
));
530 mech_type
= CKM_RSA_X_509
;
531 add_object_attribute(o
, 0, CKA_KEY_GEN_MECHANISM
, &mech_type
, sizeof(mech_type
));
533 add_object_attribute(o
, 0, CKA_SUBJECT
, subject_data
.data
, subject_data
.length
);
534 add_object_attribute(o
, 0, CKA_ENCRYPT
, &bool_true
, sizeof(bool_true
));
535 add_object_attribute(o
, 0, CKA_VERIFY
, &bool_true
, sizeof(bool_true
));
536 add_object_attribute(o
, 0, CKA_VERIFY_RECOVER
, &bool_false
, sizeof(bool_false
));
537 add_object_attribute(o
, 0, CKA_WRAP
, &bool_true
, sizeof(bool_true
));
538 add_object_attribute(o
, 0, CKA_TRUSTED
, &bool_true
, sizeof(bool_true
));
540 add_pubkey_info(hxctx
, o
, key_type
, cert
);
542 st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o
));
544 if (hx509_cert_have_private_key(cert
)) {
547 type
= CKO_PRIVATE_KEY
;
550 ret
= CKR_DEVICE_MEMORY
;
553 o
->cert
= hx509_cert_ref(cert
);
555 add_object_attribute(o
, 0, CKA_CLASS
, &type
, sizeof(type
));
556 add_object_attribute(o
, 0, CKA_TOKEN
, &bool_true
, sizeof(bool_true
));
557 add_object_attribute(o
, 0, CKA_PRIVATE
, &bool_true
, sizeof(bool_false
));
558 add_object_attribute(o
, 0, CKA_MODIFIABLE
, &bool_false
, sizeof(bool_false
));
559 add_object_attribute(o
, 0, CKA_LABEL
, foo
->label
, strlen(foo
->label
));
561 add_object_attribute(o
, 0, CKA_KEY_TYPE
, &key_type
, sizeof(key_type
));
562 add_object_attribute(o
, 0, CKA_ID
, foo
->id
, strlen(foo
->id
));
563 add_object_attribute(o
, 0, CKA_START_DATE
, empty
, 1); /* XXX */
564 add_object_attribute(o
, 0, CKA_END_DATE
, empty
, 1); /* XXX */
565 add_object_attribute(o
, 0, CKA_DERIVE
, &bool_false
, sizeof(bool_false
));
566 add_object_attribute(o
, 0, CKA_LOCAL
, &bool_false
, sizeof(bool_false
));
567 mech_type
= CKM_RSA_X_509
;
568 add_object_attribute(o
, 0, CKA_KEY_GEN_MECHANISM
, &mech_type
, sizeof(mech_type
));
570 add_object_attribute(o
, 0, CKA_SUBJECT
, subject_data
.data
, subject_data
.length
);
571 add_object_attribute(o
, 0, CKA_SENSITIVE
, &bool_true
, sizeof(bool_true
));
572 add_object_attribute(o
, 0, CKA_SECONDARY_AUTH
, &bool_false
, sizeof(bool_true
));
574 add_object_attribute(o
, 0, CKA_AUTH_PIN_FLAGS
, &flags
, sizeof(flags
));
576 add_object_attribute(o
, 0, CKA_DECRYPT
, &bool_true
, sizeof(bool_true
));
577 add_object_attribute(o
, 0, CKA_SIGN
, &bool_true
, sizeof(bool_true
));
578 add_object_attribute(o
, 0, CKA_SIGN_RECOVER
, &bool_false
, sizeof(bool_false
));
579 add_object_attribute(o
, 0, CKA_UNWRAP
, &bool_true
, sizeof(bool_true
));
580 add_object_attribute(o
, 0, CKA_EXTRACTABLE
, &bool_true
, sizeof(bool_true
));
581 add_object_attribute(o
, 0, CKA_NEVER_EXTRACTABLE
, &bool_false
, sizeof(bool_false
));
583 add_pubkey_info(hxctx
, o
, key_type
, cert
);
589 st_logf("something went wrong when adding cert!\n");
593 hx509_xfree(cert_data
.data
);
594 hx509_xfree(serial_data
.data
);
595 hx509_xfree(issuer_data
.data
);
596 hx509_xfree(subject_data
.data
);
602 add_certificate(const char *cert_file
,
608 hx509_lock lock
= NULL
;
616 flags
|= HX509_CERTS_UNPROTECT_ALL
;
620 asprintf(&str
, "PASS:%s", pin
);
622 hx509_lock_init(context
, &lock
);
623 hx509_lock_command_string(lock
, str
);
625 memset(str
, 0, strlen(str
));
629 ret
= hx509_certs_init(context
, cert_file
, flags
, lock
, &certs
);
631 st_logf("failed to open file %s\n", cert_file
);
632 return CKR_GENERAL_ERROR
;
635 ret
= hx509_certs_iter_f(context
, certs
, add_cert
, &foo
);
636 hx509_certs_free(&certs
);
638 st_logf("failed adding certs from file %s\n", cert_file
);
639 return CKR_GENERAL_ERROR
;
646 find_object_final(struct session_state
*state
)
648 if (state
->find
.attributes
) {
651 for (i
= 0; i
< state
->find
.num_attributes
; i
++) {
652 if (state
->find
.attributes
[i
].pValue
)
653 free(state
->find
.attributes
[i
].pValue
);
655 free(state
->find
.attributes
);
656 state
->find
.attributes
= NULL
;
657 state
->find
.num_attributes
= 0;
658 state
->find
.next_object
= -1;
663 reset_crypto_state(struct session_state
*state
)
665 state
->sign_object
= -1;
666 if (state
->sign_mechanism
)
667 free(state
->sign_mechanism
);
668 state
->sign_mechanism
= NULL_PTR
;
669 state
->verify_object
= -1;
670 if (state
->verify_mechanism
)
671 free(state
->verify_mechanism
);
672 state
->verify_mechanism
= NULL_PTR
;
676 close_session(struct session_state
*state
)
678 if (state
->find
.attributes
) {
679 application_error("application didn't do C_FindObjectsFinal\n");
680 find_object_final(state
);
683 state
->session_handle
= CK_INVALID_HANDLE
;
684 soft_token
.application
= NULL_PTR
;
685 soft_token
.notify
= NULL_PTR
;
686 reset_crypto_state(state
);
692 return soft_token
.open_sessions
> 0 ? "yes" : "no";
696 read_conf_file(const char *fn
, CK_USER_TYPE userType
, const char *pin
)
698 char buf
[1024], *type
, *s
, *p
;
701 CK_RV failed
= CKR_OK
;
704 st_logf("Can't open configuration file. No file specified\n");
705 return CKR_GENERAL_ERROR
;
710 st_logf("can't open configuration file %s\n", fn
);
711 return CKR_GENERAL_ERROR
;
715 while(fgets(buf
, sizeof(buf
), f
) != NULL
) {
716 buf
[strcspn(buf
, "\n")] = '\0';
718 st_logf("line: %s\n", buf
);
721 while (isspace((unsigned char)*p
))
725 while (isspace((unsigned char)*p
))
729 type
= strtok_r(p
, "\t", &s
);
733 if (strcasecmp("certificate", type
) == 0) {
734 char *cert
, *id
, *label
;
736 id
= strtok_r(NULL
, "\t", &s
);
741 st_logf("id: %s\n", id
);
742 label
= strtok_r(NULL
, "\t", &s
);
744 st_logf("no label\n");
747 cert
= strtok_r(NULL
, "\t", &s
);
749 st_logf("no certfiicate store\n");
753 st_logf("adding: %s: %s in file %s\n", id
, label
, cert
);
755 ret
= add_certificate(cert
, pin
, id
, label
);
758 } else if (strcasecmp("debug", type
) == 0) {
761 name
= strtok_r(NULL
, "\t", &s
);
763 st_logf("no filename\n");
767 if (soft_token
.logfile
)
768 fclose(soft_token
.logfile
);
770 if (strcasecmp(name
, "stdout") == 0)
771 soft_token
.logfile
= stdout
;
773 soft_token
.logfile
= fopen(name
, "a");
774 if (soft_token
.logfile
)
775 rk_cloexec_file(soft_token
.logfile
);
777 if (soft_token
.logfile
== NULL
)
778 st_logf("failed to open file: %s\n", name
);
780 } else if (strcasecmp("app-fatal", type
) == 0) {
783 name
= strtok_r(NULL
, "\t", &s
);
785 st_logf("argument to app-fatal\n");
789 if (strcmp(name
, "true") == 0 || strcmp(name
, "on") == 0)
790 soft_token
.flags
.app_error_fatal
= 1;
791 else if (strcmp(name
, "false") == 0 || strcmp(name
, "off") == 0)
792 soft_token
.flags
.app_error_fatal
= 0;
794 st_logf("unknown app-fatal: %s\n", name
);
797 st_logf("unknown type: %s\n", type
);
807 func_not_supported(void)
809 st_logf("function not supported\n");
810 return CKR_FUNCTION_NOT_SUPPORTED
;
814 get_config_file_for_user(void)
822 fn
= getenv("SOFTPKCS11RC");
825 home
= getenv("HOME");
827 if (fn
== NULL
&& home
== NULL
) {
828 struct passwd
*pw
= getpwuid(getuid());
834 asprintf(&fn
, "%s/.soft-token.rc", home
);
836 fn
= strdup("/etc/soft-token.rc");
840 char appdatafolder
[MAX_PATH
];
842 fn
= getenv("SOFTPKCS11RC");
844 /* Retrieve the roaming AppData folder for the current user. The
845 current user is the user account represented by the current
849 SUCCEEDED(SHGetFolderPath(NULL
, CSIDL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, appdatafolder
))) {
851 asprintf(&fn
, "%s\\.soft-token.rc", appdatafolder
);
861 C_Initialize(CK_VOID_PTR a
)
863 CK_C_INITIALIZE_ARGS_PTR args
= a
;
867 st_logf("Initialize\n");
871 OpenSSL_add_all_algorithms();
873 srandom(getpid() ^ (int) time(NULL
));
875 for (i
= 0; i
< MAX_NUM_SESSION
; i
++) {
876 soft_token
.state
[i
].session_handle
= CK_INVALID_HANDLE
;
877 soft_token
.state
[i
].find
.attributes
= NULL
;
878 soft_token
.state
[i
].find
.num_attributes
= 0;
879 soft_token
.state
[i
].find
.next_object
= -1;
880 reset_crypto_state(&soft_token
.state
[i
]);
883 soft_token
.flags
.hardware_slot
= 1;
884 soft_token
.flags
.app_error_fatal
= 0;
885 soft_token
.flags
.login_done
= 0;
887 soft_token
.object
.objs
= NULL
;
888 soft_token
.object
.num_objs
= 0;
890 soft_token
.logfile
= NULL
;
892 soft_token
.logfile
= stdout
;
895 soft_token
.logfile
= fopen("/tmp/log-pkcs11.txt", "a");
899 st_logf("\tCreateMutex:\t%p\n", args
->CreateMutex
);
900 st_logf("\tDestroyMutext\t%p\n", args
->DestroyMutex
);
901 st_logf("\tLockMutext\t%p\n", args
->LockMutex
);
902 st_logf("\tUnlockMutext\t%p\n", args
->UnlockMutex
);
903 st_logf("\tFlags\t%04x\n", (unsigned int)args
->flags
);
906 soft_token
.config_file
= get_config_file_for_user();
909 * This operations doesn't return CKR_OK if any of the
910 * certificates failes to be unparsed (ie password protected).
912 ret
= read_conf_file(soft_token
.config_file
, CKU_USER
, NULL
);
914 soft_token
.flags
.login_done
= 1;
920 C_Finalize(CK_VOID_PTR args
)
926 st_logf("Finalize\n");
928 for (i
= 0; i
< MAX_NUM_SESSION
; i
++) {
929 if (soft_token
.state
[i
].session_handle
!= CK_INVALID_HANDLE
) {
930 application_error("application finalized without "
931 "closing session\n");
932 close_session(&soft_token
.state
[i
]);
940 C_GetInfo(CK_INFO_PTR args
)
944 st_logf("GetInfo\n");
946 memset(args
, 17, sizeof(*args
));
947 args
->cryptokiVersion
.major
= 2;
948 args
->cryptokiVersion
.minor
= 10;
949 snprintf_fill((char *)args
->manufacturerID
,
950 sizeof(args
->manufacturerID
),
952 "Heimdal hx509 SoftToken");
953 snprintf_fill((char *)args
->libraryDescription
,
954 sizeof(args
->libraryDescription
), ' ',
955 "Heimdal hx509 SoftToken");
956 args
->libraryVersion
.major
= 2;
957 args
->libraryVersion
.minor
= 0;
962 extern CK_FUNCTION_LIST funcs
;
965 C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList
)
969 *ppFunctionList
= &funcs
;
974 C_GetSlotList(CK_BBOOL tokenPresent
,
975 CK_SLOT_ID_PTR pSlotList
,
976 CK_ULONG_PTR pulCount
)
979 st_logf("GetSlotList: %s\n",
980 tokenPresent
? "tokenPresent" : "token not Present");
988 C_GetSlotInfo(CK_SLOT_ID slotID
,
989 CK_SLOT_INFO_PTR pInfo
)
992 st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID
, has_session());
994 memset(pInfo
, 18, sizeof(*pInfo
));
997 return CKR_ARGUMENTS_BAD
;
999 snprintf_fill((char *)pInfo
->slotDescription
,
1000 sizeof(pInfo
->slotDescription
),
1002 "Heimdal hx509 SoftToken (slot)");
1003 snprintf_fill((char *)pInfo
->manufacturerID
,
1004 sizeof(pInfo
->manufacturerID
),
1006 "Heimdal hx509 SoftToken (slot)");
1007 pInfo
->flags
= CKF_TOKEN_PRESENT
;
1008 if (soft_token
.flags
.hardware_slot
)
1009 pInfo
->flags
|= CKF_HW_SLOT
;
1010 pInfo
->hardwareVersion
.major
= 1;
1011 pInfo
->hardwareVersion
.minor
= 0;
1012 pInfo
->firmwareVersion
.major
= 1;
1013 pInfo
->firmwareVersion
.minor
= 0;
1019 C_GetTokenInfo(CK_SLOT_ID slotID
,
1020 CK_TOKEN_INFO_PTR pInfo
)
1023 st_logf("GetTokenInfo: %s\n", has_session());
1025 memset(pInfo
, 19, sizeof(*pInfo
));
1027 snprintf_fill((char *)pInfo
->label
,
1028 sizeof(pInfo
->label
),
1030 "Heimdal hx509 SoftToken (token)");
1031 snprintf_fill((char *)pInfo
->manufacturerID
,
1032 sizeof(pInfo
->manufacturerID
),
1034 "Heimdal hx509 SoftToken (token)");
1035 snprintf_fill((char *)pInfo
->model
,
1036 sizeof(pInfo
->model
),
1038 "Heimdal hx509 SoftToken (token)");
1039 snprintf_fill((char *)pInfo
->serialNumber
,
1040 sizeof(pInfo
->serialNumber
),
1044 CKF_TOKEN_INITIALIZED
|
1045 CKF_USER_PIN_INITIALIZED
;
1047 if (soft_token
.flags
.login_done
== 0)
1048 pInfo
->flags
|= CKF_LOGIN_REQUIRED
;
1051 CKF_RESTORE_KEY_NOT_NEEDED |
1053 pInfo
->ulMaxSessionCount
= MAX_NUM_SESSION
;
1054 pInfo
->ulSessionCount
= soft_token
.open_sessions
;
1055 pInfo
->ulMaxRwSessionCount
= MAX_NUM_SESSION
;
1056 pInfo
->ulRwSessionCount
= soft_token
.open_sessions
;
1057 pInfo
->ulMaxPinLen
= 1024;
1058 pInfo
->ulMinPinLen
= 0;
1059 pInfo
->ulTotalPublicMemory
= 4711;
1060 pInfo
->ulFreePublicMemory
= 4712;
1061 pInfo
->ulTotalPrivateMemory
= 4713;
1062 pInfo
->ulFreePrivateMemory
= 4714;
1063 pInfo
->hardwareVersion
.major
= 2;
1064 pInfo
->hardwareVersion
.minor
= 0;
1065 pInfo
->firmwareVersion
.major
= 2;
1066 pInfo
->firmwareVersion
.minor
= 0;
1072 C_GetMechanismList(CK_SLOT_ID slotID
,
1073 CK_MECHANISM_TYPE_PTR pMechanismList
,
1074 CK_ULONG_PTR pulCount
)
1077 st_logf("GetMechanismList\n");
1080 if (pMechanismList
== NULL_PTR
)
1082 pMechanismList
[1] = CKM_RSA_PKCS
;
1088 C_GetMechanismInfo(CK_SLOT_ID slotID
,
1089 CK_MECHANISM_TYPE type
,
1090 CK_MECHANISM_INFO_PTR pInfo
)
1093 st_logf("GetMechanismInfo: slot %d type: %d\n",
1094 (int)slotID
, (int)type
);
1095 memset(pInfo
, 0, sizeof(*pInfo
));
1101 C_InitToken(CK_SLOT_ID slotID
,
1102 CK_UTF8CHAR_PTR pPin
,
1104 CK_UTF8CHAR_PTR pLabel
)
1107 st_logf("InitToken: slot %d\n", (int)slotID
);
1108 return CKR_FUNCTION_NOT_SUPPORTED
;
1112 C_OpenSession(CK_SLOT_ID slotID
,
1114 CK_VOID_PTR pApplication
,
1116 CK_SESSION_HANDLE_PTR phSession
)
1120 st_logf("OpenSession: slot: %d\n", (int)slotID
);
1122 if (soft_token
.open_sessions
== MAX_NUM_SESSION
)
1123 return CKR_SESSION_COUNT
;
1125 soft_token
.application
= pApplication
;
1126 soft_token
.notify
= Notify
;
1128 for (i
= 0; i
< MAX_NUM_SESSION
; i
++)
1129 if (soft_token
.state
[i
].session_handle
== CK_INVALID_HANDLE
)
1131 if (i
== MAX_NUM_SESSION
)
1134 soft_token
.open_sessions
++;
1136 soft_token
.state
[i
].session_handle
=
1137 (CK_SESSION_HANDLE
)(random() & 0xfffff);
1138 *phSession
= soft_token
.state
[i
].session_handle
;
1144 C_CloseSession(CK_SESSION_HANDLE hSession
)
1146 struct session_state
*state
;
1148 st_logf("CloseSession\n");
1150 if (verify_session_handle(hSession
, &state
) != CKR_OK
)
1151 application_error("closed session not open");
1153 close_session(state
);
1159 C_CloseAllSessions(CK_SLOT_ID slotID
)
1164 st_logf("CloseAllSessions\n");
1166 for (i
= 0; i
< MAX_NUM_SESSION
; i
++)
1167 if (soft_token
.state
[i
].session_handle
!= CK_INVALID_HANDLE
)
1168 close_session(&soft_token
.state
[i
]);
1174 C_GetSessionInfo(CK_SESSION_HANDLE hSession
,
1175 CK_SESSION_INFO_PTR pInfo
)
1177 st_logf("GetSessionInfo\n");
1180 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1182 memset(pInfo
, 20, sizeof(*pInfo
));
1185 if (soft_token
.flags
.login_done
)
1186 pInfo
->state
= CKS_RO_USER_FUNCTIONS
;
1188 pInfo
->state
= CKS_RO_PUBLIC_SESSION
;
1189 pInfo
->flags
= CKF_SERIAL_SESSION
;
1190 pInfo
->ulDeviceError
= 0;
1196 C_Login(CK_SESSION_HANDLE hSession
,
1197 CK_USER_TYPE userType
,
1198 CK_UTF8CHAR_PTR pPin
,
1207 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1209 if (pPin
!= NULL_PTR
) {
1210 asprintf(&pin
, "%.*s", (int)ulPinLen
, pPin
);
1211 st_logf("type: %d password: %s\n", (int)userType
, pin
);
1218 ret
= read_conf_file(soft_token
.config_file
, userType
, pin
);
1220 soft_token
.flags
.login_done
= 1;
1224 return soft_token
.flags
.login_done
? CKR_OK
: CKR_PIN_INCORRECT
;
1228 C_Logout(CK_SESSION_HANDLE hSession
)
1230 st_logf("Logout\n");
1233 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1234 return CKR_FUNCTION_NOT_SUPPORTED
;
1238 C_GetObjectSize(CK_SESSION_HANDLE hSession
,
1239 CK_OBJECT_HANDLE hObject
,
1240 CK_ULONG_PTR pulSize
)
1242 st_logf("GetObjectSize\n");
1245 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1246 return CKR_FUNCTION_NOT_SUPPORTED
;
1250 C_GetAttributeValue(CK_SESSION_HANDLE hSession
,
1251 CK_OBJECT_HANDLE hObject
,
1252 CK_ATTRIBUTE_PTR pTemplate
,
1255 struct session_state
*state
;
1256 struct st_object
*obj
;
1263 st_logf("GetAttributeValue: %lx\n",
1264 (unsigned long)HANDLE_OBJECT_ID(hObject
));
1265 VERIFY_SESSION_HANDLE(hSession
, &state
);
1267 if ((ret
= object_handle_to_object(hObject
, &obj
)) != CKR_OK
) {
1268 st_logf("object not found: %lx\n",
1269 (unsigned long)HANDLE_OBJECT_ID(hObject
));
1273 for (i
= 0; i
< ulCount
; i
++) {
1274 st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate
[i
].type
);
1275 for (j
= 0; j
< obj
->num_attributes
; j
++) {
1276 if (obj
->attrs
[j
].secret
) {
1277 pTemplate
[i
].ulValueLen
= (CK_ULONG
)-1;
1280 if (pTemplate
[i
].type
== obj
->attrs
[j
].attribute
.type
) {
1281 if (pTemplate
[i
].pValue
!= NULL_PTR
&& obj
->attrs
[j
].secret
== 0) {
1282 if (pTemplate
[i
].ulValueLen
>= obj
->attrs
[j
].attribute
.ulValueLen
)
1283 memcpy(pTemplate
[i
].pValue
, obj
->attrs
[j
].attribute
.pValue
,
1284 obj
->attrs
[j
].attribute
.ulValueLen
);
1286 pTemplate
[i
].ulValueLen
= obj
->attrs
[j
].attribute
.ulValueLen
;
1290 if (j
== obj
->num_attributes
) {
1291 st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate
[i
].type
);
1292 pTemplate
[i
].ulValueLen
= (CK_ULONG
)-1;
1300 C_FindObjectsInit(CK_SESSION_HANDLE hSession
,
1301 CK_ATTRIBUTE_PTR pTemplate
,
1304 struct session_state
*state
;
1306 st_logf("FindObjectsInit\n");
1310 VERIFY_SESSION_HANDLE(hSession
, &state
);
1312 if (state
->find
.next_object
!= -1) {
1313 application_error("application didn't do C_FindObjectsFinal\n");
1314 find_object_final(state
);
1319 print_attributes(pTemplate
, ulCount
);
1321 state
->find
.attributes
=
1322 calloc(1, ulCount
* sizeof(state
->find
.attributes
[0]));
1323 if (state
->find
.attributes
== NULL
)
1324 return CKR_DEVICE_MEMORY
;
1325 for (i
= 0; i
< ulCount
; i
++) {
1326 state
->find
.attributes
[i
].pValue
=
1327 malloc(pTemplate
[i
].ulValueLen
);
1328 if (state
->find
.attributes
[i
].pValue
== NULL
) {
1329 find_object_final(state
);
1330 return CKR_DEVICE_MEMORY
;
1332 memcpy(state
->find
.attributes
[i
].pValue
,
1333 pTemplate
[i
].pValue
, pTemplate
[i
].ulValueLen
);
1334 state
->find
.attributes
[i
].type
= pTemplate
[i
].type
;
1335 state
->find
.attributes
[i
].ulValueLen
= pTemplate
[i
].ulValueLen
;
1337 state
->find
.num_attributes
= ulCount
;
1338 state
->find
.next_object
= 0;
1340 st_logf("find all objects\n");
1341 state
->find
.attributes
= NULL
;
1342 state
->find
.num_attributes
= 0;
1343 state
->find
.next_object
= 0;
1350 C_FindObjects(CK_SESSION_HANDLE hSession
,
1351 CK_OBJECT_HANDLE_PTR phObject
,
1352 CK_ULONG ulMaxObjectCount
,
1353 CK_ULONG_PTR pulObjectCount
)
1355 struct session_state
*state
;
1360 st_logf("FindObjects\n");
1362 VERIFY_SESSION_HANDLE(hSession
, &state
);
1364 if (state
->find
.next_object
== -1) {
1365 application_error("application didn't do C_FindObjectsInit\n");
1366 return CKR_ARGUMENTS_BAD
;
1368 if (ulMaxObjectCount
== 0) {
1369 application_error("application asked for 0 objects\n");
1370 return CKR_ARGUMENTS_BAD
;
1372 *pulObjectCount
= 0;
1373 for (i
= state
->find
.next_object
; i
< soft_token
.object
.num_objs
; i
++) {
1374 st_logf("FindObjects: %d\n", i
);
1375 state
->find
.next_object
= i
+ 1;
1376 if (attributes_match(soft_token
.object
.objs
[i
],
1377 state
->find
.attributes
,
1378 state
->find
.num_attributes
)) {
1379 *phObject
++ = soft_token
.object
.objs
[i
]->object_handle
;
1381 (*pulObjectCount
)++;
1382 if (ulMaxObjectCount
== 0)
1390 C_FindObjectsFinal(CK_SESSION_HANDLE hSession
)
1392 struct session_state
*state
;
1396 st_logf("FindObjectsFinal\n");
1397 VERIFY_SESSION_HANDLE(hSession
, &state
);
1398 find_object_final(state
);
1403 commonInit(CK_ATTRIBUTE
*attr_match
, int attr_match_len
,
1404 const CK_MECHANISM_TYPE
*mechs
, int mechs_len
,
1405 const CK_MECHANISM_PTR pMechanism
, CK_OBJECT_HANDLE hKey
,
1406 struct st_object
**o
)
1412 if ((ret
= object_handle_to_object(hKey
, o
)) != CKR_OK
)
1415 ret
= attributes_match(*o
, attr_match
, attr_match_len
);
1417 application_error("called commonInit on key that doesn't "
1418 "support required attr");
1419 return CKR_ARGUMENTS_BAD
;
1422 for (i
= 0; i
< mechs_len
; i
++)
1423 if (mechs
[i
] == pMechanism
->mechanism
)
1425 if (i
== mechs_len
) {
1426 application_error("called mech (%08lx) not supported\n",
1427 pMechanism
->mechanism
);
1428 return CKR_ARGUMENTS_BAD
;
1435 dup_mechanism(CK_MECHANISM_PTR
*dp
, const CK_MECHANISM_PTR pMechanism
)
1439 p
= malloc(sizeof(*p
));
1441 return CKR_DEVICE_MEMORY
;
1446 memcpy(p
, pMechanism
, sizeof(*p
));
1452 C_DigestInit(CK_SESSION_HANDLE hSession
,
1453 CK_MECHANISM_PTR pMechanism
)
1455 st_logf("DigestInit\n");
1457 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1458 return CKR_FUNCTION_NOT_SUPPORTED
;
1462 C_SignInit(CK_SESSION_HANDLE hSession
,
1463 CK_MECHANISM_PTR pMechanism
,
1464 CK_OBJECT_HANDLE hKey
)
1466 struct session_state
*state
;
1467 CK_MECHANISM_TYPE mechs
[] = { CKM_RSA_PKCS
};
1468 CK_BBOOL bool_true
= CK_TRUE
;
1469 CK_ATTRIBUTE attr
[] = {
1470 { CKA_SIGN
, &bool_true
, sizeof(bool_true
) }
1472 struct st_object
*o
;
1476 st_logf("SignInit\n");
1477 VERIFY_SESSION_HANDLE(hSession
, &state
);
1479 ret
= commonInit(attr
, sizeof(attr
)/sizeof(attr
[0]),
1480 mechs
, sizeof(mechs
)/sizeof(mechs
[0]),
1481 pMechanism
, hKey
, &o
);
1485 ret
= dup_mechanism(&state
->sign_mechanism
, pMechanism
);
1487 state
->sign_object
= OBJECT_ID(o
);
1493 C_Sign(CK_SESSION_HANDLE hSession
,
1496 CK_BYTE_PTR pSignature
,
1497 CK_ULONG_PTR pulSignatureLen
)
1499 struct session_state
*state
;
1500 struct st_object
*o
;
1503 const AlgorithmIdentifier
*alg
;
1504 heim_octet_string sig
, data
;
1508 VERIFY_SESSION_HANDLE(hSession
, &state
);
1513 if (state
->sign_object
== -1)
1514 return CKR_ARGUMENTS_BAD
;
1516 if (pulSignatureLen
== NULL
) {
1517 st_logf("signature len NULL\n");
1518 ret
= CKR_ARGUMENTS_BAD
;
1522 if (pData
== NULL_PTR
) {
1523 st_logf("data NULL\n");
1524 ret
= CKR_ARGUMENTS_BAD
;
1528 o
= soft_token
.object
.objs
[state
->sign_object
];
1530 if (hx509_cert_have_private_key(o
->cert
) == 0) {
1531 st_logf("private key NULL\n");
1532 return CKR_ARGUMENTS_BAD
;
1535 switch(state
->sign_mechanism
->mechanism
) {
1537 alg
= hx509_signature_rsa_pkcs1_x509();
1540 ret
= CKR_FUNCTION_NOT_SUPPORTED
;
1545 data
.length
= ulDataLen
;
1547 hret
= _hx509_create_signature(context
,
1548 _hx509_cert_private_key(o
->cert
),
1554 ret
= CKR_DEVICE_ERROR
;
1557 *pulSignatureLen
= sig
.length
;
1559 if (pSignature
!= NULL_PTR
)
1560 memcpy(pSignature
, sig
.data
, sig
.length
);
1565 memset(sig
.data
, 0, sig
.length
);
1566 der_free_octet_string(&sig
);
1572 C_SignUpdate(CK_SESSION_HANDLE hSession
,
1577 st_logf("SignUpdate\n");
1578 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1579 return CKR_FUNCTION_NOT_SUPPORTED
;
1584 C_SignFinal(CK_SESSION_HANDLE hSession
,
1585 CK_BYTE_PTR pSignature
,
1586 CK_ULONG_PTR pulSignatureLen
)
1589 st_logf("SignUpdate\n");
1590 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1591 return CKR_FUNCTION_NOT_SUPPORTED
;
1595 C_VerifyInit(CK_SESSION_HANDLE hSession
,
1596 CK_MECHANISM_PTR pMechanism
,
1597 CK_OBJECT_HANDLE hKey
)
1599 struct session_state
*state
;
1600 CK_MECHANISM_TYPE mechs
[] = { CKM_RSA_PKCS
};
1601 CK_BBOOL bool_true
= CK_TRUE
;
1602 CK_ATTRIBUTE attr
[] = {
1603 { CKA_VERIFY
, &bool_true
, sizeof(bool_true
) }
1605 struct st_object
*o
;
1609 st_logf("VerifyInit\n");
1610 VERIFY_SESSION_HANDLE(hSession
, &state
);
1612 ret
= commonInit(attr
, sizeof(attr
)/sizeof(attr
[0]),
1613 mechs
, sizeof(mechs
)/sizeof(mechs
[0]),
1614 pMechanism
, hKey
, &o
);
1618 ret
= dup_mechanism(&state
->verify_mechanism
, pMechanism
);
1620 state
->verify_object
= OBJECT_ID(o
);
1626 C_Verify(CK_SESSION_HANDLE hSession
,
1629 CK_BYTE_PTR pSignature
,
1630 CK_ULONG ulSignatureLen
)
1632 struct session_state
*state
;
1633 struct st_object
*o
;
1634 const AlgorithmIdentifier
*alg
;
1637 heim_octet_string data
, sig
;
1640 st_logf("Verify\n");
1641 VERIFY_SESSION_HANDLE(hSession
, &state
);
1643 if (state
->verify_object
== -1)
1644 return CKR_ARGUMENTS_BAD
;
1646 o
= soft_token
.object
.objs
[state
->verify_object
];
1648 switch(state
->verify_mechanism
->mechanism
) {
1650 alg
= hx509_signature_rsa_pkcs1_x509();
1653 ret
= CKR_FUNCTION_NOT_SUPPORTED
;
1658 sig
.length
= ulDataLen
;
1659 data
.data
= pSignature
;
1660 data
.length
= ulSignatureLen
;
1662 hret
= _hx509_verify_signature(context
,
1668 ret
= CKR_GENERAL_ERROR
;
1679 C_VerifyUpdate(CK_SESSION_HANDLE hSession
,
1684 st_logf("VerifyUpdate\n");
1685 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1686 return CKR_FUNCTION_NOT_SUPPORTED
;
1690 C_VerifyFinal(CK_SESSION_HANDLE hSession
,
1691 CK_BYTE_PTR pSignature
,
1692 CK_ULONG ulSignatureLen
)
1695 st_logf("VerifyFinal\n");
1696 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1697 return CKR_FUNCTION_NOT_SUPPORTED
;
1701 C_GenerateRandom(CK_SESSION_HANDLE hSession
,
1702 CK_BYTE_PTR RandomData
,
1703 CK_ULONG ulRandomLen
)
1706 st_logf("GenerateRandom\n");
1707 VERIFY_SESSION_HANDLE(hSession
, NULL
);
1708 return CKR_FUNCTION_NOT_SUPPORTED
;
1712 CK_FUNCTION_LIST funcs
= {
1724 (void *)func_not_supported
, /* C_InitPIN */
1725 (void *)func_not_supported
, /* C_SetPIN */
1730 (void *)func_not_supported
, /* C_GetOperationState */
1731 (void *)func_not_supported
, /* C_SetOperationState */
1734 (void *)func_not_supported
, /* C_CreateObject */
1735 (void *)func_not_supported
, /* C_CopyObject */
1736 (void *)func_not_supported
, /* C_DestroyObject */
1737 (void *)func_not_supported
, /* C_GetObjectSize */
1738 C_GetAttributeValue
,
1739 (void *)func_not_supported
, /* C_SetAttributeValue */
1743 (void *)func_not_supported
, /* C_EncryptInit, */
1744 (void *)func_not_supported
, /* C_Encrypt, */
1745 (void *)func_not_supported
, /* C_EncryptUpdate, */
1746 (void *)func_not_supported
, /* C_EncryptFinal, */
1747 (void *)func_not_supported
, /* C_DecryptInit, */
1748 (void *)func_not_supported
, /* C_Decrypt, */
1749 (void *)func_not_supported
, /* C_DecryptUpdate, */
1750 (void *)func_not_supported
, /* C_DecryptFinal, */
1752 (void *)func_not_supported
, /* C_Digest */
1753 (void *)func_not_supported
, /* C_DigestUpdate */
1754 (void *)func_not_supported
, /* C_DigestKey */
1755 (void *)func_not_supported
, /* C_DigestFinal */
1760 (void *)func_not_supported
, /* C_SignRecoverInit */
1761 (void *)func_not_supported
, /* C_SignRecover */
1766 (void *)func_not_supported
, /* C_VerifyRecoverInit */
1767 (void *)func_not_supported
, /* C_VerifyRecover */
1768 (void *)func_not_supported
, /* C_DigestEncryptUpdate */
1769 (void *)func_not_supported
, /* C_DecryptDigestUpdate */
1770 (void *)func_not_supported
, /* C_SignEncryptUpdate */
1771 (void *)func_not_supported
, /* C_DecryptVerifyUpdate */
1772 (void *)func_not_supported
, /* C_GenerateKey */
1773 (void *)func_not_supported
, /* C_GenerateKeyPair */
1774 (void *)func_not_supported
, /* C_WrapKey */
1775 (void *)func_not_supported
, /* C_UnwrapKey */
1776 (void *)func_not_supported
, /* C_DeriveKey */
1777 (void *)func_not_supported
, /* C_SeedRandom */
1779 (void *)func_not_supported
, /* C_GetFunctionStatus */
1780 (void *)func_not_supported
, /* C_CancelFunction */
1781 (void *)func_not_supported
/* C_WaitForSlotEvent */