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