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