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