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 2010 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 /*
  26  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
  27  */
  28 
  29 #include <sys/types.h>
  30 #include <sys/systm.h>
  31 #include <sys/param.h>
  32 #include <sys/modctl.h>
  33 #include <sys/ddi.h>
  34 #include <sys/crypto/spi.h>
  35 #include <sys/crypto/impl.h>
  36 #include <sys/crypto/ioctladmin.h>
  37 #include <sys/sysmacros.h>
  38 #include <sys/strsun.h>
  39 #include <sys/sha1.h>
  40 #include <sys/random.h>
  41 #include <sys/conf.h>
  42 #include <sys/devops.h>
  43 #include <sys/sunddi.h>
  44 #include <sys/varargs.h>
  45 #include <sys/kmem.h>
  46 #include <sys/kstat.h>
  47 
  48 #include <des/des_impl.h>
  49 #include <ecc/ecc_impl.h>
  50 
  51 #define CKD_NULL                0x00000001
  52 
  53 extern struct mod_ops mod_cryptoops;
  54 
  55 /*
  56  * Module linkage information for the kernel.
  57  */
  58 static struct modlcrypto modlcrypto = {
  59         &mod_cryptoops,
  60         "EC Kernel SW Provider"
  61 };
  62 
  63 static struct modlinkage modlinkage = {
  64         MODREV_1,
  65         (void *)&modlcrypto,
  66         NULL
  67 };
  68 
  69 /*
  70  * CSPI information (entry points, provider info, etc.)
  71  */
  72 typedef enum ecc_mech_type {
  73         EC_KEY_PAIR_GEN_MECH_INFO_TYPE, /* SUN_CKM_EC_KEY_PAIR_GEN */
  74         ECDSA_MECH_INFO_TYPE,           /* SUN_CKM_ECDSA */
  75         ECDSA_SHA1_MECH_INFO_TYPE,      /* SUN_CKM_ECDSA_SHA1 */
  76         ECDH1_DERIVE_MECH_INFO_TYPE     /* SUN_CKM_ECDH1_DERIVE */
  77 } ecc_mech_type_t;
  78 
  79 /*
  80  * Context for ECDSA mechanism.
  81  */
  82 typedef struct ecc_ctx {
  83         ecc_mech_type_t mech_type;
  84         crypto_key_t *key;
  85         size_t keychunk_size;
  86         ECParams ecparams;
  87 } ecc_ctx_t;
  88 
  89 /*
  90  * Context for ECDSA_SHA1 mechanism.
  91  */
  92 typedef struct digest_ecc_ctx {
  93         ecc_mech_type_t mech_type;
  94         crypto_key_t *key;
  95         size_t keychunk_size;
  96         ECParams ecparams;
  97         union {
  98                 SHA1_CTX sha1ctx;
  99         } dctx_u;
 100 } digest_ecc_ctx_t;
 101 
 102 #define sha1_ctx        dctx_u.sha1ctx
 103 
 104 /*
 105  * Mechanism info structure passed to KCF during registration.
 106  */
 107 static crypto_mech_info_t ecc_mech_info_tab[] = {
 108         /* EC_KEY_PAIR_GEN */
 109         {SUN_CKM_EC_KEY_PAIR_GEN, EC_KEY_PAIR_GEN_MECH_INFO_TYPE,
 110             CRYPTO_FG_GENERATE_KEY_PAIR, EC_MIN_KEY_LEN, EC_MAX_KEY_LEN,
 111             CRYPTO_KEYSIZE_UNIT_IN_BITS},
 112         /* ECDH */
 113         {SUN_CKM_ECDH1_DERIVE, ECDH1_DERIVE_MECH_INFO_TYPE, CRYPTO_FG_DERIVE,
 114             EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 115         /* ECDSA */
 116         {SUN_CKM_ECDSA, ECDSA_MECH_INFO_TYPE,
 117             CRYPTO_FG_SIGN | CRYPTO_FG_VERIFY |
 118             CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC,
 119             EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS},
 120         /* ECDSA_SHA1 */
 121         {SUN_CKM_ECDSA_SHA1, ECDSA_SHA1_MECH_INFO_TYPE,
 122             CRYPTO_FG_SIGN | CRYPTO_FG_VERIFY |
 123             CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC,
 124             EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS}
 125 };
 126 
 127 static void ecc_provider_status(crypto_provider_handle_t, uint_t *);
 128 
 129 static crypto_control_ops_t ecc_control_ops = {
 130         ecc_provider_status
 131 };
 132 
 133 static int ecc_sign_init(crypto_ctx_t *, crypto_mechanism_t *,
 134     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
 135 static int ecc_sign(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
 136     crypto_req_handle_t);
 137 static int ecc_sign_update(crypto_ctx_t *, crypto_data_t *,
 138     crypto_req_handle_t);
 139 static int ecc_sign_final(crypto_ctx_t *, crypto_data_t *,
 140     crypto_req_handle_t);
 141 static int ecc_sign_atomic(crypto_provider_handle_t, crypto_session_id_t,
 142     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
 143     crypto_spi_ctx_template_t, crypto_req_handle_t);
 144 
 145 static crypto_sign_ops_t ecc_sign_ops = {
 146         ecc_sign_init,
 147         ecc_sign,
 148         ecc_sign_update,
 149         ecc_sign_final,
 150         ecc_sign_atomic,
 151         NULL,
 152         NULL,
 153         NULL
 154 };
 155 
 156 static int ecc_verify_init(crypto_ctx_t *, crypto_mechanism_t *,
 157     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
 158 static int ecc_verify(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
 159     crypto_req_handle_t);
 160 static int ecc_verify_update(crypto_ctx_t *, crypto_data_t *,
 161     crypto_req_handle_t);
 162 static int ecc_verify_final(crypto_ctx_t *, crypto_data_t *,
 163     crypto_req_handle_t);
 164 static int ecc_verify_atomic(crypto_provider_handle_t, crypto_session_id_t,
 165     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
 166     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
 167 
 168 static crypto_verify_ops_t ecc_verify_ops = {
 169         ecc_verify_init,
 170         ecc_verify,
 171         ecc_verify_update,
 172         ecc_verify_final,
 173         ecc_verify_atomic,
 174         NULL,
 175         NULL,
 176         NULL
 177 };
 178 
 179 static int ecc_nostore_key_generate_pair(crypto_provider_handle_t,
 180     crypto_session_id_t, crypto_mechanism_t *, crypto_object_attribute_t *,
 181     uint_t, crypto_object_attribute_t *, uint_t, crypto_object_attribute_t *,
 182     uint_t, crypto_object_attribute_t *, uint_t, crypto_req_handle_t);
 183 static int ecc_nostore_key_derive(crypto_provider_handle_t,
 184     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
 185     crypto_object_attribute_t *, uint_t, crypto_object_attribute_t *,
 186     uint_t, crypto_req_handle_t);
 187 
 188 static crypto_nostore_key_ops_t ecc_nostore_key_ops = {
 189         NULL,
 190         ecc_nostore_key_generate_pair,
 191         ecc_nostore_key_derive
 192 };
 193 
 194 static crypto_ops_t ecc_crypto_ops = {
 195         &ecc_control_ops,
 196         NULL,
 197         NULL,
 198         NULL,
 199         &ecc_sign_ops,
 200         &ecc_verify_ops,
 201         NULL,
 202         NULL,
 203         NULL,
 204         NULL,
 205         NULL,
 206         NULL,
 207         NULL,
 208         NULL,
 209         NULL,
 210         &ecc_nostore_key_ops,
 211         NULL,
 212 };
 213 
 214 static crypto_provider_info_t ecc_prov_info = {
 215         CRYPTO_SPI_VERSION_4,
 216         "EC Software Provider",
 217         CRYPTO_SW_PROVIDER,
 218         {&modlinkage},
 219         NULL,
 220         &ecc_crypto_ops,
 221         sizeof (ecc_mech_info_tab)/sizeof (crypto_mech_info_t),
 222         ecc_mech_info_tab
 223 };
 224 
 225 static crypto_kcf_provider_handle_t ecc_prov_handle = NULL;
 226 
 227 static int ecc_sign_common(ecc_ctx_t *, crypto_data_t *, crypto_data_t *,
 228     crypto_req_handle_t);
 229 static int ecc_verify_common(ecc_ctx_t *, crypto_data_t *, crypto_data_t *,
 230     crypto_req_handle_t);
 231 static int find_attr(crypto_object_attribute_t *, uint_t, uint64_t);
 232 static int get_template_attr_ulong(crypto_object_attribute_t *,
 233     uint_t, uint64_t, ulong_t *);
 234 static void ecc_free_context(crypto_ctx_t *);
 235 static void free_ecparams(ECParams *, boolean_t);
 236 static void free_ecprivkey(ECPrivateKey *);
 237 
 238 int
 239 _init(void)
 240 {
 241         int ret;
 242 
 243         if ((ret = mod_install(&modlinkage)) != 0)
 244                 return (ret);
 245 
 246         /* Register with KCF.  If the registration fails, remove the module. */
 247         if (crypto_register_provider(&ecc_prov_info, &ecc_prov_handle)) {
 248                 (void) mod_remove(&modlinkage);
 249                 return (EACCES);
 250         }
 251 
 252         return (0);
 253 }
 254 
 255 int
 256 _fini(void)
 257 {
 258         /* Unregister from KCF if module is registered */
 259         if (ecc_prov_handle != NULL) {
 260                 if (crypto_unregister_provider(ecc_prov_handle))
 261                         return (EBUSY);
 262 
 263                 ecc_prov_handle = NULL;
 264         }
 265 
 266         return (mod_remove(&modlinkage));
 267 }
 268 
 269 int
 270 _info(struct modinfo *modinfop)
 271 {
 272         return (mod_info(&modlinkage, modinfop));
 273 }
 274 
 275 /* ARGSUSED */
 276 static void
 277 ecc_provider_status(crypto_provider_handle_t provider, uint_t *status)
 278 {
 279         *status = CRYPTO_PROVIDER_READY;
 280 }
 281 
 282 /*
 283  * Return the index of an attribute of specified type found in
 284  * the specified array of attributes. If the attribute cannot
 285  * found, return -1.
 286  */
 287 static int
 288 find_attr(crypto_object_attribute_t *attr, uint_t nattr, uint64_t attr_type)
 289 {
 290         int i;
 291 
 292         for (i = 0; i < nattr; i++)
 293                 if (attr[i].oa_value != NULL && attr[i].oa_type == attr_type)
 294                         return (i);
 295         return (-1);
 296 }
 297 
 298 /*
 299  * Common function used by the get_template_attr_*() family of
 300  * functions. Returns the value of the specified attribute of specified
 301  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
 302  * if the length of the attribute does not match the specified length,
 303  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
 304  */
 305 static int
 306 get_template_attr_scalar_common(crypto_object_attribute_t *template,
 307     uint_t nattr, uint64_t attr_type, void *value, size_t value_len)
 308 {
 309         size_t oa_value_len;
 310         size_t offset = 0;
 311         int attr_idx;
 312 
 313         if ((attr_idx = find_attr(template, nattr, attr_type)) == -1)
 314                 return (CRYPTO_ARGUMENTS_BAD);
 315 
 316         oa_value_len = template[attr_idx].oa_value_len;
 317         if (oa_value_len != value_len) {
 318                 return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
 319         }
 320 
 321 do_copy:
 322         bcopy(template[attr_idx].oa_value, (uchar_t *)value + offset,
 323             oa_value_len);
 324 
 325         return (CRYPTO_SUCCESS);
 326 }
 327 
 328 /*
 329  * Get the value of a ulong_t attribute from the specified template.
 330  */
 331 static int
 332 get_template_attr_ulong(crypto_object_attribute_t *template,
 333     uint_t nattr, uint64_t attr_type, ulong_t *attr_value)
 334 {
 335         return (get_template_attr_scalar_common(template, nattr,
 336             attr_type, attr_value, sizeof (ulong_t)));
 337 }
 338 
 339 /*
 340  * Called from init routines to do basic sanity checks. Init routines,
 341  * e.g. sign_init should fail rather than subsequent operations.
 342  */
 343 static int
 344 check_mech_and_key(ecc_mech_type_t mech_type, crypto_key_t *key, ulong_t class)
 345 {
 346         int rv = CRYPTO_SUCCESS;
 347         uchar_t *foo;
 348         ssize_t point_len;
 349         ssize_t value_len;
 350 
 351         if (mech_type != ECDSA_SHA1_MECH_INFO_TYPE &&
 352             mech_type != ECDSA_MECH_INFO_TYPE)
 353                 return (CRYPTO_MECHANISM_INVALID);
 354 
 355         if (key->ck_format != CRYPTO_KEY_ATTR_LIST) {
 356                 return (CRYPTO_KEY_TYPE_INCONSISTENT);
 357         }
 358 
 359         switch (class) {
 360         case CKO_PUBLIC_KEY:
 361                 if ((rv = crypto_get_key_attr(key, CKA_EC_POINT, &foo,
 362                     &point_len)) != CRYPTO_SUCCESS) {
 363                         return (CRYPTO_TEMPLATE_INCOMPLETE);
 364                 }
 365                 if (point_len < CRYPTO_BITS2BYTES(EC_MIN_KEY_LEN) * 2 + 1 ||
 366                     point_len > CRYPTO_BITS2BYTES(EC_MAX_KEY_LEN) * 2 + 1)
 367                         return (CRYPTO_KEY_SIZE_RANGE);
 368                 break;
 369 
 370         case CKO_PRIVATE_KEY:
 371                 if ((rv = crypto_get_key_attr(key, CKA_VALUE, &foo,
 372                     &value_len)) != CRYPTO_SUCCESS) {
 373                         return (CRYPTO_TEMPLATE_INCOMPLETE);
 374                 }
 375                 if (value_len < CRYPTO_BITS2BYTES(EC_MIN_KEY_LEN) ||
 376                     value_len > CRYPTO_BITS2BYTES(EC_MAX_KEY_LEN))
 377                         return (CRYPTO_KEY_SIZE_RANGE);
 378                 break;
 379 
 380         default:
 381                 return (CRYPTO_TEMPLATE_INCONSISTENT);
 382         }
 383 
 384         return (rv);
 385 }
 386 
 387 /*
 388  * This function guarantees to return non-zero random numbers.
 389  * This is needed as the /dev/urandom kernel interface,
 390  * random_get_pseudo_bytes(), may return zeros.
 391  */
 392 int
 393 ecc_knzero_random_generator(uint8_t *ran_out, size_t ran_len)
 394 {
 395         int rv;
 396         size_t ebc = 0; /* count of extra bytes in extrarand */
 397         size_t i = 0;
 398         uint8_t extrarand[32];
 399         size_t extrarand_len;
 400 
 401         if ((rv = random_get_pseudo_bytes(ran_out, ran_len)) != 0)
 402                 return (rv);
 403 
 404         /*
 405          * Walk through the returned random numbers pointed by ran_out,
 406          * and look for any random number which is zero.
 407          * If we find zero, call random_get_pseudo_bytes() to generate
 408          * another 32 random numbers pool. Replace any zeros in ran_out[]
 409          * from the random number in pool.
 410          */
 411         while (i < ran_len) {
 412                 if (ran_out[i] != 0) {
 413                         i++;
 414                         continue;
 415                 }
 416 
 417                 /*
 418                  * Note that it is 'while' so we are guaranteed a
 419                  * non-zero value on exit.
 420                  */
 421                 if (ebc == 0) {
 422                         /* refresh extrarand */
 423                         extrarand_len = sizeof (extrarand);
 424                         if ((rv = random_get_pseudo_bytes(extrarand,
 425                             extrarand_len)) != 0) {
 426                                 return (rv);
 427                         }
 428 
 429                         ebc = extrarand_len;
 430                 }
 431                 /* Replace zero with byte from extrarand. */
 432                 -- ebc;
 433 
 434                 /*
 435                  * The new random byte zero/non-zero will be checked in
 436                  * the next pass through the loop.
 437                  */
 438                 ran_out[i] = extrarand[ebc];
 439         }
 440 
 441         return (CRYPTO_SUCCESS);
 442 }
 443 
 444 static void
 445 ecc_free_context(crypto_ctx_t *ctx)
 446 {
 447         ecc_ctx_t *ctxp = ctx->cc_provider_private;
 448 
 449         if (ctxp != NULL) {
 450                 bzero(ctxp->key, ctxp->keychunk_size);
 451                 kmem_free(ctxp->key, ctxp->keychunk_size);
 452 
 453                 free_ecparams(&ctxp->ecparams, B_FALSE);
 454 
 455                 if (ctxp->mech_type == ECDSA_MECH_INFO_TYPE)
 456                         kmem_free(ctxp, sizeof (ecc_ctx_t));
 457                 else
 458                         kmem_free(ctxp, sizeof (digest_ecc_ctx_t));
 459 
 460                 ctx->cc_provider_private = NULL;
 461         }
 462 }
 463 
 464 /* ARGSUSED */
 465 static int
 466 ecc_sign_verify_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
 467     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
 468     crypto_req_handle_t req)
 469 {
 470         int rv;
 471         int kmflag;
 472         ecc_ctx_t *ctxp;
 473         digest_ecc_ctx_t *dctxp;
 474         ecc_mech_type_t mech_type = mechanism->cm_type;
 475         uchar_t *params;
 476         ssize_t params_len;
 477         ECParams  *ecparams;
 478         SECKEYECParams params_item;
 479 
 480         if (crypto_get_key_attr(key, CKA_EC_PARAMS, (void *) &params,
 481             &params_len)) {
 482                 return (CRYPTO_ARGUMENTS_BAD);
 483         }
 484 
 485         /* ASN1 check */
 486         if (params[0] != 0x06 ||
 487             params[1] != params_len - 2) {
 488                 return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
 489         }
 490         params_item.data = params;
 491         params_item.len = (uint_t)params_len;
 492         kmflag = crypto_kmflag(req);
 493         if (EC_DecodeParams(&params_item, &ecparams, kmflag) != SECSuccess) {
 494                 /* bad curve OID */
 495                 return (CRYPTO_ARGUMENTS_BAD);
 496         }
 497 
 498         /*
 499          * Allocate an ECC context.
 500          */
 501         switch (mech_type) {
 502         case ECDSA_SHA1_MECH_INFO_TYPE:
 503                 dctxp = kmem_zalloc(sizeof (digest_ecc_ctx_t), kmflag);
 504                 ctxp = (ecc_ctx_t *)dctxp;
 505                 break;
 506         default:
 507                 ctxp = kmem_zalloc(sizeof (ecc_ctx_t), kmflag);
 508                 break;
 509         }
 510 
 511         if (ctxp == NULL) {
 512                 free_ecparams(ecparams, B_TRUE);
 513                 return (CRYPTO_HOST_MEMORY);
 514         }
 515 
 516         if ((rv = crypto_copy_key_to_ctx(key, &ctxp->key, &ctxp->keychunk_size,
 517             kmflag)) != CRYPTO_SUCCESS) {
 518                 switch (mech_type) {
 519                 case ECDSA_SHA1_MECH_INFO_TYPE:
 520                         kmem_free(dctxp, sizeof (digest_ecc_ctx_t));
 521                         break;
 522                 default:
 523                         kmem_free(ctxp, sizeof (ecc_ctx_t));
 524                         break;
 525                 }
 526                 free_ecparams(ecparams, B_TRUE);
 527                 return (rv);
 528         }
 529         ctxp->mech_type = mech_type;
 530         ctxp->ecparams = *ecparams;
 531         kmem_free(ecparams, sizeof (ECParams));
 532 
 533         switch (mech_type) {
 534         case ECDSA_SHA1_MECH_INFO_TYPE:
 535                 SHA1Init(&(dctxp->sha1_ctx));
 536                 break;
 537         }
 538 
 539         ctx->cc_provider_private = ctxp;
 540 
 541         return (CRYPTO_SUCCESS);
 542 }
 543 
 544 /* ARGSUSED */
 545 static int
 546 ecc_sign_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
 547     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
 548     crypto_req_handle_t req)
 549 {
 550         int rv;
 551 
 552         ecc_mech_type_t mech_type = mechanism->cm_type;
 553 
 554         if ((rv = check_mech_and_key(mech_type, key,
 555             CKO_PRIVATE_KEY)) != CRYPTO_SUCCESS)
 556                 return (rv);
 557 
 558         rv = ecc_sign_verify_common_init(ctx, mechanism, key,
 559             ctx_template, req);
 560 
 561         return (rv);
 562 }
 563 
 564 /* ARGSUSED */
 565 static int
 566 ecc_verify_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
 567     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
 568     crypto_req_handle_t req)
 569 {
 570         int rv;
 571 
 572         ecc_mech_type_t mech_type = mechanism->cm_type;
 573 
 574         if ((rv = check_mech_and_key(mech_type, key,
 575             CKO_PUBLIC_KEY)) != CRYPTO_SUCCESS)
 576                 return (rv);
 577 
 578         rv = ecc_sign_verify_common_init(ctx, mechanism, key,
 579             ctx_template, req);
 580 
 581         return (rv);
 582 }
 583 
 584 #define SHA1_DIGEST_SIZE 20
 585 
 586 #define INIT_RAW_CRYPTO_DATA(data, base, len, cd_len)   \
 587         (data).cd_format = CRYPTO_DATA_RAW;             \
 588         (data).cd_offset = 0;                           \
 589         (data).cd_raw.iov_base = (char *)base;          \
 590         (data).cd_raw.iov_len = len;                    \
 591         (data).cd_length = cd_len;
 592 
 593 static int
 594 ecc_digest_svrfy_common(digest_ecc_ctx_t *ctxp, crypto_data_t *data,
 595     crypto_data_t *signature, uchar_t flag, crypto_req_handle_t req)
 596 {
 597         int rv = CRYPTO_FAILED;
 598         uchar_t digest[SHA1_DIGEST_LENGTH];
 599         crypto_data_t der_cd;
 600         ecc_mech_type_t mech_type;
 601 
 602         ASSERT(flag & CRYPTO_DO_SIGN || flag & CRYPTO_DO_VERIFY);
 603         ASSERT(data != NULL || (flag & CRYPTO_DO_FINAL));
 604 
 605         mech_type = ctxp->mech_type;
 606         if (mech_type != ECDSA_SHA1_MECH_INFO_TYPE)
 607                 return (CRYPTO_MECHANISM_INVALID);
 608 
 609         /* Don't digest if only returning length of signature. */
 610         if (signature->cd_length > 0) {
 611                 if (mech_type == ECDSA_SHA1_MECH_INFO_TYPE) {
 612                         rv = crypto_digest_data(data, &(ctxp->sha1_ctx),
 613                             digest, (void (*)())SHA1Update,
 614                             (void (*)())SHA1Final, flag | CRYPTO_DO_SHA1);
 615                         if (rv != CRYPTO_SUCCESS)
 616                                 return (rv);
 617                 }
 618         }
 619 
 620         INIT_RAW_CRYPTO_DATA(der_cd, digest, SHA1_DIGEST_SIZE,
 621             SHA1_DIGEST_SIZE);
 622 
 623         if (flag & CRYPTO_DO_SIGN) {
 624                 rv = ecc_sign_common((ecc_ctx_t *)ctxp, &der_cd, signature,
 625                     req);
 626         } else
 627                 rv = ecc_verify_common((ecc_ctx_t *)ctxp, &der_cd, signature,
 628                     req);
 629 
 630         return (rv);
 631 }
 632 
 633 /*
 634  * This is a single-part signing routine. It does not
 635  * compute a hash before signing.
 636  */
 637 static int
 638 ecc_sign_common(ecc_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
 639     crypto_req_handle_t req)
 640 {
 641         int rv = CRYPTO_FAILED;
 642         SECStatus ss;
 643         uchar_t *param;
 644         uchar_t *private;
 645         ssize_t param_len;
 646         ssize_t private_len;
 647         uchar_t tmp_data[EC_MAX_DIGEST_LEN];
 648         uchar_t signed_data[EC_MAX_SIG_LEN];
 649         ECPrivateKey ECkey;
 650         SECItem signature_item;
 651         SECItem digest_item;
 652         crypto_key_t *key = ctx->key;
 653         int kmflag;
 654 
 655         if ((rv = crypto_get_key_attr(key, CKA_EC_PARAMS, &param,
 656             &param_len)) != CRYPTO_SUCCESS) {
 657                 return (rv);
 658         }
 659 
 660         if (data->cd_length > sizeof (tmp_data))
 661                 return (CRYPTO_DATA_LEN_RANGE);
 662 
 663         if ((rv = crypto_get_input_data(data, &digest_item.data, tmp_data))
 664             != CRYPTO_SUCCESS) {
 665                 return (rv);
 666         }
 667         digest_item.len = data->cd_length;
 668 
 669         /* structure assignment */
 670         ECkey.ecParams = ctx->ecparams;
 671 
 672         if ((rv = crypto_get_key_attr(key, CKA_VALUE, &private,
 673             &private_len)) != CRYPTO_SUCCESS) {
 674                 return (rv);
 675         }
 676         ECkey.privateValue.data = private;
 677         ECkey.privateValue.len = (uint_t)private_len;
 678 
 679         signature_item.data = signed_data;
 680         signature_item.len = sizeof (signed_data);
 681 
 682         kmflag = crypto_kmflag(req);
 683         if ((ss = ECDSA_SignDigest(&ECkey, &signature_item, &digest_item,
 684             kmflag)) != SECSuccess) {
 685                 if (ss == SECBufferTooSmall)
 686                         return (CRYPTO_BUFFER_TOO_SMALL);
 687 
 688                 return (CRYPTO_FAILED);
 689         }
 690 
 691         if (rv == CRYPTO_SUCCESS) {
 692                 /* copy out the signature */
 693                 if ((rv = crypto_put_output_data(signed_data,
 694                     signature, signature_item.len)) != CRYPTO_SUCCESS)
 695                         return (rv);
 696 
 697                 signature->cd_length = signature_item.len;
 698         }
 699 
 700         return (rv);
 701 }
 702 
 703 /* ARGSUSED */
 704 static int
 705 ecc_sign(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
 706     crypto_req_handle_t req)
 707 {
 708         int rv;
 709         ecc_ctx_t *ctxp;
 710 
 711         ASSERT(ctx->cc_provider_private != NULL);
 712         ctxp = ctx->cc_provider_private;
 713 
 714         switch (ctxp->mech_type) {
 715         case ECDSA_SHA1_MECH_INFO_TYPE:
 716                 rv = ecc_digest_svrfy_common((digest_ecc_ctx_t *)ctxp, data,
 717                     signature, CRYPTO_DO_SIGN | CRYPTO_DO_UPDATE |
 718                     CRYPTO_DO_FINAL, req);
 719                 break;
 720         default:
 721                 rv = ecc_sign_common(ctxp, data, signature, req);
 722                 break;
 723         }
 724 
 725         if (rv != CRYPTO_BUFFER_TOO_SMALL)
 726                 ecc_free_context(ctx);
 727 
 728         return (rv);
 729 }
 730 
 731 /* ARGSUSED */
 732 static int
 733 ecc_sign_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req)
 734 {
 735         int rv;
 736         digest_ecc_ctx_t *ctxp;
 737         ecc_mech_type_t mech_type;
 738 
 739         ASSERT(ctx->cc_provider_private != NULL);
 740         ctxp = ctx->cc_provider_private;
 741         mech_type = ctxp->mech_type;
 742 
 743         if (mech_type == ECDSA_MECH_INFO_TYPE) {
 744                 ecc_free_context(ctx);
 745                 return (CRYPTO_MECHANISM_INVALID);
 746         }
 747 
 748         if (mech_type == ECDSA_SHA1_MECH_INFO_TYPE)
 749                 rv = crypto_digest_data(data, &(ctxp->sha1_ctx), NULL,
 750                     (void (*)())SHA1Update, (void (*)())SHA1Final,
 751                     CRYPTO_DO_SHA1 | CRYPTO_DO_UPDATE);
 752 
 753         if (rv != CRYPTO_SUCCESS)
 754                 ecc_free_context(ctx);
 755 
 756         return (rv);
 757 }
 758 
 759 /* ARGSUSED */
 760 static int
 761 ecc_sign_final(crypto_ctx_t *ctx, crypto_data_t *signature,
 762     crypto_req_handle_t req)
 763 {
 764         int rv;
 765         digest_ecc_ctx_t *ctxp;
 766 
 767         ASSERT(ctx->cc_provider_private != NULL);
 768         ctxp = ctx->cc_provider_private;
 769 
 770         rv = ecc_digest_svrfy_common(ctxp, NULL, signature, CRYPTO_DO_SIGN |
 771             CRYPTO_DO_FINAL, req);
 772         if (rv != CRYPTO_BUFFER_TOO_SMALL)
 773                 ecc_free_context(ctx);
 774 
 775         return (rv);
 776 }
 777 
 778 /* ARGSUSED */
 779 static int
 780 ecc_sign_atomic(crypto_provider_handle_t provider,
 781     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
 782     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
 783     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
 784 {
 785         int rv;
 786         ecc_mech_type_t mech_type = mechanism->cm_type;
 787         uchar_t *params;
 788         ssize_t params_len;
 789         ECParams  *ecparams;
 790         SECKEYECParams params_item;
 791         int kmflag;
 792 
 793         if ((rv = check_mech_and_key(mech_type, key,
 794             CKO_PRIVATE_KEY)) != CRYPTO_SUCCESS)
 795                 return (rv);
 796 
 797         if (crypto_get_key_attr(key, CKA_EC_PARAMS, (void *) &params,
 798             &params_len)) {
 799                 return (CRYPTO_ARGUMENTS_BAD);
 800         }
 801 
 802         /* ASN1 check */
 803         if (params[0] != 0x06 ||
 804             params[1] != params_len - 2) {
 805                 return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
 806         }
 807         params_item.data = params;
 808         params_item.len = (uint_t)params_len;
 809         kmflag = crypto_kmflag(req);
 810         if (EC_DecodeParams(&params_item, &ecparams, kmflag) != SECSuccess) {
 811                 /* bad curve OID */
 812                 return (CRYPTO_ARGUMENTS_BAD);
 813         }
 814 
 815         if (mechanism->cm_type == ECDSA_MECH_INFO_TYPE) {
 816                 ecc_ctx_t ctx;
 817 
 818                 ctx.mech_type = mech_type;
 819                 /* structure assignment */
 820                 ctx.ecparams = *ecparams;
 821                 ctx.key = key;
 822                 rv = ecc_sign_common(&ctx, data, signature, req);
 823         } else {
 824                 digest_ecc_ctx_t dctx;
 825 
 826                 dctx.mech_type = mech_type;
 827                 /* structure assignment */
 828                 dctx.ecparams = *ecparams;
 829                 dctx.key = key;
 830                 SHA1Init(&(dctx.sha1_ctx));
 831 
 832                 rv = ecc_digest_svrfy_common(&dctx, data, signature,
 833                     CRYPTO_DO_SIGN | CRYPTO_DO_UPDATE | CRYPTO_DO_FINAL, req);
 834         }
 835         free_ecparams(ecparams, B_TRUE);
 836 
 837         return (rv);
 838 }
 839 
 840 static int
 841 ecc_verify_common(ecc_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
 842     crypto_req_handle_t req)
 843 {
 844         int rv = CRYPTO_FAILED;
 845         uchar_t *param;
 846         uchar_t *public;
 847         ssize_t param_len;
 848         ssize_t public_len;
 849         uchar_t tmp_data[EC_MAX_DIGEST_LEN];
 850         uchar_t signed_data[EC_MAX_SIG_LEN];
 851         ECPublicKey ECkey;
 852         SECItem signature_item;
 853         SECItem digest_item;
 854         crypto_key_t *key = ctx->key;
 855         int kmflag;
 856 
 857         if ((rv = crypto_get_key_attr(key, CKA_EC_PARAMS, &param,
 858             &param_len)) != CRYPTO_SUCCESS) {
 859                 return (rv);
 860         }
 861 
 862         if (signature->cd_length > sizeof (signed_data)) {
 863                 return (CRYPTO_SIGNATURE_LEN_RANGE);
 864         }
 865 
 866         if ((rv = crypto_get_input_data(signature, &signature_item.data,
 867             signed_data)) != CRYPTO_SUCCESS) {
 868                 return (rv);
 869         }
 870         signature_item.len = signature->cd_length;
 871 
 872         if (data->cd_length > sizeof (tmp_data))
 873                 return (CRYPTO_DATA_LEN_RANGE);
 874 
 875         if ((rv = crypto_get_input_data(data, &digest_item.data, tmp_data))
 876             != CRYPTO_SUCCESS) {
 877                 return (rv);
 878         }
 879         digest_item.len = data->cd_length;
 880 
 881         /* structure assignment */
 882         ECkey.ecParams = ctx->ecparams;
 883 
 884         if ((rv = crypto_get_key_attr(key, CKA_EC_POINT, &public,
 885             &public_len)) != CRYPTO_SUCCESS) {
 886                 return (rv);
 887         }
 888         ECkey.publicValue.data = public;
 889         ECkey.publicValue.len = (uint_t)public_len;
 890 
 891         kmflag = crypto_kmflag(req);
 892         if (ECDSA_VerifyDigest(&ECkey, &signature_item, &digest_item, kmflag)
 893             != SECSuccess) {
 894                 rv = CRYPTO_SIGNATURE_INVALID;
 895         } else {
 896                 rv = CRYPTO_SUCCESS;
 897         }
 898 
 899         return (rv);
 900 }
 901 
 902 /* ARGSUSED */
 903 static int
 904 ecc_verify(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
 905     crypto_req_handle_t req)
 906 {
 907         int rv;
 908         ecc_ctx_t *ctxp;
 909 
 910         ASSERT(ctx->cc_provider_private != NULL);
 911         ctxp = ctx->cc_provider_private;
 912 
 913         switch (ctxp->mech_type) {
 914         case ECDSA_SHA1_MECH_INFO_TYPE:
 915                 rv = ecc_digest_svrfy_common((digest_ecc_ctx_t *)ctxp, data,
 916                     signature, CRYPTO_DO_VERIFY | CRYPTO_DO_UPDATE |
 917                     CRYPTO_DO_FINAL, req);
 918                 break;
 919         default:
 920                 rv = ecc_verify_common(ctxp, data, signature, req);
 921                 break;
 922         }
 923 
 924         ecc_free_context(ctx);
 925         return (rv);
 926 }
 927 
 928 /* ARGSUSED */
 929 static int
 930 ecc_verify_update(crypto_ctx_t *ctx, crypto_data_t *data,
 931     crypto_req_handle_t req)
 932 {
 933         int rv;
 934         digest_ecc_ctx_t *ctxp;
 935 
 936         ASSERT(ctx->cc_provider_private != NULL);
 937         ctxp = ctx->cc_provider_private;
 938 
 939         switch (ctxp->mech_type) {
 940         case ECDSA_SHA1_MECH_INFO_TYPE:
 941                 rv = crypto_digest_data(data, &(ctxp->sha1_ctx), NULL,
 942                     (void (*)())SHA1Update, (void (*)())SHA1Final,
 943                     CRYPTO_DO_SHA1 | CRYPTO_DO_UPDATE);
 944                 break;
 945         default:
 946                 rv = CRYPTO_MECHANISM_INVALID;
 947         }
 948 
 949         if (rv != CRYPTO_SUCCESS)
 950                 ecc_free_context(ctx);
 951 
 952         return (rv);
 953 }
 954 
 955 /* ARGSUSED */
 956 static int
 957 ecc_verify_final(crypto_ctx_t *ctx, crypto_data_t *signature,
 958     crypto_req_handle_t req)
 959 {
 960         int rv;
 961         digest_ecc_ctx_t *ctxp;
 962 
 963         ASSERT(ctx->cc_provider_private != NULL);
 964         ctxp = ctx->cc_provider_private;
 965 
 966         rv = ecc_digest_svrfy_common(ctxp, NULL, signature,
 967             CRYPTO_DO_VERIFY | CRYPTO_DO_FINAL, req);
 968 
 969         ecc_free_context(ctx);
 970 
 971         return (rv);
 972 }
 973 
 974 
 975 /* ARGSUSED */
 976 static int
 977 ecc_verify_atomic(crypto_provider_handle_t provider,
 978     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
 979     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
 980     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
 981 {
 982         int rv;
 983         ecc_mech_type_t mech_type = mechanism->cm_type;
 984         uchar_t *params;
 985         ssize_t params_len;
 986         ECParams  *ecparams;
 987         SECKEYECParams params_item;
 988         int kmflag;
 989 
 990         if ((rv = check_mech_and_key(mech_type, key,
 991             CKO_PUBLIC_KEY)) != CRYPTO_SUCCESS)
 992                 return (rv);
 993 
 994         if (crypto_get_key_attr(key, CKA_EC_PARAMS, (void *) &params,
 995             &params_len)) {
 996                 return (CRYPTO_ARGUMENTS_BAD);
 997         }
 998 
 999         /* ASN1 check */
1000         if (params[0] != 0x06 ||
1001             params[1] != params_len - 2) {
1002                 return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
1003         }
1004         params_item.data = params;
1005         params_item.len = (uint_t)params_len;
1006         kmflag = crypto_kmflag(req);
1007         if (EC_DecodeParams(&params_item, &ecparams, kmflag) != SECSuccess) {
1008                 /* bad curve OID */
1009                 return (CRYPTO_ARGUMENTS_BAD);
1010         }
1011 
1012         if (mechanism->cm_type == ECDSA_MECH_INFO_TYPE) {
1013                 ecc_ctx_t ctx;
1014 
1015                 ctx.mech_type = mech_type;
1016                 /* structure assignment */
1017                 ctx.ecparams = *ecparams;
1018                 ctx.key = key;
1019                 rv = ecc_verify_common(&ctx, data, signature, req);
1020         } else {
1021                 digest_ecc_ctx_t dctx;
1022 
1023                 dctx.mech_type = mech_type;
1024                 /* structure assignment */
1025                 dctx.ecparams = *ecparams;
1026                 dctx.key = key;
1027                 SHA1Init(&(dctx.sha1_ctx));
1028 
1029                 rv = ecc_digest_svrfy_common(&dctx, data, signature,
1030                     CRYPTO_DO_VERIFY | CRYPTO_DO_UPDATE | CRYPTO_DO_FINAL, req);
1031         }
1032         free_ecparams(ecparams, B_TRUE);
1033         return (rv);
1034 }
1035 
1036 /* ARGSUSED */
1037 static int
1038 ecc_nostore_key_generate_pair(crypto_provider_handle_t provider,
1039     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1040     crypto_object_attribute_t *pub_template, uint_t pub_attribute_count,
1041     crypto_object_attribute_t *pri_template, uint_t pri_attribute_count,
1042     crypto_object_attribute_t *pub_out_template, uint_t pub_out_attribute_count,
1043     crypto_object_attribute_t *pri_out_template, uint_t pri_out_attribute_count,
1044     crypto_req_handle_t req)
1045 {
1046         int rv = CRYPTO_SUCCESS;
1047         ECPrivateKey *privKey;  /* contains both public and private values */
1048         ECParams *ecparams;
1049         SECKEYECParams params_item;
1050         ulong_t pub_key_type = ~0UL, pub_class = ~0UL;
1051         ulong_t pri_key_type = ~0UL, pri_class = ~0UL;
1052         int params_idx, value_idx, point_idx;
1053         uchar_t *params = NULL;
1054         unsigned params_len;
1055         uchar_t *value = NULL;
1056         uchar_t *point = NULL;
1057         int valuelen;
1058         int pointlen;
1059         int xylen;
1060         int kmflag;
1061 
1062         if (mechanism->cm_type != EC_KEY_PAIR_GEN_MECH_INFO_TYPE) {
1063                 return (CRYPTO_MECHANISM_INVALID);
1064         }
1065 
1066         /* optional */
1067         (void) get_template_attr_ulong(pub_template,
1068             pub_attribute_count, CKA_CLASS, &pub_class);
1069 
1070         /* optional */
1071         (void) get_template_attr_ulong(pri_template,
1072             pri_attribute_count, CKA_CLASS, &pri_class);
1073 
1074         /* optional */
1075         (void) get_template_attr_ulong(pub_template,
1076             pub_attribute_count, CKA_KEY_TYPE, &pub_key_type);
1077 
1078         /* optional */
1079         (void) get_template_attr_ulong(pri_template,
1080             pri_attribute_count, CKA_KEY_TYPE, &pri_key_type);
1081 
1082         if (pub_class != ~0UL && pub_class != CKO_PUBLIC_KEY) {
1083                 return (CRYPTO_TEMPLATE_INCONSISTENT);
1084         }
1085         pub_class = CKO_PUBLIC_KEY;
1086 
1087         if (pri_class != ~0UL && pri_class != CKO_PRIVATE_KEY) {
1088                 return (CRYPTO_TEMPLATE_INCONSISTENT);
1089         }
1090         pri_class = CKO_PRIVATE_KEY;
1091 
1092         if (pub_key_type != ~0UL && pub_key_type != CKK_EC) {
1093                 return (CRYPTO_TEMPLATE_INCONSISTENT);
1094         }
1095         pub_key_type = CKK_EC;
1096 
1097         if (pri_key_type != ~0UL && pri_key_type != CKK_EC) {
1098                 return (CRYPTO_TEMPLATE_INCONSISTENT);
1099         }
1100         pri_key_type = CKK_EC;
1101 
1102         /* public output template must contain CKA_EC_POINT attribute */
1103         if ((point_idx = find_attr(pub_out_template, pub_out_attribute_count,
1104             CKA_EC_POINT)) == -1) {
1105                 return (CRYPTO_TEMPLATE_INCOMPLETE);
1106         }
1107 
1108         /* private output template must contain CKA_VALUE attribute */
1109         if ((value_idx = find_attr(pri_out_template, pri_out_attribute_count,
1110             CKA_VALUE)) == -1) {
1111                 return (CRYPTO_TEMPLATE_INCOMPLETE);
1112         }
1113 
1114         if ((params_idx = find_attr(pub_template, pub_attribute_count,
1115             CKA_EC_PARAMS)) == -1) {
1116                 return (CRYPTO_TEMPLATE_INCOMPLETE);
1117         }
1118 
1119         params = (uchar_t *)pub_template[params_idx].oa_value;
1120         params_len = pub_template[params_idx].oa_value_len;
1121 
1122         value = (uchar_t *)pri_out_template[value_idx].oa_value;
1123         valuelen = (int)pri_out_template[value_idx].oa_value_len;
1124         point = (uchar_t *)pub_out_template[point_idx].oa_value;
1125         pointlen = (int)pub_out_template[point_idx].oa_value_len;
1126 
1127         /* ASN1 check */
1128         if (params[0] != 0x06 ||
1129             params[1] != params_len - 2) {
1130                 return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
1131         }
1132         params_item.data = params;
1133         params_item.len = params_len;
1134         kmflag = crypto_kmflag(req);
1135         if (EC_DecodeParams(&params_item, &ecparams, kmflag) != SECSuccess) {
1136                 /* bad curve OID */
1137                 return (CRYPTO_ARGUMENTS_BAD);
1138         }
1139 
1140         if (EC_NewKey(ecparams, &privKey, kmflag) != SECSuccess) {
1141                 free_ecparams(ecparams, B_TRUE);
1142                 return (CRYPTO_FAILED);
1143         }
1144 
1145         xylen = privKey->publicValue.len;
1146         /* ASSERT that xylen - 1 is divisible by 2 */
1147         if (xylen > pointlen) {
1148                 rv = CRYPTO_BUFFER_TOO_SMALL;
1149                 goto out;
1150         }
1151 
1152         if (privKey->privateValue.len > valuelen) {
1153                 rv = CRYPTO_BUFFER_TOO_SMALL;
1154                 goto out;
1155         }
1156         bcopy(privKey->privateValue.data, value, privKey->privateValue.len);
1157         pri_out_template[value_idx].oa_value_len = privKey->privateValue.len;
1158 
1159         bcopy(privKey->publicValue.data, point, xylen);
1160         pub_out_template[point_idx].oa_value_len = xylen;
1161 
1162 out:
1163         free_ecprivkey(privKey);
1164         free_ecparams(ecparams, B_TRUE);
1165         return (rv);
1166 }
1167 
1168 /* ARGSUSED */
1169 static int
1170 ecc_nostore_key_derive(crypto_provider_handle_t provider,
1171     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1172     crypto_key_t *base_key, crypto_object_attribute_t *in_attrs,
1173     uint_t in_attr_count, crypto_object_attribute_t *out_attrs,
1174     uint_t out_attr_count, crypto_req_handle_t req)
1175 {
1176         int rv = CRYPTO_SUCCESS;
1177         int params_idx, value_idx = -1, out_value_idx = -1;
1178         ulong_t key_type;
1179         ulong_t key_len;
1180         crypto_object_attribute_t *attrs;
1181         ECParams *ecparams;
1182         SECKEYECParams params_item;
1183         CK_ECDH1_DERIVE_PARAMS *mech_param;
1184         SECItem public_value_item, private_value_item, secret_item;
1185         int kmflag;
1186 
1187         if (mechanism->cm_type != ECDH1_DERIVE_MECH_INFO_TYPE) {
1188                 return (CRYPTO_MECHANISM_INVALID);
1189         }
1190 
1191         ASSERT(IS_P2ALIGNED(mechanism->cm_param, sizeof (uint64_t)));
1192         /* LINTED: pointer alignment */
1193         mech_param = (CK_ECDH1_DERIVE_PARAMS *)mechanism->cm_param;
1194         if (mech_param->kdf != CKD_NULL) {
1195                 return (CRYPTO_MECHANISM_PARAM_INVALID);
1196         }
1197 
1198         if ((base_key->ck_format != CRYPTO_KEY_ATTR_LIST) ||
1199             (base_key->ck_count == 0)) {
1200                 return (CRYPTO_ARGUMENTS_BAD);
1201         }
1202 
1203         if ((rv = get_template_attr_ulong(in_attrs, in_attr_count,
1204             CKA_KEY_TYPE, &key_type)) != CRYPTO_SUCCESS) {
1205                 return (rv);
1206         }
1207 
1208         switch (key_type) {
1209         case CKK_DES:
1210                 key_len = DES_KEYSIZE;
1211                 break;
1212         case CKK_DES2:
1213                 key_len = DES2_KEYSIZE;
1214                 break;
1215         case CKK_DES3:
1216                 key_len = DES3_KEYSIZE;
1217                 break;
1218         case CKK_RC4:
1219         case CKK_AES:
1220         case CKK_GENERIC_SECRET:
1221                 if ((rv = get_template_attr_ulong(in_attrs, in_attr_count,
1222                     CKA_VALUE_LEN, &key_len)) != CRYPTO_SUCCESS) {
1223                         return (rv);
1224                 }
1225                 break;
1226         default:
1227                 key_len = 0;
1228         }
1229 
1230         attrs = base_key->ck_attrs;
1231         if ((value_idx = find_attr(attrs, base_key->ck_count,
1232             CKA_VALUE)) == -1) {
1233                 return (CRYPTO_TEMPLATE_INCOMPLETE);
1234         }
1235 
1236         if ((params_idx = find_attr(attrs, base_key->ck_count,
1237             CKA_EC_PARAMS)) == -1) {
1238                 return (CRYPTO_TEMPLATE_INCOMPLETE);
1239         }
1240 
1241         private_value_item.data = (uchar_t *)attrs[value_idx].oa_value;
1242         private_value_item.len = attrs[value_idx].oa_value_len;
1243 
1244         params_item.len = attrs[params_idx].oa_value_len;
1245         params_item.data = (uchar_t *)attrs[params_idx].oa_value;
1246 
1247         /* ASN1 check */
1248         if (params_item.data[0] != 0x06 ||
1249             params_item.data[1] != params_item.len - 2) {
1250                 return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
1251         }
1252         kmflag = crypto_kmflag(req);
1253         if (EC_DecodeParams(&params_item, &ecparams, kmflag) != SECSuccess) {
1254                 /* bad curve OID */
1255                 return (CRYPTO_ARGUMENTS_BAD);
1256         }
1257 
1258         public_value_item.data = (uchar_t *)mech_param->pPublicData;
1259         public_value_item.len = mech_param->ulPublicDataLen;
1260 
1261         if ((out_value_idx = find_attr(out_attrs, out_attr_count,
1262             CKA_VALUE)) == -1) {
1263                 rv = CRYPTO_TEMPLATE_INCOMPLETE;
1264                 goto out;
1265         }
1266         secret_item.data = NULL;
1267         secret_item.len = 0;
1268 
1269         if (ECDH_Derive(&public_value_item, ecparams, &private_value_item,
1270             B_FALSE, &secret_item, kmflag) != SECSuccess) {
1271                 free_ecparams(ecparams, B_TRUE);
1272                 return (CRYPTO_FAILED);
1273         } else {
1274                 rv = CRYPTO_SUCCESS;
1275         }
1276 
1277         if (key_len == 0)
1278                 key_len = secret_item.len;
1279 
1280         if (key_len > secret_item.len) {
1281                 rv = CRYPTO_ATTRIBUTE_VALUE_INVALID;
1282                 goto out;
1283         }
1284         if (key_len > out_attrs[out_value_idx].oa_value_len) {
1285                 rv = CRYPTO_BUFFER_TOO_SMALL;
1286                 goto out;
1287         }
1288         bcopy(secret_item.data + secret_item.len - key_len,
1289             (uchar_t *)out_attrs[out_value_idx].oa_value, key_len);
1290         out_attrs[out_value_idx].oa_value_len = key_len;
1291 out:
1292         free_ecparams(ecparams, B_TRUE);
1293         SECITEM_FreeItem(&secret_item, B_FALSE);
1294         return (rv);
1295 }
1296 
1297 static void
1298 free_ecparams(ECParams *params, boolean_t freeit)
1299 {
1300         SECITEM_FreeItem(&params->fieldID.u.prime, B_FALSE);
1301         SECITEM_FreeItem(&params->curve.a, B_FALSE);
1302         SECITEM_FreeItem(&params->curve.b, B_FALSE);
1303         SECITEM_FreeItem(&params->curve.seed, B_FALSE);
1304         SECITEM_FreeItem(&params->base, B_FALSE);
1305         SECITEM_FreeItem(&params->order, B_FALSE);
1306         SECITEM_FreeItem(&params->DEREncoding, B_FALSE);
1307         SECITEM_FreeItem(&params->curveOID, B_FALSE);
1308         if (freeit)
1309                 kmem_free(params, sizeof (ECParams));
1310 }
1311 
1312 static void
1313 free_ecprivkey(ECPrivateKey *key)
1314 {
1315         free_ecparams(&key->ecParams, B_FALSE);
1316         SECITEM_FreeItem(&key->publicValue, B_FALSE);
1317         bzero(key->privateValue.data, key->privateValue.len);
1318         SECITEM_FreeItem(&key->privateValue, B_FALSE);
1319         SECITEM_FreeItem(&key->version, B_FALSE);
1320         kmem_free(key, sizeof (ECPrivateKey));
1321 }