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