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