1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <pthread.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <strings.h> 32 #include <sys/types.h> 33 #include <security/cryptoki.h> 34 #include <bignum.h> 35 #include "softGlobal.h" 36 #include "softSession.h" 37 #include "softObject.h" 38 #include "softDSA.h" 39 #include "softRandom.h" 40 #include "softOps.h" 41 #include "softMAC.h" 42 #include "softCrypt.h" 43 44 /* 45 * Allocate a DSA context for the active sign or verify operation. 46 * This function is called without the session lock held. 47 */ 48 CK_RV 49 soft_dsa_sign_verify_init_common(soft_session_t *session_p, 50 CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, 51 boolean_t sign) 52 { 53 54 soft_dsa_ctx_t *dsa_ctx; 55 CK_MECHANISM digest_mech; 56 soft_object_t *tmp_key = NULL; 57 CK_RV rv; 58 59 if (sign) { 60 if ((key_p->class != CKO_PRIVATE_KEY) || 61 (key_p->key_type != CKK_DSA)) 62 return (CKR_KEY_TYPE_INCONSISTENT); 63 } else { 64 if ((key_p->class != CKO_PUBLIC_KEY) || 65 (key_p->key_type != CKK_DSA)) 66 return (CKR_KEY_TYPE_INCONSISTENT); 67 } 68 69 if (pMechanism->mechanism == CKM_DSA_SHA1) { 70 digest_mech.mechanism = CKM_SHA_1; 71 rv = soft_digest_init_internal(session_p, &digest_mech); 72 if (rv != CKR_OK) 73 return (rv); 74 } 75 76 dsa_ctx = malloc(sizeof (soft_dsa_ctx_t)); 77 78 if (dsa_ctx == NULL) { 79 return (CKR_HOST_MEMORY); 80 } 81 82 /* 83 * Make a copy of the signature or verification key, and save it 84 * in the DSA crypto context since it will be used later for 85 * signing/verification. We don't want to hold any object reference 86 * on this original key while doing signing/verification. 87 */ 88 (void) pthread_mutex_lock(&key_p->object_mutex); 89 rv = soft_copy_object(key_p, &tmp_key, SOFT_COPY_OBJ_ORIG_SH, 90 NULL); 91 92 if ((rv != CKR_OK) || (tmp_key == NULL)) { 93 /* Most likely we ran out of space. */ 94 (void) pthread_mutex_unlock(&key_p->object_mutex); 95 free(dsa_ctx); 96 return (rv); 97 } 98 99 /* No need to hold the lock on the old object. */ 100 (void) pthread_mutex_unlock(&key_p->object_mutex); 101 dsa_ctx->key = tmp_key; 102 103 (void) pthread_mutex_lock(&session_p->session_mutex); 104 105 if (sign) { 106 session_p->sign.context = dsa_ctx; 107 session_p->sign.mech.mechanism = pMechanism->mechanism; 108 } else { 109 session_p->verify.context = dsa_ctx; 110 session_p->verify.mech.mechanism = pMechanism->mechanism; 111 } 112 113 (void) pthread_mutex_unlock(&session_p->session_mutex); 114 115 return (CKR_OK); 116 } 117 118 BIG_ERR_CODE 119 DSA_key_init(DSAkey *key, int size) 120 { 121 BIG_ERR_CODE err; 122 int len; 123 124 len = size / 32; 125 key->size = size; 126 if ((err = big_init1(&(key->q), 5, NULL, 0)) != BIG_OK) 127 return (err); 128 if ((err = big_init1(&(key->p), len, NULL, 0)) != BIG_OK) 129 goto ret1; 130 if ((err = big_init1(&(key->g), len, NULL, 0)) != BIG_OK) 131 goto ret2; 132 if ((err = big_init1(&(key->x), 5, NULL, 0)) != BIG_OK) 133 goto ret3; 134 if ((err = big_init1(&(key->y), len, NULL, 0)) != BIG_OK) 135 goto ret4; 136 if ((err = big_init1(&(key->k), 5, NULL, 0)) != BIG_OK) 137 goto ret5; 138 if ((err = big_init1(&(key->r), 5, NULL, 0)) != BIG_OK) 139 goto ret6; 140 if ((err = big_init1(&(key->s), 5, NULL, 0)) != BIG_OK) 141 goto ret7; 142 if ((err = big_init1(&(key->v), 5, NULL, 0)) != BIG_OK) 143 goto ret8; 144 145 return (BIG_OK); 146 147 ret8: 148 big_finish(&(key->s)); 149 ret7: 150 big_finish(&(key->r)); 151 ret6: 152 big_finish(&(key->k)); 153 ret5: 154 big_finish(&(key->y)); 155 ret4: 156 big_finish(&(key->x)); 157 ret3: 158 big_finish(&(key->g)); 159 ret2: 160 big_finish(&(key->p)); 161 ret1: 162 big_finish(&(key->q)); 163 return (err); 164 } 165 166 167 void 168 DSA_key_finish(DSAkey *key) 169 { 170 big_finish(&(key->v)); 171 big_finish(&(key->s)); 172 big_finish(&(key->r)); 173 big_finish(&(key->k)); 174 big_finish(&(key->y)); 175 big_finish(&(key->x)); 176 big_finish(&(key->g)); 177 big_finish(&(key->p)); 178 big_finish(&(key->q)); 179 } 180 181 182 CK_RV 183 dsa_sign(soft_object_t *key, CK_BYTE_PTR in, CK_ULONG inlen, CK_BYTE_PTR out) 184 { 185 186 uchar_t q[MAX_KEY_ATTR_BUFLEN]; 187 uchar_t p[MAX_KEY_ATTR_BUFLEN]; 188 uchar_t g[MAX_KEY_ATTR_BUFLEN]; 189 uchar_t x[MAX_KEY_ATTR_BUFLEN]; 190 uint_t qlen = sizeof (q); 191 uint_t plen = sizeof (p); 192 uint_t glen = sizeof (g); 193 uint_t xlen = sizeof (x); 194 DSAkey dsakey; 195 BIGNUM msg, tmp, tmp1, tmp2; 196 BIG_ERR_CODE err; 197 CK_RV rv; 198 199 rv = soft_get_private_attr(key, CKA_SUBPRIME, q, &qlen); 200 if (rv != CKR_OK) { 201 goto clean1; 202 } 203 204 if (20 != qlen) { 205 rv = CKR_KEY_SIZE_RANGE; 206 goto clean1; 207 } 208 209 rv = soft_get_private_attr(key, CKA_PRIME, p, &plen); 210 if (rv != CKR_OK) { 211 goto clean1; 212 } 213 214 rv = soft_get_private_attr(key, CKA_BASE, g, &glen); 215 if (rv != CKR_OK) { 216 goto clean1; 217 } 218 219 if (glen != plen) { 220 rv = CKR_KEY_SIZE_RANGE; 221 goto clean1; 222 } 223 224 rv = soft_get_private_attr(key, CKA_VALUE, x, &xlen); 225 if (rv != CKR_OK) { 226 goto clean1; 227 } 228 229 if (20 < xlen) { 230 rv = CKR_KEY_SIZE_RANGE; 231 goto clean1; 232 } 233 234 if ((err = DSA_key_init(&dsakey, plen * 8)) != BIG_OK) { 235 rv = CKR_HOST_MEMORY; 236 goto clean1; 237 } 238 239 if ((err = big_init(&msg, 5)) != BIG_OK) { 240 goto clean6; 241 } 242 if ((err = big_init(&tmp, plen / 4 + 11)) != BIG_OK) { 243 goto clean7; 244 } 245 if ((err = big_init(&tmp1, 11)) != BIG_OK) { 246 goto clean8; 247 } 248 if ((err = big_init(&tmp2, 5)) != BIG_OK) { 249 goto clean9; 250 } 251 252 bytestring2bignum(&(dsakey.g), g, plen); 253 bytestring2bignum(&(dsakey.x), x, 20); 254 bytestring2bignum(&(dsakey.p), p, plen); 255 bytestring2bignum(&(dsakey.q), q, 20); 256 bytestring2bignum(&msg, (uchar_t *)in, inlen); 257 258 if ((err = random_bignum(&(dsakey.k), DSA_SUBPRIME_BITS, 259 B_FALSE)) != BIG_OK) 260 goto clean10; 261 262 if ((err = big_div_pos(NULL, &(dsakey.k), &(dsakey.k), 263 &(dsakey.q))) != BIG_OK) 264 goto clean10; 265 266 if ((err = big_modexp(&tmp, &(dsakey.g), &(dsakey.k), &(dsakey.p), 267 NULL)) != BIG_OK) 268 goto clean10; 269 270 if ((err = big_div_pos(NULL, &(dsakey.r), &tmp, &(dsakey.q))) != 271 BIG_OK) 272 goto clean10; 273 274 if ((err = big_ext_gcd_pos(NULL, NULL, &tmp, &(dsakey.q), 275 &(dsakey.k))) != BIG_OK) 276 goto clean10; 277 278 if (tmp.sign == -1) 279 if ((err = big_add(&tmp, &tmp, &(dsakey.q))) != BIG_OK) 280 goto clean10; /* tmp <- k^-1 */ 281 282 if ((err = big_mul(&tmp1, &(dsakey.x), &(dsakey.r))) != BIG_OK) 283 goto clean10; 284 285 if ((err = big_add(&tmp1, &tmp1, &msg)) != BIG_OK) 286 goto clean10; 287 288 if ((err = big_mul(&tmp, &tmp1, &tmp)) != BIG_OK) 289 goto clean10; 290 291 if ((err = big_div_pos(NULL, &(dsakey.s), &tmp, &(dsakey.q))) != 292 BIG_OK) 293 goto clean10; 294 295 bignum2bytestring((uchar_t *)out, &(dsakey.r), 20); 296 bignum2bytestring((uchar_t *)out + 20, &(dsakey.s), 20); 297 298 err = BIG_OK; 299 300 clean10: 301 big_finish(&tmp2); 302 clean9: 303 big_finish(&tmp1); 304 clean8: 305 big_finish(&tmp); 306 clean7: 307 big_finish(&msg); 308 clean6: 309 DSA_key_finish(&dsakey); 310 if (err == BIG_OK) 311 rv = CKR_OK; 312 else if (err == BIG_NO_MEM) 313 rv = CKR_HOST_MEMORY; 314 else 315 rv = CKR_FUNCTION_FAILED; 316 clean1: 317 return (rv); 318 } 319 320 CK_RV 321 dsa_verify(soft_object_t *key, CK_BYTE_PTR data, CK_BYTE_PTR sig) 322 { 323 324 uchar_t g[MAX_KEY_ATTR_BUFLEN]; 325 uchar_t y[MAX_KEY_ATTR_BUFLEN]; 326 uchar_t p[MAX_KEY_ATTR_BUFLEN]; 327 uchar_t q[MAX_KEY_ATTR_BUFLEN]; 328 uint_t glen = sizeof (g); 329 uint_t ylen = sizeof (y); 330 uint_t plen = sizeof (p); 331 uint_t qlen = sizeof (q); 332 DSAkey dsakey; 333 BIGNUM msg, tmp1, tmp2, tmp3; 334 CK_RV rv; 335 336 rv = soft_get_public_attr(key, CKA_SUBPRIME, q, &qlen); 337 if (rv != CKR_OK) { 338 goto clean1; 339 } 340 341 if (20 != qlen) { 342 rv = CKR_KEY_SIZE_RANGE; 343 goto clean1; 344 } 345 346 rv = soft_get_public_attr(key, CKA_PRIME, p, &plen); 347 if (rv != CKR_OK) { 348 goto clean1; 349 } 350 351 rv = soft_get_public_attr(key, CKA_BASE, g, &glen); 352 if (rv != CKR_OK) { 353 goto clean1; 354 } 355 356 if (plen < glen) { 357 rv = CKR_KEY_SIZE_RANGE; 358 goto clean1; 359 } 360 361 rv = soft_get_public_attr(key, CKA_VALUE, y, &ylen); 362 if (rv != CKR_OK) { 363 goto clean1; 364 } 365 366 if (plen < ylen) { 367 rv = CKR_KEY_SIZE_RANGE; 368 goto clean1; 369 } 370 371 if (DSA_key_init(&dsakey, plen * 8) != BIG_OK) { 372 rv = CKR_HOST_MEMORY; 373 goto clean1; 374 } 375 376 rv = CKR_HOST_MEMORY; 377 if (big_init(&msg, 5) != BIG_OK) { 378 goto clean6; 379 } 380 if (big_init(&tmp1, plen / 2) != BIG_OK) { 381 goto clean7; 382 } 383 if (big_init(&tmp2, plen / 4) != BIG_OK) { 384 goto clean8; 385 } 386 if (big_init(&tmp3, 10) != BIG_OK) { 387 goto clean9; 388 } 389 390 bytestring2bignum(&(dsakey.g), g, glen); 391 bytestring2bignum(&(dsakey.y), y, ylen); 392 bytestring2bignum(&(dsakey.p), p, plen); 393 bytestring2bignum(&(dsakey.q), q, 20); 394 bytestring2bignum(&(dsakey.r), (uchar_t *)sig, 20); 395 bytestring2bignum(&(dsakey.s), ((uchar_t *)sig) + 20, 20); 396 bytestring2bignum(&msg, (uchar_t *)data, 20); 397 398 if (big_ext_gcd_pos(NULL, &tmp2, NULL, &(dsakey.s), &(dsakey.q)) != 399 BIG_OK) 400 goto clean10; 401 402 if (tmp2.sign == -1) 403 if (big_add(&tmp2, &tmp2, &(dsakey.q)) != BIG_OK) 404 goto clean10; /* tmp2 <- w */ 405 406 if (big_mul(&tmp1, &msg, &tmp2) != BIG_OK) 407 goto clean10; 408 409 if (big_div_pos(NULL, &tmp1, &tmp1, &(dsakey.q)) != BIG_OK) 410 goto clean10; /* tmp1 <- u_1 */ 411 412 if (big_mul(&tmp2, &tmp2, &(dsakey.r)) != BIG_OK) 413 goto clean10; 414 415 if (big_div_pos(NULL, &tmp2, &tmp2, &(dsakey.q)) != BIG_OK) 416 goto clean10; /* tmp2 <- u_2 */ 417 418 if (big_modexp(&tmp1, &(dsakey.g), &tmp1, &(dsakey.p), NULL) != 419 BIG_OK) 420 goto clean10; 421 422 if (big_modexp(&tmp2, &(dsakey.y), &tmp2, &(dsakey.p), NULL) != 423 BIG_OK) 424 goto clean10; 425 426 if (big_mul(&tmp1, &tmp1, &tmp2) != BIG_OK) 427 goto clean10; 428 429 if (big_div_pos(NULL, &tmp1, &tmp1, &(dsakey.p)) != BIG_OK) 430 goto clean10; 431 432 if (big_div_pos(NULL, &tmp1, &tmp1, &(dsakey.q)) != BIG_OK) 433 goto clean10; 434 435 if (big_cmp_abs(&tmp1, &(dsakey.r)) == 0) 436 rv = CKR_OK; 437 else 438 rv = CKR_SIGNATURE_INVALID; 439 440 clean10: 441 big_finish(&tmp3); 442 clean9: 443 big_finish(&tmp2); 444 clean8: 445 big_finish(&tmp1); 446 clean7: 447 big_finish(&msg); 448 clean6: 449 DSA_key_finish(&dsakey); 450 clean1: 451 return (rv); 452 } 453 454 455 CK_RV 456 soft_dsa_digest_sign_common(soft_session_t *session_p, CK_BYTE_PTR pData, 457 CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 458 CK_ULONG_PTR pulSignedLen, boolean_t Final) 459 { 460 461 CK_RV rv = CKR_OK; 462 CK_BYTE hash[SHA1_HASH_SIZE]; /* space enough for SHA1 and MD5 */ 463 CK_ULONG hash_len = SHA1_HASH_SIZE; 464 soft_dsa_ctx_t *dsa_ctx = session_p->sign.context; 465 soft_object_t *key = dsa_ctx->key; 466 467 /* Check arguments before performing message digest. */ 468 if (pSigned == NULL) { 469 /* Application asks for the length of the output buffer. */ 470 *pulSignedLen = DSA_SIGNATURE_LENGTH; 471 goto clean1; 472 } 473 474 /* Is the application-supplied buffer large enough? */ 475 if (*pulSignedLen < DSA_SIGNATURE_LENGTH) { 476 *pulSignedLen = DSA_SIGNATURE_LENGTH; 477 rv = CKR_BUFFER_TOO_SMALL; 478 goto clean1; 479 } 480 481 if (Final) { 482 rv = soft_digest_final(session_p, hash, &hash_len); 483 } else { 484 rv = soft_digest(session_p, pData, ulDataLen, hash, &hash_len); 485 } 486 487 if (rv != CKR_OK) { 488 /* free the signature key */ 489 soft_cleanup_object(key); 490 free(key); 491 goto clean_exit; 492 } 493 494 /* 495 * Now, we are ready to sign the data 496 * soft_dsa_sign() will free the signature key. 497 */ 498 rv = soft_dsa_sign(session_p, hash, hash_len, pSigned, pulSignedLen); 499 500 clean_exit: 501 (void) pthread_mutex_lock(&session_p->session_mutex); 502 /* soft_digest_common() has freed the digest context */ 503 session_p->digest.flags = 0; 504 (void) pthread_mutex_unlock(&session_p->session_mutex); 505 506 clean1: 507 return (rv); 508 } 509 510 511 CK_RV 512 soft_dsa_sign(soft_session_t *session_p, CK_BYTE_PTR pData, 513 CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 514 CK_ULONG_PTR pulSignedLen) 515 { 516 517 CK_RV rv = CKR_OK; 518 soft_dsa_ctx_t *dsa_ctx = session_p->sign.context; 519 soft_object_t *key = dsa_ctx->key; 520 521 if ((key->class != CKO_PRIVATE_KEY) || (key->key_type != CKK_DSA)) { 522 rv = CKR_KEY_TYPE_INCONSISTENT; 523 goto clean_exit; 524 } 525 526 /* Output length is always 40 bytes. */ 527 if (pSigned == NULL) { 528 /* Application asks for the length of the output buffer. */ 529 *pulSignedLen = DSA_SIGNATURE_LENGTH; 530 return (CKR_OK); 531 } 532 533 /* Input data length needs to be 20 bytes. */ 534 if (ulDataLen != 20) { 535 rv = CKR_DATA_LEN_RANGE; 536 goto clean_exit; 537 } 538 539 if (*pulSignedLen < DSA_SIGNATURE_LENGTH) { 540 *pulSignedLen = DSA_SIGNATURE_LENGTH; 541 return (CKR_BUFFER_TOO_SMALL); 542 } 543 544 rv = dsa_sign(key, pData, ulDataLen, pSigned); 545 if (rv == CKR_OK) { 546 *pulSignedLen = DSA_SIGNATURE_LENGTH; 547 } 548 549 clean_exit: 550 (void) pthread_mutex_lock(&session_p->session_mutex); 551 free(session_p->sign.context); 552 session_p->sign.context = NULL; 553 (void) pthread_mutex_unlock(&session_p->session_mutex); 554 soft_cleanup_object(key); 555 free(key); 556 return (rv); 557 } 558 559 560 CK_RV 561 soft_dsa_verify(soft_session_t *session_p, CK_BYTE_PTR pData, 562 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, 563 CK_ULONG ulSignatureLen) 564 { 565 566 CK_RV rv = CKR_OK; 567 soft_dsa_ctx_t *dsa_ctx = session_p->verify.context; 568 soft_object_t *key = dsa_ctx->key; 569 570 if ((key->class != CKO_PUBLIC_KEY) ||(key->key_type != CKK_DSA)) { 571 rv = CKR_KEY_TYPE_INCONSISTENT; 572 goto clean_exit; 573 } 574 575 /* The signature length is always 40 bytes. */ 576 if (ulSignatureLen != DSA_SIGNATURE_LENGTH) { 577 rv = CKR_SIGNATURE_LEN_RANGE; 578 goto clean_exit; 579 } 580 581 /* Input data length needs to be 20 bytes. */ 582 if (ulDataLen != 20) { 583 rv = CKR_DATA_LEN_RANGE; 584 goto clean_exit; 585 } 586 587 rv = dsa_verify(key, pData, pSignature); 588 589 clean_exit: 590 (void) pthread_mutex_lock(&session_p->session_mutex); 591 free(session_p->verify.context); 592 session_p->verify.context = NULL; 593 (void) pthread_mutex_unlock(&session_p->session_mutex); 594 soft_cleanup_object(key); 595 free(key); 596 return (rv); 597 } 598 599 600 CK_RV 601 soft_dsa_digest_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData, 602 CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 603 CK_ULONG ulSignedLen, boolean_t Final) 604 { 605 606 CK_RV rv; 607 CK_BYTE hash[SHA1_HASH_SIZE]; /* space enough for SHA1 and MD5 */ 608 CK_ULONG hash_len = SHA1_HASH_SIZE; 609 soft_dsa_ctx_t *dsa_ctx = session_p->verify.context; 610 soft_object_t *key = dsa_ctx->key; 611 612 if (Final) { 613 rv = soft_digest_final(session_p, hash, &hash_len); 614 } else { 615 rv = soft_digest(session_p, pData, ulDataLen, hash, &hash_len); 616 } 617 618 if (rv != CKR_OK) { 619 /* free the verification key */ 620 soft_cleanup_object(key); 621 free(key); 622 goto clean_exit; 623 } 624 625 /* 626 * Now, we are ready to verify the data using signature. 627 * soft_dsa_verify() will free the verification key. 628 */ 629 rv = soft_dsa_verify(session_p, hash, hash_len, 630 pSigned, ulSignedLen); 631 632 clean_exit: 633 (void) pthread_mutex_lock(&session_p->session_mutex); 634 /* soft_digest_common() has freed the digest context */ 635 session_p->digest.flags = 0; 636 (void) pthread_mutex_unlock(&session_p->session_mutex); 637 return (rv); 638 } 639 640 641 CK_RV 642 soft_genDSAkey_set_attribute(soft_object_t *key, CK_ATTRIBUTE_TYPE type, 643 uchar_t *value, uint32_t value_len, boolean_t public) 644 { 645 646 CK_RV rv = CKR_OK; 647 biginteger_t *dst = NULL; 648 biginteger_t src; 649 650 651 switch (type) { 652 653 case CKA_VALUE: 654 if (public) 655 dst = OBJ_PUB_DSA_VALUE(key); 656 else 657 dst = OBJ_PRI_DSA_VALUE(key); 658 break; 659 660 case CKA_PRIME: 661 if (public) 662 dst = OBJ_PUB_DSA_PRIME(key); 663 else 664 dst = OBJ_PRI_DSA_PRIME(key); 665 break; 666 667 case CKA_SUBPRIME: 668 if (public) 669 dst = OBJ_PUB_DSA_SUBPRIME(key); 670 else 671 dst = OBJ_PRI_DSA_SUBPRIME(key); 672 break; 673 674 case CKA_BASE: 675 if (public) 676 dst = OBJ_PUB_DSA_BASE(key); 677 else 678 dst = OBJ_PRI_DSA_BASE(key); 679 break; 680 } 681 682 src.big_value_len = value_len; 683 684 if ((src.big_value = malloc(value_len)) == NULL) { 685 rv = CKR_HOST_MEMORY; 686 goto cleanexit; 687 } 688 (void) memcpy(src.big_value, value, value_len); 689 690 /* Copy the attribute in the key object. */ 691 copy_bigint_attr(&src, dst); 692 693 cleanexit: 694 /* No need to free big_value because dst holds it now after copy. */ 695 return (rv); 696 697 } 698 699 700 CK_RV 701 generate_dsa_key(DSAkey *key, boolean_t token_obj) 702 { 703 BIG_ERR_CODE err; 704 705 do { 706 if ((err = random_bignum(&(key->x), DSA_SUBPRIME_BITS, 707 token_obj)) != BIG_OK) { 708 return (convert_rv(err)); 709 } 710 } while (big_cmp_abs(&(key->x), &(key->q)) > 0); 711 712 if ((err = big_modexp(&(key->y), &(key->g), (&key->x), 713 (&key->p), NULL)) != BIG_OK) 714 return (convert_rv(err)); 715 716 return (CKR_OK); 717 } 718 719 720 CK_RV 721 soft_dsa_genkey_pair(soft_object_t *pubkey, soft_object_t *prikey) 722 { 723 BIG_ERR_CODE brv; 724 CK_RV rv; 725 uchar_t prime[MAX_KEY_ATTR_BUFLEN]; 726 uint32_t prime_len = sizeof (prime); 727 uchar_t subprime[MAX_KEY_ATTR_BUFLEN]; 728 uint32_t subprime_len = sizeof (subprime); 729 uchar_t base[MAX_KEY_ATTR_BUFLEN]; 730 uint32_t base_len = sizeof (base); 731 uchar_t *pubvalue; 732 uint32_t pubvalue_len; 733 uchar_t *privalue; 734 uint32_t privalue_len; 735 DSAkey dsakey = {0}; 736 737 pubvalue = NULL; 738 privalue = NULL; 739 740 if ((pubkey == NULL) || (prikey == NULL)) { 741 return (CKR_ARGUMENTS_BAD); 742 } 743 744 /* lookup prime, subprime and base */ 745 rv = soft_get_public_attr(pubkey, CKA_PRIME, prime, &prime_len); 746 if (rv != CKR_OK) { 747 rv = CKR_TEMPLATE_INCOMPLETE; 748 goto cleanexit; 749 } 750 751 if ((prime_len < MIN_DSA_KEY_LEN) || 752 (prime_len > MAX_DSA_KEY_LEN)) { 753 rv = CKR_ATTRIBUTE_VALUE_INVALID; 754 goto cleanexit; 755 } 756 757 rv = soft_get_public_attr(pubkey, CKA_SUBPRIME, subprime, 758 &subprime_len); 759 if (rv != CKR_OK) { 760 rv = CKR_TEMPLATE_INCOMPLETE; 761 goto cleanexit; 762 } 763 764 if (subprime_len != DSA_SUBPRIME_BYTES) { 765 rv = CKR_ATTRIBUTE_VALUE_INVALID; 766 goto cleanexit; 767 } 768 769 rv = soft_get_public_attr(pubkey, CKA_BASE, base, &base_len); 770 if (rv != CKR_OK) { 771 rv = CKR_TEMPLATE_INCOMPLETE; 772 goto cleanexit; 773 } 774 775 /* 776 * initialize the dsa key 777 * Note: big_extend takes length in words 778 */ 779 if ((brv = DSA_key_init(&dsakey, prime_len * 8)) != BIG_OK) { 780 rv = convert_rv(brv); 781 goto cleanexit; 782 } 783 784 if ((brv = big_extend(&dsakey.p, (prime_len + 3) / 4)) != BIG_OK) { 785 rv = convert_rv(brv); 786 goto cleanexit; 787 } 788 789 bytestring2bignum(&dsakey.p, prime, prime_len); 790 791 if ((brv = big_extend(&dsakey.q, (subprime_len + 3) / 4)) != BIG_OK) { 792 rv = convert_rv(brv); 793 goto cleanexit; 794 } 795 796 bytestring2bignum(&dsakey.q, subprime, subprime_len); 797 798 if ((brv = big_extend(&dsakey.g, (base_len + 3) / 4)) != BIG_OK) { 799 rv = convert_rv(brv); 800 goto cleanexit; 801 } 802 803 bytestring2bignum(&dsakey.g, base, base_len); 804 805 /* 806 * generate DSA key pair 807 * Note: bignum.len is length of value in words 808 */ 809 if ((rv = generate_dsa_key(&dsakey, (IS_TOKEN_OBJECT(pubkey) || 810 IS_TOKEN_OBJECT(prikey)))) != CKR_OK) { 811 goto cleanexit; 812 } 813 814 pubvalue_len = dsakey.y.len * (int)sizeof (uint32_t); 815 if ((pubvalue = malloc(pubvalue_len)) == NULL) { 816 rv = CKR_HOST_MEMORY; 817 goto cleanexit; 818 } 819 bignum2bytestring(pubvalue, &dsakey.y, pubvalue_len); 820 821 privalue_len = dsakey.x.len * (int)sizeof (uint32_t); 822 if ((privalue = malloc(privalue_len)) == NULL) { 823 rv = CKR_HOST_MEMORY; 824 goto cleanexit; 825 } 826 bignum2bytestring(privalue, &dsakey.x, privalue_len); 827 828 /* Update attribute in public key. */ 829 if ((rv = soft_genDSAkey_set_attribute(pubkey, CKA_VALUE, 830 pubvalue, pubvalue_len, B_TRUE)) != CKR_OK) { 831 goto cleanexit; 832 } 833 /* Update attributes in private key. */ 834 if ((rv = soft_genDSAkey_set_attribute(prikey, CKA_PRIME, 835 prime, prime_len, B_FALSE)) != CKR_OK) { 836 goto cleanexit; 837 } 838 839 if ((rv = soft_genDSAkey_set_attribute(prikey, CKA_SUBPRIME, 840 subprime, subprime_len, B_FALSE)) != CKR_OK) { 841 goto cleanexit; 842 } 843 844 if ((rv = soft_genDSAkey_set_attribute(prikey, CKA_BASE, 845 base, base_len, B_FALSE)) != CKR_OK) { 846 goto cleanexit; 847 } 848 849 if ((rv = soft_genDSAkey_set_attribute(prikey, CKA_VALUE, 850 privalue, privalue_len, B_FALSE)) != CKR_OK) { 851 goto cleanexit; 852 } 853 854 cleanexit: 855 DSA_key_finish(&dsakey); 856 857 if (pubvalue != NULL) { 858 free(pubvalue); 859 } 860 861 if (privalue != NULL) { 862 free(privalue); 863 } 864 865 return (rv); 866 } 867