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