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 2008 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 119 /* size is in bits */ 120 BIG_ERR_CODE 121 DSA_key_init(DSAkey *key, int size) 122 { 123 BIG_ERR_CODE err; 124 int len, len160; 125 126 len = BITLEN2BIGNUMLEN(size); 127 len160 = BIG_CHUNKS_FOR_160BITS; 128 key->size = size; 129 if ((err = big_init1(&(key->q), len160, NULL, 0)) != BIG_OK) 130 return (err); 131 if ((err = big_init1(&(key->p), len, NULL, 0)) != BIG_OK) 132 goto ret1; 133 if ((err = big_init1(&(key->g), len, NULL, 0)) != BIG_OK) 134 goto ret2; 135 if ((err = big_init1(&(key->x), len160, NULL, 0)) != BIG_OK) 136 goto ret3; 137 if ((err = big_init1(&(key->y), len, NULL, 0)) != BIG_OK) 138 goto ret4; 139 if ((err = big_init1(&(key->k), len160, NULL, 0)) != BIG_OK) 140 goto ret5; 141 if ((err = big_init1(&(key->r), len160, NULL, 0)) != BIG_OK) 142 goto ret6; 143 if ((err = big_init1(&(key->s), len160, NULL, 0)) != BIG_OK) 144 goto ret7; 145 if ((err = big_init1(&(key->v), len160, NULL, 0)) != BIG_OK) 146 goto ret8; 147 148 return (BIG_OK); 149 150 ret8: 151 big_finish(&(key->s)); 152 ret7: 153 big_finish(&(key->r)); 154 ret6: 155 big_finish(&(key->k)); 156 ret5: 157 big_finish(&(key->y)); 158 ret4: 159 big_finish(&(key->x)); 160 ret3: 161 big_finish(&(key->g)); 162 ret2: 163 big_finish(&(key->p)); 164 ret1: 165 big_finish(&(key->q)); 166 return (err); 167 } 168 169 170 void 171 DSA_key_finish(DSAkey *key) 172 { 173 big_finish(&(key->v)); 174 big_finish(&(key->s)); 175 big_finish(&(key->r)); 176 big_finish(&(key->k)); 177 big_finish(&(key->y)); 178 big_finish(&(key->x)); 179 big_finish(&(key->g)); 180 big_finish(&(key->p)); 181 big_finish(&(key->q)); 182 } 183 184 185 CK_RV 186 dsa_sign(soft_object_t *key, CK_BYTE_PTR in, CK_ULONG inlen, CK_BYTE_PTR out) 187 { 188 189 uchar_t q[MAX_KEY_ATTR_BUFLEN]; 190 uchar_t p[MAX_KEY_ATTR_BUFLEN]; 191 uchar_t g[MAX_KEY_ATTR_BUFLEN]; 192 uchar_t x[MAX_KEY_ATTR_BUFLEN]; 193 uint_t qlen = sizeof (q); 194 uint_t plen = sizeof (p); 195 uint_t glen = sizeof (g); 196 uint_t xlen = sizeof (x); 197 DSAkey dsakey; 198 BIGNUM msg, tmp, tmp1, tmp2; 199 BIG_ERR_CODE err; 200 CK_RV rv; 201 202 rv = soft_get_private_attr(key, CKA_SUBPRIME, q, &qlen); 203 if (rv != CKR_OK) { 204 goto clean1; 205 } 206 207 if (20 != qlen) { 208 rv = CKR_KEY_SIZE_RANGE; 209 goto clean1; 210 } 211 212 rv = soft_get_private_attr(key, CKA_PRIME, p, &plen); 213 if (rv != CKR_OK) { 214 goto clean1; 215 } 216 217 rv = soft_get_private_attr(key, CKA_BASE, g, &glen); 218 if (rv != CKR_OK) { 219 goto clean1; 220 } 221 222 if (glen != plen) { 223 rv = CKR_KEY_SIZE_RANGE; 224 goto clean1; 225 } 226 227 rv = soft_get_private_attr(key, CKA_VALUE, x, &xlen); 228 if (rv != CKR_OK) { 229 goto clean1; 230 } 231 232 if (20 < xlen) { 233 rv = CKR_KEY_SIZE_RANGE; 234 goto clean1; 235 } 236 237 if ((err = DSA_key_init(&dsakey, plen * 8)) != BIG_OK) { 238 rv = CKR_HOST_MEMORY; 239 goto clean1; 240 } 241 242 if ((err = big_init(&msg, BIG_CHUNKS_FOR_160BITS)) != BIG_OK) { 243 goto clean6; 244 } 245 if ((err = big_init(&tmp, CHARLEN2BIGNUMLEN(plen) + 246 2 * BIG_CHUNKS_FOR_160BITS + 1)) != BIG_OK) { 247 goto clean7; 248 } 249 if ((err = big_init(&tmp1, 2 * BIG_CHUNKS_FOR_160BITS + 1)) != BIG_OK) { 250 goto clean8; 251 } 252 if ((err = big_init(&tmp2, BIG_CHUNKS_FOR_160BITS)) != BIG_OK) { 253 goto clean9; 254 } 255 256 bytestring2bignum(&(dsakey.g), g, plen); 257 bytestring2bignum(&(dsakey.x), x, 20); 258 bytestring2bignum(&(dsakey.p), p, plen); 259 bytestring2bignum(&(dsakey.q), q, 20); 260 bytestring2bignum(&msg, (uchar_t *)in, inlen); 261 262 if ((err = random_bignum(&(dsakey.k), DSA_SUBPRIME_BITS, 263 B_FALSE)) != BIG_OK) 264 goto clean10; 265 266 if ((err = big_div_pos(NULL, &(dsakey.k), &(dsakey.k), 267 &(dsakey.q))) != BIG_OK) 268 goto clean10; 269 270 if ((err = big_modexp(&tmp, &(dsakey.g), &(dsakey.k), &(dsakey.p), 271 NULL)) != BIG_OK) 272 goto clean10; 273 274 if ((err = big_div_pos(NULL, &(dsakey.r), &tmp, &(dsakey.q))) != 275 BIG_OK) 276 goto clean10; 277 278 if ((err = big_ext_gcd_pos(NULL, NULL, &tmp, &(dsakey.q), 279 &(dsakey.k))) != BIG_OK) 280 goto clean10; 281 282 if (tmp.sign == -1) 283 if ((err = big_add(&tmp, &tmp, &(dsakey.q))) != BIG_OK) 284 goto clean10; /* tmp <- k^-1 */ 285 286 if ((err = big_mul(&tmp1, &(dsakey.x), &(dsakey.r))) != BIG_OK) 287 goto clean10; 288 289 if ((err = big_add(&tmp1, &tmp1, &msg)) != BIG_OK) 290 goto clean10; 291 292 if ((err = big_mul(&tmp, &tmp1, &tmp)) != BIG_OK) 293 goto clean10; 294 295 if ((err = big_div_pos(NULL, &(dsakey.s), &tmp, &(dsakey.q))) != 296 BIG_OK) 297 goto clean10; 298 299 bignum2bytestring((uchar_t *)out, &(dsakey.r), 20); 300 bignum2bytestring((uchar_t *)out + 20, &(dsakey.s), 20); 301 302 err = BIG_OK; 303 304 clean10: 305 big_finish(&tmp2); 306 clean9: 307 big_finish(&tmp1); 308 clean8: 309 big_finish(&tmp); 310 clean7: 311 big_finish(&msg); 312 clean6: 313 DSA_key_finish(&dsakey); 314 if (err == BIG_OK) 315 rv = CKR_OK; 316 else if (err == BIG_NO_MEM) 317 rv = CKR_HOST_MEMORY; 318 else 319 rv = CKR_FUNCTION_FAILED; 320 clean1: 321 return (rv); 322 } 323 324 CK_RV 325 dsa_verify(soft_object_t *key, CK_BYTE_PTR data, CK_BYTE_PTR sig) 326 { 327 328 uchar_t g[MAX_KEY_ATTR_BUFLEN]; 329 uchar_t y[MAX_KEY_ATTR_BUFLEN]; 330 uchar_t p[MAX_KEY_ATTR_BUFLEN]; 331 uchar_t q[MAX_KEY_ATTR_BUFLEN]; 332 uint_t glen = sizeof (g); 333 uint_t ylen = sizeof (y); 334 uint_t plen = sizeof (p); 335 uint_t qlen = sizeof (q); 336 DSAkey dsakey; 337 BIGNUM msg, tmp1, tmp2, tmp3; 338 CK_RV rv; 339 340 rv = soft_get_public_attr(key, CKA_SUBPRIME, q, &qlen); 341 if (rv != CKR_OK) { 342 goto clean1; 343 } 344 345 if (20 != qlen) { 346 rv = CKR_KEY_SIZE_RANGE; 347 goto clean1; 348 } 349 350 rv = soft_get_public_attr(key, CKA_PRIME, p, &plen); 351 if (rv != CKR_OK) { 352 goto clean1; 353 } 354 355 rv = soft_get_public_attr(key, CKA_BASE, g, &glen); 356 if (rv != CKR_OK) { 357 goto clean1; 358 } 359 360 if (plen < glen) { 361 rv = CKR_KEY_SIZE_RANGE; 362 goto clean1; 363 } 364 365 rv = soft_get_public_attr(key, CKA_VALUE, y, &ylen); 366 if (rv != CKR_OK) { 367 goto clean1; 368 } 369 370 if (plen < ylen) { 371 rv = CKR_KEY_SIZE_RANGE; 372 goto clean1; 373 } 374 375 if (DSA_key_init(&dsakey, plen * 8) != BIG_OK) { 376 rv = CKR_HOST_MEMORY; 377 goto clean1; 378 } 379 380 rv = CKR_HOST_MEMORY; 381 if (big_init(&msg, BIG_CHUNKS_FOR_160BITS) != BIG_OK) { 382 goto clean6; 383 } 384 if (big_init(&tmp1, 2 * CHARLEN2BIGNUMLEN(plen)) != BIG_OK) { 385 goto clean7; 386 } 387 if (big_init(&tmp2, CHARLEN2BIGNUMLEN(plen)) != BIG_OK) { 388 goto clean8; 389 } 390 if (big_init(&tmp3, 2 * BIG_CHUNKS_FOR_160BITS) != BIG_OK) { 391 goto clean9; 392 } 393 394 bytestring2bignum(&(dsakey.g), g, glen); 395 bytestring2bignum(&(dsakey.y), y, ylen); 396 bytestring2bignum(&(dsakey.p), p, plen); 397 bytestring2bignum(&(dsakey.q), q, 20); 398 bytestring2bignum(&(dsakey.r), (uchar_t *)sig, 20); 399 bytestring2bignum(&(dsakey.s), ((uchar_t *)sig) + 20, 20); 400 bytestring2bignum(&msg, (uchar_t *)data, 20); 401 402 if (big_ext_gcd_pos(NULL, &tmp2, NULL, &(dsakey.s), &(dsakey.q)) != 403 BIG_OK) 404 goto clean10; 405 406 if (tmp2.sign == -1) 407 if (big_add(&tmp2, &tmp2, &(dsakey.q)) != BIG_OK) 408 goto clean10; /* tmp2 <- w */ 409 410 if (big_mul(&tmp1, &msg, &tmp2) != BIG_OK) 411 goto clean10; 412 413 if (big_div_pos(NULL, &tmp1, &tmp1, &(dsakey.q)) != BIG_OK) 414 goto clean10; /* tmp1 <- u_1 */ 415 416 if (big_mul(&tmp2, &tmp2, &(dsakey.r)) != BIG_OK) 417 goto clean10; 418 419 if (big_div_pos(NULL, &tmp2, &tmp2, &(dsakey.q)) != BIG_OK) 420 goto clean10; /* tmp2 <- u_2 */ 421 422 if (big_modexp(&tmp1, &(dsakey.g), &tmp1, &(dsakey.p), NULL) != BIG_OK) 423 goto clean10; 424 425 if (big_modexp(&tmp2, &(dsakey.y), &tmp2, &(dsakey.p), NULL) != BIG_OK) 426 goto clean10; 427 428 if (big_mul(&tmp1, &tmp1, &tmp2) != BIG_OK) 429 goto clean10; 430 431 if (big_div_pos(NULL, &tmp1, &tmp1, &(dsakey.p)) != BIG_OK) 432 goto clean10; 433 434 if (big_div_pos(NULL, &tmp1, &tmp1, &(dsakey.q)) != BIG_OK) 435 goto clean10; 436 437 if (big_cmp_abs(&tmp1, &(dsakey.r)) == 0) 438 rv = CKR_OK; 439 else 440 rv = CKR_SIGNATURE_INVALID; 441 442 clean10: 443 big_finish(&tmp3); 444 clean9: 445 big_finish(&tmp2); 446 clean8: 447 big_finish(&tmp1); 448 clean7: 449 big_finish(&msg); 450 clean6: 451 DSA_key_finish(&dsakey); 452 clean1: 453 return (rv); 454 } 455 456 457 CK_RV 458 soft_dsa_digest_sign_common(soft_session_t *session_p, CK_BYTE_PTR pData, 459 CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 460 CK_ULONG_PTR pulSignedLen, boolean_t Final) 461 { 462 463 CK_RV rv = CKR_OK; 464 CK_BYTE hash[SHA1_HASH_SIZE]; /* space enough for SHA1 and MD5 */ 465 CK_ULONG hash_len = SHA1_HASH_SIZE; 466 soft_dsa_ctx_t *dsa_ctx = session_p->sign.context; 467 soft_object_t *key = dsa_ctx->key; 468 469 /* Check arguments before performing message digest. */ 470 if (pSigned == NULL) { 471 /* Application asks for the length of the output buffer. */ 472 *pulSignedLen = DSA_SIGNATURE_LENGTH; 473 goto clean1; 474 } 475 476 /* Is the application-supplied buffer large enough? */ 477 if (*pulSignedLen < DSA_SIGNATURE_LENGTH) { 478 *pulSignedLen = DSA_SIGNATURE_LENGTH; 479 rv = CKR_BUFFER_TOO_SMALL; 480 goto clean1; 481 } 482 483 if (Final) { 484 rv = soft_digest_final(session_p, hash, &hash_len); 485 } else { 486 rv = soft_digest(session_p, pData, ulDataLen, hash, &hash_len); 487 } 488 489 if (rv != CKR_OK) { 490 /* free the signature key */ 491 soft_cleanup_object(key); 492 free(key); 493 goto clean_exit; 494 } 495 496 /* 497 * Now, we are ready to sign the data 498 * soft_dsa_sign() will free the signature key. 499 */ 500 rv = soft_dsa_sign(session_p, hash, hash_len, pSigned, pulSignedLen); 501 502 clean_exit: 503 (void) pthread_mutex_lock(&session_p->session_mutex); 504 /* soft_digest_common() has freed the digest context */ 505 session_p->digest.flags = 0; 506 (void) pthread_mutex_unlock(&session_p->session_mutex); 507 508 clean1: 509 return (rv); 510 } 511 512 513 CK_RV 514 soft_dsa_sign(soft_session_t *session_p, CK_BYTE_PTR pData, 515 CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 516 CK_ULONG_PTR pulSignedLen) 517 { 518 519 CK_RV rv = CKR_OK; 520 soft_dsa_ctx_t *dsa_ctx = session_p->sign.context; 521 soft_object_t *key = dsa_ctx->key; 522 523 if ((key->class != CKO_PRIVATE_KEY) || (key->key_type != CKK_DSA)) { 524 rv = CKR_KEY_TYPE_INCONSISTENT; 525 goto clean_exit; 526 } 527 528 /* Output length is always 40 bytes. */ 529 if (pSigned == NULL) { 530 /* Application asks for the length of the output buffer. */ 531 *pulSignedLen = DSA_SIGNATURE_LENGTH; 532 return (CKR_OK); 533 } 534 535 /* Input data length needs to be 20 bytes. */ 536 if (ulDataLen != 20) { 537 rv = CKR_DATA_LEN_RANGE; 538 goto clean_exit; 539 } 540 541 if (*pulSignedLen < DSA_SIGNATURE_LENGTH) { 542 *pulSignedLen = DSA_SIGNATURE_LENGTH; 543 return (CKR_BUFFER_TOO_SMALL); 544 } 545 546 rv = dsa_sign(key, pData, ulDataLen, pSigned); 547 if (rv == CKR_OK) { 548 *pulSignedLen = DSA_SIGNATURE_LENGTH; 549 } 550 551 clean_exit: 552 (void) pthread_mutex_lock(&session_p->session_mutex); 553 free(session_p->sign.context); 554 session_p->sign.context = NULL; 555 (void) pthread_mutex_unlock(&session_p->session_mutex); 556 soft_cleanup_object(key); 557 free(key); 558 return (rv); 559 } 560 561 562 CK_RV 563 soft_dsa_verify(soft_session_t *session_p, CK_BYTE_PTR pData, 564 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, 565 CK_ULONG ulSignatureLen) 566 { 567 568 CK_RV rv = CKR_OK; 569 soft_dsa_ctx_t *dsa_ctx = session_p->verify.context; 570 soft_object_t *key = dsa_ctx->key; 571 572 if ((key->class != CKO_PUBLIC_KEY) ||(key->key_type != CKK_DSA)) { 573 rv = CKR_KEY_TYPE_INCONSISTENT; 574 goto clean_exit; 575 } 576 577 /* The signature length is always 40 bytes. */ 578 if (ulSignatureLen != DSA_SIGNATURE_LENGTH) { 579 rv = CKR_SIGNATURE_LEN_RANGE; 580 goto clean_exit; 581 } 582 583 /* Input data length needs to be 20 bytes. */ 584 if (ulDataLen != 20) { 585 rv = CKR_DATA_LEN_RANGE; 586 goto clean_exit; 587 } 588 589 rv = dsa_verify(key, pData, pSignature); 590 591 clean_exit: 592 (void) pthread_mutex_lock(&session_p->session_mutex); 593 free(session_p->verify.context); 594 session_p->verify.context = NULL; 595 (void) pthread_mutex_unlock(&session_p->session_mutex); 596 soft_cleanup_object(key); 597 free(key); 598 return (rv); 599 } 600 601 602 CK_RV 603 soft_dsa_digest_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData, 604 CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 605 CK_ULONG ulSignedLen, boolean_t Final) 606 { 607 608 CK_RV rv; 609 CK_BYTE hash[SHA1_HASH_SIZE]; /* space enough for SHA1 and MD5 */ 610 CK_ULONG hash_len = SHA1_HASH_SIZE; 611 soft_dsa_ctx_t *dsa_ctx = session_p->verify.context; 612 soft_object_t *key = dsa_ctx->key; 613 614 if (Final) { 615 rv = soft_digest_final(session_p, hash, &hash_len); 616 } else { 617 rv = soft_digest(session_p, pData, ulDataLen, hash, &hash_len); 618 } 619 620 if (rv != CKR_OK) { 621 /* free the verification key */ 622 soft_cleanup_object(key); 623 free(key); 624 goto clean_exit; 625 } 626 627 /* 628 * Now, we are ready to verify the data using signature. 629 * soft_dsa_verify() will free the verification key. 630 */ 631 rv = soft_dsa_verify(session_p, hash, hash_len, 632 pSigned, ulSignedLen); 633 634 clean_exit: 635 (void) pthread_mutex_lock(&session_p->session_mutex); 636 /* soft_digest_common() has freed the digest context */ 637 session_p->digest.flags = 0; 638 (void) pthread_mutex_unlock(&session_p->session_mutex); 639 return (rv); 640 } 641 642 643 CK_RV 644 soft_genDSAkey_set_attribute(soft_object_t *key, CK_ATTRIBUTE_TYPE type, 645 uchar_t *value, uint32_t value_len, boolean_t public) 646 { 647 648 CK_RV rv = CKR_OK; 649 biginteger_t *dst = NULL; 650 biginteger_t src; 651 652 653 switch (type) { 654 655 case CKA_VALUE: 656 if (public) 657 dst = OBJ_PUB_DSA_VALUE(key); 658 else 659 dst = OBJ_PRI_DSA_VALUE(key); 660 break; 661 662 case CKA_PRIME: 663 if (public) 664 dst = OBJ_PUB_DSA_PRIME(key); 665 else 666 dst = OBJ_PRI_DSA_PRIME(key); 667 break; 668 669 case CKA_SUBPRIME: 670 if (public) 671 dst = OBJ_PUB_DSA_SUBPRIME(key); 672 else 673 dst = OBJ_PRI_DSA_SUBPRIME(key); 674 break; 675 676 case CKA_BASE: 677 if (public) 678 dst = OBJ_PUB_DSA_BASE(key); 679 else 680 dst = OBJ_PRI_DSA_BASE(key); 681 break; 682 } 683 684 src.big_value_len = value_len; 685 686 if ((src.big_value = malloc(value_len)) == NULL) { 687 rv = CKR_HOST_MEMORY; 688 goto cleanexit; 689 } 690 (void) memcpy(src.big_value, value, value_len); 691 692 /* Copy the attribute in the key object. */ 693 copy_bigint_attr(&src, dst); 694 695 cleanexit: 696 /* No need to free big_value because dst holds it now after copy. */ 697 return (rv); 698 699 } 700 701 702 CK_RV 703 generate_dsa_key(DSAkey *key, boolean_t token_obj) 704 { 705 BIG_ERR_CODE err; 706 707 do { 708 if ((err = random_bignum(&(key->x), DSA_SUBPRIME_BITS, 709 token_obj)) != BIG_OK) { 710 return (convert_rv(err)); 711 } 712 } while (big_cmp_abs(&(key->x), &(key->q)) > 0); 713 714 if ((err = big_modexp(&(key->y), &(key->g), (&key->x), 715 (&key->p), NULL)) != BIG_OK) 716 return (convert_rv(err)); 717 718 return (CKR_OK); 719 } 720 721 722 CK_RV 723 soft_dsa_genkey_pair(soft_object_t *pubkey, soft_object_t *prikey) 724 { 725 BIG_ERR_CODE brv; 726 CK_RV rv; 727 uchar_t prime[MAX_KEY_ATTR_BUFLEN]; 728 uint32_t prime_len = sizeof (prime); 729 uchar_t subprime[MAX_KEY_ATTR_BUFLEN]; 730 uint32_t subprime_len = sizeof (subprime); 731 uchar_t base[MAX_KEY_ATTR_BUFLEN]; 732 uint32_t base_len = sizeof (base); 733 uchar_t *pubvalue; 734 uint32_t pubvalue_len; 735 uchar_t *privalue; 736 uint32_t privalue_len; 737 DSAkey dsakey = {0}; 738 739 pubvalue = NULL; 740 privalue = NULL; 741 742 if ((pubkey == NULL) || (prikey == NULL)) { 743 return (CKR_ARGUMENTS_BAD); 744 } 745 746 /* lookup prime, subprime and base */ 747 rv = soft_get_public_attr(pubkey, CKA_PRIME, prime, &prime_len); 748 if (rv != CKR_OK) { 749 rv = CKR_TEMPLATE_INCOMPLETE; 750 goto cleanexit; 751 } 752 753 if ((prime_len < MIN_DSA_KEY_LEN) || 754 (prime_len > MAX_DSA_KEY_LEN)) { 755 rv = CKR_ATTRIBUTE_VALUE_INVALID; 756 goto cleanexit; 757 } 758 759 rv = soft_get_public_attr(pubkey, CKA_SUBPRIME, subprime, 760 &subprime_len); 761 if (rv != CKR_OK) { 762 rv = CKR_TEMPLATE_INCOMPLETE; 763 goto cleanexit; 764 } 765 766 if (subprime_len != DSA_SUBPRIME_BYTES) { 767 rv = CKR_ATTRIBUTE_VALUE_INVALID; 768 goto cleanexit; 769 } 770 771 rv = soft_get_public_attr(pubkey, CKA_BASE, base, &base_len); 772 if (rv != CKR_OK) { 773 rv = CKR_TEMPLATE_INCOMPLETE; 774 goto cleanexit; 775 } 776 777 /* 778 * initialize the dsa key 779 * Note: big_extend takes length in words 780 */ 781 if ((brv = DSA_key_init(&dsakey, prime_len * 8)) != BIG_OK) { 782 rv = convert_rv(brv); 783 goto cleanexit; 784 } 785 786 if ((brv = big_extend(&dsakey.p, 787 CHARLEN2BIGNUMLEN(prime_len))) != BIG_OK) { 788 rv = convert_rv(brv); 789 goto cleanexit; 790 } 791 792 bytestring2bignum(&dsakey.p, prime, prime_len); 793 794 if ((brv = big_extend(&dsakey.q, CHARLEN2BIGNUMLEN(subprime_len))) != 795 BIG_OK) { 796 rv = convert_rv(brv); 797 goto cleanexit; 798 } 799 800 bytestring2bignum(&dsakey.q, subprime, subprime_len); 801 802 if ((brv = big_extend(&dsakey.g, CHARLEN2BIGNUMLEN(base_len))) != 803 BIG_OK) { 804 rv = convert_rv(brv); 805 goto cleanexit; 806 } 807 808 bytestring2bignum(&dsakey.g, base, base_len); 809 810 /* 811 * generate DSA key pair 812 * Note: bignum.len is length of value in words 813 */ 814 if ((rv = generate_dsa_key(&dsakey, (IS_TOKEN_OBJECT(pubkey) || 815 IS_TOKEN_OBJECT(prikey)))) != CKR_OK) { 816 goto cleanexit; 817 } 818 819 pubvalue_len = prime_len; 820 if ((pubvalue = malloc(pubvalue_len)) == NULL) { 821 rv = CKR_HOST_MEMORY; 822 goto cleanexit; 823 } 824 bignum2bytestring(pubvalue, &dsakey.y, pubvalue_len); 825 826 privalue_len = DSA_SUBPRIME_BYTES; 827 if ((privalue = malloc(privalue_len)) == NULL) { 828 rv = CKR_HOST_MEMORY; 829 goto cleanexit; 830 } 831 bignum2bytestring(privalue, &dsakey.x, privalue_len); 832 833 /* Update attribute in public key. */ 834 if ((rv = soft_genDSAkey_set_attribute(pubkey, CKA_VALUE, 835 pubvalue, pubvalue_len, B_TRUE)) != CKR_OK) { 836 goto cleanexit; 837 } 838 /* Update attributes in private key. */ 839 if ((rv = soft_genDSAkey_set_attribute(prikey, CKA_PRIME, 840 prime, prime_len, B_FALSE)) != CKR_OK) { 841 goto cleanexit; 842 } 843 844 if ((rv = soft_genDSAkey_set_attribute(prikey, CKA_SUBPRIME, 845 subprime, subprime_len, B_FALSE)) != CKR_OK) { 846 goto cleanexit; 847 } 848 849 if ((rv = soft_genDSAkey_set_attribute(prikey, CKA_BASE, 850 base, base_len, B_FALSE)) != CKR_OK) { 851 goto cleanexit; 852 } 853 854 if ((rv = soft_genDSAkey_set_attribute(prikey, CKA_VALUE, 855 privalue, privalue_len, B_FALSE)) != CKR_OK) { 856 goto cleanexit; 857 } 858 859 cleanexit: 860 DSA_key_finish(&dsakey); 861 862 if (pubvalue != NULL) { 863 free(pubvalue); 864 } 865 866 if (privalue != NULL) { 867 free(privalue); 868 } 869 870 return (rv); 871 } 872