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