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