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