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 <stdlib.h> 29 #include <string.h> 30 #include <strings.h> 31 #include <sys/types.h> 32 #include <sys/crypto/common.h> 33 #include <security/cryptoki.h> 34 #include <bignum.h> 35 #include <des_impl.h> 36 #include "softGlobal.h" 37 #include "softSession.h" 38 #include "softObject.h" 39 #include "softEC.h" 40 #include "softRandom.h" 41 #include "softCrypt.h" 42 #include "softOps.h" 43 #include "softMAC.h" 44 45 void 46 soft_free_ecparams(ECParams *params, boolean_t freeit) 47 { 48 SECITEM_FreeItem(¶ms->fieldID.u.prime, B_FALSE); 49 SECITEM_FreeItem(¶ms->curve.a, B_FALSE); 50 SECITEM_FreeItem(¶ms->curve.b, B_FALSE); 51 SECITEM_FreeItem(¶ms->curve.seed, B_FALSE); 52 SECITEM_FreeItem(¶ms->base, B_FALSE); 53 SECITEM_FreeItem(¶ms->order, B_FALSE); 54 SECITEM_FreeItem(¶ms->DEREncoding, B_FALSE); 55 SECITEM_FreeItem(¶ms->curveOID, B_FALSE); 56 if (freeit) 57 free(params); 58 } 59 60 static void 61 soft_free_ecc_context(soft_ecc_ctx_t *ecc_ctx) 62 { 63 if (ecc_ctx != NULL) { 64 if (ecc_ctx->key != NULL) { 65 soft_cleanup_object(ecc_ctx->key); 66 free(ecc_ctx->key); 67 } 68 69 soft_free_ecparams(&ecc_ctx->ecparams, B_FALSE); 70 free(ecc_ctx); 71 } 72 } 73 74 void 75 soft_free_ecprivkey(ECPrivateKey *key) 76 { 77 soft_free_ecparams(&key->ecParams, B_FALSE); 78 /* 79 * Don't free publicValue or privateValue 80 * as these values are copied into objects. 81 */ 82 SECITEM_FreeItem(&key->version, B_FALSE); 83 free(key); 84 } 85 86 /* 87 * Called from init routines to do basic sanity checks. Init routines, 88 * e.g. sign_init should fail rather than subsequent operations. 89 */ 90 static int 91 check_key(soft_object_t *key_p, boolean_t sign) 92 { 93 biginteger_t *p; 94 ulong_t len; 95 96 if (sign) { 97 if ((key_p->class != CKO_PRIVATE_KEY) || 98 (key_p->key_type != CKK_EC)) 99 return (CKR_KEY_TYPE_INCONSISTENT); 100 101 p = OBJ_PRI_EC_VALUE(key_p); 102 len = p->big_value_len; 103 if (p->big_value == NULL) 104 len = 0; 105 106 if (len < CRYPTO_BITS2BYTES(EC_MIN_KEY_LEN) || 107 len > CRYPTO_BITS2BYTES(EC_MAX_KEY_LEN)) 108 return (CKR_KEY_SIZE_RANGE); 109 } else { 110 if ((key_p->class != CKO_PUBLIC_KEY) || 111 (key_p->key_type != CKK_EC)) 112 return (CKR_KEY_TYPE_INCONSISTENT); 113 114 p = OBJ_PUB_EC_POINT(key_p); 115 len = p->big_value_len; 116 if (p->big_value == NULL) 117 len = 0; 118 119 if (len < CRYPTO_BITS2BYTES(EC_MIN_KEY_LEN) * 2 + 1 || 120 len > CRYPTO_BITS2BYTES(EC_MAX_KEY_LEN) * 2 + 1) 121 return (CKR_KEY_SIZE_RANGE); 122 } 123 124 return (CKR_OK); 125 } 126 127 /* 128 * This function places the octet string of the specified attribute 129 * into the corresponding key object. 130 */ 131 static void 132 soft_genECkey_set_attribute(soft_object_t *key, biginteger_t *bi, 133 CK_ATTRIBUTE_TYPE type) 134 { 135 biginteger_t *dst; 136 137 switch (type) { 138 case CKA_VALUE: 139 dst = OBJ_PRI_EC_VALUE(key); 140 break; 141 142 case CKA_EC_POINT: 143 dst = OBJ_PUB_EC_POINT(key); 144 break; 145 } 146 copy_bigint_attr(bi, dst); 147 } 148 149 CK_RV 150 soft_ec_genkey_pair(soft_object_t *pubkey, soft_object_t *prikey) 151 { 152 CK_RV rv; 153 CK_ATTRIBUTE template; 154 ECPrivateKey *privKey; /* contains both public and private values */ 155 ECParams *ecparams; 156 SECKEYECParams params_item; 157 biginteger_t bi; 158 uchar_t param_buffer[EC_MAX_OID_LEN]; 159 uint_t paramlen; 160 161 if ((pubkey->class != CKO_PUBLIC_KEY) || 162 (pubkey->key_type != CKK_EC)) 163 return (CKR_KEY_TYPE_INCONSISTENT); 164 165 if ((prikey->class != CKO_PRIVATE_KEY) || 166 (prikey->key_type != CKK_EC)) 167 return (CKR_KEY_TYPE_INCONSISTENT); 168 169 template.type = CKA_EC_PARAMS; 170 template.pValue = param_buffer; 171 template.ulValueLen = sizeof (param_buffer); 172 rv = soft_get_public_key_attribute(pubkey, &template); 173 if (rv != CKR_OK) { 174 return (rv); 175 } 176 paramlen = template.ulValueLen; 177 178 /* private key also has CKA_EC_PARAMS attribute */ 179 rv = set_extra_attr_to_object(prikey, CKA_EC_PARAMS, &template); 180 if (rv != CKR_OK) { 181 return (rv); 182 } 183 184 /* ASN1 check */ 185 if (param_buffer[0] != 0x06 || 186 param_buffer[1] != paramlen - 2) { 187 return (CKR_ATTRIBUTE_VALUE_INVALID); 188 } 189 params_item.len = paramlen; 190 params_item.data = param_buffer; 191 if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) { 192 /* bad curve OID */ 193 return (CKR_ARGUMENTS_BAD); 194 } 195 196 if (EC_NewKey(ecparams, &privKey, 0) != SECSuccess) { 197 soft_free_ecparams(ecparams, B_TRUE); 198 return (CKR_FUNCTION_FAILED); 199 } 200 201 bi.big_value = privKey->privateValue.data; 202 bi.big_value_len = privKey->privateValue.len; 203 soft_genECkey_set_attribute(prikey, &bi, CKA_VALUE); 204 205 bi.big_value = privKey->publicValue.data; 206 bi.big_value_len = privKey->publicValue.len; 207 soft_genECkey_set_attribute(pubkey, &bi, CKA_EC_POINT); 208 209 soft_free_ecprivkey(privKey); 210 soft_free_ecparams(ecparams, B_TRUE); 211 212 return (CKR_OK); 213 } 214 215 CK_RV 216 soft_ec_key_derive(soft_object_t *basekey, soft_object_t *secretkey, 217 void *mech_params, size_t mech_params_len) 218 { 219 CK_RV rv; 220 CK_ATTRIBUTE template; 221 CK_ECDH1_DERIVE_PARAMS *ecdh1_derive_params = mech_params; 222 uchar_t value[EC_MAX_VALUE_LEN]; 223 uint32_t value_len = sizeof (value); 224 uchar_t params[EC_MAX_OID_LEN]; 225 uint32_t params_len = sizeof (params); 226 uint32_t keylen; 227 ECParams *ecparams; 228 SECKEYECParams params_item; 229 SECItem public_value_item, private_value_item, secret_item; 230 uchar_t *buf; 231 232 if (mech_params_len != sizeof (CK_ECDH1_DERIVE_PARAMS) || 233 ecdh1_derive_params->kdf != CKD_NULL) { 234 return (CKR_MECHANISM_PARAM_INVALID); 235 } 236 237 template.type = CKA_VALUE; 238 template.pValue = value; 239 template.ulValueLen = value_len; 240 rv = soft_get_private_key_attribute(basekey, &template); 241 if (rv != CKR_OK) { 242 return (rv); 243 } 244 value_len = template.ulValueLen; 245 private_value_item.data = value; 246 private_value_item.len = value_len; 247 248 template.type = CKA_EC_PARAMS; 249 template.pValue = params; 250 template.ulValueLen = params_len; 251 rv = soft_get_private_key_attribute(basekey, &template); 252 if (rv != CKR_OK) { 253 return (rv); 254 } 255 params_len = template.ulValueLen; 256 257 switch (secretkey->key_type) { 258 case CKK_DES: 259 keylen = DES_KEYSIZE; 260 break; 261 case CKK_DES2: 262 keylen = DES2_KEYSIZE; 263 break; 264 case CKK_DES3: 265 keylen = DES3_KEYSIZE; 266 break; 267 case CKK_RC4: 268 case CKK_AES: 269 case CKK_GENERIC_SECRET: 270 #ifdef __sparcv9 271 /* LINTED */ 272 keylen = (uint32_t)OBJ_SEC_VALUE_LEN(secretkey); 273 #else /* !__sparcv9 */ 274 keylen = OBJ_SEC_VALUE_LEN(secretkey); 275 #endif /* __sparcv9 */ 276 break; 277 } 278 279 /* ASN1 check */ 280 if (params[0] != 0x06 || 281 params[1] != params_len - 2) { 282 return (CKR_ATTRIBUTE_VALUE_INVALID); 283 } 284 params_item.data = params; 285 params_item.len = params_len; 286 if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) { 287 /* bad curve OID */ 288 return (CKR_ARGUMENTS_BAD); 289 } 290 291 public_value_item.data = ecdh1_derive_params->pPublicData; 292 public_value_item.len = ecdh1_derive_params->ulPublicDataLen; 293 294 secret_item.data = NULL; 295 secret_item.len = 0; 296 297 if (ECDH_Derive(&public_value_item, ecparams, &private_value_item, 298 B_FALSE, &secret_item, 0) != SECSuccess) { 299 soft_free_ecparams(ecparams, B_TRUE); 300 return (CKR_FUNCTION_FAILED); 301 } else { 302 rv = CKR_OK; 303 } 304 305 if (keylen == 0) 306 keylen = secret_item.len; 307 308 if (keylen > secret_item.len) { 309 rv = CKR_ATTRIBUTE_VALUE_INVALID; 310 goto out; 311 } 312 buf = malloc(keylen); 313 if (buf == NULL) { 314 rv = CKR_HOST_MEMORY; 315 goto out; 316 } 317 bcopy(secret_item.data + secret_item.len - keylen, buf, keylen); 318 OBJ_SEC_VALUE_LEN(secretkey) = keylen; 319 OBJ_SEC_VALUE(secretkey) = buf; 320 321 out: 322 soft_free_ecparams(ecparams, B_TRUE); 323 SECITEM_FreeItem(&secret_item, B_FALSE); 324 325 return (rv); 326 } 327 328 /* 329 * Allocate a ECC context for the active sign or verify operation. 330 * This function is called without the session lock held. 331 */ 332 CK_RV 333 soft_ecc_sign_verify_init_common(soft_session_t *session_p, 334 CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, 335 boolean_t sign) 336 { 337 CK_RV rv; 338 CK_ATTRIBUTE template; 339 CK_MECHANISM digest_mech; 340 soft_ecc_ctx_t *ecc_ctx; 341 soft_object_t *tmp_key = NULL; 342 uchar_t params[EC_MAX_OID_LEN]; 343 ECParams *ecparams; 344 SECKEYECParams params_item; 345 346 if ((rv = check_key(key_p, sign)) != CKR_OK) 347 return (rv); 348 349 if (pMechanism->mechanism == CKM_ECDSA_SHA1) { 350 digest_mech.mechanism = CKM_SHA_1; 351 rv = soft_digest_init_internal(session_p, &digest_mech); 352 if (rv != CKR_OK) 353 return (rv); 354 } 355 356 ecc_ctx = malloc(sizeof (soft_ecc_ctx_t)); 357 if (ecc_ctx == NULL) { 358 return (CKR_HOST_MEMORY); 359 } 360 361 /* 362 * Make a copy of the signature or verification key, and save it 363 * in the ECC crypto context since it will be used later for 364 * signing/verification. We don't want to hold any object reference 365 * on this original key while doing signing/verification. 366 */ 367 (void) pthread_mutex_lock(&key_p->object_mutex); 368 rv = soft_copy_object(key_p, &tmp_key, SOFT_COPY_OBJ_ORIG_SH, NULL); 369 if ((rv != CKR_OK) || (tmp_key == NULL)) { 370 /* Most likely we ran out of space. */ 371 (void) pthread_mutex_unlock(&key_p->object_mutex); 372 free(ecc_ctx); 373 return (rv); 374 } 375 376 377 template.type = CKA_EC_PARAMS; 378 template.pValue = params; 379 template.ulValueLen = sizeof (params); 380 rv = soft_get_private_key_attribute(key_p, &template); 381 (void) pthread_mutex_unlock(&key_p->object_mutex); 382 if (rv != CKR_OK) { 383 goto out; 384 } 385 386 /* ASN1 check */ 387 if (params[0] != 0x06 || 388 params[1] != template.ulValueLen - 2) { 389 rv = CKR_ATTRIBUTE_VALUE_INVALID; 390 goto out; 391 } 392 params_item.data = params; 393 params_item.len = template.ulValueLen; 394 395 ecc_ctx->key = tmp_key; 396 397 if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) { 398 /* bad curve OID */ 399 rv = CKR_ARGUMENTS_BAD; 400 goto out; 401 } 402 ecc_ctx->ecparams = *ecparams; 403 free(ecparams); 404 405 (void) pthread_mutex_lock(&session_p->session_mutex); 406 407 if (sign) { 408 session_p->sign.context = ecc_ctx; 409 session_p->sign.mech.mechanism = pMechanism->mechanism; 410 } else { 411 session_p->verify.context = ecc_ctx; 412 session_p->verify.mech.mechanism = pMechanism->mechanism; 413 } 414 415 (void) pthread_mutex_unlock(&session_p->session_mutex); 416 return (CKR_OK); 417 418 out: 419 soft_cleanup_object(tmp_key); 420 free(tmp_key); 421 free(ecc_ctx); 422 423 return (rv); 424 } 425 426 CK_RV 427 soft_ecc_digest_sign_common(soft_session_t *session_p, CK_BYTE_PTR pData, 428 CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 429 CK_ULONG_PTR pulSignedLen, boolean_t Final) 430 { 431 CK_RV rv = CKR_OK; 432 CK_BYTE hash[SHA1_HASH_SIZE]; 433 CK_ULONG hash_len = SHA1_HASH_SIZE; 434 435 if (pSigned != NULL) { 436 if (Final) { 437 rv = soft_digest_final(session_p, hash, &hash_len); 438 } else { 439 rv = soft_digest(session_p, pData, ulDataLen, hash, 440 &hash_len); 441 } 442 443 if (rv != CKR_OK) { 444 (void) pthread_mutex_lock(&session_p->session_mutex); 445 soft_free_ecc_context(session_p->sign.context); 446 session_p->sign.context = NULL; 447 session_p->digest.flags = 0; 448 (void) pthread_mutex_unlock(&session_p->session_mutex); 449 return (rv); 450 } 451 } 452 453 rv = soft_ecc_sign(session_p, hash, hash_len, pSigned, pulSignedLen); 454 455 clean_exit: 456 (void) pthread_mutex_lock(&session_p->session_mutex); 457 /* soft_digest_common() has freed the digest context */ 458 session_p->digest.flags = 0; 459 (void) pthread_mutex_unlock(&session_p->session_mutex); 460 461 clean1: 462 return (rv); 463 } 464 465 CK_RV 466 soft_ecc_sign(soft_session_t *session_p, CK_BYTE_PTR pData, 467 CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 468 CK_ULONG_PTR pulSignedLen) 469 { 470 CK_RV rv = CKR_OK; 471 SECStatus ss; 472 soft_ecc_ctx_t *ecc_ctx = session_p->sign.context; 473 soft_object_t *key = ecc_ctx->key; 474 uchar_t value[EC_MAX_VALUE_LEN]; 475 CK_ATTRIBUTE template; 476 ECPrivateKey ECkey; 477 SECItem signature_item; 478 SECItem digest_item; 479 480 if ((key->class != CKO_PRIVATE_KEY) || (key->key_type != CKK_EC)) { 481 rv = CKR_KEY_TYPE_INCONSISTENT; 482 goto clean_exit; 483 } 484 485 if (ulDataLen > EC_MAX_DIGEST_LEN) { 486 rv = CKR_DATA_LEN_RANGE; 487 goto clean_exit; 488 } 489 490 /* structure assignment */ 491 ECkey.ecParams = ecc_ctx->ecparams; 492 493 template.type = CKA_VALUE; 494 template.pValue = value; 495 template.ulValueLen = sizeof (value); 496 rv = soft_get_private_key_attribute(key, &template); 497 if (rv != CKR_OK) { 498 goto clean_exit; 499 } 500 501 ECkey.privateValue.data = value; 502 ECkey.privateValue.len = template.ulValueLen; 503 504 signature_item.data = pSigned; 505 signature_item.len = *pulSignedLen; 506 507 digest_item.data = pData; 508 digest_item.len = ulDataLen; 509 510 if ((ss = ECDSA_SignDigest(&ECkey, &signature_item, &digest_item, 0)) 511 != SECSuccess) { 512 if (ss == SECBufferTooSmall) 513 return (CKR_BUFFER_TOO_SMALL); 514 515 rv = CKR_FUNCTION_FAILED; 516 goto clean_exit; 517 } 518 519 if (rv == CKR_OK) { 520 *pulSignedLen = signature_item.len; 521 if (pSigned == NULL) 522 return (rv); 523 } 524 525 clean_exit: 526 (void) pthread_mutex_lock(&session_p->session_mutex); 527 soft_free_ecc_context(session_p->sign.context); 528 session_p->sign.context = NULL; 529 (void) pthread_mutex_unlock(&session_p->session_mutex); 530 return (rv); 531 } 532 533 CK_RV 534 soft_ecc_verify(soft_session_t *session_p, CK_BYTE_PTR pData, 535 CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, 536 CK_ULONG ulSignatureLen) 537 { 538 CK_RV rv = CKR_OK; 539 soft_ecc_ctx_t *ecc_ctx = session_p->verify.context; 540 soft_object_t *key = ecc_ctx->key; 541 uchar_t point[EC_MAX_POINT_LEN]; 542 CK_ATTRIBUTE template; 543 ECPublicKey ECkey; 544 SECItem signature_item; 545 SECItem digest_item; 546 547 if ((key->class != CKO_PUBLIC_KEY) ||(key->key_type != CKK_EC)) { 548 rv = CKR_KEY_TYPE_INCONSISTENT; 549 goto clean_exit; 550 } 551 552 if (ulSignatureLen > EC_MAX_SIG_LEN) { 553 rv = CKR_SIGNATURE_LEN_RANGE; 554 goto clean_exit; 555 } 556 557 if (ulDataLen > EC_MAX_DIGEST_LEN) { 558 rv = CKR_DATA_LEN_RANGE; 559 goto clean_exit; 560 } 561 562 /* structure assignment */ 563 ECkey.ecParams = ecc_ctx->ecparams; 564 565 template.type = CKA_EC_POINT; 566 template.pValue = point; 567 template.ulValueLen = sizeof (point); 568 rv = soft_get_public_key_attribute(key, &template); 569 if (rv != CKR_OK) { 570 goto clean_exit; 571 } 572 573 ECkey.publicValue.data = point; 574 ECkey.publicValue.len = template.ulValueLen; 575 576 signature_item.data = pSignature; 577 signature_item.len = ulSignatureLen; 578 579 digest_item.data = pData; 580 digest_item.len = ulDataLen; 581 582 if (ECDSA_VerifyDigest(&ECkey, &signature_item, &digest_item, 0) 583 != SECSuccess) { 584 rv = CKR_SIGNATURE_INVALID; 585 } else { 586 rv = CKR_OK; 587 } 588 589 clean_exit: 590 (void) pthread_mutex_lock(&session_p->session_mutex); 591 soft_free_ecc_context(session_p->verify.context); 592 session_p->verify.context = NULL; 593 (void) pthread_mutex_unlock(&session_p->session_mutex); 594 return (rv); 595 } 596 597 598 CK_RV 599 soft_ecc_digest_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData, 600 CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 601 CK_ULONG ulSignedLen, boolean_t Final) 602 { 603 CK_RV rv; 604 CK_BYTE hash[SHA1_HASH_SIZE]; 605 CK_ULONG hash_len = SHA1_HASH_SIZE; 606 607 if (Final) { 608 rv = soft_digest_final(session_p, hash, &hash_len); 609 } else { 610 rv = soft_digest(session_p, pData, ulDataLen, hash, &hash_len); 611 } 612 613 if (rv != CKR_OK) { 614 (void) pthread_mutex_lock(&session_p->session_mutex); 615 soft_free_ecc_context(session_p->verify.context); 616 session_p->verify.context = NULL; 617 session_p->digest.flags = 0; 618 (void) pthread_mutex_unlock(&session_p->session_mutex); 619 return (rv); 620 } 621 622 /* 623 * Now, we are ready to verify the data using signature. 624 * soft_ecc_verify() will free the verification key. 625 */ 626 rv = soft_ecc_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