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