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