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