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 /* 23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 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 <cryptoutil.h> 33 #include "softGlobal.h" 34 #include "softSession.h" 35 #include "softObject.h" 36 #include "softDSA.h" 37 #include "softOps.h" 38 #include "softMAC.h" 39 #include "softCrypt.h" 40 41 /* 42 * Allocate a DSA context for the active sign or verify operation. 43 * This function is called without the session lock held. 44 */ 45 CK_RV 46 soft_dsa_sign_verify_init_common(soft_session_t *session_p, 47 CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, 48 boolean_t sign) 49 { 50 51 soft_dsa_ctx_t *dsa_ctx; 52 CK_MECHANISM digest_mech; 53 soft_object_t *tmp_key = NULL; 54 CK_RV rv; 55 56 if (sign) { 57 if ((key_p->class != CKO_PRIVATE_KEY) || 58 (key_p->key_type != CKK_DSA)) 59 return (CKR_KEY_TYPE_INCONSISTENT); 60 } else { 61 if ((key_p->class != CKO_PUBLIC_KEY) || 62 (key_p->key_type != CKK_DSA)) 63 return (CKR_KEY_TYPE_INCONSISTENT); 64 } 65 66 if (pMechanism->mechanism == CKM_DSA_SHA1) { 67 digest_mech.mechanism = CKM_SHA_1; 68 rv = soft_digest_init_internal(session_p, &digest_mech); 69 if (rv != CKR_OK) 70 return (rv); 71 } 72 73 dsa_ctx = malloc(sizeof (soft_dsa_ctx_t)); 74 75 if (dsa_ctx == NULL) { 76 return (CKR_HOST_MEMORY); 77 } 78 79 /* 80 * Make a copy of the signature or verification key, and save it 81 * in the DSA crypto context since it will be used later for 82 * signing/verification. We don't want to hold any object reference 83 * on this original key while doing signing/verification. 84 */ 85 (void) pthread_mutex_lock(&key_p->object_mutex); 86 rv = soft_copy_object(key_p, &tmp_key, SOFT_COPY_OBJ_ORIG_SH, 87 NULL); 88 89 if ((rv != CKR_OK) || (tmp_key == NULL)) { 90 /* Most likely we ran out of space. */ 91 (void) pthread_mutex_unlock(&key_p->object_mutex); 92 free(dsa_ctx); 93 return (rv); 94 } 95 96 /* No need to hold the lock on the old object. */ 97 (void) pthread_mutex_unlock(&key_p->object_mutex); 98 dsa_ctx->key = tmp_key; 99 100 (void) pthread_mutex_lock(&session_p->session_mutex); 101 102 if (sign) { 103 session_p->sign.context = dsa_ctx; 104 session_p->sign.mech.mechanism = pMechanism->mechanism; 105 } else { 106 session_p->verify.context = dsa_ctx; 107 session_p->verify.mech.mechanism = pMechanism->mechanism; 108 } 109 110 (void) pthread_mutex_unlock(&session_p->session_mutex); 111 112 return (CKR_OK); 113 } 114 115 116 static CK_RV 117 local_dsa_sign(soft_object_t *key, CK_BYTE_PTR in, CK_ULONG inlen, 118 CK_BYTE_PTR out) 119 { 120 CK_RV rv; 121 uchar_t q[MAX_KEY_ATTR_BUFLEN]; 122 uchar_t p[MAX_KEY_ATTR_BUFLEN]; 123 uchar_t g[MAX_KEY_ATTR_BUFLEN]; 124 uchar_t x[MAX_KEY_ATTR_BUFLEN]; 125 uint_t qlen = sizeof (q); 126 uint_t plen = sizeof (p); 127 uint_t glen = sizeof (g); 128 uint_t xlen = sizeof (x); 129 DSAbytekey k; 130 131 rv = soft_get_private_value(key, CKA_PRIME, p, &plen); 132 if (rv != CKR_OK) { 133 goto clean1; 134 } 135 136 rv = soft_get_private_value(key, CKA_SUBPRIME, q, &qlen); 137 if (rv != CKR_OK) { 138 goto clean1; 139 } 140 141 rv = soft_get_private_value(key, CKA_BASE, g, &glen); 142 if (rv != CKR_OK) { 143 goto clean1; 144 } 145 146 rv = soft_get_private_value(key, CKA_VALUE, x, &xlen); 147 if (rv != CKR_OK) { 148 goto clean1; 149 } 150 151 k.prime = p; 152 k.prime_bits = CRYPTO_BYTES2BITS(plen); 153 k.subprime = q; 154 k.subprime_bits = CRYPTO_BYTES2BITS(qlen); 155 k.base = g; 156 k.base_bytes = glen; 157 k.private_x_bits = CRYPTO_BYTES2BITS(xlen); 158 k.private_x = x; 159 k.rfunc = NULL; 160 161 rv = dsa_sign(&k, in, inlen, out); 162 163 clean1: 164 return (rv); 165 } 166 167 static CK_RV 168 local_dsa_verify(soft_object_t *key, CK_BYTE_PTR data, CK_BYTE_PTR sig) 169 { 170 CK_RV rv; 171 uchar_t g[MAX_KEY_ATTR_BUFLEN]; 172 uchar_t y[MAX_KEY_ATTR_BUFLEN]; 173 uchar_t p[MAX_KEY_ATTR_BUFLEN]; 174 uchar_t q[MAX_KEY_ATTR_BUFLEN]; 175 uint_t glen = sizeof (g); 176 uint_t ylen = sizeof (y); 177 uint_t plen = sizeof (p); 178 uint_t qlen = sizeof (q); 179 DSAbytekey k; 180 181 rv = soft_get_public_value(key, CKA_PRIME, p, &plen); 182 if (rv != CKR_OK) { 183 goto clean1; 184 } 185 186 rv = soft_get_public_value(key, CKA_SUBPRIME, q, &qlen); 187 if (rv != CKR_OK) { 188 goto clean1; 189 } 190 191 rv = soft_get_public_value(key, CKA_BASE, g, &glen); 192 if (rv != CKR_OK) { 193 goto clean1; 194 } 195 196 rv = soft_get_public_value(key, CKA_VALUE, y, &ylen); 197 if (rv != CKR_OK) { 198 goto clean1; 199 } 200 201 k.prime = p; 202 k.prime_bits = CRYPTO_BYTES2BITS(plen); 203 k.subprime = q; 204 k.subprime_bits = CRYPTO_BYTES2BITS(qlen); 205 k.base = g; 206 k.base_bytes = glen; 207 k.public_y_bits = CRYPTO_BYTES2BITS(ylen); 208 k.public_y = y; 209 k.rfunc = NULL; 210 211 rv = dsa_verify(&k, data, sig); 212 213 clean1: 214 return (rv); 215 } 216 217 218 CK_RV 219 soft_dsa_digest_sign_common(soft_session_t *session_p, CK_BYTE_PTR pData, 220 CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 221 CK_ULONG_PTR pulSignedLen, boolean_t Final) 222 { 223 224 CK_RV rv = CKR_OK; 225 CK_BYTE hash[SHA1_HASH_SIZE]; /* space enough for SHA1 and MD5 */ 226 CK_ULONG hash_len = SHA1_HASH_SIZE; 227 soft_dsa_ctx_t *dsa_ctx = session_p->sign.context; 228 soft_object_t *key = dsa_ctx->key; 229 230 /* Check arguments before performing message digest. */ 231 if (pSigned == NULL) { 232 /* Application asks for the length of the output buffer. */ 233 *pulSignedLen = DSA_SIGNATURE_LENGTH; 234 goto clean1; 235 } 236 237 /* Is the application-supplied buffer large enough? */ 238 if (*pulSignedLen < DSA_SIGNATURE_LENGTH) { 239 *pulSignedLen = DSA_SIGNATURE_LENGTH; 240 rv = CKR_BUFFER_TOO_SMALL; 241 goto clean1; 242 } 243 244 if (Final) { 245 rv = soft_digest_final(session_p, hash, &hash_len); 246 } else { 247 rv = soft_digest(session_p, pData, ulDataLen, hash, &hash_len); 248 } 249 250 if (rv != CKR_OK) { 251 /* free the signature key */ 252 soft_cleanup_object(key); 253 free(key); 254 goto clean_exit; 255 } 256 257 /* 258 * Now, we are ready to sign the data 259 * soft_dsa_sign() will free the signature key. 260 */ 261 rv = soft_dsa_sign(session_p, hash, hash_len, pSigned, pulSignedLen); 262 263 clean_exit: 264 (void) pthread_mutex_lock(&session_p->session_mutex); 265 /* soft_digest_common() has freed the digest context */ 266 session_p->digest.flags = 0; 267 (void) pthread_mutex_unlock(&session_p->session_mutex); 268 269 clean1: 270 return (rv); 271 } 272 273 274 CK_RV 275 soft_dsa_sign(soft_session_t *session_p, CK_BYTE_PTR pData, 276 CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 277 CK_ULONG_PTR pulSignedLen) 278 { 279 280 CK_RV rv = CKR_OK; 281 soft_dsa_ctx_t *dsa_ctx = session_p->sign.context; 282 soft_object_t *key = dsa_ctx->key; 283 284 if ((key->class != CKO_PRIVATE_KEY) || (key->key_type != CKK_DSA)) { 285 rv = CKR_KEY_TYPE_INCONSISTENT; 286 goto clean_exit; 287 } 288 289 /* Output length is always 40 bytes. */ 290 if (pSigned == NULL) { 291 /* Application asks for the length of the output buffer. */ 292 *pulSignedLen = DSA_SIGNATURE_LENGTH; 293 return (CKR_OK); 294 } 295 296 /* Input data length needs to be 20 bytes. */ 297 if (ulDataLen != DSA_SUBPRIME_BYTES) { 298 rv = CKR_DATA_LEN_RANGE; 299 goto clean_exit; 300 } 301 302 if (*pulSignedLen < DSA_SIGNATURE_LENGTH) { 303 *pulSignedLen = DSA_SIGNATURE_LENGTH; 304 return (CKR_BUFFER_TOO_SMALL); 305 } 306 307 rv = local_dsa_sign(key, pData, ulDataLen, pSigned); 308 if (rv == CKR_OK) { 309 *pulSignedLen = DSA_SIGNATURE_LENGTH; 310 } 311 312 clean_exit: 313 (void) pthread_mutex_lock(&session_p->session_mutex); 314 free(session_p->sign.context); 315 session_p->sign.context = NULL; 316 (void) pthread_mutex_unlock(&session_p->session_mutex); 317 soft_cleanup_object(key); 318 free(key); 319 return (rv); 320 } 321 322 323 CK_RV 324 soft_dsa_verify(soft_session_t *session_p, CK_BYTE_PTR pData, 325 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, 326 CK_ULONG ulSignatureLen) 327 { 328 329 CK_RV rv = CKR_OK; 330 soft_dsa_ctx_t *dsa_ctx = session_p->verify.context; 331 soft_object_t *key = dsa_ctx->key; 332 333 if ((key->class != CKO_PUBLIC_KEY) ||(key->key_type != CKK_DSA)) { 334 rv = CKR_KEY_TYPE_INCONSISTENT; 335 goto clean_exit; 336 } 337 338 /* Input data length needs to be 20 bytes. */ 339 if (ulDataLen != DSA_SUBPRIME_BYTES) { 340 rv = CKR_DATA_LEN_RANGE; 341 goto clean_exit; 342 } 343 344 /* The signature length is always 40 bytes. */ 345 if (ulSignatureLen != DSA_SIGNATURE_LENGTH) { 346 rv = CKR_SIGNATURE_LEN_RANGE; 347 goto clean_exit; 348 } 349 350 rv = local_dsa_verify(key, pData, pSignature); 351 352 clean_exit: 353 (void) pthread_mutex_lock(&session_p->session_mutex); 354 free(session_p->verify.context); 355 session_p->verify.context = NULL; 356 (void) pthread_mutex_unlock(&session_p->session_mutex); 357 soft_cleanup_object(key); 358 free(key); 359 return (rv); 360 } 361 362 363 CK_RV 364 soft_dsa_digest_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData, 365 CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 366 CK_ULONG ulSignedLen, boolean_t Final) 367 { 368 369 CK_RV rv; 370 CK_BYTE hash[SHA1_HASH_SIZE]; /* space enough for SHA1 and MD5 */ 371 CK_ULONG hash_len = SHA1_HASH_SIZE; 372 soft_dsa_ctx_t *dsa_ctx = session_p->verify.context; 373 soft_object_t *key = dsa_ctx->key; 374 375 if (Final) { 376 rv = soft_digest_final(session_p, hash, &hash_len); 377 } else { 378 rv = soft_digest(session_p, pData, ulDataLen, hash, &hash_len); 379 } 380 381 if (rv != CKR_OK) { 382 /* free the verification key */ 383 soft_cleanup_object(key); 384 free(key); 385 goto clean_exit; 386 } 387 388 /* 389 * Now, we are ready to verify the data using signature. 390 * soft_dsa_verify() will free the verification key. 391 */ 392 rv = soft_dsa_verify(session_p, hash, hash_len, 393 pSigned, ulSignedLen); 394 395 clean_exit: 396 (void) pthread_mutex_lock(&session_p->session_mutex); 397 /* soft_digest_common() has freed the digest context */ 398 session_p->digest.flags = 0; 399 (void) pthread_mutex_unlock(&session_p->session_mutex); 400 return (rv); 401 } 402 403 404 static CK_RV 405 soft_genDSAkey_set_attribute(soft_object_t *key, CK_ATTRIBUTE_TYPE type, 406 uchar_t *value, uint32_t value_len, boolean_t public) 407 { 408 409 CK_RV rv = CKR_OK; 410 biginteger_t *dst = NULL; 411 biginteger_t src; 412 413 switch (type) { 414 415 case CKA_VALUE: 416 if (public) 417 dst = OBJ_PUB_DSA_VALUE(key); 418 else 419 dst = OBJ_PRI_DSA_VALUE(key); 420 break; 421 422 case CKA_PRIME: 423 if (public) 424 dst = OBJ_PUB_DSA_PRIME(key); 425 else 426 dst = OBJ_PRI_DSA_PRIME(key); 427 break; 428 429 case CKA_SUBPRIME: 430 if (public) 431 dst = OBJ_PUB_DSA_SUBPRIME(key); 432 else 433 dst = OBJ_PRI_DSA_SUBPRIME(key); 434 break; 435 436 case CKA_BASE: 437 if (public) 438 dst = OBJ_PUB_DSA_BASE(key); 439 else 440 dst = OBJ_PRI_DSA_BASE(key); 441 break; 442 } 443 444 /* Note: removal of preceding 0x00 imitates similar code in RSA */ 445 while (value[0] == 0) { /* remove preceding 0x00 */ 446 value++; 447 value_len--; 448 } 449 450 if ((rv = dup_bigint_attr(&src, value, value_len)) != CKR_OK) 451 goto cleanexit; 452 453 /* Copy the attribute in the key object. */ 454 copy_bigint_attr(&src, dst); 455 456 cleanexit: 457 /* No need to free big_value because dst holds it now after copy. */ 458 return (rv); 459 460 } 461 462 463 CK_RV 464 soft_dsa_genkey_pair(soft_object_t *pubkey, soft_object_t *prikey) 465 { 466 CK_RV rv; 467 uchar_t prime[MAX_KEY_ATTR_BUFLEN]; 468 uint32_t prime_len = sizeof (prime); 469 uchar_t subprime[MAX_KEY_ATTR_BUFLEN]; 470 uint32_t subprime_len = sizeof (subprime); 471 uchar_t base[MAX_KEY_ATTR_BUFLEN]; 472 uint32_t base_len = sizeof (base); 473 uchar_t pubvalue[MAX_KEY_ATTR_BUFLEN]; 474 uint32_t pubvalue_len = sizeof (pubvalue); 475 uchar_t privalue[DSA_SUBPRIME_BYTES]; 476 uint32_t privalue_len = sizeof (privalue); 477 DSAbytekey k; 478 479 if ((pubkey == NULL) || (prikey == NULL)) { 480 return (CKR_ARGUMENTS_BAD); 481 } 482 483 /* lookup prime, subprime and base */ 484 rv = soft_get_public_value(pubkey, CKA_PRIME, prime, &prime_len); 485 if (rv != CKR_OK) { 486 rv = CKR_TEMPLATE_INCOMPLETE; 487 goto cleanexit; 488 } 489 490 rv = soft_get_public_value(pubkey, CKA_SUBPRIME, subprime, 491 &subprime_len); 492 if (rv != CKR_OK) { 493 rv = CKR_TEMPLATE_INCOMPLETE; 494 goto cleanexit; 495 } 496 497 rv = soft_get_public_value(pubkey, CKA_BASE, base, &base_len); 498 if (rv != CKR_OK) { 499 rv = CKR_TEMPLATE_INCOMPLETE; 500 goto cleanexit; 501 } 502 503 /* Inputs to DSA key pair generation. */ 504 k.prime = prime; 505 k.prime_bits = CRYPTO_BYTES2BITS(prime_len); 506 k.subprime = subprime; 507 k.subprime_bits = CRYPTO_BYTES2BITS(subprime_len); 508 k.base = base; 509 k.base_bytes = base_len; 510 k.rfunc = (IS_TOKEN_OBJECT(pubkey) || IS_TOKEN_OBJECT(prikey)) ? 511 pkcs11_get_random : pkcs11_get_urandom; 512 513 /* Outputs from DSA key pair generation. */ 514 k.public_y = pubvalue; 515 k.public_y_bits = CRYPTO_BYTES2BITS(pubvalue_len); 516 k.private_x = privalue; 517 k.private_x_bits = CRYPTO_BYTES2BITS(privalue_len); 518 519 rv = dsa_genkey_pair(&k); 520 521 if (rv != CKR_OK) { 522 goto cleanexit; 523 } 524 525 /* Update attribute in public key. */ 526 if ((rv = soft_genDSAkey_set_attribute(pubkey, CKA_VALUE, 527 pubvalue, CRYPTO_BITS2BYTES(k.public_y_bits), B_TRUE)) != CKR_OK) { 528 goto cleanexit; 529 } 530 /* Update attributes in private key. */ 531 if ((rv = soft_genDSAkey_set_attribute(prikey, CKA_PRIME, 532 prime, CRYPTO_BITS2BYTES(k.prime_bits), B_FALSE)) != CKR_OK) { 533 goto cleanexit; 534 } 535 536 if ((rv = soft_genDSAkey_set_attribute(prikey, CKA_SUBPRIME, subprime, 537 CRYPTO_BITS2BYTES(k.subprime_bits), B_FALSE)) != CKR_OK) { 538 goto cleanexit; 539 } 540 541 if ((rv = soft_genDSAkey_set_attribute(prikey, CKA_BASE, 542 base, k.base_bytes, B_FALSE)) != CKR_OK) { 543 goto cleanexit; 544 } 545 546 if ((rv = soft_genDSAkey_set_attribute(prikey, CKA_VALUE, privalue, 547 CRYPTO_BITS2BYTES(k.private_x_bits), B_FALSE)) != CKR_OK) { 548 goto cleanexit; 549 } 550 551 cleanexit: 552 return (rv); 553 } 554