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