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