softEC.c revision 9127:39de79f2e5d5
1193323Sed/* 2193323Sed * CDDL HEADER START 3193323Sed * 4193323Sed * The contents of this file are subject to the terms of the 5193323Sed * Common Development and Distribution License (the "License"). 6193323Sed * You may not use this file except in compliance with the License. 7193323Sed * 8193323Sed * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9193323Sed * or http://www.opensolaris.org/os/licensing. 10193323Sed * See the License for the specific language governing permissions 11193323Sed * and limitations under the License. 12193323Sed * 13193323Sed * When distributing Covered Code, include this CDDL HEADER in each 14193323Sed * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15201360Srdivacky * If applicable, add the following below this CDDL HEADER, with the 16201360Srdivacky * fields enclosed by brackets "[]" replaced with your own identifying 17193323Sed * information: Portions Copyright [yyyy] [name of copyright owner] 18193323Sed * 19193323Sed * CDDL HEADER END 20201360Srdivacky */ 21193323Sed/* 22201360Srdivacky * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23201360Srdivacky * Use is subject to license terms. 24201360Srdivacky */ 25201360Srdivacky 26201360Srdivacky#include <stdlib.h> 27201360Srdivacky#include <string.h> 28201360Srdivacky#include <strings.h> 29201360Srdivacky#include <sys/types.h> 30201360Srdivacky#include <sys/crypto/common.h> 31201360Srdivacky#include <security/cryptoki.h> 32201360Srdivacky#include <bignum.h> 33201360Srdivacky#include <des_impl.h> 34201360Srdivacky#include "softGlobal.h" 35201360Srdivacky#include "softSession.h" 36201360Srdivacky#include "softObject.h" 37201360Srdivacky#include "softEC.h" 38201360Srdivacky#include "softCrypt.h" 39201360Srdivacky#include "softOps.h" 40201360Srdivacky#include "softMAC.h" 41201360Srdivacky 42201360Srdivackyvoid 43201360Srdivackysoft_free_ecparams(ECParams *params, boolean_t freeit) 44201360Srdivacky{ 45201360Srdivacky SECITEM_FreeItem(¶ms->fieldID.u.prime, B_FALSE); 46201360Srdivacky SECITEM_FreeItem(¶ms->curve.a, B_FALSE); 47201360Srdivacky SECITEM_FreeItem(¶ms->curve.b, B_FALSE); 48201360Srdivacky SECITEM_FreeItem(¶ms->curve.seed, B_FALSE); 49201360Srdivacky SECITEM_FreeItem(¶ms->base, B_FALSE); 50201360Srdivacky SECITEM_FreeItem(¶ms->order, B_FALSE); 51201360Srdivacky SECITEM_FreeItem(¶ms->DEREncoding, B_FALSE); 52201360Srdivacky SECITEM_FreeItem(¶ms->curveOID, B_FALSE); 53201360Srdivacky if (freeit) 54201360Srdivacky free(params); 55201360Srdivacky} 56201360Srdivacky 57201360Srdivackystatic void 58201360Srdivackysoft_free_ecc_context(soft_ecc_ctx_t *ecc_ctx) 59201360Srdivacky{ 60201360Srdivacky if (ecc_ctx != NULL) { 61201360Srdivacky if (ecc_ctx->key != NULL) { 62201360Srdivacky soft_cleanup_object(ecc_ctx->key); 63201360Srdivacky free(ecc_ctx->key); 64201360Srdivacky } 65201360Srdivacky 66201360Srdivacky soft_free_ecparams(&ecc_ctx->ecparams, B_FALSE); 67201360Srdivacky free(ecc_ctx); 68201360Srdivacky } 69201360Srdivacky} 70201360Srdivacky 71201360Srdivackyvoid 72201360Srdivackysoft_free_ecprivkey(ECPrivateKey *key) 73201360Srdivacky{ 74201360Srdivacky soft_free_ecparams(&key->ecParams, B_FALSE); 75201360Srdivacky /* 76201360Srdivacky * Don't free publicValue or privateValue 77201360Srdivacky * as these values are copied into objects. 78201360Srdivacky */ 79201360Srdivacky SECITEM_FreeItem(&key->version, B_FALSE); 80201360Srdivacky free(key); 81218893Sdim} 82218893Sdim 83218893Sdim/* 84218893Sdim * Called from init routines to do basic sanity checks. Init routines, 85193323Sed * e.g. sign_init should fail rather than subsequent operations. 86201360Srdivacky */ 87193323Sedstatic int 88193323Sedcheck_key(soft_object_t *key_p, boolean_t sign) 89193323Sed{ 90193323Sed biginteger_t *p; 91201360Srdivacky ulong_t len; 92193323Sed 93210299Sed if (sign) { 94210299Sed if ((key_p->class != CKO_PRIVATE_KEY) || 95193323Sed (key_p->key_type != CKK_EC)) 96201360Srdivacky return (CKR_KEY_TYPE_INCONSISTENT); 97193323Sed 98193323Sed p = OBJ_PRI_EC_VALUE(key_p); 99193323Sed len = p->big_value_len; 100193323Sed if (p->big_value == NULL) 101201360Srdivacky len = 0; 102193323Sed 103201360Srdivacky if (len < CRYPTO_BITS2BYTES(EC_MIN_KEY_LEN) || 104201360Srdivacky len > CRYPTO_BITS2BYTES(EC_MAX_KEY_LEN)) 105201360Srdivacky return (CKR_KEY_SIZE_RANGE); 106201360Srdivacky } else { 107201360Srdivacky if ((key_p->class != CKO_PUBLIC_KEY) || 108201360Srdivacky (key_p->key_type != CKK_EC)) 109201360Srdivacky return (CKR_KEY_TYPE_INCONSISTENT); 110201360Srdivacky 111201360Srdivacky p = OBJ_PUB_EC_POINT(key_p); 112201360Srdivacky len = p->big_value_len; 113201360Srdivacky if (p->big_value == NULL) 114201360Srdivacky len = 0; 115201360Srdivacky 116201360Srdivacky if (len < CRYPTO_BITS2BYTES(EC_MIN_KEY_LEN) * 2 + 1 || 117201360Srdivacky len > CRYPTO_BITS2BYTES(EC_MAX_KEY_LEN) * 2 + 1) 118201360Srdivacky return (CKR_KEY_SIZE_RANGE); 119201360Srdivacky } 120201360Srdivacky 121201360Srdivacky return (CKR_OK); 122201360Srdivacky} 123201360Srdivacky 124201360Srdivacky/* 125201360Srdivacky * This function places the octet string of the specified attribute 126201360Srdivacky * into the corresponding key object. 127201360Srdivacky */ 128201360Srdivackystatic void 129201360Srdivackysoft_genECkey_set_attribute(soft_object_t *key, biginteger_t *bi, 130201360Srdivacky CK_ATTRIBUTE_TYPE type) 131201360Srdivacky{ 132201360Srdivacky biginteger_t *dst; 133201360Srdivacky 134201360Srdivacky switch (type) { 135201360Srdivacky case CKA_VALUE: 136201360Srdivacky dst = OBJ_PRI_EC_VALUE(key); 137201360Srdivacky break; 138201360Srdivacky 139201360Srdivacky case CKA_EC_POINT: 140201360Srdivacky dst = OBJ_PUB_EC_POINT(key); 141201360Srdivacky break; 142201360Srdivacky } 143201360Srdivacky copy_bigint_attr(bi, dst); 144201360Srdivacky} 145201360Srdivacky 146201360SrdivackyCK_RV 147201360Srdivackysoft_ec_genkey_pair(soft_object_t *pubkey, soft_object_t *prikey) 148201360Srdivacky{ 149201360Srdivacky CK_RV rv; 150201360Srdivacky CK_ATTRIBUTE template; 151201360Srdivacky ECPrivateKey *privKey; /* contains both public and private values */ 152201360Srdivacky ECParams *ecparams; 153201360Srdivacky SECKEYECParams params_item; 154201360Srdivacky biginteger_t bi; 155201360Srdivacky uchar_t param_buffer[EC_MAX_OID_LEN]; 156201360Srdivacky uint_t paramlen; 157201360Srdivacky 158201360Srdivacky if ((pubkey->class != CKO_PUBLIC_KEY) || 159201360Srdivacky (pubkey->key_type != CKK_EC)) 160201360Srdivacky return (CKR_KEY_TYPE_INCONSISTENT); 161201360Srdivacky 162201360Srdivacky if ((prikey->class != CKO_PRIVATE_KEY) || 163201360Srdivacky (prikey->key_type != CKK_EC)) 164201360Srdivacky return (CKR_KEY_TYPE_INCONSISTENT); 165201360Srdivacky 166201360Srdivacky template.type = CKA_EC_PARAMS; 167201360Srdivacky template.pValue = param_buffer; 168201360Srdivacky template.ulValueLen = sizeof (param_buffer); 169201360Srdivacky rv = soft_get_public_key_attribute(pubkey, &template); 170201360Srdivacky if (rv != CKR_OK) { 171201360Srdivacky return (rv); 172201360Srdivacky } 173201360Srdivacky paramlen = template.ulValueLen; 174201360Srdivacky 175201360Srdivacky /* private key also has CKA_EC_PARAMS attribute */ 176201360Srdivacky rv = set_extra_attr_to_object(prikey, CKA_EC_PARAMS, &template); 177201360Srdivacky if (rv != CKR_OK) { 178201360Srdivacky return (rv); 179201360Srdivacky } 180201360Srdivacky 181201360Srdivacky /* ASN1 check */ 182201360Srdivacky if (param_buffer[0] != 0x06 || 183201360Srdivacky param_buffer[1] != paramlen - 2) { 184201360Srdivacky return (CKR_ATTRIBUTE_VALUE_INVALID); 185201360Srdivacky } 186201360Srdivacky params_item.len = paramlen; 187201360Srdivacky params_item.data = param_buffer; 188201360Srdivacky if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) { 189201360Srdivacky /* bad curve OID */ 190201360Srdivacky return (CKR_ARGUMENTS_BAD); 191201360Srdivacky } 192201360Srdivacky 193201360Srdivacky if (EC_NewKey(ecparams, &privKey, 0) != SECSuccess) { 194201360Srdivacky soft_free_ecparams(ecparams, B_TRUE); 195201360Srdivacky return (CKR_FUNCTION_FAILED); 196201360Srdivacky } 197201360Srdivacky 198201360Srdivacky bi.big_value = privKey->privateValue.data; 199201360Srdivacky bi.big_value_len = privKey->privateValue.len; 200201360Srdivacky soft_genECkey_set_attribute(prikey, &bi, CKA_VALUE); 201201360Srdivacky 202201360Srdivacky bi.big_value = privKey->publicValue.data; 203207618Srdivacky bi.big_value_len = privKey->publicValue.len; 204201360Srdivacky soft_genECkey_set_attribute(pubkey, &bi, CKA_EC_POINT); 205207618Srdivacky 206221345Sdim soft_free_ecprivkey(privKey); 207221345Sdim soft_free_ecparams(ecparams, B_TRUE); 208221345Sdim 209221345Sdim return (CKR_OK); 210193323Sed} 211201360Srdivacky 212193323SedCK_RV 213193323Sedsoft_ec_key_derive(soft_object_t *basekey, soft_object_t *secretkey, 214193323Sed void *mech_params, size_t mech_params_len) 215193323Sed{ 216201360Srdivacky CK_RV rv; 217193323Sed CK_ATTRIBUTE template; 218210299Sed CK_ECDH1_DERIVE_PARAMS *ecdh1_derive_params = mech_params; 219210299Sed uchar_t value[EC_MAX_VALUE_LEN]; 220210299Sed uint32_t value_len = sizeof (value); 221210299Sed uchar_t params[EC_MAX_OID_LEN]; 222210299Sed uint32_t params_len = sizeof (params); 223210299Sed uint32_t keylen; 224210299Sed ECParams *ecparams; 225210299Sed SECKEYECParams params_item; 226210299Sed SECItem public_value_item, private_value_item, secret_item; 227210299Sed uchar_t *buf; 228210299Sed 229210299Sed if (mech_params_len != sizeof (CK_ECDH1_DERIVE_PARAMS) || 230210299Sed ecdh1_derive_params->kdf != CKD_NULL) { 231210299Sed return (CKR_MECHANISM_PARAM_INVALID); 232210299Sed } 233210299Sed 234210299Sed template.type = CKA_VALUE; 235210299Sed template.pValue = value; 236210299Sed template.ulValueLen = value_len; 237210299Sed rv = soft_get_private_key_attribute(basekey, &template); 238210299Sed if (rv != CKR_OK) { 239193323Sed return (rv); 240201360Srdivacky } 241193323Sed value_len = template.ulValueLen; 242193323Sed private_value_item.data = value; 243193323Sed private_value_item.len = value_len; 244193323Sed 245201360Srdivacky template.type = CKA_EC_PARAMS; 246193323Sed template.pValue = params; 247210299Sed template.ulValueLen = params_len; 248210299Sed rv = soft_get_private_key_attribute(basekey, &template); 249210299Sed if (rv != CKR_OK) { 250210299Sed return (rv); 251210299Sed } 252210299Sed params_len = template.ulValueLen; 253210299Sed 254210299Sed switch (secretkey->key_type) { 255210299Sed case CKK_DES: 256210299Sed keylen = DES_KEYSIZE; 257210299Sed break; 258210299Sed case CKK_DES2: 259210299Sed keylen = DES2_KEYSIZE; 260210299Sed break; 261210299Sed case CKK_DES3: 262210299Sed keylen = DES3_KEYSIZE; 263210299Sed break; 264210299Sed case CKK_RC4: 265210299Sed case CKK_AES: 266210299Sed case CKK_GENERIC_SECRET: 267210299Sed#ifdef __sparcv9 268210299Sed /* LINTED */ 269210299Sed keylen = (uint32_t)OBJ_SEC_VALUE_LEN(secretkey); 270210299Sed#else /* !__sparcv9 */ 271210299Sed keylen = OBJ_SEC_VALUE_LEN(secretkey); 272210299Sed#endif /* __sparcv9 */ 273210299Sed break; 274210299Sed } 275210299Sed 276210299Sed /* ASN1 check */ 277210299Sed if (params[0] != 0x06 || 278210299Sed params[1] != params_len - 2) { 279210299Sed return (CKR_ATTRIBUTE_VALUE_INVALID); 280210299Sed } 281210299Sed params_item.data = params; 282210299Sed params_item.len = params_len; 283210299Sed if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) { 284210299Sed /* bad curve OID */ 285210299Sed return (CKR_ARGUMENTS_BAD); 286210299Sed } 287210299Sed 288210299Sed public_value_item.data = ecdh1_derive_params->pPublicData; 289210299Sed public_value_item.len = ecdh1_derive_params->ulPublicDataLen; 290210299Sed 291210299Sed secret_item.data = NULL; 292210299Sed secret_item.len = 0; 293210299Sed 294210299Sed if (ECDH_Derive(&public_value_item, ecparams, &private_value_item, 295210299Sed B_FALSE, &secret_item, 0) != SECSuccess) { 296210299Sed soft_free_ecparams(ecparams, B_TRUE); 297210299Sed return (CKR_FUNCTION_FAILED); 298210299Sed } else { 299210299Sed rv = CKR_OK; 300210299Sed } 301210299Sed 302210299Sed if (keylen == 0) 303210299Sed keylen = secret_item.len; 304210299Sed 305210299Sed if (keylen > secret_item.len) { 306210299Sed rv = CKR_ATTRIBUTE_VALUE_INVALID; 307210299Sed goto out; 308210299Sed } 309210299Sed buf = malloc(keylen); 310210299Sed if (buf == NULL) { 311210299Sed rv = CKR_HOST_MEMORY; 312210299Sed goto out; 313210299Sed } 314210299Sed bcopy(secret_item.data + secret_item.len - keylen, buf, keylen); 315210299Sed OBJ_SEC_VALUE_LEN(secretkey) = keylen; 316210299Sed OBJ_SEC_VALUE(secretkey) = buf; 317210299Sed 318210299Sedout: 319210299Sed soft_free_ecparams(ecparams, B_TRUE); 320210299Sed SECITEM_FreeItem(&secret_item, B_FALSE); 321210299Sed 322210299Sed return (rv); 323210299Sed} 324210299Sed 325210299Sed/* 326210299Sed * Allocate a ECC context for the active sign or verify operation. 327210299Sed * This function is called without the session lock held. 328210299Sed */ 329210299SedCK_RV 330210299Sedsoft_ecc_sign_verify_init_common(soft_session_t *session_p, 331210299Sed CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, 332210299Sed boolean_t sign) 333210299Sed{ 334210299Sed CK_RV rv; 335210299Sed CK_ATTRIBUTE template; 336210299Sed CK_MECHANISM digest_mech; 337210299Sed soft_ecc_ctx_t *ecc_ctx; 338210299Sed soft_object_t *tmp_key = NULL; 339210299Sed uchar_t params[EC_MAX_OID_LEN]; 340210299Sed ECParams *ecparams; 341210299Sed SECKEYECParams params_item; 342210299Sed 343210299Sed if ((rv = check_key(key_p, sign)) != CKR_OK) 344210299Sed return (rv); 345210299Sed 346210299Sed if (pMechanism->mechanism == CKM_ECDSA_SHA1) { 347210299Sed digest_mech.mechanism = CKM_SHA_1; 348210299Sed rv = soft_digest_init_internal(session_p, &digest_mech); 349210299Sed if (rv != CKR_OK) 350210299Sed return (rv); 351210299Sed } 352210299Sed 353210299Sed ecc_ctx = malloc(sizeof (soft_ecc_ctx_t)); 354210299Sed if (ecc_ctx == NULL) { 355210299Sed return (CKR_HOST_MEMORY); 356210299Sed } 357210299Sed 358210299Sed /* 359210299Sed * Make a copy of the signature or verification key, and save it 360210299Sed * in the ECC crypto context since it will be used later for 361210299Sed * signing/verification. We don't want to hold any object reference 362210299Sed * on this original key while doing signing/verification. 363210299Sed */ 364210299Sed (void) pthread_mutex_lock(&key_p->object_mutex); 365210299Sed rv = soft_copy_object(key_p, &tmp_key, SOFT_COPY_OBJ_ORIG_SH, NULL); 366210299Sed if ((rv != CKR_OK) || (tmp_key == NULL)) { 367210299Sed /* Most likely we ran out of space. */ 368210299Sed (void) pthread_mutex_unlock(&key_p->object_mutex); 369210299Sed free(ecc_ctx); 370210299Sed return (rv); 371210299Sed } 372210299Sed 373210299Sed 374210299Sed template.type = CKA_EC_PARAMS; 375210299Sed template.pValue = params; 376210299Sed template.ulValueLen = sizeof (params); 377210299Sed rv = soft_get_private_key_attribute(key_p, &template); 378210299Sed (void) pthread_mutex_unlock(&key_p->object_mutex); 379210299Sed if (rv != CKR_OK) { 380210299Sed goto out; 381210299Sed } 382210299Sed 383210299Sed /* ASN1 check */ 384210299Sed if (params[0] != 0x06 || 385210299Sed params[1] != template.ulValueLen - 2) { 386210299Sed rv = CKR_ATTRIBUTE_VALUE_INVALID; 387210299Sed goto out; 388210299Sed } 389210299Sed params_item.data = params; 390210299Sed params_item.len = template.ulValueLen; 391210299Sed 392210299Sed ecc_ctx->key = tmp_key; 393210299Sed 394210299Sed if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) { 395210299Sed /* bad curve OID */ 396210299Sed rv = CKR_ARGUMENTS_BAD; 397210299Sed goto out; 398221345Sdim } 399210299Sed ecc_ctx->ecparams = *ecparams; 400210299Sed free(ecparams); 401193323Sed 402201360Srdivacky (void) pthread_mutex_lock(&session_p->session_mutex); 403193323Sed 404193323Sed if (sign) { 405193323Sed session_p->sign.context = ecc_ctx; 406193323Sed session_p->sign.mech.mechanism = pMechanism->mechanism; 407201360Srdivacky } else { 408193323Sed session_p->verify.context = ecc_ctx; 409210299Sed session_p->verify.mech.mechanism = pMechanism->mechanism; 410210299Sed } 411210299Sed 412210299Sed (void) pthread_mutex_unlock(&session_p->session_mutex); 413210299Sed return (CKR_OK); 414210299Sed 415210299Sedout: 416210299Sed soft_cleanup_object(tmp_key); 417210299Sed free(tmp_key); 418210299Sed free(ecc_ctx); 419210299Sed 420210299Sed return (rv); 421210299Sed} 422210299Sed 423210299SedCK_RV 424210299Sedsoft_ecc_digest_sign_common(soft_session_t *session_p, CK_BYTE_PTR pData, 425210299Sed CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 426193323Sed CK_ULONG_PTR pulSignedLen, boolean_t Final) 427201360Srdivacky{ 428193323Sed CK_RV rv = CKR_OK; 429193323Sed CK_BYTE hash[SHA1_HASH_SIZE]; 430193323Sed CK_ULONG hash_len = SHA1_HASH_SIZE; 431193323Sed 432201360Srdivacky if (pSigned != NULL) { 433193323Sed if (Final) { 434210299Sed rv = soft_digest_final(session_p, hash, &hash_len); 435210299Sed } else { 436210299Sed rv = soft_digest(session_p, pData, ulDataLen, hash, 437210299Sed &hash_len); 438210299Sed } 439193323Sed 440201360Srdivacky if (rv != CKR_OK) { 441193323Sed (void) pthread_mutex_lock(&session_p->session_mutex); 442193323Sed soft_free_ecc_context(session_p->sign.context); 443193323Sed session_p->sign.context = NULL; 444193323Sed session_p->digest.flags = 0; 445201360Srdivacky (void) pthread_mutex_unlock(&session_p->session_mutex); 446193323Sed return (rv); 447210299Sed } 448210299Sed } 449210299Sed 450210299Sed rv = soft_ecc_sign(session_p, hash, hash_len, pSigned, pulSignedLen); 451210299Sed 452193323Sedclean_exit: 453201360Srdivacky (void) pthread_mutex_lock(&session_p->session_mutex); 454193323Sed /* soft_digest_common() has freed the digest context */ 455193323Sed session_p->digest.flags = 0; 456193323Sed (void) pthread_mutex_unlock(&session_p->session_mutex); 457193323Sed 458201360Srdivackyclean1: 459193323Sed return (rv); 460201360Srdivacky} 461210299Sed 462210299SedCK_RV 463210299Sedsoft_ecc_sign(soft_session_t *session_p, CK_BYTE_PTR pData, 464193323Sed CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 465201360Srdivacky CK_ULONG_PTR pulSignedLen) 466193323Sed{ 467193323Sed CK_RV rv = CKR_OK; 468193323Sed SECStatus ss; 469193323Sed soft_ecc_ctx_t *ecc_ctx = session_p->sign.context; 470201360Srdivacky soft_object_t *key = ecc_ctx->key; 471193323Sed uchar_t value[EC_MAX_VALUE_LEN]; 472210299Sed ECPrivateKey ECkey; 473210299Sed SECItem signature_item; 474210299Sed SECItem digest_item; 475193323Sed uint_t value_len; 476201360Srdivacky 477193323Sed if ((key->class != CKO_PRIVATE_KEY) || (key->key_type != CKK_EC)) { 478193323Sed rv = CKR_KEY_TYPE_INCONSISTENT; 479193323Sed goto clean_exit; 480193323Sed } 481201360Srdivacky 482193323Sed if (ulDataLen > EC_MAX_DIGEST_LEN) { 483210299Sed rv = CKR_DATA_LEN_RANGE; 484210299Sed goto clean_exit; 485210299Sed } 486193323Sed 487201360Srdivacky /* structure assignment */ 488193323Sed ECkey.ecParams = ecc_ctx->ecparams; 489193323Sed 490193323Sed value_len = EC_MAX_VALUE_LEN; 491193323Sed rv = soft_get_private_value(key, CKA_VALUE, value, &value_len); 492201360Srdivacky if (rv != CKR_OK) { 493193323Sed goto clean_exit; 494210299Sed } 495210299Sed 496210299Sed ECkey.privateValue.data = value; 497210299Sed ECkey.privateValue.len = value_len; 498210299Sed 499210299Sed signature_item.data = pSigned; 500210299Sed signature_item.len = *pulSignedLen; 501210299Sed 502210299Sed digest_item.data = pData; 503210299Sed digest_item.len = ulDataLen; 504210299Sed 505210299Sed if ((ss = ECDSA_SignDigest(&ECkey, &signature_item, &digest_item, 0)) 506210299Sed != SECSuccess) { 507210299Sed if (ss == SECBufferTooSmall) 508210299Sed return (CKR_BUFFER_TOO_SMALL); 509210299Sed 510210299Sed rv = CKR_FUNCTION_FAILED; 511210299Sed goto clean_exit; 512210299Sed } 513210299Sed 514210299Sed if (rv == CKR_OK) { 515193323Sed *pulSignedLen = signature_item.len; 516201360Srdivacky if (pSigned == NULL) 517193323Sed return (rv); 518193323Sed } 519193323Sed 520193323Sedclean_exit: 521201360Srdivacky (void) pthread_mutex_lock(&session_p->session_mutex); 522201360Srdivacky soft_free_ecc_context(session_p->sign.context); 523210299Sed session_p->sign.context = NULL; 524210299Sed (void) pthread_mutex_unlock(&session_p->session_mutex); 525210299Sed return (rv); 526210299Sed} 527193323Sed 528201360SrdivackyCK_RV 529193323Sedsoft_ecc_verify(soft_session_t *session_p, CK_BYTE_PTR pData, 530193323Sed CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, 531193323Sed CK_ULONG ulSignatureLen) 532193323Sed{ 533201360Srdivacky CK_RV rv = CKR_OK; 534193323Sed soft_ecc_ctx_t *ecc_ctx = session_p->verify.context; 535210299Sed soft_object_t *key = ecc_ctx->key; 536210299Sed uchar_t point[EC_MAX_POINT_LEN]; 537210299Sed CK_ATTRIBUTE template; 538210299Sed ECPublicKey ECkey; 539210299Sed SECItem signature_item; 540193323Sed SECItem digest_item; 541201360Srdivacky 542193323Sed if ((key->class != CKO_PUBLIC_KEY) ||(key->key_type != CKK_EC)) { 543193323Sed rv = CKR_KEY_TYPE_INCONSISTENT; 544193323Sed goto clean_exit; 545193323Sed } 546201360Srdivacky 547201360Srdivacky if (ulSignatureLen > EC_MAX_SIG_LEN) { 548210299Sed rv = CKR_SIGNATURE_LEN_RANGE; 549210299Sed goto clean_exit; 550210299Sed } 551210299Sed 552193323Sed if (ulDataLen > EC_MAX_DIGEST_LEN) { 553201360Srdivacky rv = CKR_DATA_LEN_RANGE; 554193323Sed goto clean_exit; 555193323Sed } 556193323Sed 557193323Sed /* structure assignment */ 558201360Srdivacky ECkey.ecParams = ecc_ctx->ecparams; 559201360Srdivacky 560210299Sed template.type = CKA_EC_POINT; 561210299Sed template.pValue = point; 562193323Sed template.ulValueLen = sizeof (point); 563201360Srdivacky rv = soft_get_public_key_attribute(key, &template); 564193323Sed if (rv != CKR_OK) { 565193323Sed goto clean_exit; 566193323Sed } 567193323Sed 568201360Srdivacky ECkey.publicValue.data = point; 569201360Srdivacky ECkey.publicValue.len = template.ulValueLen; 570210299Sed 571210299Sed signature_item.data = pSignature; 572193323Sed signature_item.len = ulSignatureLen; 573201360Srdivacky 574193323Sed digest_item.data = pData; 575193323Sed digest_item.len = ulDataLen; 576193323Sed 577193323Sed if (ECDSA_VerifyDigest(&ECkey, &signature_item, &digest_item, 0) 578201360Srdivacky != SECSuccess) { 579201360Srdivacky rv = CKR_SIGNATURE_INVALID; 580210299Sed } else { 581210299Sed rv = CKR_OK; 582210299Sed } 583210299Sed 584210299Sedclean_exit: 585210299Sed (void) pthread_mutex_lock(&session_p->session_mutex); 586210299Sed soft_free_ecc_context(session_p->verify.context); 587210299Sed session_p->verify.context = NULL; 588210299Sed (void) pthread_mutex_unlock(&session_p->session_mutex); 589210299Sed return (rv); 590210299Sed} 591210299Sed 592193323Sed 593201360SrdivackyCK_RV 594193323Sedsoft_ecc_digest_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData, 595193323Sed CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, 596193323Sed CK_ULONG ulSignedLen, boolean_t Final) 597193323Sed{ 598201360Srdivacky CK_RV rv; 599201360Srdivacky CK_BYTE hash[SHA1_HASH_SIZE]; 600201360Srdivacky CK_ULONG hash_len = SHA1_HASH_SIZE; 601210299Sed 602210299Sed if (Final) { 603210299Sed rv = soft_digest_final(session_p, hash, &hash_len); 604210299Sed } else { 605210299Sed rv = soft_digest(session_p, pData, ulDataLen, hash, &hash_len); 606193323Sed } 607201360Srdivacky 608193323Sed if (rv != CKR_OK) { 609193323Sed (void) pthread_mutex_lock(&session_p->session_mutex); 610193323Sed soft_free_ecc_context(session_p->verify.context); 611193323Sed session_p->verify.context = NULL; 612201360Srdivacky session_p->digest.flags = 0; 613201360Srdivacky (void) pthread_mutex_unlock(&session_p->session_mutex); 614201360Srdivacky return (rv); 615210299Sed } 616210299Sed 617210299Sed /* 618210299Sed * Now, we are ready to verify the data using signature. 619210299Sed * soft_ecc_verify() will free the verification key. 620193323Sed */ 621201360Srdivacky rv = soft_ecc_verify(session_p, hash, hash_len, 622193323Sed pSigned, ulSignedLen); 623193323Sed 624193323Sedclean_exit: 625193323Sed (void) pthread_mutex_lock(&session_p->session_mutex); 626201360Srdivacky /* soft_digest_common() has freed the digest context */ 627201360Srdivacky session_p->digest.flags = 0; 628210299Sed (void) pthread_mutex_unlock(&session_p->session_mutex); 629210299Sed return (rv); 630210299Sed} 631210299Sed