15697Smcpowers /* 25697Smcpowers * CDDL HEADER START 35697Smcpowers * 45697Smcpowers * The contents of this file are subject to the terms of the 55697Smcpowers * Common Development and Distribution License (the "License"). 65697Smcpowers * You may not use this file except in compliance with the License. 75697Smcpowers * 85697Smcpowers * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95697Smcpowers * or http://www.opensolaris.org/os/licensing. 105697Smcpowers * See the License for the specific language governing permissions 115697Smcpowers * and limitations under the License. 125697Smcpowers * 135697Smcpowers * When distributing Covered Code, include this CDDL HEADER in each 145697Smcpowers * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155697Smcpowers * If applicable, add the following below this CDDL HEADER, with the 165697Smcpowers * fields enclosed by brackets "[]" replaced with your own identifying 175697Smcpowers * information: Portions Copyright [yyyy] [name of copyright owner] 185697Smcpowers * 195697Smcpowers * CDDL HEADER END 205697Smcpowers */ 215697Smcpowers /* 22*7188Smcpowers * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 235697Smcpowers * Use is subject to license terms. 245697Smcpowers */ 255697Smcpowers 265697Smcpowers #pragma ident "%Z%%M% %I% %E% SMI" 275697Smcpowers 285697Smcpowers #include <sys/types.h> 295697Smcpowers #include <sys/systm.h> 305697Smcpowers #include <sys/param.h> 315697Smcpowers #include <sys/modctl.h> 325697Smcpowers #include <sys/ddi.h> 335697Smcpowers #include <sys/crypto/spi.h> 34*7188Smcpowers #include <sys/crypto/impl.h> 355697Smcpowers #include <sys/sysmacros.h> 365697Smcpowers #include <sys/strsun.h> 375697Smcpowers #include <sys/sha1.h> 385697Smcpowers #include <sys/random.h> 395697Smcpowers #include <sys/conf.h> 405697Smcpowers #include <sys/devops.h> 415697Smcpowers #include <sys/sunddi.h> 425697Smcpowers #include <sys/varargs.h> 435697Smcpowers #include <sys/kmem.h> 445697Smcpowers #include <sys/kstat.h> 455697Smcpowers 465697Smcpowers #include "des_impl.h" 475697Smcpowers #include "ecc_impl.h" 485697Smcpowers 495697Smcpowers #define CKD_NULL 0x00000001 505697Smcpowers 515697Smcpowers extern struct mod_ops mod_cryptoops; 525697Smcpowers 535697Smcpowers /* 545697Smcpowers * Module linkage information for the kernel. 555697Smcpowers */ 565697Smcpowers static struct modlcrypto modlcrypto = { 575697Smcpowers &mod_cryptoops, 585697Smcpowers "EC Kernel SW Provider" 595697Smcpowers }; 605697Smcpowers 615697Smcpowers static struct modlinkage modlinkage = { 625697Smcpowers MODREV_1, 635697Smcpowers (void *)&modlcrypto, 645697Smcpowers NULL 655697Smcpowers }; 665697Smcpowers 675697Smcpowers /* 685697Smcpowers * CSPI information (entry points, provider info, etc.) 695697Smcpowers */ 705697Smcpowers typedef enum ecc_mech_type { 715697Smcpowers EC_KEY_PAIR_GEN_MECH_INFO_TYPE, /* SUN_CKM_EC_KEY_PAIR_GEN */ 725697Smcpowers ECDSA_MECH_INFO_TYPE, /* SUN_CKM_ECDSA */ 735697Smcpowers ECDSA_SHA1_MECH_INFO_TYPE, /* SUN_CKM_ECDSA_SHA1 */ 745697Smcpowers ECDH1_DERIVE_MECH_INFO_TYPE /* SUN_CKM_ECDH1_DERIVE */ 755697Smcpowers } ecc_mech_type_t; 765697Smcpowers 775697Smcpowers /* 785697Smcpowers * Context for ECDSA mechanism. 795697Smcpowers */ 805697Smcpowers typedef struct ecc_ctx { 815697Smcpowers ecc_mech_type_t mech_type; 825697Smcpowers crypto_key_t *key; 835697Smcpowers size_t keychunk_size; 845697Smcpowers ECParams ecparams; 855697Smcpowers } ecc_ctx_t; 865697Smcpowers 875697Smcpowers /* 885697Smcpowers * Context for ECDSA_SHA1 mechanism. 895697Smcpowers */ 905697Smcpowers typedef struct digest_ecc_ctx { 915697Smcpowers ecc_mech_type_t mech_type; 925697Smcpowers crypto_key_t *key; 935697Smcpowers size_t keychunk_size; 945697Smcpowers ECParams ecparams; 955697Smcpowers union { 965697Smcpowers SHA1_CTX sha1ctx; 975697Smcpowers } dctx_u; 985697Smcpowers } digest_ecc_ctx_t; 995697Smcpowers 1005697Smcpowers #define sha1_ctx dctx_u.sha1ctx 1015697Smcpowers 1025697Smcpowers /* 1035697Smcpowers * Mechanism info structure passed to KCF during registration. 1045697Smcpowers */ 1055697Smcpowers static crypto_mech_info_t ecc_mech_info_tab[] = { 1065697Smcpowers /* EC_KEY_PAIR_GEN */ 1075697Smcpowers {SUN_CKM_EC_KEY_PAIR_GEN, EC_KEY_PAIR_GEN_MECH_INFO_TYPE, 1085697Smcpowers CRYPTO_FG_GENERATE_KEY_PAIR, EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, 1095697Smcpowers CRYPTO_KEYSIZE_UNIT_IN_BITS}, 1105697Smcpowers /* ECDH */ 1115697Smcpowers {SUN_CKM_ECDH1_DERIVE, ECDH1_DERIVE_MECH_INFO_TYPE, CRYPTO_FG_DERIVE, 1125697Smcpowers EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 1135697Smcpowers /* ECDSA */ 1145697Smcpowers {SUN_CKM_ECDSA, ECDSA_MECH_INFO_TYPE, 1155697Smcpowers CRYPTO_FG_SIGN | CRYPTO_FG_VERIFY | 1165697Smcpowers CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC, 1175697Smcpowers EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 1185697Smcpowers /* ECDSA_SHA1 */ 1195697Smcpowers {SUN_CKM_ECDSA_SHA1, ECDSA_SHA1_MECH_INFO_TYPE, 1205697Smcpowers CRYPTO_FG_SIGN | CRYPTO_FG_VERIFY | 1215697Smcpowers CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC, 1225697Smcpowers EC_MIN_KEY_LEN, EC_MAX_KEY_LEN, CRYPTO_KEYSIZE_UNIT_IN_BITS} 1235697Smcpowers }; 1245697Smcpowers 1255697Smcpowers static void ecc_provider_status(crypto_provider_handle_t, uint_t *); 1265697Smcpowers 1275697Smcpowers static crypto_control_ops_t ecc_control_ops = { 1285697Smcpowers ecc_provider_status 1295697Smcpowers }; 1305697Smcpowers 1315697Smcpowers static int ecc_sign_init(crypto_ctx_t *, crypto_mechanism_t *, 1325697Smcpowers crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 1335697Smcpowers static int ecc_sign(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 1345697Smcpowers crypto_req_handle_t); 1355697Smcpowers static int ecc_sign_update(crypto_ctx_t *, crypto_data_t *, 1365697Smcpowers crypto_req_handle_t); 1375697Smcpowers static int ecc_sign_final(crypto_ctx_t *, crypto_data_t *, 1385697Smcpowers crypto_req_handle_t); 1395697Smcpowers static int ecc_sign_atomic(crypto_provider_handle_t, crypto_session_id_t, 1405697Smcpowers crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *, 1415697Smcpowers crypto_spi_ctx_template_t, crypto_req_handle_t); 1425697Smcpowers 1435697Smcpowers static crypto_sign_ops_t ecc_sign_ops = { 1445697Smcpowers ecc_sign_init, 1455697Smcpowers ecc_sign, 1465697Smcpowers ecc_sign_update, 1475697Smcpowers ecc_sign_final, 1485697Smcpowers ecc_sign_atomic, 1495697Smcpowers NULL, 1505697Smcpowers NULL, 1515697Smcpowers NULL 1525697Smcpowers }; 1535697Smcpowers 1545697Smcpowers static int ecc_verify_init(crypto_ctx_t *, crypto_mechanism_t *, 1555697Smcpowers crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 1565697Smcpowers static int ecc_verify(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 1575697Smcpowers crypto_req_handle_t); 1585697Smcpowers static int ecc_verify_update(crypto_ctx_t *, crypto_data_t *, 1595697Smcpowers crypto_req_handle_t); 1605697Smcpowers static int ecc_verify_final(crypto_ctx_t *, crypto_data_t *, 1615697Smcpowers crypto_req_handle_t); 1625697Smcpowers static int ecc_verify_atomic(crypto_provider_handle_t, crypto_session_id_t, 1635697Smcpowers crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, 1645697Smcpowers crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t); 1655697Smcpowers 1665697Smcpowers static crypto_verify_ops_t ecc_verify_ops = { 1675697Smcpowers ecc_verify_init, 1685697Smcpowers ecc_verify, 1695697Smcpowers ecc_verify_update, 1705697Smcpowers ecc_verify_final, 1715697Smcpowers ecc_verify_atomic, 1725697Smcpowers NULL, 1735697Smcpowers NULL, 1745697Smcpowers NULL 1755697Smcpowers }; 1765697Smcpowers 1775697Smcpowers static int ecc_nostore_key_generate_pair(crypto_provider_handle_t, 1785697Smcpowers crypto_session_id_t, crypto_mechanism_t *, crypto_object_attribute_t *, 1795697Smcpowers uint_t, crypto_object_attribute_t *, uint_t, crypto_object_attribute_t *, 1805697Smcpowers uint_t, crypto_object_attribute_t *, uint_t, crypto_req_handle_t); 1815697Smcpowers static int ecc_nostore_key_derive(crypto_provider_handle_t, 1825697Smcpowers crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, 1835697Smcpowers crypto_object_attribute_t *, uint_t, crypto_object_attribute_t *, 1845697Smcpowers uint_t, crypto_req_handle_t); 1855697Smcpowers 1865697Smcpowers static crypto_nostore_key_ops_t ecc_nostore_key_ops = { 1875697Smcpowers NULL, 1885697Smcpowers ecc_nostore_key_generate_pair, 1895697Smcpowers ecc_nostore_key_derive 1905697Smcpowers }; 1915697Smcpowers 1925697Smcpowers static crypto_ops_t ecc_crypto_ops = { 1935697Smcpowers &ecc_control_ops, 1945697Smcpowers NULL, 1955697Smcpowers NULL, 1965697Smcpowers NULL, 1975697Smcpowers &ecc_sign_ops, 1985697Smcpowers &ecc_verify_ops, 1995697Smcpowers NULL, 2005697Smcpowers NULL, 2015697Smcpowers NULL, 2025697Smcpowers NULL, 2035697Smcpowers NULL, 2045697Smcpowers NULL, 2055697Smcpowers NULL, 2065697Smcpowers NULL, 2075697Smcpowers NULL, 2085697Smcpowers &ecc_nostore_key_ops 2095697Smcpowers }; 2105697Smcpowers 2115697Smcpowers static crypto_provider_info_t ecc_prov_info = { 2125697Smcpowers CRYPTO_SPI_VERSION_3, 2135697Smcpowers "EC Software Provider", 2145697Smcpowers CRYPTO_SW_PROVIDER, 2155697Smcpowers {&modlinkage}, 2165697Smcpowers NULL, 2175697Smcpowers &ecc_crypto_ops, 2185697Smcpowers sizeof (ecc_mech_info_tab)/sizeof (crypto_mech_info_t), 2195697Smcpowers ecc_mech_info_tab 2205697Smcpowers }; 2215697Smcpowers 2225697Smcpowers static crypto_kcf_provider_handle_t ecc_prov_handle = NULL; 2235697Smcpowers 2245697Smcpowers static int ecc_sign_common(ecc_ctx_t *, crypto_data_t *, crypto_data_t *, 2255697Smcpowers crypto_req_handle_t); 2265697Smcpowers static int ecc_verify_common(ecc_ctx_t *, crypto_data_t *, crypto_data_t *, 2275697Smcpowers crypto_req_handle_t); 2285697Smcpowers static int find_attr(crypto_object_attribute_t *, uint_t, uint64_t); 2295697Smcpowers static int get_template_attr_ulong(crypto_object_attribute_t *, 2305697Smcpowers uint_t, uint64_t, ulong_t *); 2315697Smcpowers static void ecc_free_context(crypto_ctx_t *); 2325697Smcpowers static void free_ecparams(ECParams *, boolean_t); 2335697Smcpowers static void free_ecprivkey(ECPrivateKey *); 2345697Smcpowers 2355697Smcpowers int 2365697Smcpowers _init(void) 2375697Smcpowers { 2385697Smcpowers int ret; 2395697Smcpowers 2405697Smcpowers /* 2415697Smcpowers * Register with KCF. If the registration fails, return error. 2425697Smcpowers */ 2435697Smcpowers if ((ret = crypto_register_provider(&ecc_prov_info, 2445697Smcpowers &ecc_prov_handle)) != CRYPTO_SUCCESS) { 2455697Smcpowers cmn_err(CE_WARN, "ecc _init: crypto_register_provider()" 2465697Smcpowers "failed (0x%x)", ret); 2475697Smcpowers return (EACCES); 2485697Smcpowers } 2495697Smcpowers 2505697Smcpowers if ((ret = mod_install(&modlinkage)) != 0) { 2515697Smcpowers int rv; 2525697Smcpowers 2535697Smcpowers ASSERT(ecc_prov_handle != NULL); 2545697Smcpowers /* We should not return if the unregister returns busy. */ 2555697Smcpowers while ((rv = crypto_unregister_provider(ecc_prov_handle)) 2565697Smcpowers == CRYPTO_BUSY) { 2575697Smcpowers cmn_err(CE_WARN, "ecc _init: " 2585697Smcpowers "crypto_unregister_provider() " 2595697Smcpowers "failed (0x%x). Retrying.", rv); 2605697Smcpowers /* wait 10 seconds and try again. */ 2615697Smcpowers delay(10 * drv_usectohz(1000000)); 2625697Smcpowers } 2635697Smcpowers } 2645697Smcpowers 2655697Smcpowers return (ret); 2665697Smcpowers } 2675697Smcpowers 2685697Smcpowers int 2695697Smcpowers _fini(void) 2705697Smcpowers { 2715697Smcpowers int ret; 2725697Smcpowers 2735697Smcpowers /* 2745697Smcpowers * Unregister from KCF if previous registration succeeded. 2755697Smcpowers */ 2765697Smcpowers if (ecc_prov_handle != NULL) { 2775697Smcpowers if ((ret = crypto_unregister_provider(ecc_prov_handle)) != 2785697Smcpowers CRYPTO_SUCCESS) { 2795697Smcpowers cmn_err(CE_WARN, "ecc _fini: " 2805697Smcpowers "crypto_unregister_provider() " 2815697Smcpowers "failed (0x%x)", ret); 2825697Smcpowers return (EBUSY); 2835697Smcpowers } 2845697Smcpowers ecc_prov_handle = NULL; 2855697Smcpowers } 2865697Smcpowers 2875697Smcpowers return (mod_remove(&modlinkage)); 2885697Smcpowers } 2895697Smcpowers 2905697Smcpowers int 2915697Smcpowers _info(struct modinfo *modinfop) 2925697Smcpowers { 2935697Smcpowers return (mod_info(&modlinkage, modinfop)); 2945697Smcpowers } 2955697Smcpowers 2965697Smcpowers /* ARGSUSED */ 2975697Smcpowers static void 2985697Smcpowers ecc_provider_status(crypto_provider_handle_t provider, uint_t *status) 2995697Smcpowers { 3005697Smcpowers *status = CRYPTO_PROVIDER_READY; 3015697Smcpowers } 3025697Smcpowers 3035697Smcpowers /* 3045697Smcpowers * Return the index of an attribute of specified type found in 3055697Smcpowers * the specified array of attributes. If the attribute cannot 3065697Smcpowers * found, return -1. 3075697Smcpowers */ 3085697Smcpowers static int 3095697Smcpowers find_attr(crypto_object_attribute_t *attr, uint_t nattr, uint64_t attr_type) 3105697Smcpowers { 3115697Smcpowers int i; 3125697Smcpowers 3135697Smcpowers for (i = 0; i < nattr; i++) 3145697Smcpowers if (attr[i].oa_value != NULL && attr[i].oa_type == attr_type) 3155697Smcpowers return (i); 3165697Smcpowers return (-1); 3175697Smcpowers } 3185697Smcpowers 3195697Smcpowers /* 3205697Smcpowers * Common function used by the get_template_attr_*() family of 3215697Smcpowers * functions. Returns the value of the specified attribute of specified 3225697Smcpowers * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID 3235697Smcpowers * if the length of the attribute does not match the specified length, 3245697Smcpowers * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found. 3255697Smcpowers */ 3265697Smcpowers static int 3275697Smcpowers get_template_attr_scalar_common(crypto_object_attribute_t *template, 3285697Smcpowers uint_t nattr, uint64_t attr_type, void *value, size_t value_len) 3295697Smcpowers { 3305697Smcpowers size_t oa_value_len; 3315697Smcpowers size_t offset = 0; 3325697Smcpowers int attr_idx; 3335697Smcpowers 3345697Smcpowers if ((attr_idx = find_attr(template, nattr, attr_type)) == -1) 3355697Smcpowers return (CRYPTO_ARGUMENTS_BAD); 3365697Smcpowers 3375697Smcpowers oa_value_len = template[attr_idx].oa_value_len; 3385697Smcpowers if (oa_value_len != value_len) { 3395697Smcpowers return (CRYPTO_ATTRIBUTE_VALUE_INVALID); 3405697Smcpowers } 3415697Smcpowers 3425697Smcpowers do_copy: 3435697Smcpowers bcopy(template[attr_idx].oa_value, (uchar_t *)value + offset, 3445697Smcpowers oa_value_len); 3455697Smcpowers 3465697Smcpowers return (CRYPTO_SUCCESS); 3475697Smcpowers } 3485697Smcpowers 3495697Smcpowers /* 3505697Smcpowers * Get the value of a ulong_t attribute from the specified template. 3515697Smcpowers */ 3525697Smcpowers static int 3535697Smcpowers get_template_attr_ulong(crypto_object_attribute_t *template, 3545697Smcpowers uint_t nattr, uint64_t attr_type, ulong_t *attr_value) 3555697Smcpowers { 3565697Smcpowers return (get_template_attr_scalar_common(template, nattr, 3575697Smcpowers attr_type, attr_value, sizeof (ulong_t))); 3585697Smcpowers } 3595697Smcpowers 3605697Smcpowers /* 3615697Smcpowers * Called from init routines to do basic sanity checks. Init routines, 3625697Smcpowers * e.g. sign_init should fail rather than subsequent operations. 3635697Smcpowers */ 3645697Smcpowers static int 3655697Smcpowers check_mech_and_key(ecc_mech_type_t mech_type, crypto_key_t *key, ulong_t class) 3665697Smcpowers { 3675697Smcpowers int rv = CRYPTO_SUCCESS; 3685697Smcpowers uchar_t *foo; 3695697Smcpowers ssize_t point_len; 3705697Smcpowers ssize_t value_len; 3715697Smcpowers 3725697Smcpowers if (mech_type != ECDSA_SHA1_MECH_INFO_TYPE && 3735697Smcpowers mech_type != ECDSA_MECH_INFO_TYPE) 3745697Smcpowers return (CRYPTO_MECHANISM_INVALID); 3755697Smcpowers 3765697Smcpowers if (key->ck_format != CRYPTO_KEY_ATTR_LIST) { 3775697Smcpowers return (CRYPTO_KEY_TYPE_INCONSISTENT); 3785697Smcpowers } 3795697Smcpowers 3805697Smcpowers switch (class) { 3815697Smcpowers case CKO_PUBLIC_KEY: 382*7188Smcpowers if ((rv = crypto_get_key_attr(key, CKA_EC_POINT, &foo, 383*7188Smcpowers &point_len)) != CRYPTO_SUCCESS) { 3845697Smcpowers return (CRYPTO_TEMPLATE_INCOMPLETE); 3855697Smcpowers } 3865697Smcpowers if (point_len < CRYPTO_BITS2BYTES(EC_MIN_KEY_LEN) * 2 + 1 || 3875697Smcpowers point_len > CRYPTO_BITS2BYTES(EC_MAX_KEY_LEN) * 2 + 1) 3885697Smcpowers return (CRYPTO_KEY_SIZE_RANGE); 3895697Smcpowers break; 3905697Smcpowers 3915697Smcpowers case CKO_PRIVATE_KEY: 392*7188Smcpowers if ((rv = crypto_get_key_attr(key, CKA_VALUE, &foo, 393*7188Smcpowers &value_len)) != CRYPTO_SUCCESS) { 3945697Smcpowers return (CRYPTO_TEMPLATE_INCOMPLETE); 3955697Smcpowers } 3965697Smcpowers if (value_len < CRYPTO_BITS2BYTES(EC_MIN_KEY_LEN) || 3975697Smcpowers value_len > CRYPTO_BITS2BYTES(EC_MAX_KEY_LEN)) 3985697Smcpowers return (CRYPTO_KEY_SIZE_RANGE); 3995697Smcpowers break; 4005697Smcpowers 4015697Smcpowers default: 4025697Smcpowers return (CRYPTO_TEMPLATE_INCONSISTENT); 4035697Smcpowers } 4045697Smcpowers 4055697Smcpowers return (rv); 4065697Smcpowers } 4075697Smcpowers 4085697Smcpowers /* 4095697Smcpowers * This function guarantees to return non-zero random numbers. 4105697Smcpowers * This is needed as the /dev/urandom kernel interface, 4115697Smcpowers * random_get_pseudo_bytes(), may return zeros. 4125697Smcpowers */ 4135697Smcpowers int 4145697Smcpowers ecc_knzero_random_generator(uint8_t *ran_out, size_t ran_len) 4155697Smcpowers { 4165697Smcpowers int rv; 4175697Smcpowers size_t ebc = 0; /* count of extra bytes in extrarand */ 4185697Smcpowers size_t i = 0; 4195697Smcpowers uint8_t extrarand[32]; 4205697Smcpowers size_t extrarand_len; 4215697Smcpowers 4225697Smcpowers if ((rv = random_get_pseudo_bytes(ran_out, ran_len)) != 0) 4235697Smcpowers return (rv); 4245697Smcpowers 4255697Smcpowers /* 4265697Smcpowers * Walk through the returned random numbers pointed by ran_out, 4275697Smcpowers * and look for any random number which is zero. 4285697Smcpowers * If we find zero, call random_get_pseudo_bytes() to generate 4295697Smcpowers * another 32 random numbers pool. Replace any zeros in ran_out[] 4305697Smcpowers * from the random number in pool. 4315697Smcpowers */ 4325697Smcpowers while (i < ran_len) { 4335697Smcpowers if (ran_out[i] != 0) { 4345697Smcpowers i++; 4355697Smcpowers continue; 4365697Smcpowers } 4375697Smcpowers 4385697Smcpowers /* 4395697Smcpowers * Note that it is 'while' so we are guaranteed a 4405697Smcpowers * non-zero value on exit. 4415697Smcpowers */ 4425697Smcpowers if (ebc == 0) { 4435697Smcpowers /* refresh extrarand */ 4445697Smcpowers extrarand_len = sizeof (extrarand); 4455697Smcpowers if ((rv = random_get_pseudo_bytes(extrarand, 4465697Smcpowers extrarand_len)) != 0) { 4475697Smcpowers return (rv); 4485697Smcpowers } 4495697Smcpowers 4505697Smcpowers ebc = extrarand_len; 4515697Smcpowers } 4525697Smcpowers /* Replace zero with byte from extrarand. */ 4535697Smcpowers -- ebc; 4545697Smcpowers 4555697Smcpowers /* 4565697Smcpowers * The new random byte zero/non-zero will be checked in 4575697Smcpowers * the next pass through the loop. 4585697Smcpowers */ 4595697Smcpowers ran_out[i] = extrarand[ebc]; 4605697Smcpowers } 4615697Smcpowers 4625697Smcpowers return (CRYPTO_SUCCESS); 4635697Smcpowers } 4645697Smcpowers 4655697Smcpowers static void 4665697Smcpowers ecc_free_context(crypto_ctx_t *ctx) 4675697Smcpowers { 4685697Smcpowers ecc_ctx_t *ctxp = ctx->cc_provider_private; 4695697Smcpowers 4705697Smcpowers if (ctxp != NULL) { 4715697Smcpowers bzero(ctxp->key, ctxp->keychunk_size); 4725697Smcpowers kmem_free(ctxp->key, ctxp->keychunk_size); 4735697Smcpowers 4745697Smcpowers free_ecparams(&ctxp->ecparams, B_FALSE); 4755697Smcpowers 4765697Smcpowers if (ctxp->mech_type == ECDSA_MECH_INFO_TYPE) 4775697Smcpowers kmem_free(ctxp, sizeof (ecc_ctx_t)); 4785697Smcpowers else 4795697Smcpowers kmem_free(ctxp, sizeof (digest_ecc_ctx_t)); 4805697Smcpowers 4815697Smcpowers ctx->cc_provider_private = NULL; 4825697Smcpowers } 4835697Smcpowers } 4845697Smcpowers 4855697Smcpowers /* ARGSUSED */ 4865697Smcpowers static int 4875697Smcpowers ecc_sign_verify_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 4885697Smcpowers crypto_key_t *key, crypto_spi_ctx_template_t ctx_template, 4895697Smcpowers crypto_req_handle_t req) 4905697Smcpowers { 4915697Smcpowers int rv; 4925697Smcpowers int kmflag; 4935697Smcpowers ecc_ctx_t *ctxp; 4945697Smcpowers digest_ecc_ctx_t *dctxp; 4955697Smcpowers ecc_mech_type_t mech_type = mechanism->cm_type; 4965697Smcpowers uchar_t *params; 4975697Smcpowers ssize_t params_len; 4985697Smcpowers ECParams *ecparams; 4995697Smcpowers SECKEYECParams params_item; 5005697Smcpowers 501*7188Smcpowers if (crypto_get_key_attr(key, CKA_EC_PARAMS, (void *) ¶ms, 5025697Smcpowers ¶ms_len)) { 5035697Smcpowers return (CRYPTO_ARGUMENTS_BAD); 5045697Smcpowers } 5055697Smcpowers 5065697Smcpowers /* ASN1 check */ 5075697Smcpowers if (params[0] != 0x06 || 5085697Smcpowers params[1] != params_len - 2) { 5095697Smcpowers return (CRYPTO_ATTRIBUTE_VALUE_INVALID); 5105697Smcpowers } 5115697Smcpowers params_item.data = params; 5125697Smcpowers params_item.len = (uint_t)params_len; 5135697Smcpowers kmflag = crypto_kmflag(req); 5145697Smcpowers if (EC_DecodeParams(¶ms_item, &ecparams, kmflag) != SECSuccess) { 5155697Smcpowers /* bad curve OID */ 5165697Smcpowers return (CRYPTO_ARGUMENTS_BAD); 5175697Smcpowers } 5185697Smcpowers 5195697Smcpowers /* 5205697Smcpowers * Allocate an ECC context. 5215697Smcpowers */ 5225697Smcpowers switch (mech_type) { 5235697Smcpowers case ECDSA_SHA1_MECH_INFO_TYPE: 5245697Smcpowers dctxp = kmem_zalloc(sizeof (digest_ecc_ctx_t), kmflag); 5255697Smcpowers ctxp = (ecc_ctx_t *)dctxp; 5265697Smcpowers break; 5275697Smcpowers default: 5285697Smcpowers ctxp = kmem_zalloc(sizeof (ecc_ctx_t), kmflag); 5295697Smcpowers break; 5305697Smcpowers } 5315697Smcpowers 5325697Smcpowers if (ctxp == NULL) { 5335697Smcpowers free_ecparams(ecparams, B_TRUE); 5345697Smcpowers return (CRYPTO_HOST_MEMORY); 5355697Smcpowers } 5365697Smcpowers 537*7188Smcpowers if ((rv = crypto_copy_key_to_ctx(key, &ctxp->key, &ctxp->keychunk_size, 538*7188Smcpowers kmflag)) != CRYPTO_SUCCESS) { 5395697Smcpowers switch (mech_type) { 5405697Smcpowers case ECDSA_SHA1_MECH_INFO_TYPE: 5415697Smcpowers kmem_free(dctxp, sizeof (digest_ecc_ctx_t)); 5425697Smcpowers break; 5435697Smcpowers default: 5445697Smcpowers kmem_free(ctxp, sizeof (ecc_ctx_t)); 5455697Smcpowers break; 5465697Smcpowers } 5475697Smcpowers free_ecparams(ecparams, B_TRUE); 5485697Smcpowers return (rv); 5495697Smcpowers } 5505697Smcpowers ctxp->mech_type = mech_type; 5515697Smcpowers ctxp->ecparams = *ecparams; 5525697Smcpowers kmem_free(ecparams, sizeof (ECParams)); 5535697Smcpowers 5545697Smcpowers switch (mech_type) { 5555697Smcpowers case ECDSA_SHA1_MECH_INFO_TYPE: 5565697Smcpowers SHA1Init(&(dctxp->sha1_ctx)); 5575697Smcpowers break; 5585697Smcpowers } 5595697Smcpowers 5605697Smcpowers ctx->cc_provider_private = ctxp; 5615697Smcpowers 5625697Smcpowers return (CRYPTO_SUCCESS); 5635697Smcpowers } 5645697Smcpowers 5655697Smcpowers /* ARGSUSED */ 5665697Smcpowers static int 5675697Smcpowers ecc_sign_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 5685697Smcpowers crypto_key_t *key, crypto_spi_ctx_template_t ctx_template, 5695697Smcpowers crypto_req_handle_t req) 5705697Smcpowers { 5715697Smcpowers int rv; 5725697Smcpowers 5735697Smcpowers ecc_mech_type_t mech_type = mechanism->cm_type; 5745697Smcpowers 5755697Smcpowers if ((rv = check_mech_and_key(mech_type, key, 5765697Smcpowers CKO_PRIVATE_KEY)) != CRYPTO_SUCCESS) 5775697Smcpowers return (rv); 5785697Smcpowers 5795697Smcpowers rv = ecc_sign_verify_common_init(ctx, mechanism, key, 5805697Smcpowers ctx_template, req); 5815697Smcpowers 5825697Smcpowers return (rv); 5835697Smcpowers } 5845697Smcpowers 5855697Smcpowers /* ARGSUSED */ 5865697Smcpowers static int 5875697Smcpowers ecc_verify_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 5885697Smcpowers crypto_key_t *key, crypto_spi_ctx_template_t ctx_template, 5895697Smcpowers crypto_req_handle_t req) 5905697Smcpowers { 5915697Smcpowers int rv; 5925697Smcpowers 5935697Smcpowers ecc_mech_type_t mech_type = mechanism->cm_type; 5945697Smcpowers 5955697Smcpowers if ((rv = check_mech_and_key(mech_type, key, 5965697Smcpowers CKO_PUBLIC_KEY)) != CRYPTO_SUCCESS) 5975697Smcpowers return (rv); 5985697Smcpowers 5995697Smcpowers rv = ecc_sign_verify_common_init(ctx, mechanism, key, 6005697Smcpowers ctx_template, req); 6015697Smcpowers 6025697Smcpowers return (rv); 6035697Smcpowers } 6045697Smcpowers 6055697Smcpowers #define SHA1_DIGEST_SIZE 20 6065697Smcpowers 6075697Smcpowers #define INIT_RAW_CRYPTO_DATA(data, base, len, cd_len) \ 6085697Smcpowers (data).cd_format = CRYPTO_DATA_RAW; \ 6095697Smcpowers (data).cd_offset = 0; \ 6105697Smcpowers (data).cd_raw.iov_base = (char *)base; \ 6115697Smcpowers (data).cd_raw.iov_len = len; \ 6125697Smcpowers (data).cd_length = cd_len; 6135697Smcpowers 6145697Smcpowers static int 6155697Smcpowers ecc_digest_svrfy_common(digest_ecc_ctx_t *ctxp, crypto_data_t *data, 6165697Smcpowers crypto_data_t *signature, uchar_t flag, crypto_req_handle_t req) 6175697Smcpowers { 6185697Smcpowers int rv = CRYPTO_FAILED; 6195697Smcpowers uchar_t digest[SHA1_DIGEST_LENGTH]; 6205697Smcpowers crypto_data_t der_cd; 6215697Smcpowers ecc_mech_type_t mech_type; 6225697Smcpowers 623*7188Smcpowers ASSERT(flag & CRYPTO_DO_SIGN || flag & CRYPTO_DO_VERIFY); 624*7188Smcpowers ASSERT(data != NULL || (flag & CRYPTO_DO_FINAL)); 6255697Smcpowers 6265697Smcpowers mech_type = ctxp->mech_type; 6275697Smcpowers if (mech_type != ECDSA_SHA1_MECH_INFO_TYPE) 6285697Smcpowers return (CRYPTO_MECHANISM_INVALID); 6295697Smcpowers 6305697Smcpowers /* Don't digest if only returning length of signature. */ 6315697Smcpowers if (signature->cd_length > 0) { 6325697Smcpowers if (mech_type == ECDSA_SHA1_MECH_INFO_TYPE) { 633*7188Smcpowers rv = crypto_digest_data(data, &(ctxp->sha1_ctx), 634*7188Smcpowers digest, (void (*)())SHA1Update, 635*7188Smcpowers (void (*)())SHA1Final, flag | CRYPTO_DO_SHA1); 6365697Smcpowers if (rv != CRYPTO_SUCCESS) 6375697Smcpowers return (rv); 6385697Smcpowers } 6395697Smcpowers } 6405697Smcpowers 6415697Smcpowers INIT_RAW_CRYPTO_DATA(der_cd, digest, SHA1_DIGEST_SIZE, 6425697Smcpowers SHA1_DIGEST_SIZE); 6435697Smcpowers 644*7188Smcpowers if (flag & CRYPTO_DO_SIGN) { 6455697Smcpowers rv = ecc_sign_common((ecc_ctx_t *)ctxp, &der_cd, signature, 6465697Smcpowers req); 6475697Smcpowers } else 6485697Smcpowers rv = ecc_verify_common((ecc_ctx_t *)ctxp, &der_cd, signature, 6495697Smcpowers req); 6505697Smcpowers 6515697Smcpowers return (rv); 6525697Smcpowers } 6535697Smcpowers 6545697Smcpowers /* 6555697Smcpowers * This is a single-part signing routine. It does not 6565697Smcpowers * compute a hash before signing. 6575697Smcpowers */ 6585697Smcpowers static int 6595697Smcpowers ecc_sign_common(ecc_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature, 6605697Smcpowers crypto_req_handle_t req) 6615697Smcpowers { 6625697Smcpowers int rv = CRYPTO_FAILED; 6635697Smcpowers SECStatus ss; 6645697Smcpowers uchar_t *param; 6655697Smcpowers uchar_t *private; 6665697Smcpowers ssize_t param_len; 6675697Smcpowers ssize_t private_len; 6685697Smcpowers uchar_t tmp_data[EC_MAX_DIGEST_LEN]; 6695697Smcpowers uchar_t signed_data[EC_MAX_SIG_LEN]; 6705697Smcpowers ECPrivateKey ECkey; 6715697Smcpowers SECItem signature_item; 6725697Smcpowers SECItem digest_item; 6735697Smcpowers crypto_key_t *key = ctx->key; 6745697Smcpowers int kmflag; 6755697Smcpowers 676*7188Smcpowers if ((rv = crypto_get_key_attr(key, CKA_EC_PARAMS, ¶m, 6775697Smcpowers ¶m_len)) != CRYPTO_SUCCESS) { 6785697Smcpowers return (rv); 6795697Smcpowers } 6805697Smcpowers 6815697Smcpowers if (data->cd_length > sizeof (tmp_data)) 6825697Smcpowers return (CRYPTO_DATA_LEN_RANGE); 6835697Smcpowers 684*7188Smcpowers if ((rv = crypto_get_input_data(data, &digest_item.data, tmp_data)) 6855697Smcpowers != CRYPTO_SUCCESS) { 6865697Smcpowers return (rv); 6875697Smcpowers } 6885697Smcpowers digest_item.len = data->cd_length; 6895697Smcpowers 6905697Smcpowers /* structure assignment */ 6915697Smcpowers ECkey.ecParams = ctx->ecparams; 6925697Smcpowers 693*7188Smcpowers if ((rv = crypto_get_key_attr(key, CKA_VALUE, &private, 6945697Smcpowers &private_len)) != CRYPTO_SUCCESS) { 6955697Smcpowers return (rv); 6965697Smcpowers } 6975697Smcpowers ECkey.privateValue.data = private; 6985697Smcpowers ECkey.privateValue.len = (uint_t)private_len; 6995697Smcpowers 7005697Smcpowers signature_item.data = signed_data; 7015697Smcpowers signature_item.len = sizeof (signed_data); 7025697Smcpowers 7035697Smcpowers kmflag = crypto_kmflag(req); 7045697Smcpowers if ((ss = ECDSA_SignDigest(&ECkey, &signature_item, &digest_item, 7055697Smcpowers kmflag)) != SECSuccess) { 7065697Smcpowers if (ss == SECBufferTooSmall) 7075697Smcpowers return (CRYPTO_BUFFER_TOO_SMALL); 7085697Smcpowers 7095697Smcpowers return (CRYPTO_FAILED); 7105697Smcpowers } 7115697Smcpowers 7125697Smcpowers if (rv == CRYPTO_SUCCESS) { 7135697Smcpowers /* copy out the signature */ 714*7188Smcpowers if ((rv = crypto_put_output_data(signed_data, 7155697Smcpowers signature, signature_item.len)) != CRYPTO_SUCCESS) 7165697Smcpowers return (rv); 7175697Smcpowers 7185697Smcpowers signature->cd_length = signature_item.len; 7195697Smcpowers } 7205697Smcpowers 7215697Smcpowers return (rv); 7225697Smcpowers } 7235697Smcpowers 7245697Smcpowers /* ARGSUSED */ 7255697Smcpowers static int 7265697Smcpowers ecc_sign(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature, 7275697Smcpowers crypto_req_handle_t req) 7285697Smcpowers { 7295697Smcpowers int rv; 7305697Smcpowers ecc_ctx_t *ctxp; 7315697Smcpowers 7325697Smcpowers ASSERT(ctx->cc_provider_private != NULL); 7335697Smcpowers ctxp = ctx->cc_provider_private; 7345697Smcpowers 7355697Smcpowers switch (ctxp->mech_type) { 7365697Smcpowers case ECDSA_SHA1_MECH_INFO_TYPE: 7375697Smcpowers rv = ecc_digest_svrfy_common((digest_ecc_ctx_t *)ctxp, data, 738*7188Smcpowers signature, CRYPTO_DO_SIGN | CRYPTO_DO_UPDATE | 739*7188Smcpowers CRYPTO_DO_FINAL, req); 7405697Smcpowers break; 7415697Smcpowers default: 7425697Smcpowers rv = ecc_sign_common(ctxp, data, signature, req); 7435697Smcpowers break; 7445697Smcpowers } 7455697Smcpowers 7465697Smcpowers if (rv != CRYPTO_BUFFER_TOO_SMALL) 7475697Smcpowers ecc_free_context(ctx); 7485697Smcpowers 7495697Smcpowers return (rv); 7505697Smcpowers } 7515697Smcpowers 7525697Smcpowers /* ARGSUSED */ 7535697Smcpowers static int 7545697Smcpowers ecc_sign_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req) 7555697Smcpowers { 7565697Smcpowers int rv; 7575697Smcpowers digest_ecc_ctx_t *ctxp; 7585697Smcpowers ecc_mech_type_t mech_type; 7595697Smcpowers 7605697Smcpowers ASSERT(ctx->cc_provider_private != NULL); 7615697Smcpowers ctxp = ctx->cc_provider_private; 7625697Smcpowers mech_type = ctxp->mech_type; 7635697Smcpowers 7645697Smcpowers if (mech_type == ECDSA_MECH_INFO_TYPE) { 7655697Smcpowers ecc_free_context(ctx); 7665697Smcpowers return (CRYPTO_MECHANISM_INVALID); 7675697Smcpowers } 7685697Smcpowers 7695697Smcpowers if (mech_type == ECDSA_SHA1_MECH_INFO_TYPE) 770*7188Smcpowers rv = crypto_digest_data(data, &(ctxp->sha1_ctx), NULL, 771*7188Smcpowers (void (*)())SHA1Update, (void (*)())SHA1Final, 772*7188Smcpowers CRYPTO_DO_SHA1 | CRYPTO_DO_UPDATE); 7735697Smcpowers 7745697Smcpowers if (rv != CRYPTO_SUCCESS) 7755697Smcpowers ecc_free_context(ctx); 7765697Smcpowers 7775697Smcpowers return (rv); 7785697Smcpowers } 7795697Smcpowers 7805697Smcpowers /* ARGSUSED */ 7815697Smcpowers static int 7825697Smcpowers ecc_sign_final(crypto_ctx_t *ctx, crypto_data_t *signature, 7835697Smcpowers crypto_req_handle_t req) 7845697Smcpowers { 7855697Smcpowers int rv; 7865697Smcpowers digest_ecc_ctx_t *ctxp; 7875697Smcpowers 7885697Smcpowers ASSERT(ctx->cc_provider_private != NULL); 7895697Smcpowers ctxp = ctx->cc_provider_private; 7905697Smcpowers 791*7188Smcpowers rv = ecc_digest_svrfy_common(ctxp, NULL, signature, CRYPTO_DO_SIGN | 792*7188Smcpowers CRYPTO_DO_FINAL, req); 7935697Smcpowers if (rv != CRYPTO_BUFFER_TOO_SMALL) 7945697Smcpowers ecc_free_context(ctx); 7955697Smcpowers 7965697Smcpowers return (rv); 7975697Smcpowers } 7985697Smcpowers 7995697Smcpowers /* ARGSUSED */ 8005697Smcpowers static int 8015697Smcpowers ecc_sign_atomic(crypto_provider_handle_t provider, 8025697Smcpowers crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 8035697Smcpowers crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature, 8045697Smcpowers crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) 8055697Smcpowers { 8065697Smcpowers int rv; 8075697Smcpowers ecc_mech_type_t mech_type = mechanism->cm_type; 8085697Smcpowers uchar_t *params; 8095697Smcpowers ssize_t params_len; 8105697Smcpowers ECParams *ecparams; 8115697Smcpowers SECKEYECParams params_item; 8125697Smcpowers int kmflag; 8135697Smcpowers 8145697Smcpowers if ((rv = check_mech_and_key(mech_type, key, 8155697Smcpowers CKO_PRIVATE_KEY)) != CRYPTO_SUCCESS) 8165697Smcpowers return (rv); 8175697Smcpowers 818*7188Smcpowers if (crypto_get_key_attr(key, CKA_EC_PARAMS, (void *) ¶ms, 8195697Smcpowers ¶ms_len)) { 8205697Smcpowers return (CRYPTO_ARGUMENTS_BAD); 8215697Smcpowers } 8225697Smcpowers 8235697Smcpowers /* ASN1 check */ 8245697Smcpowers if (params[0] != 0x06 || 8255697Smcpowers params[1] != params_len - 2) { 8265697Smcpowers return (CRYPTO_ATTRIBUTE_VALUE_INVALID); 8275697Smcpowers } 8285697Smcpowers params_item.data = params; 8295697Smcpowers params_item.len = (uint_t)params_len; 8305697Smcpowers kmflag = crypto_kmflag(req); 8315697Smcpowers if (EC_DecodeParams(¶ms_item, &ecparams, kmflag) != SECSuccess) { 8325697Smcpowers /* bad curve OID */ 8335697Smcpowers return (CRYPTO_ARGUMENTS_BAD); 8345697Smcpowers } 8355697Smcpowers 8365697Smcpowers if (mechanism->cm_type == ECDSA_MECH_INFO_TYPE) { 8375697Smcpowers ecc_ctx_t ctx; 8385697Smcpowers 8395697Smcpowers ctx.mech_type = mech_type; 8405697Smcpowers /* structure assignment */ 8415697Smcpowers ctx.ecparams = *ecparams; 8425697Smcpowers ctx.key = key; 8435697Smcpowers rv = ecc_sign_common(&ctx, data, signature, req); 8445697Smcpowers } else { 8455697Smcpowers digest_ecc_ctx_t dctx; 8465697Smcpowers 8475697Smcpowers dctx.mech_type = mech_type; 8485697Smcpowers /* structure assignment */ 8495697Smcpowers dctx.ecparams = *ecparams; 8505697Smcpowers dctx.key = key; 8515697Smcpowers SHA1Init(&(dctx.sha1_ctx)); 8525697Smcpowers 8535697Smcpowers rv = ecc_digest_svrfy_common(&dctx, data, signature, 854*7188Smcpowers CRYPTO_DO_SIGN | CRYPTO_DO_UPDATE | CRYPTO_DO_FINAL, req); 8555697Smcpowers } 8565697Smcpowers free_ecparams(ecparams, B_TRUE); 8575697Smcpowers 8585697Smcpowers return (rv); 8595697Smcpowers } 8605697Smcpowers 8615697Smcpowers static int 8625697Smcpowers ecc_verify_common(ecc_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature, 8635697Smcpowers crypto_req_handle_t req) 8645697Smcpowers { 8655697Smcpowers int rv = CRYPTO_FAILED; 8665697Smcpowers uchar_t *param; 8675697Smcpowers uchar_t *public; 8685697Smcpowers ssize_t param_len; 8695697Smcpowers ssize_t public_len; 8705697Smcpowers uchar_t tmp_data[EC_MAX_DIGEST_LEN]; 8715697Smcpowers uchar_t signed_data[EC_MAX_SIG_LEN]; 8725697Smcpowers ECPublicKey ECkey; 8735697Smcpowers SECItem signature_item; 8745697Smcpowers SECItem digest_item; 8755697Smcpowers crypto_key_t *key = ctx->key; 8765697Smcpowers int kmflag; 8775697Smcpowers 878*7188Smcpowers if ((rv = crypto_get_key_attr(key, CKA_EC_PARAMS, ¶m, 8795697Smcpowers ¶m_len)) != CRYPTO_SUCCESS) { 8805697Smcpowers return (rv); 8815697Smcpowers } 8825697Smcpowers 8835697Smcpowers if (signature->cd_length > sizeof (signed_data)) { 8845697Smcpowers return (CRYPTO_SIGNATURE_LEN_RANGE); 8855697Smcpowers } 8865697Smcpowers 887*7188Smcpowers if ((rv = crypto_get_input_data(signature, &signature_item.data, 8885697Smcpowers signed_data)) != CRYPTO_SUCCESS) { 8895697Smcpowers return (rv); 8905697Smcpowers } 8915697Smcpowers signature_item.len = signature->cd_length; 8925697Smcpowers 8935697Smcpowers if (data->cd_length > sizeof (tmp_data)) 8945697Smcpowers return (CRYPTO_DATA_LEN_RANGE); 8955697Smcpowers 896*7188Smcpowers if ((rv = crypto_get_input_data(data, &digest_item.data, tmp_data)) 8975697Smcpowers != CRYPTO_SUCCESS) { 8985697Smcpowers return (rv); 8995697Smcpowers } 9005697Smcpowers digest_item.len = data->cd_length; 9015697Smcpowers 9025697Smcpowers /* structure assignment */ 9035697Smcpowers ECkey.ecParams = ctx->ecparams; 9045697Smcpowers 905*7188Smcpowers if ((rv = crypto_get_key_attr(key, CKA_EC_POINT, &public, 9065697Smcpowers &public_len)) != CRYPTO_SUCCESS) { 9075697Smcpowers return (rv); 9085697Smcpowers } 9095697Smcpowers ECkey.publicValue.data = public; 9105697Smcpowers ECkey.publicValue.len = (uint_t)public_len; 9115697Smcpowers 9125697Smcpowers kmflag = crypto_kmflag(req); 9135697Smcpowers if (ECDSA_VerifyDigest(&ECkey, &signature_item, &digest_item, kmflag) 9145697Smcpowers != SECSuccess) { 9155697Smcpowers rv = CRYPTO_SIGNATURE_INVALID; 9165697Smcpowers } else { 9175697Smcpowers rv = CRYPTO_SUCCESS; 9185697Smcpowers } 9195697Smcpowers 9205697Smcpowers return (rv); 9215697Smcpowers } 9225697Smcpowers 9235697Smcpowers /* ARGSUSED */ 9245697Smcpowers static int 9255697Smcpowers ecc_verify(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature, 9265697Smcpowers crypto_req_handle_t req) 9275697Smcpowers { 9285697Smcpowers int rv; 9295697Smcpowers ecc_ctx_t *ctxp; 9305697Smcpowers 9315697Smcpowers ASSERT(ctx->cc_provider_private != NULL); 9325697Smcpowers ctxp = ctx->cc_provider_private; 9335697Smcpowers 9345697Smcpowers switch (ctxp->mech_type) { 9355697Smcpowers case ECDSA_SHA1_MECH_INFO_TYPE: 9365697Smcpowers rv = ecc_digest_svrfy_common((digest_ecc_ctx_t *)ctxp, data, 937*7188Smcpowers signature, CRYPTO_DO_VERIFY | CRYPTO_DO_UPDATE | 938*7188Smcpowers CRYPTO_DO_FINAL, req); 9395697Smcpowers break; 9405697Smcpowers default: 9415697Smcpowers rv = ecc_verify_common(ctxp, data, signature, req); 9425697Smcpowers break; 9435697Smcpowers } 9445697Smcpowers 9455697Smcpowers ecc_free_context(ctx); 9465697Smcpowers return (rv); 9475697Smcpowers } 9485697Smcpowers 9495697Smcpowers /* ARGSUSED */ 9505697Smcpowers static int 9515697Smcpowers ecc_verify_update(crypto_ctx_t *ctx, crypto_data_t *data, 9525697Smcpowers crypto_req_handle_t req) 9535697Smcpowers { 9545697Smcpowers int rv; 9555697Smcpowers digest_ecc_ctx_t *ctxp; 9565697Smcpowers 9575697Smcpowers ASSERT(ctx->cc_provider_private != NULL); 9585697Smcpowers ctxp = ctx->cc_provider_private; 9595697Smcpowers 9605697Smcpowers switch (ctxp->mech_type) { 9615697Smcpowers case ECDSA_SHA1_MECH_INFO_TYPE: 962*7188Smcpowers rv = crypto_digest_data(data, &(ctxp->sha1_ctx), NULL, 963*7188Smcpowers (void (*)())SHA1Update, (void (*)())SHA1Final, 964*7188Smcpowers CRYPTO_DO_SHA1 | CRYPTO_DO_UPDATE); 9655697Smcpowers break; 9665697Smcpowers default: 9675697Smcpowers rv = CRYPTO_MECHANISM_INVALID; 9685697Smcpowers } 9695697Smcpowers 9705697Smcpowers if (rv != CRYPTO_SUCCESS) 9715697Smcpowers ecc_free_context(ctx); 9725697Smcpowers 9735697Smcpowers return (rv); 9745697Smcpowers } 9755697Smcpowers 9765697Smcpowers /* ARGSUSED */ 9775697Smcpowers static int 9785697Smcpowers ecc_verify_final(crypto_ctx_t *ctx, crypto_data_t *signature, 9795697Smcpowers crypto_req_handle_t req) 9805697Smcpowers { 9815697Smcpowers int rv; 9825697Smcpowers digest_ecc_ctx_t *ctxp; 9835697Smcpowers 9845697Smcpowers ASSERT(ctx->cc_provider_private != NULL); 9855697Smcpowers ctxp = ctx->cc_provider_private; 9865697Smcpowers 9875697Smcpowers rv = ecc_digest_svrfy_common(ctxp, NULL, signature, 988*7188Smcpowers CRYPTO_DO_VERIFY | CRYPTO_DO_FINAL, req); 9895697Smcpowers 9905697Smcpowers ecc_free_context(ctx); 9915697Smcpowers 9925697Smcpowers return (rv); 9935697Smcpowers } 9945697Smcpowers 9955697Smcpowers 9965697Smcpowers /* ARGSUSED */ 9975697Smcpowers static int 9985697Smcpowers ecc_verify_atomic(crypto_provider_handle_t provider, 9995697Smcpowers crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 10005697Smcpowers crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature, 10015697Smcpowers crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) 10025697Smcpowers { 10035697Smcpowers int rv; 10045697Smcpowers ecc_mech_type_t mech_type = mechanism->cm_type; 10055697Smcpowers uchar_t *params; 10065697Smcpowers ssize_t params_len; 10075697Smcpowers ECParams *ecparams; 10085697Smcpowers SECKEYECParams params_item; 10095697Smcpowers int kmflag; 10105697Smcpowers 10115697Smcpowers if ((rv = check_mech_and_key(mech_type, key, 10125697Smcpowers CKO_PUBLIC_KEY)) != CRYPTO_SUCCESS) 10135697Smcpowers return (rv); 10145697Smcpowers 1015*7188Smcpowers if (crypto_get_key_attr(key, CKA_EC_PARAMS, (void *) ¶ms, 10165697Smcpowers ¶ms_len)) { 10175697Smcpowers return (CRYPTO_ARGUMENTS_BAD); 10185697Smcpowers } 10195697Smcpowers 10205697Smcpowers /* ASN1 check */ 10215697Smcpowers if (params[0] != 0x06 || 10225697Smcpowers params[1] != params_len - 2) { 10235697Smcpowers return (CRYPTO_ATTRIBUTE_VALUE_INVALID); 10245697Smcpowers } 10255697Smcpowers params_item.data = params; 10265697Smcpowers params_item.len = (uint_t)params_len; 10275697Smcpowers kmflag = crypto_kmflag(req); 10285697Smcpowers if (EC_DecodeParams(¶ms_item, &ecparams, kmflag) != SECSuccess) { 10295697Smcpowers /* bad curve OID */ 10305697Smcpowers return (CRYPTO_ARGUMENTS_BAD); 10315697Smcpowers } 10325697Smcpowers 10335697Smcpowers if (mechanism->cm_type == ECDSA_MECH_INFO_TYPE) { 10345697Smcpowers ecc_ctx_t ctx; 10355697Smcpowers 10365697Smcpowers ctx.mech_type = mech_type; 10375697Smcpowers /* structure assignment */ 10385697Smcpowers ctx.ecparams = *ecparams; 10395697Smcpowers ctx.key = key; 10405697Smcpowers rv = ecc_verify_common(&ctx, data, signature, req); 10415697Smcpowers } else { 10425697Smcpowers digest_ecc_ctx_t dctx; 10435697Smcpowers 10445697Smcpowers dctx.mech_type = mech_type; 10455697Smcpowers /* structure assignment */ 10465697Smcpowers dctx.ecparams = *ecparams; 10475697Smcpowers dctx.key = key; 10485697Smcpowers SHA1Init(&(dctx.sha1_ctx)); 10495697Smcpowers 10505697Smcpowers rv = ecc_digest_svrfy_common(&dctx, data, signature, 1051*7188Smcpowers CRYPTO_DO_VERIFY | CRYPTO_DO_UPDATE | CRYPTO_DO_FINAL, req); 10525697Smcpowers } 10535697Smcpowers free_ecparams(ecparams, B_TRUE); 10545697Smcpowers return (rv); 10555697Smcpowers } 10565697Smcpowers 10575697Smcpowers /* ARGSUSED */ 10585697Smcpowers static int 10595697Smcpowers ecc_nostore_key_generate_pair(crypto_provider_handle_t provider, 10605697Smcpowers crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 10615697Smcpowers crypto_object_attribute_t *pub_template, uint_t pub_attribute_count, 10625697Smcpowers crypto_object_attribute_t *pri_template, uint_t pri_attribute_count, 10635697Smcpowers crypto_object_attribute_t *pub_out_template, uint_t pub_out_attribute_count, 10645697Smcpowers crypto_object_attribute_t *pri_out_template, uint_t pri_out_attribute_count, 10655697Smcpowers crypto_req_handle_t req) 10665697Smcpowers { 10675697Smcpowers int rv = CRYPTO_SUCCESS; 10685697Smcpowers ECPrivateKey *privKey; /* contains both public and private values */ 10695697Smcpowers ECParams *ecparams; 10705697Smcpowers SECKEYECParams params_item; 10715697Smcpowers ulong_t pub_key_type = ~0UL, pub_class = ~0UL; 10725697Smcpowers ulong_t pri_key_type = ~0UL, pri_class = ~0UL; 10735697Smcpowers int params_idx, value_idx, point_idx; 10745697Smcpowers uchar_t *params = NULL; 10755697Smcpowers unsigned params_len; 10765697Smcpowers uchar_t *value = NULL; 10775697Smcpowers uchar_t *point = NULL; 10785697Smcpowers int valuelen; 10795697Smcpowers int pointlen; 10805697Smcpowers int xylen; 10815697Smcpowers int kmflag; 10825697Smcpowers 10835697Smcpowers if (mechanism->cm_type != EC_KEY_PAIR_GEN_MECH_INFO_TYPE) { 10845697Smcpowers return (CRYPTO_MECHANISM_INVALID); 10855697Smcpowers } 10865697Smcpowers 10875697Smcpowers /* optional */ 10885697Smcpowers (void) get_template_attr_ulong(pub_template, 10895697Smcpowers pub_attribute_count, CKA_CLASS, &pub_class); 10905697Smcpowers 10915697Smcpowers /* optional */ 10925697Smcpowers (void) get_template_attr_ulong(pri_template, 10935697Smcpowers pri_attribute_count, CKA_CLASS, &pri_class); 10945697Smcpowers 10955697Smcpowers /* optional */ 10965697Smcpowers (void) get_template_attr_ulong(pub_template, 10975697Smcpowers pub_attribute_count, CKA_KEY_TYPE, &pub_key_type); 10985697Smcpowers 10995697Smcpowers /* optional */ 11005697Smcpowers (void) get_template_attr_ulong(pri_template, 11015697Smcpowers pri_attribute_count, CKA_KEY_TYPE, &pri_key_type); 11025697Smcpowers 11035697Smcpowers if (pub_class != ~0UL && pub_class != CKO_PUBLIC_KEY) { 11045697Smcpowers return (CRYPTO_TEMPLATE_INCONSISTENT); 11055697Smcpowers } 11065697Smcpowers pub_class = CKO_PUBLIC_KEY; 11075697Smcpowers 11085697Smcpowers if (pri_class != ~0UL && pri_class != CKO_PRIVATE_KEY) { 11095697Smcpowers return (CRYPTO_TEMPLATE_INCONSISTENT); 11105697Smcpowers } 11115697Smcpowers pri_class = CKO_PRIVATE_KEY; 11125697Smcpowers 11135697Smcpowers if (pub_key_type != ~0UL && pub_key_type != CKK_EC) { 11145697Smcpowers return (CRYPTO_TEMPLATE_INCONSISTENT); 11155697Smcpowers } 11165697Smcpowers pub_key_type = CKK_EC; 11175697Smcpowers 11185697Smcpowers if (pri_key_type != ~0UL && pri_key_type != CKK_EC) { 11195697Smcpowers return (CRYPTO_TEMPLATE_INCONSISTENT); 11205697Smcpowers } 11215697Smcpowers pri_key_type = CKK_EC; 11225697Smcpowers 11235697Smcpowers /* public output template must contain CKA_EC_POINT attribute */ 11245697Smcpowers if ((point_idx = find_attr(pub_out_template, pub_out_attribute_count, 11255697Smcpowers CKA_EC_POINT)) == -1) { 11265697Smcpowers return (CRYPTO_TEMPLATE_INCOMPLETE); 11275697Smcpowers } 11285697Smcpowers 11295697Smcpowers /* private output template must contain CKA_VALUE attribute */ 11305697Smcpowers if ((value_idx = find_attr(pri_out_template, pri_out_attribute_count, 11315697Smcpowers CKA_VALUE)) == -1) { 11325697Smcpowers return (CRYPTO_TEMPLATE_INCOMPLETE); 11335697Smcpowers } 11345697Smcpowers 11355697Smcpowers if ((params_idx = find_attr(pub_template, pub_attribute_count, 11365697Smcpowers CKA_EC_PARAMS)) == -1) { 11375697Smcpowers return (CRYPTO_TEMPLATE_INCOMPLETE); 11385697Smcpowers } 11395697Smcpowers 11405697Smcpowers params = (uchar_t *)pub_template[params_idx].oa_value; 11415697Smcpowers params_len = pub_template[params_idx].oa_value_len; 11425697Smcpowers 11435697Smcpowers value = (uchar_t *)pri_out_template[value_idx].oa_value; 11445697Smcpowers valuelen = (int)pri_out_template[value_idx].oa_value_len; 11455697Smcpowers point = (uchar_t *)pub_out_template[point_idx].oa_value; 11465697Smcpowers pointlen = (int)pub_out_template[point_idx].oa_value_len; 11475697Smcpowers 11485697Smcpowers /* ASN1 check */ 11495697Smcpowers if (params[0] != 0x06 || 11505697Smcpowers params[1] != params_len - 2) { 11515697Smcpowers return (CRYPTO_ATTRIBUTE_VALUE_INVALID); 11525697Smcpowers } 11535697Smcpowers params_item.data = params; 11545697Smcpowers params_item.len = params_len; 11555697Smcpowers kmflag = crypto_kmflag(req); 11565697Smcpowers if (EC_DecodeParams(¶ms_item, &ecparams, kmflag) != SECSuccess) { 11575697Smcpowers /* bad curve OID */ 11585697Smcpowers return (CRYPTO_ARGUMENTS_BAD); 11595697Smcpowers } 11605697Smcpowers 11615697Smcpowers if (EC_NewKey(ecparams, &privKey, kmflag) != SECSuccess) { 11625697Smcpowers free_ecparams(ecparams, B_TRUE); 11635697Smcpowers return (CRYPTO_FAILED); 11645697Smcpowers } 11655697Smcpowers 11665697Smcpowers xylen = privKey->publicValue.len; 11675697Smcpowers /* ASSERT that xylen - 1 is divisible by 2 */ 11685697Smcpowers if (xylen > pointlen) { 11695697Smcpowers rv = CRYPTO_BUFFER_TOO_SMALL; 11705697Smcpowers goto out; 11715697Smcpowers } 11725697Smcpowers 11735697Smcpowers if (privKey->privateValue.len > valuelen) { 11745697Smcpowers rv = CRYPTO_BUFFER_TOO_SMALL; 11755697Smcpowers goto out; 11765697Smcpowers } 11775697Smcpowers bcopy(privKey->privateValue.data, value, privKey->privateValue.len); 11785697Smcpowers pri_out_template[value_idx].oa_value_len = privKey->privateValue.len; 11795697Smcpowers 11805697Smcpowers bcopy(privKey->publicValue.data, point, xylen); 11815697Smcpowers pub_out_template[point_idx].oa_value_len = xylen; 11825697Smcpowers 11835697Smcpowers out: 11845697Smcpowers free_ecprivkey(privKey); 11855697Smcpowers free_ecparams(ecparams, B_TRUE); 11865697Smcpowers return (rv); 11875697Smcpowers } 11885697Smcpowers 11895697Smcpowers /* ARGSUSED */ 11905697Smcpowers static int 11915697Smcpowers ecc_nostore_key_derive(crypto_provider_handle_t provider, 11925697Smcpowers crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 11935697Smcpowers crypto_key_t *base_key, crypto_object_attribute_t *in_attrs, 11945697Smcpowers uint_t in_attr_count, crypto_object_attribute_t *out_attrs, 11955697Smcpowers uint_t out_attr_count, crypto_req_handle_t req) 11965697Smcpowers { 11975697Smcpowers int rv = CRYPTO_SUCCESS; 11985697Smcpowers int params_idx, value_idx = -1, out_value_idx = -1; 11995697Smcpowers ulong_t key_type; 12005697Smcpowers ulong_t key_len; 12015697Smcpowers crypto_object_attribute_t *attrs; 12025697Smcpowers ECParams *ecparams; 12035697Smcpowers SECKEYECParams params_item; 12045697Smcpowers CK_ECDH1_DERIVE_PARAMS *mech_param; 12055697Smcpowers SECItem public_value_item, private_value_item, secret_item; 12065697Smcpowers int kmflag; 12075697Smcpowers 12085697Smcpowers if (mechanism->cm_type != ECDH1_DERIVE_MECH_INFO_TYPE) { 12095697Smcpowers return (CRYPTO_MECHANISM_INVALID); 12105697Smcpowers } 12115697Smcpowers 12125697Smcpowers ASSERT(IS_P2ALIGNED(mechanism->cm_param, sizeof (uint64_t))); 12135697Smcpowers /* LINTED: pointer alignment */ 12145697Smcpowers mech_param = (CK_ECDH1_DERIVE_PARAMS *)mechanism->cm_param; 12155697Smcpowers if (mech_param->kdf != CKD_NULL) { 12165697Smcpowers return (CRYPTO_MECHANISM_PARAM_INVALID); 12175697Smcpowers } 12185697Smcpowers 12195697Smcpowers if ((base_key->ck_format != CRYPTO_KEY_ATTR_LIST) || 12205697Smcpowers (base_key->ck_count == 0)) { 12215697Smcpowers return (CRYPTO_ARGUMENTS_BAD); 12225697Smcpowers } 12235697Smcpowers 12245697Smcpowers if ((rv = get_template_attr_ulong(in_attrs, in_attr_count, 12255697Smcpowers CKA_KEY_TYPE, &key_type)) != CRYPTO_SUCCESS) { 12265697Smcpowers return (rv); 12275697Smcpowers } 12285697Smcpowers 12295697Smcpowers switch (key_type) { 12305697Smcpowers case CKK_DES: 12315697Smcpowers key_len = DES_KEYSIZE; 12325697Smcpowers break; 12335697Smcpowers case CKK_DES2: 12345697Smcpowers key_len = DES2_KEYSIZE; 12355697Smcpowers break; 12365697Smcpowers case CKK_DES3: 12375697Smcpowers key_len = DES3_KEYSIZE; 12385697Smcpowers break; 12395697Smcpowers case CKK_RC4: 12405697Smcpowers case CKK_AES: 12415697Smcpowers case CKK_GENERIC_SECRET: 12425697Smcpowers if ((rv = get_template_attr_ulong(in_attrs, in_attr_count, 12435697Smcpowers CKA_VALUE_LEN, &key_len)) != CRYPTO_SUCCESS) { 12445697Smcpowers return (rv); 12455697Smcpowers } 12465697Smcpowers break; 12475697Smcpowers default: 12485697Smcpowers key_len = 0; 12495697Smcpowers } 12505697Smcpowers 12515697Smcpowers attrs = base_key->ck_attrs; 12525697Smcpowers if ((value_idx = find_attr(attrs, base_key->ck_count, 12535697Smcpowers CKA_VALUE)) == -1) { 12545697Smcpowers return (CRYPTO_TEMPLATE_INCOMPLETE); 12555697Smcpowers } 12565697Smcpowers 12575697Smcpowers if ((params_idx = find_attr(attrs, base_key->ck_count, 12585697Smcpowers CKA_EC_PARAMS)) == -1) { 12595697Smcpowers return (CRYPTO_TEMPLATE_INCOMPLETE); 12605697Smcpowers } 12615697Smcpowers 12625697Smcpowers private_value_item.data = (uchar_t *)attrs[value_idx].oa_value; 12635697Smcpowers private_value_item.len = attrs[value_idx].oa_value_len; 12645697Smcpowers 12655697Smcpowers params_item.len = attrs[params_idx].oa_value_len; 12665697Smcpowers params_item.data = (uchar_t *)attrs[params_idx].oa_value; 12675697Smcpowers 12685697Smcpowers /* ASN1 check */ 12695697Smcpowers if (params_item.data[0] != 0x06 || 12705697Smcpowers params_item.data[1] != params_item.len - 2) { 12715697Smcpowers return (CRYPTO_ATTRIBUTE_VALUE_INVALID); 12725697Smcpowers } 12735697Smcpowers kmflag = crypto_kmflag(req); 12745697Smcpowers if (EC_DecodeParams(¶ms_item, &ecparams, kmflag) != SECSuccess) { 12755697Smcpowers /* bad curve OID */ 12765697Smcpowers return (CRYPTO_ARGUMENTS_BAD); 12775697Smcpowers } 12785697Smcpowers 12795697Smcpowers public_value_item.data = (uchar_t *)mech_param->pPublicData; 12805697Smcpowers public_value_item.len = mech_param->ulPublicDataLen; 12815697Smcpowers 12825697Smcpowers if ((out_value_idx = find_attr(out_attrs, out_attr_count, 12835697Smcpowers CKA_VALUE)) == -1) { 12845697Smcpowers rv = CRYPTO_TEMPLATE_INCOMPLETE; 12855697Smcpowers goto out; 12865697Smcpowers } 12875697Smcpowers secret_item.data = NULL; 12885697Smcpowers secret_item.len = 0; 12895697Smcpowers 12905697Smcpowers if (ECDH_Derive(&public_value_item, ecparams, &private_value_item, 12915697Smcpowers B_FALSE, &secret_item, kmflag) != SECSuccess) { 12925697Smcpowers free_ecparams(ecparams, B_TRUE); 12935697Smcpowers return (CRYPTO_FAILED); 12945697Smcpowers } else { 12955697Smcpowers rv = CRYPTO_SUCCESS; 12965697Smcpowers } 12975697Smcpowers 12985697Smcpowers if (key_len == 0) 12995697Smcpowers key_len = secret_item.len; 13005697Smcpowers 13015697Smcpowers if (key_len > secret_item.len) { 13025697Smcpowers rv = CRYPTO_ATTRIBUTE_VALUE_INVALID; 13035697Smcpowers goto out; 13045697Smcpowers } 13055697Smcpowers if (key_len > out_attrs[out_value_idx].oa_value_len) { 13065697Smcpowers rv = CRYPTO_BUFFER_TOO_SMALL; 13075697Smcpowers goto out; 13085697Smcpowers } 13095697Smcpowers bcopy(secret_item.data + secret_item.len - key_len, 13105697Smcpowers (uchar_t *)out_attrs[out_value_idx].oa_value, key_len); 13115697Smcpowers out_attrs[out_value_idx].oa_value_len = key_len; 13125697Smcpowers out: 13135697Smcpowers free_ecparams(ecparams, B_TRUE); 13145697Smcpowers SECITEM_FreeItem(&secret_item, B_FALSE); 13155697Smcpowers return (rv); 13165697Smcpowers } 13175697Smcpowers 13185697Smcpowers static void 13195697Smcpowers free_ecparams(ECParams *params, boolean_t freeit) 13205697Smcpowers { 13215697Smcpowers SECITEM_FreeItem(¶ms->fieldID.u.prime, B_FALSE); 13225697Smcpowers SECITEM_FreeItem(¶ms->curve.a, B_FALSE); 13235697Smcpowers SECITEM_FreeItem(¶ms->curve.b, B_FALSE); 13245697Smcpowers SECITEM_FreeItem(¶ms->curve.seed, B_FALSE); 13255697Smcpowers SECITEM_FreeItem(¶ms->base, B_FALSE); 13265697Smcpowers SECITEM_FreeItem(¶ms->order, B_FALSE); 13275697Smcpowers SECITEM_FreeItem(¶ms->DEREncoding, B_FALSE); 13285697Smcpowers SECITEM_FreeItem(¶ms->curveOID, B_FALSE); 13295697Smcpowers if (freeit) 13305697Smcpowers kmem_free(params, sizeof (ECParams)); 13315697Smcpowers } 13325697Smcpowers 13335697Smcpowers static void 13345697Smcpowers free_ecprivkey(ECPrivateKey *key) 13355697Smcpowers { 13365697Smcpowers free_ecparams(&key->ecParams, B_FALSE); 13375697Smcpowers SECITEM_FreeItem(&key->publicValue, B_FALSE); 13385697Smcpowers bzero(key->privateValue.data, key->privateValue.len); 13395697Smcpowers SECITEM_FreeItem(&key->privateValue, B_FALSE); 13405697Smcpowers SECITEM_FreeItem(&key->version, B_FALSE); 13415697Smcpowers kmem_free(key, sizeof (ECPrivateKey)); 13425697Smcpowers } 1343