|
Line 0
Link Here
|
|
|
1 |
/* |
| 2 |
* Copyright (c) 2004-2006, Stockholms universitet |
| 3 |
* (Stockholm University, Stockholm Sweden) |
| 4 |
* All rights reserved. |
| 5 |
* |
| 6 |
* Redistribution and use in source and binary forms, with or without |
| 7 |
* modification, are permitted provided that the following conditions |
| 8 |
* are met: |
| 9 |
* |
| 10 |
* 1. Redistributions of source code must retain the above copyright |
| 11 |
* notice, this list of conditions and the following disclaimer. |
| 12 |
* |
| 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. |
| 16 |
* |
| 17 |
* 3. Neither the name of the university 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. |
| 20 |
* |
| 21 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 22 |
* AND 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 COPYRIGHT OWNER OR CONTRIBUTORS BE |
| 25 |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 26 |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 27 |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 28 |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 29 |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 30 |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 31 |
* POSSIBILITY OF SUCH DAMAGE. |
| 32 |
*/ |
| 33 |
|
| 34 |
#include "locl.h" |
| 35 |
|
| 36 |
/* RCSID("$Id: main.c,v 1.24 2006/01/11 12:42:53 lha Exp $"); */ |
| 37 |
|
| 38 |
#define OBJECT_ID_MASK 0xfff |
| 39 |
#define HANDLE_OBJECT_ID(h) ((h) & OBJECT_ID_MASK) |
| 40 |
#define OBJECT_ID(obj) HANDLE_OBJECT_ID((obj)->object_handle) |
| 41 |
|
| 42 |
#if OPENSSL_VERSION_NUMBER < 0x10100000L |
| 43 |
#define RSA_PKCS1_SSLeay RSA_PKCS1_OpenSSL |
| 44 |
#endif |
| 45 |
|
| 46 |
struct st_attr { |
| 47 |
CK_ATTRIBUTE attribute; |
| 48 |
int secret; |
| 49 |
}; |
| 50 |
|
| 51 |
struct st_object { |
| 52 |
CK_OBJECT_HANDLE object_handle; |
| 53 |
struct st_attr *attrs; |
| 54 |
int num_attributes; |
| 55 |
enum { |
| 56 |
STO_T_CERTIFICATE, |
| 57 |
STO_T_PRIVATE_KEY, |
| 58 |
STO_T_PUBLIC_KEY |
| 59 |
} type; |
| 60 |
union { |
| 61 |
X509 *cert; |
| 62 |
EVP_PKEY *public_key; |
| 63 |
struct { |
| 64 |
const char *file; |
| 65 |
EVP_PKEY *key; |
| 66 |
X509 *cert; |
| 67 |
} private_key; |
| 68 |
} u; |
| 69 |
}; |
| 70 |
|
| 71 |
static struct soft_token { |
| 72 |
CK_VOID_PTR application; |
| 73 |
CK_NOTIFY notify; |
| 74 |
struct { |
| 75 |
struct st_object **objs; |
| 76 |
int num_objs; |
| 77 |
} object; |
| 78 |
struct { |
| 79 |
int hardware_slot; |
| 80 |
int app_error_fatal; |
| 81 |
int login_done; |
| 82 |
} flags; |
| 83 |
int open_sessions; |
| 84 |
struct session_state { |
| 85 |
CK_SESSION_HANDLE session_handle; |
| 86 |
|
| 87 |
struct { |
| 88 |
CK_ATTRIBUTE *attributes; |
| 89 |
CK_ULONG num_attributes; |
| 90 |
int next_object; |
| 91 |
} find; |
| 92 |
|
| 93 |
int encrypt_object; |
| 94 |
CK_MECHANISM_PTR encrypt_mechanism; |
| 95 |
int decrypt_object; |
| 96 |
CK_MECHANISM_PTR decrypt_mechanism; |
| 97 |
int sign_object; |
| 98 |
CK_MECHANISM_PTR sign_mechanism; |
| 99 |
int verify_object; |
| 100 |
CK_MECHANISM_PTR verify_mechanism; |
| 101 |
int digest_object; |
| 102 |
} state[10]; |
| 103 |
#define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0])) |
| 104 |
FILE *logfile; |
| 105 |
} soft_token; |
| 106 |
|
| 107 |
static void |
| 108 |
application_error(const char *fmt, ...) |
| 109 |
{ |
| 110 |
va_list ap; |
| 111 |
va_start(ap, fmt); |
| 112 |
vprintf(fmt, ap); |
| 113 |
va_end(ap); |
| 114 |
if (soft_token.flags.app_error_fatal) |
| 115 |
abort(); |
| 116 |
} |
| 117 |
|
| 118 |
static void |
| 119 |
st_logf(const char *fmt, ...) |
| 120 |
{ |
| 121 |
va_list ap; |
| 122 |
if (soft_token.logfile == NULL) |
| 123 |
return; |
| 124 |
va_start(ap, fmt); |
| 125 |
vfprintf(soft_token.logfile, fmt, ap); |
| 126 |
va_end(ap); |
| 127 |
fflush(soft_token.logfile); |
| 128 |
} |
| 129 |
|
| 130 |
static void |
| 131 |
snprintf_fill(char *str, size_t size, char fillchar, const char *fmt, ...) |
| 132 |
{ |
| 133 |
int len; |
| 134 |
va_list ap; |
| 135 |
len = vsnprintf(str, size, fmt, ap); |
| 136 |
va_end(ap); |
| 137 |
if (len < 0 || len > (int) size) |
| 138 |
return; |
| 139 |
while(len < (int) size) |
| 140 |
str[len++] = fillchar; |
| 141 |
} |
| 142 |
|
| 143 |
#ifndef TEST_APP |
| 144 |
#define printf error_use_st_logf |
| 145 |
#endif |
| 146 |
|
| 147 |
#define VERIFY_SESSION_HANDLE(s, state) \ |
| 148 |
{ \ |
| 149 |
CK_RV ret; \ |
| 150 |
ret = verify_session_handle(s, state); \ |
| 151 |
if (ret != CKR_OK) { \ |
| 152 |
/* return CKR_OK */; \ |
| 153 |
} \ |
| 154 |
} |
| 155 |
|
| 156 |
static CK_RV |
| 157 |
verify_session_handle(CK_SESSION_HANDLE hSession, |
| 158 |
struct session_state **state) |
| 159 |
{ |
| 160 |
size_t i; |
| 161 |
|
| 162 |
for (i = 0; i < MAX_NUM_SESSION; i++){ |
| 163 |
if (soft_token.state[i].session_handle == hSession) |
| 164 |
break; |
| 165 |
} |
| 166 |
if (i == MAX_NUM_SESSION) { |
| 167 |
application_error("use of invalid handle: 0x%08lx\n", |
| 168 |
(unsigned long)hSession); |
| 169 |
return CKR_SESSION_HANDLE_INVALID; |
| 170 |
} |
| 171 |
if (state) |
| 172 |
*state = &soft_token.state[i]; |
| 173 |
return CKR_OK; |
| 174 |
} |
| 175 |
|
| 176 |
static CK_RV |
| 177 |
object_handle_to_object(CK_OBJECT_HANDLE handle, |
| 178 |
struct st_object **object) |
| 179 |
{ |
| 180 |
int i = HANDLE_OBJECT_ID(handle); |
| 181 |
|
| 182 |
*object = NULL; |
| 183 |
if (i >= soft_token.object.num_objs) |
| 184 |
return CKR_ARGUMENTS_BAD; |
| 185 |
if (soft_token.object.objs[i] == NULL) |
| 186 |
return CKR_ARGUMENTS_BAD; |
| 187 |
if (soft_token.object.objs[i]->object_handle != handle) |
| 188 |
return CKR_ARGUMENTS_BAD; |
| 189 |
*object = soft_token.object.objs[i]; |
| 190 |
return CKR_OK; |
| 191 |
} |
| 192 |
|
| 193 |
static int |
| 194 |
attributes_match(const struct st_object *obj, |
| 195 |
const CK_ATTRIBUTE *attributes, |
| 196 |
CK_ULONG num_attributes) |
| 197 |
{ |
| 198 |
CK_ULONG i; |
| 199 |
int j; |
| 200 |
st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj)); |
| 201 |
|
| 202 |
for (i = 0; i < num_attributes; i++) { |
| 203 |
int match = 0; |
| 204 |
for (j = 0; j < obj->num_attributes; j++) { |
| 205 |
if (attributes[i].type == obj->attrs[j].attribute.type && |
| 206 |
attributes[i].ulValueLen == obj->attrs[j].attribute.ulValueLen && |
| 207 |
memcmp(attributes[i].pValue, obj->attrs[j].attribute.pValue, |
| 208 |
attributes[i].ulValueLen) == 0) { |
| 209 |
match = 1; |
| 210 |
break; |
| 211 |
} |
| 212 |
} |
| 213 |
if (match == 0) { |
| 214 |
st_logf("type %d attribute have no match\n", attributes[i].type); |
| 215 |
return 0; |
| 216 |
} |
| 217 |
} |
| 218 |
st_logf("attribute matches\n"); |
| 219 |
return 1; |
| 220 |
} |
| 221 |
|
| 222 |
static void |
| 223 |
print_attributes(const CK_ATTRIBUTE *attributes, |
| 224 |
CK_ULONG num_attributes) |
| 225 |
{ |
| 226 |
CK_ULONG i; |
| 227 |
|
| 228 |
st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes); |
| 229 |
|
| 230 |
for (i = 0; i < num_attributes; i++) { |
| 231 |
st_logf(" type: "); |
| 232 |
switch (attributes[i].type) { |
| 233 |
case CKA_TOKEN: { |
| 234 |
CK_BBOOL *ck_true; |
| 235 |
if (attributes[i].ulValueLen != sizeof(CK_BBOOL)) { |
| 236 |
application_error("token attribute wrong length\n"); |
| 237 |
break; |
| 238 |
} |
| 239 |
ck_true = attributes[i].pValue; |
| 240 |
st_logf("token: %s", *ck_true ? "TRUE" : "FALSE"); |
| 241 |
break; |
| 242 |
} |
| 243 |
case CKA_CLASS: { |
| 244 |
CK_OBJECT_CLASS *class; |
| 245 |
if (attributes[i].ulValueLen != sizeof(CK_ULONG)) { |
| 246 |
application_error("class attribute wrong length\n"); |
| 247 |
break; |
| 248 |
} |
| 249 |
class = attributes[i].pValue; |
| 250 |
st_logf("class "); |
| 251 |
switch (*class) { |
| 252 |
case CKO_CERTIFICATE: |
| 253 |
st_logf("certificate"); |
| 254 |
break; |
| 255 |
case CKO_PUBLIC_KEY: |
| 256 |
st_logf("public key"); |
| 257 |
break; |
| 258 |
case CKO_PRIVATE_KEY: |
| 259 |
st_logf("private key"); |
| 260 |
break; |
| 261 |
case CKO_SECRET_KEY: |
| 262 |
st_logf("secret key"); |
| 263 |
break; |
| 264 |
case CKO_DOMAIN_PARAMETERS: |
| 265 |
st_logf("domain parameters"); |
| 266 |
break; |
| 267 |
default: |
| 268 |
st_logf("[class %lx]", (long unsigned)*class); |
| 269 |
break; |
| 270 |
} |
| 271 |
break; |
| 272 |
} |
| 273 |
case CKA_PRIVATE: |
| 274 |
st_logf("private"); |
| 275 |
break; |
| 276 |
case CKA_LABEL: |
| 277 |
st_logf("label"); |
| 278 |
break; |
| 279 |
case CKA_APPLICATION: |
| 280 |
st_logf("application"); |
| 281 |
break; |
| 282 |
case CKA_VALUE: |
| 283 |
st_logf("value"); |
| 284 |
break; |
| 285 |
case CKA_ID: |
| 286 |
st_logf("id"); |
| 287 |
break; |
| 288 |
default: |
| 289 |
st_logf("[unknown 0x%08lx]", (unsigned long)attributes[i].type); |
| 290 |
break; |
| 291 |
} |
| 292 |
st_logf("\n"); |
| 293 |
} |
| 294 |
} |
| 295 |
|
| 296 |
static struct st_object * |
| 297 |
add_st_object(void) |
| 298 |
{ |
| 299 |
struct st_object *o, **objs; |
| 300 |
int i; |
| 301 |
|
| 302 |
o = malloc(sizeof(*o)); |
| 303 |
if (o == NULL) |
| 304 |
return NULL; |
| 305 |
memset(o, 0, sizeof(*o)); |
| 306 |
o->attrs = NULL; |
| 307 |
o->num_attributes = 0; |
| 308 |
|
| 309 |
for (i = 0; i < soft_token.object.num_objs; i++) { |
| 310 |
if (soft_token.object.objs == NULL) { |
| 311 |
soft_token.object.objs[i] = o; |
| 312 |
break; |
| 313 |
} |
| 314 |
} |
| 315 |
if (i == soft_token.object.num_objs) { |
| 316 |
objs = realloc(soft_token.object.objs, |
| 317 |
(soft_token.object.num_objs + 1) * sizeof(soft_token.object.objs[0])); |
| 318 |
if (objs == NULL) { |
| 319 |
free(o); |
| 320 |
return NULL; |
| 321 |
} |
| 322 |
soft_token.object.objs = objs; |
| 323 |
soft_token.object.objs[soft_token.object.num_objs++] = o; |
| 324 |
} |
| 325 |
soft_token.object.objs[i]->object_handle = |
| 326 |
(random() & (~OBJECT_ID_MASK)) | i; |
| 327 |
|
| 328 |
return o; |
| 329 |
} |
| 330 |
|
| 331 |
static CK_RV |
| 332 |
add_object_attribute(struct st_object *o, |
| 333 |
int secret, |
| 334 |
CK_ATTRIBUTE_TYPE type, |
| 335 |
CK_VOID_PTR pValue, |
| 336 |
CK_ULONG ulValueLen) |
| 337 |
{ |
| 338 |
struct st_attr *a; |
| 339 |
int i; |
| 340 |
|
| 341 |
i = o->num_attributes; |
| 342 |
a = realloc(o->attrs, (i + 1) * sizeof(o->attrs[0])); |
| 343 |
if (a == NULL) |
| 344 |
return CKR_DEVICE_MEMORY; |
| 345 |
o->attrs = a; |
| 346 |
o->attrs[i].secret = secret; |
| 347 |
o->attrs[i].attribute.type = type; |
| 348 |
o->attrs[i].attribute.pValue = malloc(ulValueLen); |
| 349 |
if (o->attrs[i].attribute.pValue == NULL && ulValueLen != 0) |
| 350 |
return CKR_DEVICE_MEMORY; |
| 351 |
memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen); |
| 352 |
o->attrs[i].attribute.ulValueLen = ulValueLen; |
| 353 |
o->num_attributes++; |
| 354 |
|
| 355 |
return CKR_OK; |
| 356 |
} |
| 357 |
|
| 358 |
static CK_RV |
| 359 |
add_pubkey_info(struct st_object *o, CK_KEY_TYPE key_type, EVP_PKEY *key) |
| 360 |
{ |
| 361 |
switch (key_type) { |
| 362 |
case CKK_RSA: { |
| 363 |
CK_BYTE *modulus = NULL; |
| 364 |
size_t modulus_len = 0; |
| 365 |
CK_ULONG modulus_bits = 0; |
| 366 |
CK_BYTE *exponent = NULL; |
| 367 |
size_t exponent_len = 0; |
| 368 |
RSA* rsa = NULL; |
| 369 |
const BIGNUM *n = NULL, *e = NULL; |
| 370 |
|
| 371 |
rsa = EVP_PKEY_get0_RSA(key); |
| 372 |
RSA_get0_key(rsa, &n, &e, NULL); |
| 373 |
|
| 374 |
modulus_bits = BN_num_bits(n); |
| 375 |
|
| 376 |
modulus_len = BN_num_bytes(n); |
| 377 |
modulus = malloc(modulus_len); |
| 378 |
BN_bn2bin(n, modulus); |
| 379 |
|
| 380 |
exponent_len = BN_num_bytes(e); |
| 381 |
exponent = malloc(exponent_len); |
| 382 |
BN_bn2bin(e, exponent); |
| 383 |
|
| 384 |
add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len); |
| 385 |
add_object_attribute(o, 0, CKA_MODULUS_BITS, |
| 386 |
&modulus_bits, sizeof(modulus_bits)); |
| 387 |
add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT, |
| 388 |
exponent, exponent_len); |
| 389 |
|
| 390 |
RSA_set_method(rsa, RSA_PKCS1_OpenSSL()); |
| 391 |
|
| 392 |
free(modulus); |
| 393 |
free(exponent); |
| 394 |
} |
| 395 |
default: |
| 396 |
/* XXX */ |
| 397 |
break; |
| 398 |
} |
| 399 |
return CKR_OK; |
| 400 |
} |
| 401 |
|
| 402 |
|
| 403 |
static int |
| 404 |
pem_callback(char *buf, int num, int w, void *key) |
| 405 |
{ |
| 406 |
return -1; |
| 407 |
} |
| 408 |
|
| 409 |
|
| 410 |
static CK_RV |
| 411 |
add_certificate(char *label, |
| 412 |
const char *cert_file, |
| 413 |
const char *private_key_file, |
| 414 |
char *id, |
| 415 |
int anchor) |
| 416 |
{ |
| 417 |
struct st_object *o = NULL; |
| 418 |
CK_BBOOL bool_true = CK_TRUE; |
| 419 |
CK_BBOOL bool_false = CK_FALSE; |
| 420 |
CK_OBJECT_CLASS c; |
| 421 |
CK_CERTIFICATE_TYPE cert_type = CKC_X_509; |
| 422 |
CK_KEY_TYPE key_type; |
| 423 |
CK_MECHANISM_TYPE mech_type; |
| 424 |
void *cert_data = NULL; |
| 425 |
size_t cert_length; |
| 426 |
void *subject_data = NULL; |
| 427 |
size_t subject_length; |
| 428 |
void *issuer_data = NULL; |
| 429 |
size_t issuer_length; |
| 430 |
void *serial_data = NULL; |
| 431 |
size_t serial_length; |
| 432 |
CK_RV ret = CKR_GENERAL_ERROR; |
| 433 |
X509 *cert; |
| 434 |
EVP_PKEY *public_key; |
| 435 |
|
| 436 |
size_t id_len = strlen(id); |
| 437 |
|
| 438 |
{ |
| 439 |
FILE *f; |
| 440 |
|
| 441 |
f = fopen(cert_file, "r"); |
| 442 |
if (f == NULL) { |
| 443 |
st_logf("failed to open file %s\n", cert_file); |
| 444 |
return CKR_GENERAL_ERROR; |
| 445 |
} |
| 446 |
|
| 447 |
cert = PEM_read_X509(f, NULL, NULL, NULL); |
| 448 |
fclose(f); |
| 449 |
if (cert == NULL) { |
| 450 |
st_logf("failed reading PEM cert\n"); |
| 451 |
return CKR_GENERAL_ERROR; |
| 452 |
} |
| 453 |
|
| 454 |
OPENSSL_ASN1_MALLOC_ENCODE(X509, cert_data, cert_length, cert, ret); |
| 455 |
if (ret) |
| 456 |
goto out; |
| 457 |
|
| 458 |
OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, issuer_data, issuer_length, |
| 459 |
X509_get_issuer_name(cert), ret); |
| 460 |
if (ret) |
| 461 |
goto out; |
| 462 |
|
| 463 |
OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, subject_data, subject_length, |
| 464 |
X509_get_subject_name(cert), ret); |
| 465 |
if (ret) |
| 466 |
goto out; |
| 467 |
|
| 468 |
OPENSSL_ASN1_MALLOC_ENCODE(ASN1_INTEGER, serial_data, serial_length, |
| 469 |
X509_get_serialNumber(cert), ret); |
| 470 |
if (ret) |
| 471 |
goto out; |
| 472 |
|
| 473 |
} |
| 474 |
|
| 475 |
st_logf("done parsing, adding to internal structure\n"); |
| 476 |
|
| 477 |
o = add_st_object(); |
| 478 |
if (o == NULL) { |
| 479 |
ret = CKR_DEVICE_MEMORY; |
| 480 |
goto out; |
| 481 |
} |
| 482 |
o->type = STO_T_CERTIFICATE; |
| 483 |
o->u.cert = cert; |
| 484 |
public_key = X509_get_pubkey(o->u.cert); |
| 485 |
|
| 486 |
switch (EVP_PKEY_base_id(public_key)) { |
| 487 |
case EVP_PKEY_RSA: |
| 488 |
key_type = CKK_RSA; |
| 489 |
break; |
| 490 |
case EVP_PKEY_DSA: |
| 491 |
key_type = CKK_DSA; |
| 492 |
break; |
| 493 |
default: |
| 494 |
/* XXX */ |
| 495 |
break; |
| 496 |
} |
| 497 |
|
| 498 |
c = CKO_CERTIFICATE; |
| 499 |
add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c)); |
| 500 |
add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true)); |
| 501 |
add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false)); |
| 502 |
add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false)); |
| 503 |
add_object_attribute(o, 0, CKA_LABEL, label, strlen(label)); |
| 504 |
|
| 505 |
add_object_attribute(o, 0, CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type)); |
| 506 |
add_object_attribute(o, 0, CKA_ID, id, id_len); |
| 507 |
|
| 508 |
add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length); |
| 509 |
add_object_attribute(o, 0, CKA_ISSUER, issuer_data, issuer_length); |
| 510 |
add_object_attribute(o, 0, CKA_SERIAL_NUMBER, serial_data, serial_length); |
| 511 |
add_object_attribute(o, 0, CKA_VALUE, cert_data, cert_length); |
| 512 |
if (anchor) |
| 513 |
add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true)); |
| 514 |
else |
| 515 |
add_object_attribute(o, 0, CKA_TRUSTED, &bool_false, sizeof(bool_false)); |
| 516 |
|
| 517 |
st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o)); |
| 518 |
|
| 519 |
o = add_st_object(); |
| 520 |
if (o == NULL) { |
| 521 |
ret = CKR_DEVICE_MEMORY; |
| 522 |
goto out; |
| 523 |
} |
| 524 |
o->type = STO_T_PUBLIC_KEY; |
| 525 |
o->u.public_key = public_key; |
| 526 |
|
| 527 |
c = CKO_PUBLIC_KEY; |
| 528 |
add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c)); |
| 529 |
add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true)); |
| 530 |
add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false)); |
| 531 |
add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false)); |
| 532 |
add_object_attribute(o, 0, CKA_LABEL, label, strlen(label)); |
| 533 |
|
| 534 |
add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type)); |
| 535 |
add_object_attribute(o, 0, CKA_ID, id, id_len); |
| 536 |
add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */ |
| 537 |
add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */ |
| 538 |
add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false)); |
| 539 |
add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false)); |
| 540 |
mech_type = CKM_RSA_X_509; |
| 541 |
add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type)); |
| 542 |
|
| 543 |
add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length); |
| 544 |
add_object_attribute(o, 0, CKA_ENCRYPT, &bool_true, sizeof(bool_true)); |
| 545 |
add_object_attribute(o, 0, CKA_VERIFY, &bool_true, sizeof(bool_true)); |
| 546 |
add_object_attribute(o, 0, CKA_VERIFY_RECOVER, &bool_false, sizeof(bool_false)); |
| 547 |
add_object_attribute(o, 0, CKA_WRAP, &bool_true, sizeof(bool_true)); |
| 548 |
add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true)); |
| 549 |
|
| 550 |
add_pubkey_info(o, key_type, public_key); |
| 551 |
|
| 552 |
st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o)); |
| 553 |
|
| 554 |
if (private_key_file) { |
| 555 |
CK_FLAGS flags; |
| 556 |
FILE *f; |
| 557 |
|
| 558 |
o = add_st_object(); |
| 559 |
if (o == NULL) { |
| 560 |
ret = CKR_DEVICE_MEMORY; |
| 561 |
goto out; |
| 562 |
} |
| 563 |
o->type = STO_T_PRIVATE_KEY; |
| 564 |
o->u.private_key.file = strdup(private_key_file); |
| 565 |
o->u.private_key.key = NULL; |
| 566 |
|
| 567 |
o->u.private_key.cert = cert; |
| 568 |
|
| 569 |
c = CKO_PRIVATE_KEY; |
| 570 |
add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c)); |
| 571 |
add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true)); |
| 572 |
add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false)); |
| 573 |
add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false)); |
| 574 |
add_object_attribute(o, 0, CKA_LABEL, label, strlen(label)); |
| 575 |
|
| 576 |
add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type)); |
| 577 |
add_object_attribute(o, 0, CKA_ID, id, id_len); |
| 578 |
add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */ |
| 579 |
add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */ |
| 580 |
add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false)); |
| 581 |
add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false)); |
| 582 |
mech_type = CKM_RSA_X_509; |
| 583 |
add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type)); |
| 584 |
|
| 585 |
add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length); |
| 586 |
add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true)); |
| 587 |
add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true)); |
| 588 |
flags = 0; |
| 589 |
add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags)); |
| 590 |
|
| 591 |
add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true)); |
| 592 |
add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true)); |
| 593 |
add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false)); |
| 594 |
add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true)); |
| 595 |
add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true)); |
| 596 |
add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false)); |
| 597 |
|
| 598 |
add_pubkey_info(o, key_type, public_key); |
| 599 |
|
| 600 |
f = fopen(private_key_file, "r"); |
| 601 |
if (f == NULL) { |
| 602 |
st_logf("failed to open private key\n"); |
| 603 |
return CKR_GENERAL_ERROR; |
| 604 |
} |
| 605 |
|
| 606 |
o->u.private_key.key = PEM_read_PrivateKey(f, NULL, pem_callback, NULL); |
| 607 |
fclose(f); |
| 608 |
if (o->u.private_key.key == NULL) { |
| 609 |
st_logf("failed to read private key a startup\n"); |
| 610 |
/* don't bother with this failure for now, |
| 611 |
fix it at C_Login time */; |
| 612 |
} else { |
| 613 |
/* XXX verify keytype */ |
| 614 |
|
| 615 |
if (key_type == CKK_RSA) { |
| 616 |
RSA *rsa = EVP_PKEY_get0_RSA(o->u.private_key.key); |
| 617 |
RSA_set_method(rsa, RSA_PKCS1_OpenSSL()); |
| 618 |
} |
| 619 |
|
| 620 |
if (X509_check_private_key(cert, o->u.private_key.key) != 1) { |
| 621 |
EVP_PKEY_free(o->u.private_key.key); |
| 622 |
o->u.private_key.key = NULL; |
| 623 |
st_logf("private key doesn't verify\n"); |
| 624 |
} else { |
| 625 |
st_logf("private key usable\n"); |
| 626 |
soft_token.flags.login_done = 1; |
| 627 |
} |
| 628 |
} |
| 629 |
} |
| 630 |
|
| 631 |
ret = CKR_OK; |
| 632 |
out: |
| 633 |
if (ret != CKR_OK) { |
| 634 |
st_logf("something went wrong when adding cert!\n"); |
| 635 |
|
| 636 |
/* XXX wack o */; |
| 637 |
} |
| 638 |
free(cert_data); |
| 639 |
free(serial_data); |
| 640 |
free(issuer_data); |
| 641 |
free(subject_data); |
| 642 |
|
| 643 |
return ret; |
| 644 |
} |
| 645 |
|
| 646 |
static void |
| 647 |
find_object_final(struct session_state *state) |
| 648 |
{ |
| 649 |
if (state->find.attributes) { |
| 650 |
CK_ULONG i; |
| 651 |
|
| 652 |
for (i = 0; i < state->find.num_attributes; i++) { |
| 653 |
if (state->find.attributes[i].pValue) |
| 654 |
free(state->find.attributes[i].pValue); |
| 655 |
} |
| 656 |
free(state->find.attributes); |
| 657 |
state->find.attributes = NULL; |
| 658 |
state->find.num_attributes = 0; |
| 659 |
state->find.next_object = -1; |
| 660 |
} |
| 661 |
} |
| 662 |
|
| 663 |
static void |
| 664 |
reset_crypto_state(struct session_state *state) |
| 665 |
{ |
| 666 |
state->encrypt_object = -1; |
| 667 |
if (state->encrypt_mechanism) |
| 668 |
free(state->encrypt_mechanism); |
| 669 |
state->encrypt_mechanism = NULL_PTR; |
| 670 |
state->decrypt_object = -1; |
| 671 |
if (state->decrypt_mechanism) |
| 672 |
free(state->decrypt_mechanism); |
| 673 |
state->decrypt_mechanism = NULL_PTR; |
| 674 |
state->sign_object = -1; |
| 675 |
if (state->sign_mechanism) |
| 676 |
free(state->sign_mechanism); |
| 677 |
state->sign_mechanism = NULL_PTR; |
| 678 |
state->verify_object = -1; |
| 679 |
if (state->verify_mechanism) |
| 680 |
free(state->verify_mechanism); |
| 681 |
state->verify_mechanism = NULL_PTR; |
| 682 |
state->digest_object = -1; |
| 683 |
} |
| 684 |
|
| 685 |
static void |
| 686 |
close_session(struct session_state *state) |
| 687 |
{ |
| 688 |
if (state->find.attributes) { |
| 689 |
application_error("application didn't do C_FindObjectsFinal\n"); |
| 690 |
find_object_final(state); |
| 691 |
} |
| 692 |
|
| 693 |
state->session_handle = CK_INVALID_HANDLE; |
| 694 |
soft_token.application = NULL_PTR; |
| 695 |
soft_token.notify = NULL_PTR; |
| 696 |
reset_crypto_state(state); |
| 697 |
} |
| 698 |
|
| 699 |
static const char * |
| 700 |
has_session(void) |
| 701 |
{ |
| 702 |
return soft_token.open_sessions > 0 ? "yes" : "no"; |
| 703 |
} |
| 704 |
|
| 705 |
static void |
| 706 |
read_conf_file(const char *fn) |
| 707 |
{ |
| 708 |
char buf[1024], *cert, *key, *id, *label, *s, *p; |
| 709 |
int anchor; |
| 710 |
FILE *f; |
| 711 |
|
| 712 |
f = fopen(fn, "r"); |
| 713 |
if (f == NULL) { |
| 714 |
st_logf("can't open configuration file %s\n", fn); |
| 715 |
return; |
| 716 |
} |
| 717 |
|
| 718 |
while(fgets(buf, sizeof(buf), f) != NULL) { |
| 719 |
buf[strcspn(buf, "\n")] = '\0'; |
| 720 |
|
| 721 |
anchor = 0; |
| 722 |
|
| 723 |
st_logf("line: %s\n", buf); |
| 724 |
|
| 725 |
p = buf; |
| 726 |
while (isspace(*p)) |
| 727 |
p++; |
| 728 |
if (*p == '#') |
| 729 |
continue; |
| 730 |
while (isspace(*p)) |
| 731 |
p++; |
| 732 |
|
| 733 |
s = NULL; |
| 734 |
id = strtok_r(p, "\t", &s); |
| 735 |
if (id == NULL) |
| 736 |
continue; |
| 737 |
label = strtok_r(NULL, "\t", &s); |
| 738 |
if (label == NULL) |
| 739 |
continue; |
| 740 |
cert = strtok_r(NULL, "\t", &s); |
| 741 |
if (cert == NULL) |
| 742 |
continue; |
| 743 |
key = strtok_r(NULL, "\t", &s); |
| 744 |
|
| 745 |
/* XXX */ |
| 746 |
if (strcmp(id, "anchor") == 0) { |
| 747 |
id = "\x00\x00"; |
| 748 |
anchor = 1; |
| 749 |
} |
| 750 |
|
| 751 |
st_logf("adding: %s\n", label); |
| 752 |
|
| 753 |
add_certificate(label, cert, key, id, anchor); |
| 754 |
} |
| 755 |
} |
| 756 |
|
| 757 |
static CK_RV |
| 758 |
func_not_supported(void) |
| 759 |
{ |
| 760 |
st_logf("function not supported\n"); |
| 761 |
return CKR_FUNCTION_NOT_SUPPORTED; |
| 762 |
} |
| 763 |
|
| 764 |
CK_RV |
| 765 |
C_Initialize(CK_VOID_PTR a) |
| 766 |
{ |
| 767 |
CK_C_INITIALIZE_ARGS_PTR args = a; |
| 768 |
st_logf("Initialize\n"); |
| 769 |
size_t i; |
| 770 |
|
| 771 |
OpenSSL_add_all_algorithms(); |
| 772 |
ERR_load_crypto_strings(); |
| 773 |
|
| 774 |
srandom(getpid() ^ time(NULL)); |
| 775 |
|
| 776 |
for (i = 0; i < MAX_NUM_SESSION; i++) { |
| 777 |
soft_token.state[i].session_handle = CK_INVALID_HANDLE; |
| 778 |
soft_token.state[i].find.attributes = NULL; |
| 779 |
soft_token.state[i].find.num_attributes = 0; |
| 780 |
soft_token.state[i].find.next_object = -1; |
| 781 |
reset_crypto_state(&soft_token.state[i]); |
| 782 |
} |
| 783 |
|
| 784 |
soft_token.flags.hardware_slot = 1; |
| 785 |
soft_token.flags.app_error_fatal = 0; |
| 786 |
soft_token.flags.login_done = 0; |
| 787 |
|
| 788 |
soft_token.object.objs = NULL; |
| 789 |
soft_token.object.num_objs = 0; |
| 790 |
|
| 791 |
soft_token.logfile = NULL; |
| 792 |
#if 1 |
| 793 |
// soft_token.logfile = stdout; |
| 794 |
#endif |
| 795 |
#if 0 |
| 796 |
soft_token.logfile = fopen("/tmp/log-pkcs11.txt", "a"); |
| 797 |
#endif |
| 798 |
|
| 799 |
if (a != NULL_PTR) { |
| 800 |
st_logf("\tCreateMutex:\t%p\n", args->CreateMutex); |
| 801 |
st_logf("\tDestroyMutext\t%p\n", args->DestroyMutex); |
| 802 |
st_logf("\tLockMutext\t%p\n", args->LockMutex); |
| 803 |
st_logf("\tUnlockMutext\t%p\n", args->UnlockMutex); |
| 804 |
st_logf("\tFlags\t%04x\n", (unsigned int)args->flags); |
| 805 |
} |
| 806 |
|
| 807 |
{ |
| 808 |
char *fn = NULL, *home = NULL; |
| 809 |
|
| 810 |
if (getuid() == geteuid()) { |
| 811 |
fn = getenv("SOFTPKCS11RC"); |
| 812 |
if (fn) |
| 813 |
fn = strdup(fn); |
| 814 |
home = getenv("HOME"); |
| 815 |
} |
| 816 |
if (fn == NULL && home == NULL) { |
| 817 |
struct passwd *pw = getpwuid(getuid()); |
| 818 |
if(pw != NULL) |
| 819 |
home = pw->pw_dir; |
| 820 |
} |
| 821 |
if (fn == NULL) { |
| 822 |
if (home) |
| 823 |
asprintf(&fn, "%s/.soft-token.rc", home); |
| 824 |
else |
| 825 |
fn = strdup("/etc/soft-token.rc"); |
| 826 |
} |
| 827 |
|
| 828 |
read_conf_file(fn); |
| 829 |
free(fn); |
| 830 |
} |
| 831 |
|
| 832 |
return CKR_OK; |
| 833 |
} |
| 834 |
|
| 835 |
CK_RV |
| 836 |
C_Finalize(CK_VOID_PTR args) |
| 837 |
{ |
| 838 |
size_t i; |
| 839 |
|
| 840 |
st_logf("Finalize\n"); |
| 841 |
|
| 842 |
for (i = 0; i < MAX_NUM_SESSION; i++) { |
| 843 |
if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) { |
| 844 |
application_error("application finalized without " |
| 845 |
"closing session\n"); |
| 846 |
close_session(&soft_token.state[i]); |
| 847 |
} |
| 848 |
} |
| 849 |
|
| 850 |
return CKR_OK; |
| 851 |
} |
| 852 |
|
| 853 |
CK_RV |
| 854 |
C_GetInfo(CK_INFO_PTR args) |
| 855 |
{ |
| 856 |
st_logf("GetInfo\n"); |
| 857 |
|
| 858 |
memset(args, 17, sizeof(*args)); |
| 859 |
args->cryptokiVersion.major = 2; |
| 860 |
args->cryptokiVersion.minor = 10; |
| 861 |
snprintf_fill((char *)args->manufacturerID, |
| 862 |
sizeof(args->manufacturerID), |
| 863 |
' ', |
| 864 |
"SoftToken"); |
| 865 |
snprintf_fill((char *)args->libraryDescription, |
| 866 |
sizeof(args->libraryDescription), ' ', |
| 867 |
"SoftToken"); |
| 868 |
args->libraryVersion.major = 1; |
| 869 |
args->libraryVersion.minor = 8; |
| 870 |
|
| 871 |
return CKR_OK; |
| 872 |
} |
| 873 |
|
| 874 |
extern CK_FUNCTION_LIST funcs; |
| 875 |
|
| 876 |
CK_RV |
| 877 |
C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) |
| 878 |
{ |
| 879 |
*ppFunctionList = &funcs; |
| 880 |
return CKR_OK; |
| 881 |
} |
| 882 |
|
| 883 |
CK_RV |
| 884 |
C_GetSlotList(CK_BBOOL tokenPresent, |
| 885 |
CK_SLOT_ID_PTR pSlotList, |
| 886 |
CK_ULONG_PTR pulCount) |
| 887 |
{ |
| 888 |
st_logf("GetSlotList: %s\n", |
| 889 |
tokenPresent ? "tokenPresent" : "token not Present"); |
| 890 |
if (pSlotList) |
| 891 |
pSlotList[0] = 1; |
| 892 |
*pulCount = 1; |
| 893 |
return CKR_OK; |
| 894 |
} |
| 895 |
|
| 896 |
CK_RV |
| 897 |
C_GetSlotInfo(CK_SLOT_ID slotID, |
| 898 |
CK_SLOT_INFO_PTR pInfo) |
| 899 |
{ |
| 900 |
st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID, has_session()); |
| 901 |
|
| 902 |
memset(pInfo, 18, sizeof(*pInfo)); |
| 903 |
|
| 904 |
if (slotID != 1) |
| 905 |
return CKR_ARGUMENTS_BAD; |
| 906 |
|
| 907 |
snprintf_fill((char *)pInfo->slotDescription, |
| 908 |
sizeof(pInfo->slotDescription), |
| 909 |
' ', |
| 910 |
"SoftToken (slot)"); |
| 911 |
snprintf_fill((char *)pInfo->manufacturerID, |
| 912 |
sizeof(pInfo->manufacturerID), |
| 913 |
' ', |
| 914 |
"SoftToken (slot)"); |
| 915 |
pInfo->flags = CKF_TOKEN_PRESENT; |
| 916 |
if (soft_token.flags.hardware_slot) |
| 917 |
pInfo->flags |= CKF_HW_SLOT; |
| 918 |
pInfo->hardwareVersion.major = 1; |
| 919 |
pInfo->hardwareVersion.minor = 0; |
| 920 |
pInfo->firmwareVersion.major = 1; |
| 921 |
pInfo->firmwareVersion.minor = 0; |
| 922 |
|
| 923 |
return CKR_OK; |
| 924 |
} |
| 925 |
|
| 926 |
CK_RV |
| 927 |
C_GetTokenInfo(CK_SLOT_ID slotID, |
| 928 |
CK_TOKEN_INFO_PTR pInfo) |
| 929 |
{ |
| 930 |
st_logf("GetTokenInfo: %s\n", has_session()); |
| 931 |
|
| 932 |
memset(pInfo, 19, sizeof(*pInfo)); |
| 933 |
|
| 934 |
snprintf_fill((char *)pInfo->label, |
| 935 |
sizeof(pInfo->label), |
| 936 |
' ', |
| 937 |
"SoftToken (token)"); |
| 938 |
snprintf_fill((char *)pInfo->manufacturerID, |
| 939 |
sizeof(pInfo->manufacturerID), |
| 940 |
' ', |
| 941 |
"SoftToken (token)"); |
| 942 |
snprintf_fill((char *)pInfo->model, |
| 943 |
sizeof(pInfo->model), |
| 944 |
' ', |
| 945 |
"SoftToken (token)"); |
| 946 |
snprintf_fill((char *)pInfo->serialNumber, |
| 947 |
sizeof(pInfo->serialNumber), |
| 948 |
' ', |
| 949 |
"4711"); |
| 950 |
pInfo->flags = |
| 951 |
CKF_TOKEN_INITIALIZED | |
| 952 |
CKF_USER_PIN_INITIALIZED; |
| 953 |
|
| 954 |
if (soft_token.flags.login_done == 0) |
| 955 |
pInfo->flags |= CKF_LOGIN_REQUIRED; |
| 956 |
|
| 957 |
/* CFK_RNG | |
| 958 |
CKF_RESTORE_KEY_NOT_NEEDED | |
| 959 |
*/ |
| 960 |
pInfo->ulMaxSessionCount = MAX_NUM_SESSION; |
| 961 |
pInfo->ulSessionCount = soft_token.open_sessions; |
| 962 |
pInfo->ulMaxRwSessionCount = MAX_NUM_SESSION; |
| 963 |
pInfo->ulRwSessionCount = soft_token.open_sessions; |
| 964 |
pInfo->ulMaxPinLen = 1024; |
| 965 |
pInfo->ulMinPinLen = 0; |
| 966 |
pInfo->ulTotalPublicMemory = 4711; |
| 967 |
pInfo->ulFreePublicMemory = 4712; |
| 968 |
pInfo->ulTotalPrivateMemory = 4713; |
| 969 |
pInfo->ulFreePrivateMemory = 4714; |
| 970 |
pInfo->hardwareVersion.major = 2; |
| 971 |
pInfo->hardwareVersion.minor = 0; |
| 972 |
pInfo->firmwareVersion.major = 2; |
| 973 |
pInfo->firmwareVersion.minor = 0; |
| 974 |
|
| 975 |
return CKR_OK; |
| 976 |
} |
| 977 |
|
| 978 |
CK_RV |
| 979 |
C_GetMechanismList(CK_SLOT_ID slotID, |
| 980 |
CK_MECHANISM_TYPE_PTR pMechanismList, |
| 981 |
CK_ULONG_PTR pulCount) |
| 982 |
{ |
| 983 |
st_logf("GetMechanismList\n"); |
| 984 |
|
| 985 |
*pulCount = 2; |
| 986 |
if (pMechanismList == NULL_PTR) |
| 987 |
return CKR_OK; |
| 988 |
pMechanismList[0] = CKM_RSA_X_509; |
| 989 |
pMechanismList[1] = CKM_RSA_PKCS; |
| 990 |
|
| 991 |
return CKR_OK; |
| 992 |
} |
| 993 |
|
| 994 |
CK_RV |
| 995 |
C_GetMechanismInfo(CK_SLOT_ID slotID, |
| 996 |
CK_MECHANISM_TYPE type, |
| 997 |
CK_MECHANISM_INFO_PTR pInfo) |
| 998 |
{ |
| 999 |
st_logf("GetMechanismInfo: slot %d type: %d\n", |
| 1000 |
(int)slotID, (int)type); |
| 1001 |
return CKR_FUNCTION_NOT_SUPPORTED; |
| 1002 |
} |
| 1003 |
|
| 1004 |
CK_RV |
| 1005 |
C_InitToken(CK_SLOT_ID slotID, |
| 1006 |
CK_UTF8CHAR_PTR pPin, |
| 1007 |
CK_ULONG ulPinLen, |
| 1008 |
CK_UTF8CHAR_PTR pLabel) |
| 1009 |
{ |
| 1010 |
st_logf("InitToken: slot %d\n", (int)slotID); |
| 1011 |
return CKR_FUNCTION_NOT_SUPPORTED; |
| 1012 |
} |
| 1013 |
|
| 1014 |
CK_RV |
| 1015 |
C_OpenSession(CK_SLOT_ID slotID, |
| 1016 |
CK_FLAGS flags, |
| 1017 |
CK_VOID_PTR pApplication, |
| 1018 |
CK_NOTIFY Notify, |
| 1019 |
CK_SESSION_HANDLE_PTR phSession) |
| 1020 |
{ |
| 1021 |
size_t i; |
| 1022 |
|
| 1023 |
st_logf("OpenSession: slot: %d\n", (int)slotID); |
| 1024 |
|
| 1025 |
if (soft_token.open_sessions == MAX_NUM_SESSION) |
| 1026 |
return CKR_SESSION_COUNT; |
| 1027 |
|
| 1028 |
soft_token.application = pApplication; |
| 1029 |
soft_token.notify = Notify; |
| 1030 |
|
| 1031 |
for (i = 0; i < MAX_NUM_SESSION; i++) |
| 1032 |
if (soft_token.state[i].session_handle == CK_INVALID_HANDLE) |
| 1033 |
break; |
| 1034 |
if (i == MAX_NUM_SESSION) |
| 1035 |
abort(); |
| 1036 |
|
| 1037 |
soft_token.open_sessions++; |
| 1038 |
|
| 1039 |
soft_token.state[i].session_handle = |
| 1040 |
(CK_SESSION_HANDLE)(random() & 0xfffff); |
| 1041 |
*phSession = soft_token.state[i].session_handle; |
| 1042 |
|
| 1043 |
return CKR_OK; |
| 1044 |
} |
| 1045 |
|
| 1046 |
CK_RV |
| 1047 |
C_CloseSession(CK_SESSION_HANDLE hSession) |
| 1048 |
{ |
| 1049 |
struct session_state *state; |
| 1050 |
st_logf("CloseSession\n"); |
| 1051 |
|
| 1052 |
if (verify_session_handle(hSession, &state) != CKR_OK) |
| 1053 |
application_error("closed session not open"); |
| 1054 |
else |
| 1055 |
close_session(state); |
| 1056 |
|
| 1057 |
return CKR_OK; |
| 1058 |
} |
| 1059 |
|
| 1060 |
CK_RV |
| 1061 |
C_CloseAllSessions(CK_SLOT_ID slotID) |
| 1062 |
{ |
| 1063 |
size_t i; |
| 1064 |
|
| 1065 |
st_logf("CloseAllSessions\n"); |
| 1066 |
|
| 1067 |
for (i = 0; i < MAX_NUM_SESSION; i++) |
| 1068 |
if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) |
| 1069 |
close_session(&soft_token.state[i]); |
| 1070 |
|
| 1071 |
return CKR_OK; |
| 1072 |
} |
| 1073 |
|
| 1074 |
CK_RV |
| 1075 |
C_GetSessionInfo(CK_SESSION_HANDLE hSession, |
| 1076 |
CK_SESSION_INFO_PTR pInfo) |
| 1077 |
{ |
| 1078 |
st_logf("GetSessionInfo\n"); |
| 1079 |
|
| 1080 |
VERIFY_SESSION_HANDLE(hSession, NULL); |
| 1081 |
|
| 1082 |
memset(pInfo, 20, sizeof(*pInfo)); |
| 1083 |
|
| 1084 |
pInfo->slotID = 1; |
| 1085 |
if (soft_token.flags.login_done) |
| 1086 |
pInfo->state = CKS_RO_USER_FUNCTIONS; |
| 1087 |
else |
| 1088 |
pInfo->state = CKS_RO_PUBLIC_SESSION; |
| 1089 |
pInfo->flags = CKF_SERIAL_SESSION; |
| 1090 |
pInfo->ulDeviceError = 0; |
| 1091 |
|
| 1092 |
return CKR_OK; |
| 1093 |
} |
| 1094 |
|
| 1095 |
CK_RV |
| 1096 |
C_Login(CK_SESSION_HANDLE hSession, |
| 1097 |
CK_USER_TYPE userType, |
| 1098 |
CK_UTF8CHAR_PTR pPin, |
| 1099 |
CK_ULONG ulPinLen) |
| 1100 |
{ |
| 1101 |
char *pin = NULL; |
| 1102 |
int i; |
| 1103 |
|
| 1104 |
st_logf("Login\n"); |
| 1105 |
|
| 1106 |
VERIFY_SESSION_HANDLE(hSession, NULL); |
| 1107 |
|
| 1108 |
if (pPin != NULL_PTR) { |
| 1109 |
asprintf(&pin, "%.*s", (int)ulPinLen, pPin); |
| 1110 |
st_logf("type: %d password: %s\n", (int)userType, pin); |
| 1111 |
} |
| 1112 |
|
| 1113 |
for (i = 0; i < soft_token.object.num_objs; i++) { |
| 1114 |
struct st_object *o = soft_token.object.objs[i]; |
| 1115 |
FILE *f; |
| 1116 |
|
| 1117 |
if (o->type != STO_T_PRIVATE_KEY) |
| 1118 |
continue; |
| 1119 |
|
| 1120 |
if (o->u.private_key.key) |
| 1121 |
continue; |
| 1122 |
|
| 1123 |
f = fopen(o->u.private_key.file, "r"); |
| 1124 |
if (f == NULL) { |
| 1125 |
st_logf("can't open private file: %s\n", o->u.private_key.file); |
| 1126 |
continue; |
| 1127 |
} |
| 1128 |
|
| 1129 |
o->u.private_key.key = PEM_read_PrivateKey(f, NULL, NULL, pin); |
| 1130 |
fclose(f); |
| 1131 |
if (o->u.private_key.key == NULL) { |
| 1132 |
st_logf("failed to read key: %s error: %s\n", |
| 1133 |
o->u.private_key.file, |
| 1134 |
ERR_error_string(ERR_get_error(), NULL)); |
| 1135 |
/* just ignore failure */; |
| 1136 |
continue; |
| 1137 |
} |
| 1138 |
|
| 1139 |
/* XXX check keytype */ |
| 1140 |
RSA *rsa = EVP_PKEY_get0_RSA(o->u.private_key.key); |
| 1141 |
RSA_set_method(rsa, RSA_PKCS1_OpenSSL()); |
| 1142 |
|
| 1143 |
if (X509_check_private_key(o->u.private_key.cert, o->u.private_key.key) != 1) { |
| 1144 |
EVP_PKEY_free(o->u.private_key.key); |
| 1145 |
o->u.private_key.key = NULL; |
| 1146 |
st_logf("private key %s doesn't verify\n", o->u.private_key.file); |
| 1147 |
continue; |
| 1148 |
} |
| 1149 |
|
| 1150 |
soft_token.flags.login_done = 1; |
| 1151 |
} |
| 1152 |
free(pin); |
| 1153 |
|
| 1154 |
return soft_token.flags.login_done ? CKR_OK : CKR_PIN_INCORRECT; |
| 1155 |
} |
| 1156 |
|
| 1157 |
CK_RV |
| 1158 |
C_Logout(CK_SESSION_HANDLE hSession) |
| 1159 |
{ |
| 1160 |
st_logf("Logout\n"); |
| 1161 |
VERIFY_SESSION_HANDLE(hSession, NULL); |
| 1162 |
return CKR_FUNCTION_NOT_SUPPORTED; |
| 1163 |
} |
| 1164 |
|
| 1165 |
CK_RV |
| 1166 |
C_GetObjectSize(CK_SESSION_HANDLE hSession, |
| 1167 |
CK_OBJECT_HANDLE hObject, |
| 1168 |
CK_ULONG_PTR pulSize) |
| 1169 |
{ |
| 1170 |
st_logf("GetObjectSize\n"); |
| 1171 |
VERIFY_SESSION_HANDLE(hSession, NULL); |
| 1172 |
return CKR_FUNCTION_NOT_SUPPORTED; |
| 1173 |
} |
| 1174 |
|
| 1175 |
CK_RV |
| 1176 |
C_GetAttributeValue(CK_SESSION_HANDLE hSession, |
| 1177 |
CK_OBJECT_HANDLE hObject, |
| 1178 |
CK_ATTRIBUTE_PTR pTemplate, |
| 1179 |
CK_ULONG ulCount) |
| 1180 |
{ |
| 1181 |
struct session_state *state; |
| 1182 |
struct st_object *obj; |
| 1183 |
CK_ULONG i; |
| 1184 |
CK_RV ret; |
| 1185 |
int j; |
| 1186 |
|
| 1187 |
st_logf("GetAttributeValue: %lx\n", |
| 1188 |
(unsigned long)HANDLE_OBJECT_ID(hObject)); |
| 1189 |
VERIFY_SESSION_HANDLE(hSession, &state); |
| 1190 |
|
| 1191 |
if ((ret = object_handle_to_object(hObject, &obj)) != CKR_OK) { |
| 1192 |
st_logf("object not found: %lx\n", |
| 1193 |
(unsigned long)HANDLE_OBJECT_ID(hObject)); |
| 1194 |
return ret; |
| 1195 |
} |
| 1196 |
|
| 1197 |
ret = CKR_OK; |
| 1198 |
for (i = 0; i < ulCount; i++) { |
| 1199 |
st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate[i].type); |
| 1200 |
for (j = 0; j < obj->num_attributes; j++) { |
| 1201 |
if (obj->attrs[j].secret) { |
| 1202 |
pTemplate[i].ulValueLen = (CK_ULONG)-1; |
| 1203 |
break; |
| 1204 |
} |
| 1205 |
if (pTemplate[i].type == obj->attrs[j].attribute.type) { |
| 1206 |
if (pTemplate[i].pValue != NULL_PTR && obj->attrs[j].secret == 0) { |
| 1207 |
if (pTemplate[i].ulValueLen >= obj->attrs[j].attribute.ulValueLen) |
| 1208 |
memcpy(pTemplate[i].pValue, obj->attrs[j].attribute.pValue, |
| 1209 |
obj->attrs[j].attribute.ulValueLen); |
| 1210 |
} |
| 1211 |
pTemplate[i].ulValueLen = obj->attrs[j].attribute.ulValueLen; |
| 1212 |
break; |
| 1213 |
} |
| 1214 |
} |
| 1215 |
if (j == obj->num_attributes) { |
| 1216 |
st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate[i].type); |
| 1217 |
pTemplate[i].ulValueLen = (CK_ULONG)-1; |
| 1218 |
ret = CKR_ATTRIBUTE_TYPE_INVALID; |
| 1219 |
} |
| 1220 |
|
| 1221 |
} |
| 1222 |
return ret; |
| 1223 |
} |
| 1224 |
|
| 1225 |
CK_RV |
| 1226 |
C_FindObjectsInit(CK_SESSION_HANDLE hSession, |
| 1227 |
CK_ATTRIBUTE_PTR pTemplate, |
| 1228 |
CK_ULONG ulCount) |
| 1229 |
{ |
| 1230 |
struct session_state *state; |
| 1231 |
|
| 1232 |
st_logf("FindObjectsInit\n"); |
| 1233 |
|
| 1234 |
VERIFY_SESSION_HANDLE(hSession, &state); |
| 1235 |
|
| 1236 |
if (state->find.next_object != -1) { |
| 1237 |
application_error("application didn't do C_FindObjectsFinal\n"); |
| 1238 |
find_object_final(state); |
| 1239 |
} |
| 1240 |
if (ulCount) { |
| 1241 |
CK_ULONG i; |
| 1242 |
|
| 1243 |
print_attributes(pTemplate, ulCount); |
| 1244 |
|
| 1245 |
state->find.attributes = |
| 1246 |
calloc(1, ulCount * sizeof(state->find.attributes[0])); |
| 1247 |
if (state->find.attributes == NULL) |
| 1248 |
return CKR_DEVICE_MEMORY; |
| 1249 |
for (i = 0; i < ulCount; i++) { |
| 1250 |
state->find.attributes[i].pValue = |
| 1251 |
malloc(pTemplate[i].ulValueLen); |
| 1252 |
if (state->find.attributes[i].pValue == NULL) { |
| 1253 |
find_object_final(state); |
| 1254 |
return CKR_DEVICE_MEMORY; |
| 1255 |
} |
| 1256 |
memcpy(state->find.attributes[i].pValue, |
| 1257 |
pTemplate[i].pValue, pTemplate[i].ulValueLen); |
| 1258 |
state->find.attributes[i].type = pTemplate[i].type; |
| 1259 |
state->find.attributes[i].ulValueLen = pTemplate[i].ulValueLen; |
| 1260 |
} |
| 1261 |
state->find.num_attributes = ulCount; |
| 1262 |
state->find.next_object = 0; |
| 1263 |
} else { |
| 1264 |
st_logf("find all objects\n"); |
| 1265 |
state->find.attributes = NULL; |
| 1266 |
state->find.num_attributes = 0; |
| 1267 |
state->find.next_object = 0; |
| 1268 |
} |
| 1269 |
|
| 1270 |
return CKR_OK; |
| 1271 |
} |
| 1272 |
|
| 1273 |
CK_RV |
| 1274 |
C_FindObjects(CK_SESSION_HANDLE hSession, |
| 1275 |
CK_OBJECT_HANDLE_PTR phObject, |
| 1276 |
CK_ULONG ulMaxObjectCount, |
| 1277 |
CK_ULONG_PTR pulObjectCount) |
| 1278 |
{ |
| 1279 |
struct session_state *state; |
| 1280 |
int i; |
| 1281 |
|
| 1282 |
st_logf("FindObjects\n"); |
| 1283 |
|
| 1284 |
VERIFY_SESSION_HANDLE(hSession, &state); |
| 1285 |
|
| 1286 |
if (state->find.next_object == -1) { |
| 1287 |
application_error("application didn't do C_FindObjectsInit\n"); |
| 1288 |
return CKR_ARGUMENTS_BAD; |
| 1289 |
} |
| 1290 |
if (ulMaxObjectCount == 0) { |
| 1291 |
application_error("application asked for 0 objects\n"); |
| 1292 |
return CKR_ARGUMENTS_BAD; |
| 1293 |
} |
| 1294 |
*pulObjectCount = 0; |
| 1295 |
for (i = state->find.next_object; i < soft_token.object.num_objs; i++) { |
| 1296 |
st_logf("FindObjects: %d\n", i); |
| 1297 |
state->find.next_object = i + 1; |
| 1298 |
if (attributes_match(soft_token.object.objs[i], |
| 1299 |
state->find.attributes, |
| 1300 |
state->find.num_attributes)) { |
| 1301 |
*phObject++ = soft_token.object.objs[i]->object_handle; |
| 1302 |
ulMaxObjectCount--; |
| 1303 |
(*pulObjectCount)++; |
| 1304 |
if (ulMaxObjectCount == 0) |
| 1305 |
break; |
| 1306 |
} |
| 1307 |
} |
| 1308 |
return CKR_OK; |
| 1309 |
} |
| 1310 |
|
| 1311 |
CK_RV |
| 1312 |
C_FindObjectsFinal(CK_SESSION_HANDLE hSession) |
| 1313 |
{ |
| 1314 |
struct session_state *state; |
| 1315 |
|
| 1316 |
st_logf("FindObjectsFinal\n"); |
| 1317 |
VERIFY_SESSION_HANDLE(hSession, &state); |
| 1318 |
find_object_final(state); |
| 1319 |
return CKR_OK; |
| 1320 |
} |
| 1321 |
|
| 1322 |
static CK_RV |
| 1323 |
commonInit(CK_ATTRIBUTE *attr_match, int attr_match_len, |
| 1324 |
const CK_MECHANISM_TYPE *mechs, int mechs_len, |
| 1325 |
const CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, |
| 1326 |
struct st_object **o) |
| 1327 |
{ |
| 1328 |
CK_RV ret; |
| 1329 |
int i; |
| 1330 |
|
| 1331 |
*o = NULL; |
| 1332 |
if ((ret = object_handle_to_object(hKey, o)) != CKR_OK) |
| 1333 |
return ret; |
| 1334 |
|
| 1335 |
ret = attributes_match(*o, attr_match, attr_match_len); |
| 1336 |
if (!ret) { |
| 1337 |
application_error("called commonInit on key that doesn't " |
| 1338 |
"support required attr"); |
| 1339 |
return CKR_ARGUMENTS_BAD; |
| 1340 |
} |
| 1341 |
|
| 1342 |
for (i = 0; i < mechs_len; i++) |
| 1343 |
if (mechs[i] == pMechanism->mechanism) |
| 1344 |
break; |
| 1345 |
if (i == mechs_len) { |
| 1346 |
application_error("called mech (%08lx) not supported\n", |
| 1347 |
pMechanism->mechanism); |
| 1348 |
return CKR_ARGUMENTS_BAD; |
| 1349 |
} |
| 1350 |
return CKR_OK; |
| 1351 |
} |
| 1352 |
|
| 1353 |
|
| 1354 |
static CK_RV |
| 1355 |
dup_mechanism(CK_MECHANISM_PTR *dup, const CK_MECHANISM_PTR pMechanism) |
| 1356 |
{ |
| 1357 |
CK_MECHANISM_PTR p; |
| 1358 |
|
| 1359 |
p = malloc(sizeof(*p)); |
| 1360 |
if (p == NULL) |
| 1361 |
return CKR_DEVICE_MEMORY; |
| 1362 |
|
| 1363 |
if (*dup) |
| 1364 |
free(*dup); |
| 1365 |
*dup = p; |
| 1366 |
memcpy(p, pMechanism, sizeof(*p)); |
| 1367 |
|
| 1368 |
return CKR_OK; |
| 1369 |
} |
| 1370 |
|
| 1371 |
|
| 1372 |
CK_RV |
| 1373 |
C_EncryptInit(CK_SESSION_HANDLE hSession, |
| 1374 |
CK_MECHANISM_PTR pMechanism, |
| 1375 |
CK_OBJECT_HANDLE hKey) |
| 1376 |
{ |
| 1377 |
struct session_state *state; |
| 1378 |
CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 }; |
| 1379 |
CK_BBOOL bool_true = CK_TRUE; |
| 1380 |
CK_ATTRIBUTE attr[] = { |
| 1381 |
{ CKA_ENCRYPT, &bool_true, sizeof(bool_true) } |
| 1382 |
}; |
| 1383 |
struct st_object *o; |
| 1384 |
CK_RV ret; |
| 1385 |
|
| 1386 |
st_logf("EncryptInit\n"); |
| 1387 |
VERIFY_SESSION_HANDLE(hSession, &state); |
| 1388 |
|
| 1389 |
ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]), |
| 1390 |
mechs, sizeof(mechs)/sizeof(mechs[0]), |
| 1391 |
pMechanism, hKey, &o); |
| 1392 |
if (ret) |
| 1393 |
return ret; |
| 1394 |
|
| 1395 |
ret = dup_mechanism(&state->encrypt_mechanism, pMechanism); |
| 1396 |
if (ret == CKR_OK) |
| 1397 |
state->encrypt_object = OBJECT_ID(o); |
| 1398 |
|
| 1399 |
return ret; |
| 1400 |
} |
| 1401 |
|
| 1402 |
CK_RV |
| 1403 |
C_Encrypt(CK_SESSION_HANDLE hSession, |
| 1404 |
CK_BYTE_PTR pData, |
| 1405 |
CK_ULONG ulDataLen, |
| 1406 |
CK_BYTE_PTR pEncryptedData, |
| 1407 |
CK_ULONG_PTR pulEncryptedDataLen) |
| 1408 |
{ |
| 1409 |
struct session_state *state; |
| 1410 |
struct st_object *o; |
| 1411 |
void *buffer = NULL; |
| 1412 |
CK_RV ret; |
| 1413 |
RSA *rsa; |
| 1414 |
int padding, len, buffer_len, padding_len; |
| 1415 |
|
| 1416 |
st_logf("Encrypt\n"); |
| 1417 |
|
| 1418 |
VERIFY_SESSION_HANDLE(hSession, &state); |
| 1419 |
|
| 1420 |
if (state->encrypt_object == -1) |
| 1421 |
return CKR_ARGUMENTS_BAD; |
| 1422 |
|
| 1423 |
o = soft_token.object.objs[state->encrypt_object]; |
| 1424 |
|
| 1425 |
if (o->u.public_key == NULL) { |
| 1426 |
st_logf("public key NULL\n"); |
| 1427 |
return CKR_ARGUMENTS_BAD; |
| 1428 |
} |
| 1429 |
|
| 1430 |
rsa = EVP_PKEY_get0_RSA(o->u.public_key); |
| 1431 |
if (rsa == NULL) |
| 1432 |
return CKR_ARGUMENTS_BAD; |
| 1433 |
|
| 1434 |
RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */ |
| 1435 |
|
| 1436 |
buffer_len = RSA_size(rsa); |
| 1437 |
|
| 1438 |
buffer = malloc(buffer_len); |
| 1439 |
if (buffer == NULL) { |
| 1440 |
ret = CKR_DEVICE_MEMORY; |
| 1441 |
goto out; |
| 1442 |
} |
| 1443 |
|
| 1444 |
ret = CKR_OK; |
| 1445 |
switch(state->encrypt_mechanism->mechanism) { |
| 1446 |
case CKM_RSA_PKCS: |
| 1447 |
padding = RSA_PKCS1_PADDING; |
| 1448 |
padding_len = RSA_PKCS1_PADDING_SIZE; |
| 1449 |
break; |
| 1450 |
case CKM_RSA_X_509: |
| 1451 |
padding = RSA_NO_PADDING; |
| 1452 |
padding_len = 0; |
| 1453 |
break; |
| 1454 |
default: |
| 1455 |
ret = CKR_FUNCTION_NOT_SUPPORTED; |
| 1456 |
goto out; |
| 1457 |
} |
| 1458 |
|
| 1459 |
if (buffer_len + padding_len < (long) ulDataLen) { |
| 1460 |
ret = CKR_ARGUMENTS_BAD; |
| 1461 |
goto out; |
| 1462 |
} |
| 1463 |
|
| 1464 |
if (pulEncryptedDataLen == NULL) { |
| 1465 |
st_logf("pulEncryptedDataLen NULL\n"); |
| 1466 |
ret = CKR_ARGUMENTS_BAD; |
| 1467 |
goto out; |
| 1468 |
} |
| 1469 |
|
| 1470 |
if (pData == NULL_PTR) { |
| 1471 |
st_logf("data NULL\n"); |
| 1472 |
ret = CKR_ARGUMENTS_BAD; |
| 1473 |
goto out; |
| 1474 |
} |
| 1475 |
|
| 1476 |
len = RSA_public_encrypt(ulDataLen, pData, buffer, rsa, padding); |
| 1477 |
if (len <= 0) { |
| 1478 |
ret = CKR_DEVICE_ERROR; |
| 1479 |
goto out; |
| 1480 |
} |
| 1481 |
if (len > buffer_len) |
| 1482 |
abort(); |
| 1483 |
|
| 1484 |
if (pEncryptedData != NULL_PTR) |
| 1485 |
memcpy(pEncryptedData, buffer, len); |
| 1486 |
*pulEncryptedDataLen = len; |
| 1487 |
|
| 1488 |
out: |
| 1489 |
if (buffer) { |
| 1490 |
memset(buffer, 0, buffer_len); |
| 1491 |
free(buffer); |
| 1492 |
} |
| 1493 |
return ret; |
| 1494 |
} |
| 1495 |
|
| 1496 |
CK_RV |
| 1497 |
C_EncryptUpdate(CK_SESSION_HANDLE hSession, |
| 1498 |
CK_BYTE_PTR pPart, |
| 1499 |
CK_ULONG ulPartLen, |
| 1500 |
CK_BYTE_PTR pEncryptedPart, |
| 1501 |
CK_ULONG_PTR pulEncryptedPartLen) |
| 1502 |
{ |
| 1503 |
st_logf("EncryptUpdate\n"); |
| 1504 |
VERIFY_SESSION_HANDLE(hSession, NULL); |
| 1505 |
return CKR_FUNCTION_NOT_SUPPORTED; |
| 1506 |
} |
| 1507 |
|
| 1508 |
|
| 1509 |
CK_RV |
| 1510 |
C_EncryptFinal(CK_SESSION_HANDLE hSession, |
| 1511 |
CK_BYTE_PTR pLastEncryptedPart, |
| 1512 |
CK_ULONG_PTR pulLastEncryptedPartLen) |
| 1513 |
{ |
| 1514 |
st_logf("EncryptFinal\n"); |
| 1515 |
VERIFY_SESSION_HANDLE(hSession, NULL); |
| 1516 |
return CKR_FUNCTION_NOT_SUPPORTED; |
| 1517 |
} |
| 1518 |
|
| 1519 |
|
| 1520 |
/* C_DecryptInit initializes a decryption operation. */ |
| 1521 |
CK_RV |
| 1522 |
C_DecryptInit(CK_SESSION_HANDLE hSession, |
| 1523 |
CK_MECHANISM_PTR pMechanism, |
| 1524 |
CK_OBJECT_HANDLE hKey) |
| 1525 |
{ |
| 1526 |
struct session_state *state; |
| 1527 |
CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 }; |
| 1528 |
CK_BBOOL bool_true = CK_TRUE; |
| 1529 |
CK_ATTRIBUTE attr[] = { |
| 1530 |
{ CKA_DECRYPT, &bool_true, sizeof(bool_true) } |
| 1531 |
}; |
| 1532 |
struct st_object *o; |
| 1533 |
CK_RV ret; |
| 1534 |
|
| 1535 |
st_logf("DecryptInit\n"); |
| 1536 |
VERIFY_SESSION_HANDLE(hSession, &state); |
| 1537 |
|
| 1538 |
ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]), |
| 1539 |
mechs, sizeof(mechs)/sizeof(mechs[0]), |
| 1540 |
pMechanism, hKey, &o); |
| 1541 |
if (ret) |
| 1542 |
return ret; |
| 1543 |
|
| 1544 |
ret = dup_mechanism(&state->decrypt_mechanism, pMechanism); |
| 1545 |
if (ret == CKR_OK) |
| 1546 |
state->decrypt_object = OBJECT_ID(o); |
| 1547 |
|
| 1548 |
return CKR_OK; |
| 1549 |
} |
| 1550 |
|
| 1551 |
|
| 1552 |
CK_RV |
| 1553 |
C_Decrypt(CK_SESSION_HANDLE hSession, |
| 1554 |
CK_BYTE_PTR pEncryptedData, |
| 1555 |
CK_ULONG ulEncryptedDataLen, |
| 1556 |
CK_BYTE_PTR pData, |
| 1557 |
CK_ULONG_PTR pulDataLen) |
| 1558 |
{ |
| 1559 |
struct session_state *state; |
| 1560 |
struct st_object *o; |
| 1561 |
void *buffer = NULL; |
| 1562 |
CK_RV ret; |
| 1563 |
RSA *rsa; |
| 1564 |
int padding, len, buffer_len, padding_len; |
| 1565 |
|
| 1566 |
st_logf("Decrypt\n"); |
| 1567 |
|
| 1568 |
VERIFY_SESSION_HANDLE(hSession, &state); |
| 1569 |
|
| 1570 |
if (state->decrypt_object == -1) |
| 1571 |
return CKR_ARGUMENTS_BAD; |
| 1572 |
|
| 1573 |
o = soft_token.object.objs[state->decrypt_object]; |
| 1574 |
|
| 1575 |
if (o->u.private_key.key == NULL) { |
| 1576 |
st_logf("private key NULL\n"); |
| 1577 |
return CKR_ARGUMENTS_BAD; |
| 1578 |
} |
| 1579 |
|
| 1580 |
rsa = EVP_PKEY_get0_RSA(o->u.private_key.key); |
| 1581 |
if (rsa == NULL) |
| 1582 |
return CKR_ARGUMENTS_BAD; |
| 1583 |
|
| 1584 |
RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */ |
| 1585 |
|
| 1586 |
buffer_len = RSA_size(rsa); |
| 1587 |
|
| 1588 |
buffer = malloc(buffer_len); |
| 1589 |
if (buffer == NULL) { |
| 1590 |
ret = CKR_DEVICE_MEMORY; |
| 1591 |
goto out; |
| 1592 |
} |
| 1593 |
|
| 1594 |
ret = CKR_OK; |
| 1595 |
switch(state->decrypt_mechanism->mechanism) { |
| 1596 |
case CKM_RSA_PKCS: |
| 1597 |
padding = RSA_PKCS1_PADDING; |
| 1598 |
padding_len = RSA_PKCS1_PADDING_SIZE; |
| 1599 |
break; |
| 1600 |
case CKM_RSA_X_509: |
| 1601 |
padding = RSA_NO_PADDING; |
| 1602 |
padding_len = 0; |
| 1603 |
break; |
| 1604 |
default: |
| 1605 |
ret = CKR_FUNCTION_NOT_SUPPORTED; |
| 1606 |
goto out; |
| 1607 |
} |
| 1608 |
|
| 1609 |
if (buffer_len + padding_len < (long) ulEncryptedDataLen) { |
| 1610 |
ret = CKR_ARGUMENTS_BAD; |
| 1611 |
goto out; |
| 1612 |
} |
| 1613 |
|
| 1614 |
if (pulDataLen == NULL) { |
| 1615 |
st_logf("pulDataLen NULL\n"); |
| 1616 |
ret = CKR_ARGUMENTS_BAD; |
| 1617 |
goto out; |
| 1618 |
} |
| 1619 |
|
| 1620 |
if (pEncryptedData == NULL_PTR) { |
| 1621 |
st_logf("data NULL\n"); |
| 1622 |
ret = CKR_ARGUMENTS_BAD; |
| 1623 |
goto out; |
| 1624 |
} |
| 1625 |
|
| 1626 |
len = RSA_private_decrypt(ulEncryptedDataLen, pEncryptedData, buffer, |
| 1627 |
rsa, padding); |
| 1628 |
if (len <= 0) { |
| 1629 |
ret = CKR_DEVICE_ERROR; |
| 1630 |
goto out; |
| 1631 |
} |
| 1632 |
if (len > buffer_len) |
| 1633 |
abort(); |
| 1634 |
|
| 1635 |
if (pData != NULL_PTR) |
| 1636 |
memcpy(pData, buffer, len); |
| 1637 |
*pulDataLen = len; |
| 1638 |
|
| 1639 |
out: |
| 1640 |
if (buffer) { |
| 1641 |
memset(buffer, 0, buffer_len); |
| 1642 |
free(buffer); |
| 1643 |
} |
| 1644 |
return ret; |
| 1645 |
} |
| 1646 |
|
| 1647 |
|
| 1648 |
CK_RV |
| 1649 |
C_DecryptUpdate(CK_SESSION_HANDLE hSession, |
| 1650 |
CK_BYTE_PTR pEncryptedPart, |
| 1651 |
CK_ULONG ulEncryptedPartLen, |
| 1652 |
CK_BYTE_PTR pPart, |
| 1653 |
CK_ULONG_PTR pulPartLen) |
| 1654 |
|
| 1655 |
{ |
| 1656 |
st_logf("DecryptUpdate\n"); |
| 1657 |
VERIFY_SESSION_HANDLE(hSession, NULL); |
| 1658 |
return CKR_FUNCTION_NOT_SUPPORTED; |
| 1659 |
} |
| 1660 |
|
| 1661 |
|
| 1662 |
CK_RV |
| 1663 |
C_DecryptFinal(CK_SESSION_HANDLE hSession, |
| 1664 |
CK_BYTE_PTR pLastPart, |
| 1665 |
CK_ULONG_PTR pulLastPartLen) |
| 1666 |
{ |
| 1667 |
st_logf("DecryptFinal\n"); |
| 1668 |
VERIFY_SESSION_HANDLE(hSession, NULL); |
| 1669 |
return CKR_FUNCTION_NOT_SUPPORTED; |
| 1670 |
} |
| 1671 |
|
| 1672 |
CK_RV |
| 1673 |
C_DigestInit(CK_SESSION_HANDLE hSession, |
| 1674 |
CK_MECHANISM_PTR pMechanism) |
| 1675 |
{ |
| 1676 |
st_logf("DigestInit\n"); |
| 1677 |
VERIFY_SESSION_HANDLE(hSession, NULL); |
| 1678 |
return CKR_FUNCTION_NOT_SUPPORTED; |
| 1679 |
} |
| 1680 |
|
| 1681 |
CK_RV |
| 1682 |
C_SignInit(CK_SESSION_HANDLE hSession, |
| 1683 |
CK_MECHANISM_PTR pMechanism, |
| 1684 |
CK_OBJECT_HANDLE hKey) |
| 1685 |
{ |
| 1686 |
struct session_state *state; |
| 1687 |
CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 }; |
| 1688 |
CK_BBOOL bool_true = CK_TRUE; |
| 1689 |
CK_ATTRIBUTE attr[] = { |
| 1690 |
{ CKA_SIGN, &bool_true, sizeof(bool_true) } |
| 1691 |
}; |
| 1692 |
struct st_object *o; |
| 1693 |
CK_RV ret; |
| 1694 |
|
| 1695 |
st_logf("SignInit\n"); |
| 1696 |
VERIFY_SESSION_HANDLE(hSession, &state); |
| 1697 |
|
| 1698 |
ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]), |
| 1699 |
mechs, sizeof(mechs)/sizeof(mechs[0]), |
| 1700 |
pMechanism, hKey, &o); |
| 1701 |
if (ret) |
| 1702 |
return ret; |
| 1703 |
|
| 1704 |
ret = dup_mechanism(&state->sign_mechanism, pMechanism); |
| 1705 |
if (ret == CKR_OK) |
| 1706 |
state->sign_object = OBJECT_ID(o); |
| 1707 |
|
| 1708 |
return CKR_OK; |
| 1709 |
} |
| 1710 |
|
| 1711 |
CK_RV |
| 1712 |
C_Sign(CK_SESSION_HANDLE hSession, |
| 1713 |
CK_BYTE_PTR pData, |
| 1714 |
CK_ULONG ulDataLen, |
| 1715 |
CK_BYTE_PTR pSignature, |
| 1716 |
CK_ULONG_PTR pulSignatureLen) |
| 1717 |
{ |
| 1718 |
struct session_state *state; |
| 1719 |
struct st_object *o; |
| 1720 |
void *buffer = NULL; |
| 1721 |
CK_RV ret; |
| 1722 |
RSA *rsa; |
| 1723 |
int padding, len, buffer_len; |
| 1724 |
size_t padding_len; |
| 1725 |
|
| 1726 |
st_logf("Sign\n"); |
| 1727 |
VERIFY_SESSION_HANDLE(hSession, &state); |
| 1728 |
|
| 1729 |
if (state->sign_object == -1) |
| 1730 |
return CKR_ARGUMENTS_BAD; |
| 1731 |
|
| 1732 |
o = soft_token.object.objs[state->sign_object]; |
| 1733 |
|
| 1734 |
if (o->u.private_key.key == NULL) { |
| 1735 |
st_logf("private key NULL\n"); |
| 1736 |
return CKR_ARGUMENTS_BAD; |
| 1737 |
} |
| 1738 |
|
| 1739 |
rsa = EVP_PKEY_get0_RSA(o->u.private_key.key); |
| 1740 |
if (rsa == NULL) |
| 1741 |
return CKR_ARGUMENTS_BAD; |
| 1742 |
|
| 1743 |
RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */ |
| 1744 |
|
| 1745 |
buffer_len = RSA_size(rsa); |
| 1746 |
|
| 1747 |
buffer = malloc(buffer_len); |
| 1748 |
if (buffer == NULL) { |
| 1749 |
ret = CKR_DEVICE_MEMORY; |
| 1750 |
goto out; |
| 1751 |
} |
| 1752 |
|
| 1753 |
switch(state->sign_mechanism->mechanism) { |
| 1754 |
case CKM_RSA_PKCS: |
| 1755 |
padding = RSA_PKCS1_PADDING; |
| 1756 |
padding_len = RSA_PKCS1_PADDING_SIZE; |
| 1757 |
break; |
| 1758 |
case CKM_RSA_X_509: |
| 1759 |
padding = RSA_NO_PADDING; |
| 1760 |
padding_len = 0; |
| 1761 |
break; |
| 1762 |
default: |
| 1763 |
ret = CKR_FUNCTION_NOT_SUPPORTED; |
| 1764 |
goto out; |
| 1765 |
} |
| 1766 |
|
| 1767 |
if ((size_t) buffer_len < ulDataLen + padding_len) { |
| 1768 |
ret = CKR_ARGUMENTS_BAD; |
| 1769 |
goto out; |
| 1770 |
} |
| 1771 |
|
| 1772 |
if (pulSignatureLen == NULL) { |
| 1773 |
st_logf("signature len NULL\n"); |
| 1774 |
ret = CKR_ARGUMENTS_BAD; |
| 1775 |
goto out; |
| 1776 |
} |
| 1777 |
|
| 1778 |
if (pData == NULL_PTR) { |
| 1779 |
st_logf("data NULL\n"); |
| 1780 |
ret = CKR_ARGUMENTS_BAD; |
| 1781 |
goto out; |
| 1782 |
} |
| 1783 |
|
| 1784 |
len = RSA_private_encrypt(ulDataLen, pData, buffer, rsa, padding); |
| 1785 |
st_logf("private encrypt done\n"); |
| 1786 |
if (len <= 0) { |
| 1787 |
ret = CKR_DEVICE_ERROR; |
| 1788 |
goto out; |
| 1789 |
} |
| 1790 |
if (len > buffer_len) |
| 1791 |
abort(); |
| 1792 |
|
| 1793 |
if (pSignature != NULL_PTR) |
| 1794 |
memcpy(pSignature, buffer, len); |
| 1795 |
*pulSignatureLen = len; |
| 1796 |
|
| 1797 |
ret = CKR_OK; |
| 1798 |
|
| 1799 |
out: |
| 1800 |
if (buffer) { |
| 1801 |
memset(buffer, 0, buffer_len); |
| 1802 |
free(buffer); |
| 1803 |
} |
| 1804 |
return ret; |
| 1805 |
} |
| 1806 |
|
| 1807 |
CK_RV |
| 1808 |
C_SignUpdate(CK_SESSION_HANDLE hSession, |
| 1809 |
CK_BYTE_PTR pPart, |
| 1810 |
CK_ULONG ulPartLen) |
| 1811 |
{ |
| 1812 |
st_logf("SignUpdate\n"); |
| 1813 |
VERIFY_SESSION_HANDLE(hSession, NULL); |
| 1814 |
return CKR_FUNCTION_NOT_SUPPORTED; |
| 1815 |
} |
| 1816 |
|
| 1817 |
|
| 1818 |
CK_RV |
| 1819 |
C_SignFinal(CK_SESSION_HANDLE hSession, |
| 1820 |
CK_BYTE_PTR pSignature, |
| 1821 |
CK_ULONG_PTR pulSignatureLen) |
| 1822 |
{ |
| 1823 |
st_logf("SignUpdate\n"); |
| 1824 |
VERIFY_SESSION_HANDLE(hSession, NULL); |
| 1825 |
return CKR_FUNCTION_NOT_SUPPORTED; |
| 1826 |
} |
| 1827 |
|
| 1828 |
CK_RV |
| 1829 |
C_VerifyInit(CK_SESSION_HANDLE hSession, |
| 1830 |
CK_MECHANISM_PTR pMechanism, |
| 1831 |
CK_OBJECT_HANDLE hKey) |
| 1832 |
{ |
| 1833 |
struct session_state *state; |
| 1834 |
CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 }; |
| 1835 |
CK_BBOOL bool_true = CK_TRUE; |
| 1836 |
CK_ATTRIBUTE attr[] = { |
| 1837 |
{ CKA_VERIFY, &bool_true, sizeof(bool_true) } |
| 1838 |
}; |
| 1839 |
struct st_object *o; |
| 1840 |
CK_RV ret; |
| 1841 |
|
| 1842 |
st_logf("VerifyInit\n"); |
| 1843 |
VERIFY_SESSION_HANDLE(hSession, &state); |
| 1844 |
|
| 1845 |
ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]), |
| 1846 |
mechs, sizeof(mechs)/sizeof(mechs[0]), |
| 1847 |
pMechanism, hKey, &o); |
| 1848 |
if (ret) |
| 1849 |
return ret; |
| 1850 |
|
| 1851 |
ret = dup_mechanism(&state->verify_mechanism, pMechanism); |
| 1852 |
if (ret == CKR_OK) |
| 1853 |
state->verify_object = OBJECT_ID(o); |
| 1854 |
|
| 1855 |
return ret; |
| 1856 |
} |
| 1857 |
|
| 1858 |
CK_RV |
| 1859 |
C_Verify(CK_SESSION_HANDLE hSession, |
| 1860 |
CK_BYTE_PTR pData, |
| 1861 |
CK_ULONG ulDataLen, |
| 1862 |
CK_BYTE_PTR pSignature, |
| 1863 |
CK_ULONG ulSignatureLen) |
| 1864 |
{ |
| 1865 |
struct session_state *state; |
| 1866 |
struct st_object *o; |
| 1867 |
void *buffer = NULL; |
| 1868 |
CK_RV ret; |
| 1869 |
RSA *rsa; |
| 1870 |
int padding, len, buffer_len; |
| 1871 |
|
| 1872 |
st_logf("Verify\n"); |
| 1873 |
VERIFY_SESSION_HANDLE(hSession, &state); |
| 1874 |
|
| 1875 |
if (state->verify_object == -1) |
| 1876 |
return CKR_ARGUMENTS_BAD; |
| 1877 |
|
| 1878 |
o = soft_token.object.objs[state->verify_object]; |
| 1879 |
|
| 1880 |
if (o->u.public_key == NULL) { |
| 1881 |
st_logf("public key NULL\n"); |
| 1882 |
return CKR_ARGUMENTS_BAD; |
| 1883 |
} |
| 1884 |
|
| 1885 |
rsa = EVP_PKEY_get0_RSA(o->u.public_key); |
| 1886 |
if (rsa == NULL) |
| 1887 |
return CKR_ARGUMENTS_BAD; |
| 1888 |
|
| 1889 |
RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */ |
| 1890 |
|
| 1891 |
buffer_len = RSA_size(rsa); |
| 1892 |
|
| 1893 |
buffer = malloc(buffer_len); |
| 1894 |
if (buffer == NULL) { |
| 1895 |
ret = CKR_DEVICE_MEMORY; |
| 1896 |
goto out; |
| 1897 |
} |
| 1898 |
|
| 1899 |
ret = CKR_OK; |
| 1900 |
switch(state->verify_mechanism->mechanism) { |
| 1901 |
case CKM_RSA_PKCS: |
| 1902 |
padding = RSA_PKCS1_PADDING; |
| 1903 |
break; |
| 1904 |
case CKM_RSA_X_509: |
| 1905 |
padding = RSA_NO_PADDING; |
| 1906 |
break; |
| 1907 |
default: |
| 1908 |
ret = CKR_FUNCTION_NOT_SUPPORTED; |
| 1909 |
goto out; |
| 1910 |
} |
| 1911 |
|
| 1912 |
if (buffer_len < (long) ulDataLen) { |
| 1913 |
ret = CKR_ARGUMENTS_BAD; |
| 1914 |
goto out; |
| 1915 |
} |
| 1916 |
|
| 1917 |
if (pSignature == NULL) { |
| 1918 |
st_logf("signature NULL\n"); |
| 1919 |
ret = CKR_ARGUMENTS_BAD; |
| 1920 |
goto out; |
| 1921 |
} |
| 1922 |
|
| 1923 |
if (pData == NULL_PTR) { |
| 1924 |
st_logf("data NULL\n"); |
| 1925 |
ret = CKR_ARGUMENTS_BAD; |
| 1926 |
goto out; |
| 1927 |
} |
| 1928 |
|
| 1929 |
len = RSA_public_decrypt(ulDataLen, pData, buffer, rsa, padding); |
| 1930 |
st_logf("private encrypt done\n"); |
| 1931 |
if (len <= 0) { |
| 1932 |
ret = CKR_DEVICE_ERROR; |
| 1933 |
goto out; |
| 1934 |
} |
| 1935 |
if (len > buffer_len) |
| 1936 |
abort(); |
| 1937 |
|
| 1938 |
if ((size_t) len != ulSignatureLen) { |
| 1939 |
ret = CKR_GENERAL_ERROR; |
| 1940 |
goto out; |
| 1941 |
} |
| 1942 |
|
| 1943 |
if (memcmp(pSignature, buffer, len) != 0) { |
| 1944 |
ret = CKR_GENERAL_ERROR; |
| 1945 |
goto out; |
| 1946 |
} |
| 1947 |
|
| 1948 |
out: |
| 1949 |
if (buffer) { |
| 1950 |
memset(buffer, 0, buffer_len); |
| 1951 |
free(buffer); |
| 1952 |
} |
| 1953 |
return ret; |
| 1954 |
} |
| 1955 |
|
| 1956 |
|
| 1957 |
CK_RV |
| 1958 |
C_VerifyUpdate(CK_SESSION_HANDLE hSession, |
| 1959 |
CK_BYTE_PTR pPart, |
| 1960 |
CK_ULONG ulPartLen) |
| 1961 |
{ |
| 1962 |
st_logf("VerifyUpdate\n"); |
| 1963 |
VERIFY_SESSION_HANDLE(hSession, NULL); |
| 1964 |
return CKR_FUNCTION_NOT_SUPPORTED; |
| 1965 |
} |
| 1966 |
|
| 1967 |
CK_RV |
| 1968 |
C_VerifyFinal(CK_SESSION_HANDLE hSession, |
| 1969 |
CK_BYTE_PTR pSignature, |
| 1970 |
CK_ULONG ulSignatureLen) |
| 1971 |
{ |
| 1972 |
st_logf("VerifyFinal\n"); |
| 1973 |
VERIFY_SESSION_HANDLE(hSession, NULL); |
| 1974 |
return CKR_FUNCTION_NOT_SUPPORTED; |
| 1975 |
} |
| 1976 |
|
| 1977 |
CK_RV |
| 1978 |
C_GenerateRandom(CK_SESSION_HANDLE hSession, |
| 1979 |
CK_BYTE_PTR RandomData, |
| 1980 |
CK_ULONG ulRandomLen) |
| 1981 |
{ |
| 1982 |
st_logf("GenerateRandom\n"); |
| 1983 |
VERIFY_SESSION_HANDLE(hSession, NULL); |
| 1984 |
return CKR_FUNCTION_NOT_SUPPORTED; |
| 1985 |
} |
| 1986 |
|
| 1987 |
|
| 1988 |
CK_FUNCTION_LIST funcs = { |
| 1989 |
{ 2, 11 }, |
| 1990 |
C_Initialize, |
| 1991 |
C_Finalize, |
| 1992 |
C_GetInfo, |
| 1993 |
C_GetFunctionList, |
| 1994 |
C_GetSlotList, |
| 1995 |
C_GetSlotInfo, |
| 1996 |
C_GetTokenInfo, |
| 1997 |
C_GetMechanismList, |
| 1998 |
C_GetMechanismInfo, |
| 1999 |
C_InitToken, |
| 2000 |
(void *)func_not_supported, /* C_InitPIN */ |
| 2001 |
(void *)func_not_supported, /* C_SetPIN */ |
| 2002 |
C_OpenSession, |
| 2003 |
C_CloseSession, |
| 2004 |
C_CloseAllSessions, |
| 2005 |
C_GetSessionInfo, |
| 2006 |
(void *)func_not_supported, /* C_GetOperationState */ |
| 2007 |
(void *)func_not_supported, /* C_SetOperationState */ |
| 2008 |
C_Login, |
| 2009 |
C_Logout, |
| 2010 |
(void *)func_not_supported, /* C_CreateObject */ |
| 2011 |
(void *)func_not_supported, /* C_CopyObject */ |
| 2012 |
(void *)func_not_supported, /* C_DestroyObject */ |
| 2013 |
(void *)func_not_supported, /* C_GetObjectSize */ |
| 2014 |
C_GetAttributeValue, |
| 2015 |
(void *)func_not_supported, /* C_SetAttributeValue */ |
| 2016 |
C_FindObjectsInit, |
| 2017 |
C_FindObjects, |
| 2018 |
C_FindObjectsFinal, |
| 2019 |
C_EncryptInit, |
| 2020 |
C_Encrypt, |
| 2021 |
C_EncryptUpdate, |
| 2022 |
C_EncryptFinal, |
| 2023 |
C_DecryptInit, |
| 2024 |
C_Decrypt, |
| 2025 |
C_DecryptUpdate, |
| 2026 |
C_DecryptFinal, |
| 2027 |
C_DigestInit, |
| 2028 |
(void *)func_not_supported, /* C_Digest */ |
| 2029 |
(void *)func_not_supported, /* C_DigestUpdate */ |
| 2030 |
(void *)func_not_supported, /* C_DigestKey */ |
| 2031 |
(void *)func_not_supported, /* C_DigestFinal */ |
| 2032 |
C_SignInit, |
| 2033 |
C_Sign, |
| 2034 |
C_SignUpdate, |
| 2035 |
C_SignFinal, |
| 2036 |
(void *)func_not_supported, /* C_SignRecoverInit */ |
| 2037 |
(void *)func_not_supported, /* C_SignRecover */ |
| 2038 |
C_VerifyInit, |
| 2039 |
C_Verify, |
| 2040 |
C_VerifyUpdate, |
| 2041 |
C_VerifyFinal, |
| 2042 |
(void *)func_not_supported, /* C_VerifyRecoverInit */ |
| 2043 |
(void *)func_not_supported, /* C_VerifyRecover */ |
| 2044 |
(void *)func_not_supported, /* C_DigestEncryptUpdate */ |
| 2045 |
(void *)func_not_supported, /* C_DecryptDigestUpdate */ |
| 2046 |
(void *)func_not_supported, /* C_SignEncryptUpdate */ |
| 2047 |
(void *)func_not_supported, /* C_DecryptVerifyUpdate */ |
| 2048 |
(void *)func_not_supported, /* C_GenerateKey */ |
| 2049 |
(void *)func_not_supported, /* C_GenerateKeyPair */ |
| 2050 |
(void *)func_not_supported, /* C_WrapKey */ |
| 2051 |
(void *)func_not_supported, /* C_UnwrapKey */ |
| 2052 |
(void *)func_not_supported, /* C_DeriveKey */ |
| 2053 |
(void *)func_not_supported, /* C_SeedRandom */ |
| 2054 |
C_GenerateRandom, |
| 2055 |
(void *)func_not_supported, /* C_GetFunctionStatus */ |
| 2056 |
(void *)func_not_supported, /* C_CancelFunction */ |
| 2057 |
(void *)func_not_supported /* C_WaitForSlotEvent */ |
| 2058 |
}; |