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