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