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*11751SAnthony.Scarpino@Sun.COM * Copyright 2010 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
19110732SAnthony.Scarpino@Sun.COM static void ecc_POST(int *);
19210732SAnthony.Scarpino@Sun.COM
19310732SAnthony.Scarpino@Sun.COM static crypto_fips140_ops_t ecc_fips140_ops = {
19410732SAnthony.Scarpino@Sun.COM ecc_POST
19510732SAnthony.Scarpino@Sun.COM };
19610732SAnthony.Scarpino@Sun.COM
19710732SAnthony.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,
21410732SAnthony.Scarpino@Sun.COM &ecc_nostore_key_ops,
21510732SAnthony.Scarpino@Sun.COM &ecc_fips140_ops
2165697Smcpowers };
2175697Smcpowers
2185697Smcpowers static crypto_provider_info_t ecc_prov_info = {
21910732SAnthony.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
_init(void)2475697Smcpowers _init(void)
2485697Smcpowers {
2495697Smcpowers int ret;
2505697Smcpowers
251*11751SAnthony.Scarpino@Sun.COM if ((ret = mod_install(&modlinkage)) != 0)
252*11751SAnthony.Scarpino@Sun.COM return (ret);
253*11751SAnthony.Scarpino@Sun.COM
254*11751SAnthony.Scarpino@Sun.COM /* Register with KCF. If the registration fails, remove the module. */
255*11751SAnthony.Scarpino@Sun.COM if (crypto_register_provider(&ecc_prov_info, &ecc_prov_handle)) {
256*11751SAnthony.Scarpino@Sun.COM (void) mod_remove(&modlinkage);
2575697Smcpowers return (EACCES);
2585697Smcpowers }
2595697Smcpowers
260*11751SAnthony.Scarpino@Sun.COM return (0);
2615697Smcpowers }
2625697Smcpowers
2635697Smcpowers int
_fini(void)2645697Smcpowers _fini(void)
2655697Smcpowers {
266*11751SAnthony.Scarpino@Sun.COM /* Unregister from KCF if module is registered */
2675697Smcpowers if (ecc_prov_handle != NULL) {
268*11751SAnthony.Scarpino@Sun.COM if (crypto_unregister_provider(ecc_prov_handle))
2695697Smcpowers return (EBUSY);
270*11751SAnthony.Scarpino@Sun.COM
2715697Smcpowers ecc_prov_handle = NULL;
2725697Smcpowers }
2735697Smcpowers
2745697Smcpowers return (mod_remove(&modlinkage));
2755697Smcpowers }
2765697Smcpowers
2775697Smcpowers int
_info(struct modinfo * modinfop)2785697Smcpowers _info(struct modinfo *modinfop)
2795697Smcpowers {
2805697Smcpowers return (mod_info(&modlinkage, modinfop));
2815697Smcpowers }
2825697Smcpowers
2835697Smcpowers /* ARGSUSED */
2845697Smcpowers static void
ecc_provider_status(crypto_provider_handle_t provider,uint_t * status)2855697Smcpowers ecc_provider_status(crypto_provider_handle_t provider, uint_t *status)
2865697Smcpowers {
2875697Smcpowers *status = CRYPTO_PROVIDER_READY;
2885697Smcpowers }
2895697Smcpowers
2905697Smcpowers /*
2915697Smcpowers * Return the index of an attribute of specified type found in
2925697Smcpowers * the specified array of attributes. If the attribute cannot
2935697Smcpowers * found, return -1.
2945697Smcpowers */
2955697Smcpowers static int
find_attr(crypto_object_attribute_t * attr,uint_t nattr,uint64_t attr_type)2965697Smcpowers find_attr(crypto_object_attribute_t *attr, uint_t nattr, uint64_t attr_type)
2975697Smcpowers {
2985697Smcpowers int i;
2995697Smcpowers
3005697Smcpowers for (i = 0; i < nattr; i++)
3015697Smcpowers if (attr[i].oa_value != NULL && attr[i].oa_type == attr_type)
3025697Smcpowers return (i);
3035697Smcpowers return (-1);
3045697Smcpowers }
3055697Smcpowers
3065697Smcpowers /*
3075697Smcpowers * Common function used by the get_template_attr_*() family of
3085697Smcpowers * functions. Returns the value of the specified attribute of specified
3095697Smcpowers * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
3105697Smcpowers * if the length of the attribute does not match the specified length,
3115697Smcpowers * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
3125697Smcpowers */
3135697Smcpowers static int
get_template_attr_scalar_common(crypto_object_attribute_t * template,uint_t nattr,uint64_t attr_type,void * value,size_t value_len)3145697Smcpowers get_template_attr_scalar_common(crypto_object_attribute_t *template,
3155697Smcpowers uint_t nattr, uint64_t attr_type, void *value, size_t value_len)
3165697Smcpowers {
3175697Smcpowers size_t oa_value_len;
3185697Smcpowers size_t offset = 0;
3195697Smcpowers int attr_idx;
3205697Smcpowers
3215697Smcpowers if ((attr_idx = find_attr(template, nattr, attr_type)) == -1)
3225697Smcpowers return (CRYPTO_ARGUMENTS_BAD);
3235697Smcpowers
3245697Smcpowers oa_value_len = template[attr_idx].oa_value_len;
3255697Smcpowers if (oa_value_len != value_len) {
3265697Smcpowers return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
3275697Smcpowers }
3285697Smcpowers
3295697Smcpowers do_copy:
3305697Smcpowers bcopy(template[attr_idx].oa_value, (uchar_t *)value + offset,
3315697Smcpowers oa_value_len);
3325697Smcpowers
3335697Smcpowers return (CRYPTO_SUCCESS);
3345697Smcpowers }
3355697Smcpowers
3365697Smcpowers /*
3375697Smcpowers * Get the value of a ulong_t attribute from the specified template.
3385697Smcpowers */
3395697Smcpowers static int
get_template_attr_ulong(crypto_object_attribute_t * template,uint_t nattr,uint64_t attr_type,ulong_t * attr_value)3405697Smcpowers get_template_attr_ulong(crypto_object_attribute_t *template,
3415697Smcpowers uint_t nattr, uint64_t attr_type, ulong_t *attr_value)
3425697Smcpowers {
3435697Smcpowers return (get_template_attr_scalar_common(template, nattr,
3445697Smcpowers attr_type, attr_value, sizeof (ulong_t)));
3455697Smcpowers }
3465697Smcpowers
3475697Smcpowers /*
3485697Smcpowers * Called from init routines to do basic sanity checks. Init routines,
3495697Smcpowers * e.g. sign_init should fail rather than subsequent operations.
3505697Smcpowers */
3515697Smcpowers static int
check_mech_and_key(ecc_mech_type_t mech_type,crypto_key_t * key,ulong_t class)3525697Smcpowers check_mech_and_key(ecc_mech_type_t mech_type, crypto_key_t *key, ulong_t class)
3535697Smcpowers {
3545697Smcpowers int rv = CRYPTO_SUCCESS;
3555697Smcpowers uchar_t *foo;
3565697Smcpowers ssize_t point_len;
3575697Smcpowers ssize_t value_len;
3585697Smcpowers
3595697Smcpowers if (mech_type != ECDSA_SHA1_MECH_INFO_TYPE &&
3605697Smcpowers mech_type != ECDSA_MECH_INFO_TYPE)
3615697Smcpowers return (CRYPTO_MECHANISM_INVALID);
3625697Smcpowers
3635697Smcpowers if (key->ck_format != CRYPTO_KEY_ATTR_LIST) {
3645697Smcpowers return (CRYPTO_KEY_TYPE_INCONSISTENT);
3655697Smcpowers }
3665697Smcpowers
3675697Smcpowers switch (class) {
3685697Smcpowers case CKO_PUBLIC_KEY:
3697188Smcpowers if ((rv = crypto_get_key_attr(key, CKA_EC_POINT, &foo,
3707188Smcpowers &point_len)) != CRYPTO_SUCCESS) {
3715697Smcpowers return (CRYPTO_TEMPLATE_INCOMPLETE);
3725697Smcpowers }
3735697Smcpowers if (point_len < CRYPTO_BITS2BYTES(EC_MIN_KEY_LEN) * 2 + 1 ||
3745697Smcpowers point_len > CRYPTO_BITS2BYTES(EC_MAX_KEY_LEN) * 2 + 1)
3755697Smcpowers return (CRYPTO_KEY_SIZE_RANGE);
3765697Smcpowers break;
3775697Smcpowers
3785697Smcpowers case CKO_PRIVATE_KEY:
3797188Smcpowers if ((rv = crypto_get_key_attr(key, CKA_VALUE, &foo,
3807188Smcpowers &value_len)) != CRYPTO_SUCCESS) {
3815697Smcpowers return (CRYPTO_TEMPLATE_INCOMPLETE);
3825697Smcpowers }
3835697Smcpowers if (value_len < CRYPTO_BITS2BYTES(EC_MIN_KEY_LEN) ||
3845697Smcpowers value_len > CRYPTO_BITS2BYTES(EC_MAX_KEY_LEN))
3855697Smcpowers return (CRYPTO_KEY_SIZE_RANGE);
3865697Smcpowers break;
3875697Smcpowers
3885697Smcpowers default:
3895697Smcpowers return (CRYPTO_TEMPLATE_INCONSISTENT);
3905697Smcpowers }
3915697Smcpowers
3925697Smcpowers return (rv);
3935697Smcpowers }
3945697Smcpowers
3955697Smcpowers /*
3965697Smcpowers * This function guarantees to return non-zero random numbers.
3975697Smcpowers * This is needed as the /dev/urandom kernel interface,
3985697Smcpowers * random_get_pseudo_bytes(), may return zeros.
3995697Smcpowers */
4005697Smcpowers int
ecc_knzero_random_generator(uint8_t * ran_out,size_t ran_len)4015697Smcpowers ecc_knzero_random_generator(uint8_t *ran_out, size_t ran_len)
4025697Smcpowers {
4035697Smcpowers int rv;
4045697Smcpowers size_t ebc = 0; /* count of extra bytes in extrarand */
4055697Smcpowers size_t i = 0;
4065697Smcpowers uint8_t extrarand[32];
4075697Smcpowers size_t extrarand_len;
4085697Smcpowers
40910732SAnthony.Scarpino@Sun.COM if ((rv = random_get_pseudo_bytes_fips140(ran_out, ran_len)) != 0)
4105697Smcpowers return (rv);
4115697Smcpowers
4125697Smcpowers /*
4135697Smcpowers * Walk through the returned random numbers pointed by ran_out,
4145697Smcpowers * and look for any random number which is zero.
4155697Smcpowers * If we find zero, call random_get_pseudo_bytes() to generate
4165697Smcpowers * another 32 random numbers pool. Replace any zeros in ran_out[]
4175697Smcpowers * from the random number in pool.
4185697Smcpowers */
4195697Smcpowers while (i < ran_len) {
4205697Smcpowers if (ran_out[i] != 0) {
4215697Smcpowers i++;
4225697Smcpowers continue;
4235697Smcpowers }
4245697Smcpowers
4255697Smcpowers /*
4265697Smcpowers * Note that it is 'while' so we are guaranteed a
4275697Smcpowers * non-zero value on exit.
4285697Smcpowers */
4295697Smcpowers if (ebc == 0) {
4305697Smcpowers /* refresh extrarand */
4315697Smcpowers extrarand_len = sizeof (extrarand);
43210732SAnthony.Scarpino@Sun.COM if ((rv = random_get_pseudo_bytes_fips140(extrarand,
4335697Smcpowers extrarand_len)) != 0) {
4345697Smcpowers return (rv);
4355697Smcpowers }
4365697Smcpowers
4375697Smcpowers ebc = extrarand_len;
4385697Smcpowers }
4395697Smcpowers /* Replace zero with byte from extrarand. */
4405697Smcpowers -- ebc;
4415697Smcpowers
4425697Smcpowers /*
4435697Smcpowers * The new random byte zero/non-zero will be checked in
4445697Smcpowers * the next pass through the loop.
4455697Smcpowers */
4465697Smcpowers ran_out[i] = extrarand[ebc];
4475697Smcpowers }
4485697Smcpowers
4495697Smcpowers return (CRYPTO_SUCCESS);
4505697Smcpowers }
4515697Smcpowers
4525697Smcpowers static void
ecc_free_context(crypto_ctx_t * ctx)4535697Smcpowers ecc_free_context(crypto_ctx_t *ctx)
4545697Smcpowers {
4555697Smcpowers ecc_ctx_t *ctxp = ctx->cc_provider_private;
4565697Smcpowers
4575697Smcpowers if (ctxp != NULL) {
4585697Smcpowers bzero(ctxp->key, ctxp->keychunk_size);
4595697Smcpowers kmem_free(ctxp->key, ctxp->keychunk_size);
4605697Smcpowers
4615697Smcpowers free_ecparams(&ctxp->ecparams, B_FALSE);
4625697Smcpowers
4635697Smcpowers if (ctxp->mech_type == ECDSA_MECH_INFO_TYPE)
4645697Smcpowers kmem_free(ctxp, sizeof (ecc_ctx_t));
4655697Smcpowers else
4665697Smcpowers kmem_free(ctxp, sizeof (digest_ecc_ctx_t));
4675697Smcpowers
4685697Smcpowers ctx->cc_provider_private = NULL;
4695697Smcpowers }
4705697Smcpowers }
4715697Smcpowers
4725697Smcpowers /* ARGSUSED */
4735697Smcpowers static int
ecc_sign_verify_common_init(crypto_ctx_t * ctx,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t ctx_template,crypto_req_handle_t req)4745697Smcpowers ecc_sign_verify_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
4755697Smcpowers crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
4765697Smcpowers crypto_req_handle_t req)
4775697Smcpowers {
4785697Smcpowers int rv;
4795697Smcpowers int kmflag;
4805697Smcpowers ecc_ctx_t *ctxp;
4815697Smcpowers digest_ecc_ctx_t *dctxp;
4825697Smcpowers ecc_mech_type_t mech_type = mechanism->cm_type;
4835697Smcpowers uchar_t *params;
4845697Smcpowers ssize_t params_len;
4855697Smcpowers ECParams *ecparams;
4865697Smcpowers SECKEYECParams params_item;
4875697Smcpowers
4887188Smcpowers if (crypto_get_key_attr(key, CKA_EC_PARAMS, (void *) ¶ms,
4895697Smcpowers ¶ms_len)) {
4905697Smcpowers return (CRYPTO_ARGUMENTS_BAD);
4915697Smcpowers }
4925697Smcpowers
4935697Smcpowers /* ASN1 check */
4945697Smcpowers if (params[0] != 0x06 ||
4955697Smcpowers params[1] != params_len - 2) {
4965697Smcpowers return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
4975697Smcpowers }
4985697Smcpowers params_item.data = params;
4995697Smcpowers params_item.len = (uint_t)params_len;
5005697Smcpowers kmflag = crypto_kmflag(req);
5015697Smcpowers if (EC_DecodeParams(¶ms_item, &ecparams, kmflag) != SECSuccess) {
5025697Smcpowers /* bad curve OID */
5035697Smcpowers return (CRYPTO_ARGUMENTS_BAD);
5045697Smcpowers }
5055697Smcpowers
5065697Smcpowers /*
5075697Smcpowers * Allocate an ECC context.
5085697Smcpowers */
5095697Smcpowers switch (mech_type) {
5105697Smcpowers case ECDSA_SHA1_MECH_INFO_TYPE:
5115697Smcpowers dctxp = kmem_zalloc(sizeof (digest_ecc_ctx_t), kmflag);
5125697Smcpowers ctxp = (ecc_ctx_t *)dctxp;
5135697Smcpowers break;
5145697Smcpowers default:
5155697Smcpowers ctxp = kmem_zalloc(sizeof (ecc_ctx_t), kmflag);
5165697Smcpowers break;
5175697Smcpowers }
5185697Smcpowers
5195697Smcpowers if (ctxp == NULL) {
5205697Smcpowers free_ecparams(ecparams, B_TRUE);
5215697Smcpowers return (CRYPTO_HOST_MEMORY);
5225697Smcpowers }
5235697Smcpowers
5247188Smcpowers if ((rv = crypto_copy_key_to_ctx(key, &ctxp->key, &ctxp->keychunk_size,
5257188Smcpowers kmflag)) != CRYPTO_SUCCESS) {
5265697Smcpowers switch (mech_type) {
5275697Smcpowers case ECDSA_SHA1_MECH_INFO_TYPE:
5285697Smcpowers kmem_free(dctxp, sizeof (digest_ecc_ctx_t));
5295697Smcpowers break;
5305697Smcpowers default:
5315697Smcpowers kmem_free(ctxp, sizeof (ecc_ctx_t));
5325697Smcpowers break;
5335697Smcpowers }
5345697Smcpowers free_ecparams(ecparams, B_TRUE);
5355697Smcpowers return (rv);
5365697Smcpowers }
5375697Smcpowers ctxp->mech_type = mech_type;
5385697Smcpowers ctxp->ecparams = *ecparams;
5395697Smcpowers kmem_free(ecparams, sizeof (ECParams));
5405697Smcpowers
5415697Smcpowers switch (mech_type) {
5425697Smcpowers case ECDSA_SHA1_MECH_INFO_TYPE:
5435697Smcpowers SHA1Init(&(dctxp->sha1_ctx));
5445697Smcpowers break;
5455697Smcpowers }
5465697Smcpowers
5475697Smcpowers ctx->cc_provider_private = ctxp;
5485697Smcpowers
5495697Smcpowers return (CRYPTO_SUCCESS);
5505697Smcpowers }
5515697Smcpowers
5525697Smcpowers /* ARGSUSED */
5535697Smcpowers static int
ecc_sign_init(crypto_ctx_t * ctx,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t ctx_template,crypto_req_handle_t req)5545697Smcpowers ecc_sign_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
5555697Smcpowers crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
5565697Smcpowers crypto_req_handle_t req)
5575697Smcpowers {
5585697Smcpowers int rv;
5595697Smcpowers
5605697Smcpowers ecc_mech_type_t mech_type = mechanism->cm_type;
5615697Smcpowers
5625697Smcpowers if ((rv = check_mech_and_key(mech_type, key,
5635697Smcpowers CKO_PRIVATE_KEY)) != CRYPTO_SUCCESS)
5645697Smcpowers return (rv);
5655697Smcpowers
5665697Smcpowers rv = ecc_sign_verify_common_init(ctx, mechanism, key,
5675697Smcpowers ctx_template, req);
5685697Smcpowers
5695697Smcpowers return (rv);
5705697Smcpowers }
5715697Smcpowers
5725697Smcpowers /* ARGSUSED */
5735697Smcpowers static int
ecc_verify_init(crypto_ctx_t * ctx,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t ctx_template,crypto_req_handle_t req)5745697Smcpowers ecc_verify_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
5755697Smcpowers crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
5765697Smcpowers crypto_req_handle_t req)
5775697Smcpowers {
5785697Smcpowers int rv;
5795697Smcpowers
5805697Smcpowers ecc_mech_type_t mech_type = mechanism->cm_type;
5815697Smcpowers
5825697Smcpowers if ((rv = check_mech_and_key(mech_type, key,
5835697Smcpowers CKO_PUBLIC_KEY)) != CRYPTO_SUCCESS)
5845697Smcpowers return (rv);
5855697Smcpowers
5865697Smcpowers rv = ecc_sign_verify_common_init(ctx, mechanism, key,
5875697Smcpowers ctx_template, req);
5885697Smcpowers
5895697Smcpowers return (rv);
5905697Smcpowers }
5915697Smcpowers
5925697Smcpowers #define SHA1_DIGEST_SIZE 20
5935697Smcpowers
5945697Smcpowers #define INIT_RAW_CRYPTO_DATA(data, base, len, cd_len) \
5955697Smcpowers (data).cd_format = CRYPTO_DATA_RAW; \
5965697Smcpowers (data).cd_offset = 0; \
5975697Smcpowers (data).cd_raw.iov_base = (char *)base; \
5985697Smcpowers (data).cd_raw.iov_len = len; \
5995697Smcpowers (data).cd_length = cd_len;
6005697Smcpowers
6015697Smcpowers static int
ecc_digest_svrfy_common(digest_ecc_ctx_t * ctxp,crypto_data_t * data,crypto_data_t * signature,uchar_t flag,crypto_req_handle_t req)6025697Smcpowers ecc_digest_svrfy_common(digest_ecc_ctx_t *ctxp, crypto_data_t *data,
6035697Smcpowers crypto_data_t *signature, uchar_t flag, crypto_req_handle_t req)
6045697Smcpowers {
6055697Smcpowers int rv = CRYPTO_FAILED;
6065697Smcpowers uchar_t digest[SHA1_DIGEST_LENGTH];
6075697Smcpowers crypto_data_t der_cd;
6085697Smcpowers ecc_mech_type_t mech_type;
6095697Smcpowers
6107188Smcpowers ASSERT(flag & CRYPTO_DO_SIGN || flag & CRYPTO_DO_VERIFY);
6117188Smcpowers ASSERT(data != NULL || (flag & CRYPTO_DO_FINAL));
6125697Smcpowers
6135697Smcpowers mech_type = ctxp->mech_type;
6145697Smcpowers if (mech_type != ECDSA_SHA1_MECH_INFO_TYPE)
6155697Smcpowers return (CRYPTO_MECHANISM_INVALID);
6165697Smcpowers
6175697Smcpowers /* Don't digest if only returning length of signature. */
6185697Smcpowers if (signature->cd_length > 0) {
6195697Smcpowers if (mech_type == ECDSA_SHA1_MECH_INFO_TYPE) {
6207188Smcpowers rv = crypto_digest_data(data, &(ctxp->sha1_ctx),
6217188Smcpowers digest, (void (*)())SHA1Update,
6227188Smcpowers (void (*)())SHA1Final, flag | CRYPTO_DO_SHA1);
6235697Smcpowers if (rv != CRYPTO_SUCCESS)
6245697Smcpowers return (rv);
6255697Smcpowers }
6265697Smcpowers }
6275697Smcpowers
6285697Smcpowers INIT_RAW_CRYPTO_DATA(der_cd, digest, SHA1_DIGEST_SIZE,
6295697Smcpowers SHA1_DIGEST_SIZE);
6305697Smcpowers
6317188Smcpowers if (flag & CRYPTO_DO_SIGN) {
6325697Smcpowers rv = ecc_sign_common((ecc_ctx_t *)ctxp, &der_cd, signature,
6335697Smcpowers req);
6345697Smcpowers } else
6355697Smcpowers rv = ecc_verify_common((ecc_ctx_t *)ctxp, &der_cd, signature,
6365697Smcpowers req);
6375697Smcpowers
6385697Smcpowers return (rv);
6395697Smcpowers }
6405697Smcpowers
6415697Smcpowers /*
6425697Smcpowers * This is a single-part signing routine. It does not
6435697Smcpowers * compute a hash before signing.
6445697Smcpowers */
6455697Smcpowers static int
ecc_sign_common(ecc_ctx_t * ctx,crypto_data_t * data,crypto_data_t * signature,crypto_req_handle_t req)6465697Smcpowers ecc_sign_common(ecc_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
6475697Smcpowers crypto_req_handle_t req)
6485697Smcpowers {
6495697Smcpowers int rv = CRYPTO_FAILED;
6505697Smcpowers SECStatus ss;
6515697Smcpowers uchar_t *param;
6525697Smcpowers uchar_t *private;
6535697Smcpowers ssize_t param_len;
6545697Smcpowers ssize_t private_len;
6555697Smcpowers uchar_t tmp_data[EC_MAX_DIGEST_LEN];
6565697Smcpowers uchar_t signed_data[EC_MAX_SIG_LEN];
6575697Smcpowers ECPrivateKey ECkey;
6585697Smcpowers SECItem signature_item;
6595697Smcpowers SECItem digest_item;
6605697Smcpowers crypto_key_t *key = ctx->key;
6615697Smcpowers int kmflag;
6625697Smcpowers
6637188Smcpowers if ((rv = crypto_get_key_attr(key, CKA_EC_PARAMS, ¶m,
6645697Smcpowers ¶m_len)) != CRYPTO_SUCCESS) {
6655697Smcpowers return (rv);
6665697Smcpowers }
6675697Smcpowers
6685697Smcpowers if (data->cd_length > sizeof (tmp_data))
6695697Smcpowers return (CRYPTO_DATA_LEN_RANGE);
6705697Smcpowers
6717188Smcpowers if ((rv = crypto_get_input_data(data, &digest_item.data, tmp_data))
6725697Smcpowers != CRYPTO_SUCCESS) {
6735697Smcpowers return (rv);
6745697Smcpowers }
6755697Smcpowers digest_item.len = data->cd_length;
6765697Smcpowers
6775697Smcpowers /* structure assignment */
6785697Smcpowers ECkey.ecParams = ctx->ecparams;
6795697Smcpowers
6807188Smcpowers if ((rv = crypto_get_key_attr(key, CKA_VALUE, &private,
6815697Smcpowers &private_len)) != CRYPTO_SUCCESS) {
6825697Smcpowers return (rv);
6835697Smcpowers }
6845697Smcpowers ECkey.privateValue.data = private;
6855697Smcpowers ECkey.privateValue.len = (uint_t)private_len;
6865697Smcpowers
6875697Smcpowers signature_item.data = signed_data;
6885697Smcpowers signature_item.len = sizeof (signed_data);
6895697Smcpowers
6905697Smcpowers kmflag = crypto_kmflag(req);
6915697Smcpowers if ((ss = ECDSA_SignDigest(&ECkey, &signature_item, &digest_item,
6925697Smcpowers kmflag)) != SECSuccess) {
6935697Smcpowers if (ss == SECBufferTooSmall)
6945697Smcpowers return (CRYPTO_BUFFER_TOO_SMALL);
6955697Smcpowers
6965697Smcpowers return (CRYPTO_FAILED);
6975697Smcpowers }
6985697Smcpowers
6995697Smcpowers if (rv == CRYPTO_SUCCESS) {
7005697Smcpowers /* copy out the signature */
7017188Smcpowers if ((rv = crypto_put_output_data(signed_data,
7025697Smcpowers signature, signature_item.len)) != CRYPTO_SUCCESS)
7035697Smcpowers return (rv);
7045697Smcpowers
7055697Smcpowers signature->cd_length = signature_item.len;
7065697Smcpowers }
7075697Smcpowers
7085697Smcpowers return (rv);
7095697Smcpowers }
7105697Smcpowers
7115697Smcpowers /* ARGSUSED */
7125697Smcpowers static int
ecc_sign(crypto_ctx_t * ctx,crypto_data_t * data,crypto_data_t * signature,crypto_req_handle_t req)7135697Smcpowers ecc_sign(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
7145697Smcpowers crypto_req_handle_t req)
7155697Smcpowers {
7165697Smcpowers int rv;
7175697Smcpowers ecc_ctx_t *ctxp;
7185697Smcpowers
7195697Smcpowers ASSERT(ctx->cc_provider_private != NULL);
7205697Smcpowers ctxp = ctx->cc_provider_private;
7215697Smcpowers
7225697Smcpowers switch (ctxp->mech_type) {
7235697Smcpowers case ECDSA_SHA1_MECH_INFO_TYPE:
7245697Smcpowers rv = ecc_digest_svrfy_common((digest_ecc_ctx_t *)ctxp, data,
7257188Smcpowers signature, CRYPTO_DO_SIGN | CRYPTO_DO_UPDATE |
7267188Smcpowers CRYPTO_DO_FINAL, req);
7275697Smcpowers break;
7285697Smcpowers default:
7295697Smcpowers rv = ecc_sign_common(ctxp, data, signature, req);
7305697Smcpowers break;
7315697Smcpowers }
7325697Smcpowers
7335697Smcpowers if (rv != CRYPTO_BUFFER_TOO_SMALL)
7345697Smcpowers ecc_free_context(ctx);
7355697Smcpowers
7365697Smcpowers return (rv);
7375697Smcpowers }
7385697Smcpowers
7395697Smcpowers /* ARGSUSED */
7405697Smcpowers static int
ecc_sign_update(crypto_ctx_t * ctx,crypto_data_t * data,crypto_req_handle_t req)7415697Smcpowers ecc_sign_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req)
7425697Smcpowers {
7435697Smcpowers int rv;
7445697Smcpowers digest_ecc_ctx_t *ctxp;
7455697Smcpowers ecc_mech_type_t mech_type;
7465697Smcpowers
7475697Smcpowers ASSERT(ctx->cc_provider_private != NULL);
7485697Smcpowers ctxp = ctx->cc_provider_private;
7495697Smcpowers mech_type = ctxp->mech_type;
7505697Smcpowers
7515697Smcpowers if (mech_type == ECDSA_MECH_INFO_TYPE) {
7525697Smcpowers ecc_free_context(ctx);
7535697Smcpowers return (CRYPTO_MECHANISM_INVALID);
7545697Smcpowers }
7555697Smcpowers
7565697Smcpowers if (mech_type == ECDSA_SHA1_MECH_INFO_TYPE)
7577188Smcpowers rv = crypto_digest_data(data, &(ctxp->sha1_ctx), NULL,
7587188Smcpowers (void (*)())SHA1Update, (void (*)())SHA1Final,
7597188Smcpowers CRYPTO_DO_SHA1 | CRYPTO_DO_UPDATE);
7605697Smcpowers
7615697Smcpowers if (rv != CRYPTO_SUCCESS)
7625697Smcpowers ecc_free_context(ctx);
7635697Smcpowers
7645697Smcpowers return (rv);
7655697Smcpowers }
7665697Smcpowers
7675697Smcpowers /* ARGSUSED */
7685697Smcpowers static int
ecc_sign_final(crypto_ctx_t * ctx,crypto_data_t * signature,crypto_req_handle_t req)7695697Smcpowers ecc_sign_final(crypto_ctx_t *ctx, crypto_data_t *signature,
7705697Smcpowers crypto_req_handle_t req)
7715697Smcpowers {
7725697Smcpowers int rv;
7735697Smcpowers digest_ecc_ctx_t *ctxp;
7745697Smcpowers
7755697Smcpowers ASSERT(ctx->cc_provider_private != NULL);
7765697Smcpowers ctxp = ctx->cc_provider_private;
7775697Smcpowers
7787188Smcpowers rv = ecc_digest_svrfy_common(ctxp, NULL, signature, CRYPTO_DO_SIGN |
7797188Smcpowers CRYPTO_DO_FINAL, req);
7805697Smcpowers if (rv != CRYPTO_BUFFER_TOO_SMALL)
7815697Smcpowers ecc_free_context(ctx);
7825697Smcpowers
7835697Smcpowers return (rv);
7845697Smcpowers }
7855697Smcpowers
7865697Smcpowers /* ARGSUSED */
7875697Smcpowers static int
ecc_sign_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * data,crypto_data_t * signature,crypto_spi_ctx_template_t ctx_template,crypto_req_handle_t req)7885697Smcpowers ecc_sign_atomic(crypto_provider_handle_t provider,
7895697Smcpowers crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
7905697Smcpowers crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
7915697Smcpowers crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
7925697Smcpowers {
7935697Smcpowers int rv;
7945697Smcpowers ecc_mech_type_t mech_type = mechanism->cm_type;
7955697Smcpowers uchar_t *params;
7965697Smcpowers ssize_t params_len;
7975697Smcpowers ECParams *ecparams;
7985697Smcpowers SECKEYECParams params_item;
7995697Smcpowers int kmflag;
8005697Smcpowers
8015697Smcpowers if ((rv = check_mech_and_key(mech_type, key,
8025697Smcpowers CKO_PRIVATE_KEY)) != CRYPTO_SUCCESS)
8035697Smcpowers return (rv);
8045697Smcpowers
8057188Smcpowers if (crypto_get_key_attr(key, CKA_EC_PARAMS, (void *) ¶ms,
8065697Smcpowers ¶ms_len)) {
8075697Smcpowers return (CRYPTO_ARGUMENTS_BAD);
8085697Smcpowers }
8095697Smcpowers
8105697Smcpowers /* ASN1 check */
8115697Smcpowers if (params[0] != 0x06 ||
8125697Smcpowers params[1] != params_len - 2) {
8135697Smcpowers return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
8145697Smcpowers }
8155697Smcpowers params_item.data = params;
8165697Smcpowers params_item.len = (uint_t)params_len;
8175697Smcpowers kmflag = crypto_kmflag(req);
8185697Smcpowers if (EC_DecodeParams(¶ms_item, &ecparams, kmflag) != SECSuccess) {
8195697Smcpowers /* bad curve OID */
8205697Smcpowers return (CRYPTO_ARGUMENTS_BAD);
8215697Smcpowers }
8225697Smcpowers
8235697Smcpowers if (mechanism->cm_type == ECDSA_MECH_INFO_TYPE) {
8245697Smcpowers ecc_ctx_t ctx;
8255697Smcpowers
8265697Smcpowers ctx.mech_type = mech_type;
8275697Smcpowers /* structure assignment */
8285697Smcpowers ctx.ecparams = *ecparams;
8295697Smcpowers ctx.key = key;
8305697Smcpowers rv = ecc_sign_common(&ctx, data, signature, req);
8315697Smcpowers } else {
8325697Smcpowers digest_ecc_ctx_t dctx;
8335697Smcpowers
8345697Smcpowers dctx.mech_type = mech_type;
8355697Smcpowers /* structure assignment */
8365697Smcpowers dctx.ecparams = *ecparams;
8375697Smcpowers dctx.key = key;
8385697Smcpowers SHA1Init(&(dctx.sha1_ctx));
8395697Smcpowers
8405697Smcpowers rv = ecc_digest_svrfy_common(&dctx, data, signature,
8417188Smcpowers CRYPTO_DO_SIGN | CRYPTO_DO_UPDATE | CRYPTO_DO_FINAL, req);
8425697Smcpowers }
8435697Smcpowers free_ecparams(ecparams, B_TRUE);
8445697Smcpowers
8455697Smcpowers return (rv);
8465697Smcpowers }
8475697Smcpowers
8485697Smcpowers static int
ecc_verify_common(ecc_ctx_t * ctx,crypto_data_t * data,crypto_data_t * signature,crypto_req_handle_t req)8495697Smcpowers ecc_verify_common(ecc_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
8505697Smcpowers crypto_req_handle_t req)
8515697Smcpowers {
8525697Smcpowers int rv = CRYPTO_FAILED;
8535697Smcpowers uchar_t *param;
8545697Smcpowers uchar_t *public;
8555697Smcpowers ssize_t param_len;
8565697Smcpowers ssize_t public_len;
8575697Smcpowers uchar_t tmp_data[EC_MAX_DIGEST_LEN];
8585697Smcpowers uchar_t signed_data[EC_MAX_SIG_LEN];
8595697Smcpowers ECPublicKey ECkey;
8605697Smcpowers SECItem signature_item;
8615697Smcpowers SECItem digest_item;
8625697Smcpowers crypto_key_t *key = ctx->key;
8635697Smcpowers int kmflag;
8645697Smcpowers
8657188Smcpowers if ((rv = crypto_get_key_attr(key, CKA_EC_PARAMS, ¶m,
8665697Smcpowers ¶m_len)) != CRYPTO_SUCCESS) {
8675697Smcpowers return (rv);
8685697Smcpowers }
8695697Smcpowers
8705697Smcpowers if (signature->cd_length > sizeof (signed_data)) {
8715697Smcpowers return (CRYPTO_SIGNATURE_LEN_RANGE);
8725697Smcpowers }
8735697Smcpowers
8747188Smcpowers if ((rv = crypto_get_input_data(signature, &signature_item.data,
8755697Smcpowers signed_data)) != CRYPTO_SUCCESS) {
8765697Smcpowers return (rv);
8775697Smcpowers }
8785697Smcpowers signature_item.len = signature->cd_length;
8795697Smcpowers
8805697Smcpowers if (data->cd_length > sizeof (tmp_data))
8815697Smcpowers return (CRYPTO_DATA_LEN_RANGE);
8825697Smcpowers
8837188Smcpowers if ((rv = crypto_get_input_data(data, &digest_item.data, tmp_data))
8845697Smcpowers != CRYPTO_SUCCESS) {
8855697Smcpowers return (rv);
8865697Smcpowers }
8875697Smcpowers digest_item.len = data->cd_length;
8885697Smcpowers
8895697Smcpowers /* structure assignment */
8905697Smcpowers ECkey.ecParams = ctx->ecparams;
8915697Smcpowers
8927188Smcpowers if ((rv = crypto_get_key_attr(key, CKA_EC_POINT, &public,
8935697Smcpowers &public_len)) != CRYPTO_SUCCESS) {
8945697Smcpowers return (rv);
8955697Smcpowers }
8965697Smcpowers ECkey.publicValue.data = public;
8975697Smcpowers ECkey.publicValue.len = (uint_t)public_len;
8985697Smcpowers
8995697Smcpowers kmflag = crypto_kmflag(req);
9005697Smcpowers if (ECDSA_VerifyDigest(&ECkey, &signature_item, &digest_item, kmflag)
9015697Smcpowers != SECSuccess) {
9025697Smcpowers rv = CRYPTO_SIGNATURE_INVALID;
9035697Smcpowers } else {
9045697Smcpowers rv = CRYPTO_SUCCESS;
9055697Smcpowers }
9065697Smcpowers
9075697Smcpowers return (rv);
9085697Smcpowers }
9095697Smcpowers
9105697Smcpowers /* ARGSUSED */
9115697Smcpowers static int
ecc_verify(crypto_ctx_t * ctx,crypto_data_t * data,crypto_data_t * signature,crypto_req_handle_t req)9125697Smcpowers ecc_verify(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
9135697Smcpowers crypto_req_handle_t req)
9145697Smcpowers {
9155697Smcpowers int rv;
9165697Smcpowers ecc_ctx_t *ctxp;
9175697Smcpowers
9185697Smcpowers ASSERT(ctx->cc_provider_private != NULL);
9195697Smcpowers ctxp = ctx->cc_provider_private;
9205697Smcpowers
9215697Smcpowers switch (ctxp->mech_type) {
9225697Smcpowers case ECDSA_SHA1_MECH_INFO_TYPE:
9235697Smcpowers rv = ecc_digest_svrfy_common((digest_ecc_ctx_t *)ctxp, data,
9247188Smcpowers signature, CRYPTO_DO_VERIFY | CRYPTO_DO_UPDATE |
9257188Smcpowers CRYPTO_DO_FINAL, req);
9265697Smcpowers break;
9275697Smcpowers default:
9285697Smcpowers rv = ecc_verify_common(ctxp, data, signature, req);
9295697Smcpowers break;
9305697Smcpowers }
9315697Smcpowers
9325697Smcpowers ecc_free_context(ctx);
9335697Smcpowers return (rv);
9345697Smcpowers }
9355697Smcpowers
9365697Smcpowers /* ARGSUSED */
9375697Smcpowers static int
ecc_verify_update(crypto_ctx_t * ctx,crypto_data_t * data,crypto_req_handle_t req)9385697Smcpowers ecc_verify_update(crypto_ctx_t *ctx, crypto_data_t *data,
9395697Smcpowers crypto_req_handle_t req)
9405697Smcpowers {
9415697Smcpowers int rv;
9425697Smcpowers digest_ecc_ctx_t *ctxp;
9435697Smcpowers
9445697Smcpowers ASSERT(ctx->cc_provider_private != NULL);
9455697Smcpowers ctxp = ctx->cc_provider_private;
9465697Smcpowers
9475697Smcpowers switch (ctxp->mech_type) {
9485697Smcpowers case ECDSA_SHA1_MECH_INFO_TYPE:
9497188Smcpowers rv = crypto_digest_data(data, &(ctxp->sha1_ctx), NULL,
9507188Smcpowers (void (*)())SHA1Update, (void (*)())SHA1Final,
9517188Smcpowers CRYPTO_DO_SHA1 | CRYPTO_DO_UPDATE);
9525697Smcpowers break;
9535697Smcpowers default:
9545697Smcpowers rv = CRYPTO_MECHANISM_INVALID;
9555697Smcpowers }
9565697Smcpowers
9575697Smcpowers if (rv != CRYPTO_SUCCESS)
9585697Smcpowers ecc_free_context(ctx);
9595697Smcpowers
9605697Smcpowers return (rv);
9615697Smcpowers }
9625697Smcpowers
9635697Smcpowers /* ARGSUSED */
9645697Smcpowers static int
ecc_verify_final(crypto_ctx_t * ctx,crypto_data_t * signature,crypto_req_handle_t req)9655697Smcpowers ecc_verify_final(crypto_ctx_t *ctx, crypto_data_t *signature,
9665697Smcpowers crypto_req_handle_t req)
9675697Smcpowers {
9685697Smcpowers int rv;
9695697Smcpowers digest_ecc_ctx_t *ctxp;
9705697Smcpowers
9715697Smcpowers ASSERT(ctx->cc_provider_private != NULL);
9725697Smcpowers ctxp = ctx->cc_provider_private;
9735697Smcpowers
9745697Smcpowers rv = ecc_digest_svrfy_common(ctxp, NULL, signature,
9757188Smcpowers CRYPTO_DO_VERIFY | CRYPTO_DO_FINAL, req);
9765697Smcpowers
9775697Smcpowers ecc_free_context(ctx);
9785697Smcpowers
9795697Smcpowers return (rv);
9805697Smcpowers }
9815697Smcpowers
9825697Smcpowers
9835697Smcpowers /* ARGSUSED */
9845697Smcpowers static int
ecc_verify_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * data,crypto_data_t * signature,crypto_spi_ctx_template_t ctx_template,crypto_req_handle_t req)9855697Smcpowers ecc_verify_atomic(crypto_provider_handle_t provider,
9865697Smcpowers crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
9875697Smcpowers crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
9885697Smcpowers crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
9895697Smcpowers {
9905697Smcpowers int rv;
9915697Smcpowers ecc_mech_type_t mech_type = mechanism->cm_type;
9925697Smcpowers uchar_t *params;
9935697Smcpowers ssize_t params_len;
9945697Smcpowers ECParams *ecparams;
9955697Smcpowers SECKEYECParams params_item;
9965697Smcpowers int kmflag;
9975697Smcpowers
9985697Smcpowers if ((rv = check_mech_and_key(mech_type, key,
9995697Smcpowers CKO_PUBLIC_KEY)) != CRYPTO_SUCCESS)
10005697Smcpowers return (rv);
10015697Smcpowers
10027188Smcpowers if (crypto_get_key_attr(key, CKA_EC_PARAMS, (void *) ¶ms,
10035697Smcpowers ¶ms_len)) {
10045697Smcpowers return (CRYPTO_ARGUMENTS_BAD);
10055697Smcpowers }
10065697Smcpowers
10075697Smcpowers /* ASN1 check */
10085697Smcpowers if (params[0] != 0x06 ||
10095697Smcpowers params[1] != params_len - 2) {
10105697Smcpowers return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
10115697Smcpowers }
10125697Smcpowers params_item.data = params;
10135697Smcpowers params_item.len = (uint_t)params_len;
10145697Smcpowers kmflag = crypto_kmflag(req);
10155697Smcpowers if (EC_DecodeParams(¶ms_item, &ecparams, kmflag) != SECSuccess) {
10165697Smcpowers /* bad curve OID */
10175697Smcpowers return (CRYPTO_ARGUMENTS_BAD);
10185697Smcpowers }
10195697Smcpowers
10205697Smcpowers if (mechanism->cm_type == ECDSA_MECH_INFO_TYPE) {
10215697Smcpowers ecc_ctx_t ctx;
10225697Smcpowers
10235697Smcpowers ctx.mech_type = mech_type;
10245697Smcpowers /* structure assignment */
10255697Smcpowers ctx.ecparams = *ecparams;
10265697Smcpowers ctx.key = key;
10275697Smcpowers rv = ecc_verify_common(&ctx, data, signature, req);
10285697Smcpowers } else {
10295697Smcpowers digest_ecc_ctx_t dctx;
10305697Smcpowers
10315697Smcpowers dctx.mech_type = mech_type;
10325697Smcpowers /* structure assignment */
10335697Smcpowers dctx.ecparams = *ecparams;
10345697Smcpowers dctx.key = key;
10355697Smcpowers SHA1Init(&(dctx.sha1_ctx));
10365697Smcpowers
10375697Smcpowers rv = ecc_digest_svrfy_common(&dctx, data, signature,
10387188Smcpowers CRYPTO_DO_VERIFY | CRYPTO_DO_UPDATE | CRYPTO_DO_FINAL, req);
10395697Smcpowers }
10405697Smcpowers free_ecparams(ecparams, B_TRUE);
10415697Smcpowers return (rv);
10425697Smcpowers }
10435697Smcpowers
10445697Smcpowers /* ARGSUSED */
10455697Smcpowers static int
ecc_nostore_key_generate_pair(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_object_attribute_t * pub_template,uint_t pub_attribute_count,crypto_object_attribute_t * pri_template,uint_t pri_attribute_count,crypto_object_attribute_t * pub_out_template,uint_t pub_out_attribute_count,crypto_object_attribute_t * pri_out_template,uint_t pri_out_attribute_count,crypto_req_handle_t req)10465697Smcpowers ecc_nostore_key_generate_pair(crypto_provider_handle_t provider,
10475697Smcpowers crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
10485697Smcpowers crypto_object_attribute_t *pub_template, uint_t pub_attribute_count,
10495697Smcpowers crypto_object_attribute_t *pri_template, uint_t pri_attribute_count,
10505697Smcpowers crypto_object_attribute_t *pub_out_template, uint_t pub_out_attribute_count,
10515697Smcpowers crypto_object_attribute_t *pri_out_template, uint_t pri_out_attribute_count,
10525697Smcpowers crypto_req_handle_t req)
10535697Smcpowers {
10545697Smcpowers int rv = CRYPTO_SUCCESS;
10555697Smcpowers ECPrivateKey *privKey; /* contains both public and private values */
10565697Smcpowers ECParams *ecparams;
10575697Smcpowers SECKEYECParams params_item;
10585697Smcpowers ulong_t pub_key_type = ~0UL, pub_class = ~0UL;
10595697Smcpowers ulong_t pri_key_type = ~0UL, pri_class = ~0UL;
10605697Smcpowers int params_idx, value_idx, point_idx;
10615697Smcpowers uchar_t *params = NULL;
10625697Smcpowers unsigned params_len;
10635697Smcpowers uchar_t *value = NULL;
10645697Smcpowers uchar_t *point = NULL;
10655697Smcpowers int valuelen;
10665697Smcpowers int pointlen;
10675697Smcpowers int xylen;
10685697Smcpowers int kmflag;
10695697Smcpowers
10705697Smcpowers if (mechanism->cm_type != EC_KEY_PAIR_GEN_MECH_INFO_TYPE) {
10715697Smcpowers return (CRYPTO_MECHANISM_INVALID);
10725697Smcpowers }
10735697Smcpowers
10745697Smcpowers /* optional */
10755697Smcpowers (void) get_template_attr_ulong(pub_template,
10765697Smcpowers pub_attribute_count, CKA_CLASS, &pub_class);
10775697Smcpowers
10785697Smcpowers /* optional */
10795697Smcpowers (void) get_template_attr_ulong(pri_template,
10805697Smcpowers pri_attribute_count, CKA_CLASS, &pri_class);
10815697Smcpowers
10825697Smcpowers /* optional */
10835697Smcpowers (void) get_template_attr_ulong(pub_template,
10845697Smcpowers pub_attribute_count, CKA_KEY_TYPE, &pub_key_type);
10855697Smcpowers
10865697Smcpowers /* optional */
10875697Smcpowers (void) get_template_attr_ulong(pri_template,
10885697Smcpowers pri_attribute_count, CKA_KEY_TYPE, &pri_key_type);
10895697Smcpowers
10905697Smcpowers if (pub_class != ~0UL && pub_class != CKO_PUBLIC_KEY) {
10915697Smcpowers return (CRYPTO_TEMPLATE_INCONSISTENT);
10925697Smcpowers }
10935697Smcpowers pub_class = CKO_PUBLIC_KEY;
10945697Smcpowers
10955697Smcpowers if (pri_class != ~0UL && pri_class != CKO_PRIVATE_KEY) {
10965697Smcpowers return (CRYPTO_TEMPLATE_INCONSISTENT);
10975697Smcpowers }
10985697Smcpowers pri_class = CKO_PRIVATE_KEY;
10995697Smcpowers
11005697Smcpowers if (pub_key_type != ~0UL && pub_key_type != CKK_EC) {
11015697Smcpowers return (CRYPTO_TEMPLATE_INCONSISTENT);
11025697Smcpowers }
11035697Smcpowers pub_key_type = CKK_EC;
11045697Smcpowers
11055697Smcpowers if (pri_key_type != ~0UL && pri_key_type != CKK_EC) {
11065697Smcpowers return (CRYPTO_TEMPLATE_INCONSISTENT);
11075697Smcpowers }
11085697Smcpowers pri_key_type = CKK_EC;
11095697Smcpowers
11105697Smcpowers /* public output template must contain CKA_EC_POINT attribute */
11115697Smcpowers if ((point_idx = find_attr(pub_out_template, pub_out_attribute_count,
11125697Smcpowers CKA_EC_POINT)) == -1) {
11135697Smcpowers return (CRYPTO_TEMPLATE_INCOMPLETE);
11145697Smcpowers }
11155697Smcpowers
11165697Smcpowers /* private output template must contain CKA_VALUE attribute */
11175697Smcpowers if ((value_idx = find_attr(pri_out_template, pri_out_attribute_count,
11185697Smcpowers CKA_VALUE)) == -1) {
11195697Smcpowers return (CRYPTO_TEMPLATE_INCOMPLETE);
11205697Smcpowers }
11215697Smcpowers
11225697Smcpowers if ((params_idx = find_attr(pub_template, pub_attribute_count,
11235697Smcpowers CKA_EC_PARAMS)) == -1) {
11245697Smcpowers return (CRYPTO_TEMPLATE_INCOMPLETE);
11255697Smcpowers }
11265697Smcpowers
11275697Smcpowers params = (uchar_t *)pub_template[params_idx].oa_value;
11285697Smcpowers params_len = pub_template[params_idx].oa_value_len;
11295697Smcpowers
11305697Smcpowers value = (uchar_t *)pri_out_template[value_idx].oa_value;
11315697Smcpowers valuelen = (int)pri_out_template[value_idx].oa_value_len;
11325697Smcpowers point = (uchar_t *)pub_out_template[point_idx].oa_value;
11335697Smcpowers pointlen = (int)pub_out_template[point_idx].oa_value_len;
11345697Smcpowers
11355697Smcpowers /* ASN1 check */
11365697Smcpowers if (params[0] != 0x06 ||
11375697Smcpowers params[1] != params_len - 2) {
11385697Smcpowers return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
11395697Smcpowers }
11405697Smcpowers params_item.data = params;
11415697Smcpowers params_item.len = params_len;
11425697Smcpowers kmflag = crypto_kmflag(req);
11435697Smcpowers if (EC_DecodeParams(¶ms_item, &ecparams, kmflag) != SECSuccess) {
11445697Smcpowers /* bad curve OID */
11455697Smcpowers return (CRYPTO_ARGUMENTS_BAD);
11465697Smcpowers }
11475697Smcpowers
11485697Smcpowers if (EC_NewKey(ecparams, &privKey, kmflag) != SECSuccess) {
11495697Smcpowers free_ecparams(ecparams, B_TRUE);
11505697Smcpowers return (CRYPTO_FAILED);
11515697Smcpowers }
11525697Smcpowers
11535697Smcpowers xylen = privKey->publicValue.len;
11545697Smcpowers /* ASSERT that xylen - 1 is divisible by 2 */
11555697Smcpowers if (xylen > pointlen) {
11565697Smcpowers rv = CRYPTO_BUFFER_TOO_SMALL;
11575697Smcpowers goto out;
11585697Smcpowers }
11595697Smcpowers
11605697Smcpowers if (privKey->privateValue.len > valuelen) {
11615697Smcpowers rv = CRYPTO_BUFFER_TOO_SMALL;
11625697Smcpowers goto out;
11635697Smcpowers }
11645697Smcpowers bcopy(privKey->privateValue.data, value, privKey->privateValue.len);
11655697Smcpowers pri_out_template[value_idx].oa_value_len = privKey->privateValue.len;
11665697Smcpowers
11675697Smcpowers bcopy(privKey->publicValue.data, point, xylen);
11685697Smcpowers pub_out_template[point_idx].oa_value_len = xylen;
11695697Smcpowers
117010732SAnthony.Scarpino@Sun.COM if (kcf_get_fips140_mode() == FIPS140_MODE_ENABLED) {
117110500SHai-May.Chao@Sun.COM /* Pair-wise consistency test */
117210500SHai-May.Chao@Sun.COM if ((rv = fips_pairwise_check(privKey)) != CRYPTO_SUCCESS)
117310500SHai-May.Chao@Sun.COM cmn_err(CE_WARN, "ecc: fips_pairwise_check() "
117410500SHai-May.Chao@Sun.COM "failed (0x%x).", rv);
117510500SHai-May.Chao@Sun.COM }
117610500SHai-May.Chao@Sun.COM
11775697Smcpowers out:
11785697Smcpowers free_ecprivkey(privKey);
11795697Smcpowers free_ecparams(ecparams, B_TRUE);
11805697Smcpowers return (rv);
11815697Smcpowers }
11825697Smcpowers
11835697Smcpowers /* ARGSUSED */
11845697Smcpowers static int
ecc_nostore_key_derive(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * base_key,crypto_object_attribute_t * in_attrs,uint_t in_attr_count,crypto_object_attribute_t * out_attrs,uint_t out_attr_count,crypto_req_handle_t req)11855697Smcpowers ecc_nostore_key_derive(crypto_provider_handle_t provider,
11865697Smcpowers crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
11875697Smcpowers crypto_key_t *base_key, crypto_object_attribute_t *in_attrs,
11885697Smcpowers uint_t in_attr_count, crypto_object_attribute_t *out_attrs,
11895697Smcpowers uint_t out_attr_count, crypto_req_handle_t req)
11905697Smcpowers {
11915697Smcpowers int rv = CRYPTO_SUCCESS;
11925697Smcpowers int params_idx, value_idx = -1, out_value_idx = -1;
11935697Smcpowers ulong_t key_type;
11945697Smcpowers ulong_t key_len;
11955697Smcpowers crypto_object_attribute_t *attrs;
11965697Smcpowers ECParams *ecparams;
11975697Smcpowers SECKEYECParams params_item;
11985697Smcpowers CK_ECDH1_DERIVE_PARAMS *mech_param;
11995697Smcpowers SECItem public_value_item, private_value_item, secret_item;
12005697Smcpowers int kmflag;
12015697Smcpowers
12025697Smcpowers if (mechanism->cm_type != ECDH1_DERIVE_MECH_INFO_TYPE) {
12035697Smcpowers return (CRYPTO_MECHANISM_INVALID);
12045697Smcpowers }
12055697Smcpowers
12065697Smcpowers ASSERT(IS_P2ALIGNED(mechanism->cm_param, sizeof (uint64_t)));
12075697Smcpowers /* LINTED: pointer alignment */
12085697Smcpowers mech_param = (CK_ECDH1_DERIVE_PARAMS *)mechanism->cm_param;
12095697Smcpowers if (mech_param->kdf != CKD_NULL) {
12105697Smcpowers return (CRYPTO_MECHANISM_PARAM_INVALID);
12115697Smcpowers }
12125697Smcpowers
12135697Smcpowers if ((base_key->ck_format != CRYPTO_KEY_ATTR_LIST) ||
12145697Smcpowers (base_key->ck_count == 0)) {
12155697Smcpowers return (CRYPTO_ARGUMENTS_BAD);
12165697Smcpowers }
12175697Smcpowers
12185697Smcpowers if ((rv = get_template_attr_ulong(in_attrs, in_attr_count,
12195697Smcpowers CKA_KEY_TYPE, &key_type)) != CRYPTO_SUCCESS) {
12205697Smcpowers return (rv);
12215697Smcpowers }
12225697Smcpowers
12235697Smcpowers switch (key_type) {
12245697Smcpowers case CKK_DES:
12255697Smcpowers key_len = DES_KEYSIZE;
12265697Smcpowers break;
12275697Smcpowers case CKK_DES2:
12285697Smcpowers key_len = DES2_KEYSIZE;
12295697Smcpowers break;
12305697Smcpowers case CKK_DES3:
12315697Smcpowers key_len = DES3_KEYSIZE;
12325697Smcpowers break;
12335697Smcpowers case CKK_RC4:
12345697Smcpowers case CKK_AES:
12355697Smcpowers case CKK_GENERIC_SECRET:
12365697Smcpowers if ((rv = get_template_attr_ulong(in_attrs, in_attr_count,
12375697Smcpowers CKA_VALUE_LEN, &key_len)) != CRYPTO_SUCCESS) {
12385697Smcpowers return (rv);
12395697Smcpowers }
12405697Smcpowers break;
12415697Smcpowers default:
12425697Smcpowers key_len = 0;
12435697Smcpowers }
12445697Smcpowers
12455697Smcpowers attrs = base_key->ck_attrs;
12465697Smcpowers if ((value_idx = find_attr(attrs, base_key->ck_count,
12475697Smcpowers CKA_VALUE)) == -1) {
12485697Smcpowers return (CRYPTO_TEMPLATE_INCOMPLETE);
12495697Smcpowers }
12505697Smcpowers
12515697Smcpowers if ((params_idx = find_attr(attrs, base_key->ck_count,
12525697Smcpowers CKA_EC_PARAMS)) == -1) {
12535697Smcpowers return (CRYPTO_TEMPLATE_INCOMPLETE);
12545697Smcpowers }
12555697Smcpowers
12565697Smcpowers private_value_item.data = (uchar_t *)attrs[value_idx].oa_value;
12575697Smcpowers private_value_item.len = attrs[value_idx].oa_value_len;
12585697Smcpowers
12595697Smcpowers params_item.len = attrs[params_idx].oa_value_len;
12605697Smcpowers params_item.data = (uchar_t *)attrs[params_idx].oa_value;
12615697Smcpowers
12625697Smcpowers /* ASN1 check */
12635697Smcpowers if (params_item.data[0] != 0x06 ||
12645697Smcpowers params_item.data[1] != params_item.len - 2) {
12655697Smcpowers return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
12665697Smcpowers }
12675697Smcpowers kmflag = crypto_kmflag(req);
12685697Smcpowers if (EC_DecodeParams(¶ms_item, &ecparams, kmflag) != SECSuccess) {
12695697Smcpowers /* bad curve OID */
12705697Smcpowers return (CRYPTO_ARGUMENTS_BAD);
12715697Smcpowers }
12725697Smcpowers
12735697Smcpowers public_value_item.data = (uchar_t *)mech_param->pPublicData;
12745697Smcpowers public_value_item.len = mech_param->ulPublicDataLen;
12755697Smcpowers
12765697Smcpowers if ((out_value_idx = find_attr(out_attrs, out_attr_count,
12775697Smcpowers CKA_VALUE)) == -1) {
12785697Smcpowers rv = CRYPTO_TEMPLATE_INCOMPLETE;
12795697Smcpowers goto out;
12805697Smcpowers }
12815697Smcpowers secret_item.data = NULL;
12825697Smcpowers secret_item.len = 0;
12835697Smcpowers
12845697Smcpowers if (ECDH_Derive(&public_value_item, ecparams, &private_value_item,
12855697Smcpowers B_FALSE, &secret_item, kmflag) != SECSuccess) {
12865697Smcpowers free_ecparams(ecparams, B_TRUE);
12875697Smcpowers return (CRYPTO_FAILED);
12885697Smcpowers } else {
12895697Smcpowers rv = CRYPTO_SUCCESS;
12905697Smcpowers }
12915697Smcpowers
12925697Smcpowers if (key_len == 0)
12935697Smcpowers key_len = secret_item.len;
12945697Smcpowers
12955697Smcpowers if (key_len > secret_item.len) {
12965697Smcpowers rv = CRYPTO_ATTRIBUTE_VALUE_INVALID;
12975697Smcpowers goto out;
12985697Smcpowers }
12995697Smcpowers if (key_len > out_attrs[out_value_idx].oa_value_len) {
13005697Smcpowers rv = CRYPTO_BUFFER_TOO_SMALL;
13015697Smcpowers goto out;
13025697Smcpowers }
13035697Smcpowers bcopy(secret_item.data + secret_item.len - key_len,
13045697Smcpowers (uchar_t *)out_attrs[out_value_idx].oa_value, key_len);
13055697Smcpowers out_attrs[out_value_idx].oa_value_len = key_len;
13065697Smcpowers out:
13075697Smcpowers free_ecparams(ecparams, B_TRUE);
13085697Smcpowers SECITEM_FreeItem(&secret_item, B_FALSE);
13095697Smcpowers return (rv);
13105697Smcpowers }
13115697Smcpowers
13125697Smcpowers static void
free_ecparams(ECParams * params,boolean_t freeit)13135697Smcpowers free_ecparams(ECParams *params, boolean_t freeit)
13145697Smcpowers {
13155697Smcpowers SECITEM_FreeItem(¶ms->fieldID.u.prime, B_FALSE);
13165697Smcpowers SECITEM_FreeItem(¶ms->curve.a, B_FALSE);
13175697Smcpowers SECITEM_FreeItem(¶ms->curve.b, B_FALSE);
13185697Smcpowers SECITEM_FreeItem(¶ms->curve.seed, B_FALSE);
13195697Smcpowers SECITEM_FreeItem(¶ms->base, B_FALSE);
13205697Smcpowers SECITEM_FreeItem(¶ms->order, B_FALSE);
13215697Smcpowers SECITEM_FreeItem(¶ms->DEREncoding, B_FALSE);
13225697Smcpowers SECITEM_FreeItem(¶ms->curveOID, B_FALSE);
13235697Smcpowers if (freeit)
13245697Smcpowers kmem_free(params, sizeof (ECParams));
13255697Smcpowers }
13265697Smcpowers
13275697Smcpowers static void
free_ecprivkey(ECPrivateKey * key)13285697Smcpowers free_ecprivkey(ECPrivateKey *key)
13295697Smcpowers {
13305697Smcpowers free_ecparams(&key->ecParams, B_FALSE);
13315697Smcpowers SECITEM_FreeItem(&key->publicValue, B_FALSE);
13325697Smcpowers bzero(key->privateValue.data, key->privateValue.len);
13335697Smcpowers SECITEM_FreeItem(&key->privateValue, B_FALSE);
13345697Smcpowers SECITEM_FreeItem(&key->version, B_FALSE);
13355697Smcpowers kmem_free(key, sizeof (ECPrivateKey));
13365697Smcpowers }
133710500SHai-May.Chao@Sun.COM
133810500SHai-May.Chao@Sun.COM /*
133910500SHai-May.Chao@Sun.COM * Pair-wise Consistency Test
134010500SHai-May.Chao@Sun.COM */
134110500SHai-May.Chao@Sun.COM static int
fips_pairwise_check(ECPrivateKey * ecdsa_private_key)134210500SHai-May.Chao@Sun.COM fips_pairwise_check(ECPrivateKey *ecdsa_private_key)
134310500SHai-May.Chao@Sun.COM {
134410500SHai-May.Chao@Sun.COM
134510500SHai-May.Chao@Sun.COM SECItem signature_item;
134610500SHai-May.Chao@Sun.COM SECItem digest_item;
134710500SHai-May.Chao@Sun.COM uchar_t signed_data[EC_MAX_SIG_LEN];
134810500SHai-May.Chao@Sun.COM uchar_t sha1[SHA1_DIGEST_SIZE];
134910500SHai-May.Chao@Sun.COM ECPublicKey ecdsa_public_key;
135010500SHai-May.Chao@Sun.COM SHA1_CTX *sha1_context;
135110500SHai-May.Chao@Sun.COM int rv;
135210500SHai-May.Chao@Sun.COM static uint8_t msg[] = {
135310500SHai-May.Chao@Sun.COM "OpenSolarisCommunity"
135410500SHai-May.Chao@Sun.COM };
135510500SHai-May.Chao@Sun.COM
135610500SHai-May.Chao@Sun.COM /* construct public key from private key. */
135710500SHai-May.Chao@Sun.COM if ((EC_CopyParams(ecdsa_private_key->ecParams.arena,
135810500SHai-May.Chao@Sun.COM &ecdsa_public_key.ecParams, &ecdsa_private_key->ecParams))
135910500SHai-May.Chao@Sun.COM != SECSuccess)
136010500SHai-May.Chao@Sun.COM return (CRYPTO_FAILED);
136110500SHai-May.Chao@Sun.COM
136210500SHai-May.Chao@Sun.COM ecdsa_public_key.publicValue = ecdsa_private_key->publicValue;
136310500SHai-May.Chao@Sun.COM
136410500SHai-May.Chao@Sun.COM if ((sha1_context = kmem_zalloc(sizeof (SHA1_CTX),
136510500SHai-May.Chao@Sun.COM KM_SLEEP)) == NULL)
136610500SHai-May.Chao@Sun.COM return (CRYPTO_HOST_MEMORY);
136710500SHai-May.Chao@Sun.COM
136810500SHai-May.Chao@Sun.COM SHA1Init(sha1_context);
136910500SHai-May.Chao@Sun.COM SHA1Update(sha1_context, msg, SHA1_DIGEST_SIZE);
137010500SHai-May.Chao@Sun.COM SHA1Final(sha1, sha1_context);
137110500SHai-May.Chao@Sun.COM
137210500SHai-May.Chao@Sun.COM digest_item.data = sha1;
137310500SHai-May.Chao@Sun.COM digest_item.len = SHA1_DIGEST_SIZE;
137410500SHai-May.Chao@Sun.COM signature_item.data = signed_data;
137510500SHai-May.Chao@Sun.COM signature_item.len = sizeof (signed_data);
137610500SHai-May.Chao@Sun.COM
137710500SHai-May.Chao@Sun.COM if ((ECDSA_SignDigest(ecdsa_private_key, &signature_item,
137810500SHai-May.Chao@Sun.COM &digest_item, 0)) != SECSuccess) {
137910500SHai-May.Chao@Sun.COM rv = CRYPTO_FAILED;
138010500SHai-May.Chao@Sun.COM goto loser;
138110500SHai-May.Chao@Sun.COM }
138210500SHai-May.Chao@Sun.COM
138310500SHai-May.Chao@Sun.COM if (ECDSA_VerifyDigest(&ecdsa_public_key, &signature_item,
138410500SHai-May.Chao@Sun.COM &digest_item, 0) != SECSuccess) {
138510500SHai-May.Chao@Sun.COM rv = CRYPTO_SIGNATURE_INVALID;
138610500SHai-May.Chao@Sun.COM } else {
138710500SHai-May.Chao@Sun.COM rv = CRYPTO_SUCCESS;
138810500SHai-May.Chao@Sun.COM }
138910500SHai-May.Chao@Sun.COM
139010500SHai-May.Chao@Sun.COM loser:
139110500SHai-May.Chao@Sun.COM kmem_free(sha1_context, sizeof (SHA1_CTX));
139210500SHai-May.Chao@Sun.COM return (rv);
139310500SHai-May.Chao@Sun.COM
139410500SHai-May.Chao@Sun.COM }
139510500SHai-May.Chao@Sun.COM
139610500SHai-May.Chao@Sun.COM
139710500SHai-May.Chao@Sun.COM /*
139810500SHai-May.Chao@Sun.COM * ECC Power-Up Self-Test
139910500SHai-May.Chao@Sun.COM */
140010500SHai-May.Chao@Sun.COM void
ecc_POST(int * rc)140110500SHai-May.Chao@Sun.COM ecc_POST(int *rc)
140210500SHai-May.Chao@Sun.COM {
140310500SHai-May.Chao@Sun.COM
140410500SHai-May.Chao@Sun.COM *rc = fips_ecdsa_post();
140510500SHai-May.Chao@Sun.COM
140610500SHai-May.Chao@Sun.COM }
1407