xref: /illumos-gate/usr/src/uts/common/crypto/io/ecc.c (revision bea83d026ee1bd1b2a2419e1d0232f107a5d7d9b)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.h>
29 #include <sys/systm.h>
30 #include <sys/param.h>
31 #include <sys/modctl.h>
32 #include <sys/ddi.h>
33 #include <sys/crypto/spi.h>
34 #include <sys/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_impl.h"
46 #include "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 int
235 _init(void)
236 {
237 	int ret;
238 
239 	/*
240 	 * Register with KCF. If the registration fails, return error.
241 	 */
242 	if ((ret = crypto_register_provider(&ecc_prov_info,
243 	    &ecc_prov_handle)) != CRYPTO_SUCCESS) {
244 		cmn_err(CE_WARN, "ecc _init: crypto_register_provider()"
245 		    "failed (0x%x)", ret);
246 		return (EACCES);
247 	}
248 
249 	if ((ret = mod_install(&modlinkage)) != 0) {
250 		int rv;
251 
252 		ASSERT(ecc_prov_handle != NULL);
253 		/* We should not return if the unregister returns busy. */
254 		while ((rv = crypto_unregister_provider(ecc_prov_handle))
255 		    == CRYPTO_BUSY) {
256 			cmn_err(CE_WARN, "ecc _init: "
257 			    "crypto_unregister_provider() "
258 			    "failed (0x%x). Retrying.", rv);
259 			/* wait 10 seconds and try again. */
260 			delay(10 * drv_usectohz(1000000));
261 		}
262 	}
263 
264 	return (ret);
265 }
266 
267 int
268 _fini(void)
269 {
270 	int ret;
271 
272 	/*
273 	 * Unregister from KCF if previous registration succeeded.
274 	 */
275 	if (ecc_prov_handle != NULL) {
276 		if ((ret = crypto_unregister_provider(ecc_prov_handle)) !=
277 		    CRYPTO_SUCCESS) {
278 			cmn_err(CE_WARN, "ecc _fini: "
279 			    "crypto_unregister_provider() "
280 			    "failed (0x%x)", ret);
281 			return (EBUSY);
282 		}
283 		ecc_prov_handle = NULL;
284 	}
285 
286 	return (mod_remove(&modlinkage));
287 }
288 
289 int
290 _info(struct modinfo *modinfop)
291 {
292 	return (mod_info(&modlinkage, modinfop));
293 }
294 
295 /* ARGSUSED */
296 static void
297 ecc_provider_status(crypto_provider_handle_t provider, uint_t *status)
298 {
299 	*status = CRYPTO_PROVIDER_READY;
300 }
301 
302 /*
303  * Utility routine to look up a attribute of type, 'type',
304  * in the key.
305  */
306 static int
307 get_key_attr(crypto_key_t *key, crypto_attr_type_t type,
308     uchar_t **value, ssize_t *value_len)
309 {
310 	int i;
311 
312 	ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
313 	for (i = 0; i < key->ck_count; i++) {
314 		if (key->ck_attrs[i].oa_type == type) {
315 			*value = (uchar_t *)key->ck_attrs[i].oa_value;
316 			*value_len = key->ck_attrs[i].oa_value_len;
317 			return (CRYPTO_SUCCESS);
318 		}
319 	}
320 
321 	return (CRYPTO_FAILED);
322 }
323 
324 /*
325  * Return the index of an attribute of specified type found in
326  * the specified array of attributes. If the attribute cannot
327  * found, return -1.
328  */
329 static int
330 find_attr(crypto_object_attribute_t *attr, uint_t nattr, uint64_t attr_type)
331 {
332 	int i;
333 
334 	for (i = 0; i < nattr; i++)
335 		if (attr[i].oa_value != NULL && attr[i].oa_type == attr_type)
336 			return (i);
337 	return (-1);
338 }
339 
340 /*
341  * Common function used by the get_template_attr_*() family of
342  * functions. Returns the value of the specified attribute of specified
343  * length. Returns CRYPTO_SUCCESS on success, CRYPTO_ATTRIBUTE_VALUE_INVALID
344  * if the length of the attribute does not match the specified length,
345  * or CRYPTO_ARGUMENTS_BAD if the attribute cannot be found.
346  */
347 static int
348 get_template_attr_scalar_common(crypto_object_attribute_t *template,
349     uint_t nattr, uint64_t attr_type, void *value, size_t value_len)
350 {
351 	size_t oa_value_len;
352 	size_t offset = 0;
353 	int attr_idx;
354 
355 	if ((attr_idx = find_attr(template, nattr, attr_type)) == -1)
356 		return (CRYPTO_ARGUMENTS_BAD);
357 
358 	oa_value_len = template[attr_idx].oa_value_len;
359 	if (oa_value_len != value_len) {
360 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
361 	}
362 
363 do_copy:
364 	bcopy(template[attr_idx].oa_value, (uchar_t *)value + offset,
365 	    oa_value_len);
366 
367 	return (CRYPTO_SUCCESS);
368 }
369 
370 /*
371  * Get the value of a ulong_t attribute from the specified template.
372  */
373 static int
374 get_template_attr_ulong(crypto_object_attribute_t *template,
375     uint_t nattr, uint64_t attr_type, ulong_t *attr_value)
376 {
377 	return (get_template_attr_scalar_common(template, nattr,
378 	    attr_type, attr_value, sizeof (ulong_t)));
379 }
380 
381 /*
382  * Called from init routines to do basic sanity checks. Init routines,
383  * e.g. sign_init should fail rather than subsequent operations.
384  */
385 static int
386 check_mech_and_key(ecc_mech_type_t mech_type, crypto_key_t *key, ulong_t class)
387 {
388 	int rv = CRYPTO_SUCCESS;
389 	uchar_t *foo;
390 	ssize_t point_len;
391 	ssize_t value_len;
392 
393 	if (mech_type != ECDSA_SHA1_MECH_INFO_TYPE &&
394 	    mech_type != ECDSA_MECH_INFO_TYPE)
395 		return (CRYPTO_MECHANISM_INVALID);
396 
397 	if (key->ck_format != CRYPTO_KEY_ATTR_LIST) {
398 		return (CRYPTO_KEY_TYPE_INCONSISTENT);
399 	}
400 
401 	switch (class) {
402 	case CKO_PUBLIC_KEY:
403 		if ((rv = get_key_attr(key, CKA_EC_POINT, &foo, &point_len))
404 		    != CRYPTO_SUCCESS) {
405 			return (CRYPTO_TEMPLATE_INCOMPLETE);
406 		}
407 		if (point_len < CRYPTO_BITS2BYTES(EC_MIN_KEY_LEN) * 2 + 1 ||
408 		    point_len > CRYPTO_BITS2BYTES(EC_MAX_KEY_LEN) * 2 + 1)
409 			return (CRYPTO_KEY_SIZE_RANGE);
410 		break;
411 
412 	case CKO_PRIVATE_KEY:
413 		if ((rv = get_key_attr(key, CKA_VALUE, &foo, &value_len))
414 		    != CRYPTO_SUCCESS) {
415 			return (CRYPTO_TEMPLATE_INCOMPLETE);
416 		}
417 		if (value_len < CRYPTO_BITS2BYTES(EC_MIN_KEY_LEN) ||
418 		    value_len > CRYPTO_BITS2BYTES(EC_MAX_KEY_LEN))
419 			return (CRYPTO_KEY_SIZE_RANGE);
420 		break;
421 
422 	default:
423 		return (CRYPTO_TEMPLATE_INCONSISTENT);
424 	}
425 
426 	return (rv);
427 }
428 
429 /*
430  * This function guarantees to return non-zero random numbers.
431  * This is needed as the /dev/urandom kernel interface,
432  * random_get_pseudo_bytes(), may return zeros.
433  */
434 int
435 ecc_knzero_random_generator(uint8_t *ran_out, size_t ran_len)
436 {
437 	int rv;
438 	size_t ebc = 0; /* count of extra bytes in extrarand */
439 	size_t i = 0;
440 	uint8_t extrarand[32];
441 	size_t extrarand_len;
442 
443 	if ((rv = random_get_pseudo_bytes(ran_out, ran_len)) != 0)
444 		return (rv);
445 
446 	/*
447 	 * Walk through the returned random numbers pointed by ran_out,
448 	 * and look for any random number which is zero.
449 	 * If we find zero, call random_get_pseudo_bytes() to generate
450 	 * another 32 random numbers pool. Replace any zeros in ran_out[]
451 	 * from the random number in pool.
452 	 */
453 	while (i < ran_len) {
454 		if (ran_out[i] != 0) {
455 			i++;
456 			continue;
457 		}
458 
459 		/*
460 		 * Note that it is 'while' so we are guaranteed a
461 		 * non-zero value on exit.
462 		 */
463 		if (ebc == 0) {
464 			/* refresh extrarand */
465 			extrarand_len = sizeof (extrarand);
466 			if ((rv = random_get_pseudo_bytes(extrarand,
467 			    extrarand_len)) != 0) {
468 				return (rv);
469 			}
470 
471 			ebc = extrarand_len;
472 		}
473 		/* Replace zero with byte from extrarand. */
474 		-- ebc;
475 
476 		/*
477 		 * The new random byte zero/non-zero will be checked in
478 		 * the next pass through the loop.
479 		 */
480 		ran_out[i] = extrarand[ebc];
481 	}
482 
483 	return (CRYPTO_SUCCESS);
484 }
485 
486 typedef enum cmd_type {
487 	COPY_FROM_DATA,
488 	COPY_TO_DATA,
489 	COMPARE_TO_DATA,
490 	SHA1_DIGEST_DATA
491 } cmd_type_t;
492 
493 /*
494  * Utility routine to apply the command, 'cmd', to the
495  * data in the uio structure.
496  */
497 static int
498 process_uio_data(crypto_data_t *data, uchar_t *buf, int len,
499     cmd_type_t cmd, void *digest_ctx)
500 {
501 	uio_t *uiop = data->cd_uio;
502 	off_t offset = data->cd_offset;
503 	size_t length = len;
504 	uint_t vec_idx;
505 	size_t cur_len;
506 	uchar_t *datap;
507 
508 	ASSERT(data->cd_format == CRYPTO_DATA_UIO);
509 	if (uiop->uio_segflg != UIO_SYSSPACE) {
510 		return (CRYPTO_ARGUMENTS_BAD);
511 	}
512 
513 	/*
514 	 * Jump to the first iovec containing data to be
515 	 * processed.
516 	 */
517 	for (vec_idx = 0; vec_idx < uiop->uio_iovcnt &&
518 	    offset >= uiop->uio_iov[vec_idx].iov_len;
519 	    offset -= uiop->uio_iov[vec_idx++].iov_len)
520 		;
521 
522 	if (vec_idx == uiop->uio_iovcnt) {
523 		/*
524 		 * The caller specified an offset that is larger than
525 		 * the total size of the buffers it provided.
526 		 */
527 		return (CRYPTO_DATA_LEN_RANGE);
528 	}
529 
530 	while (vec_idx < uiop->uio_iovcnt && length > 0) {
531 		cur_len = MIN(uiop->uio_iov[vec_idx].iov_len -
532 		    offset, length);
533 
534 		datap = (uchar_t *)(uiop->uio_iov[vec_idx].iov_base +
535 		    offset);
536 		switch (cmd) {
537 		case COPY_FROM_DATA:
538 			bcopy(datap, buf, cur_len);
539 			buf += cur_len;
540 			break;
541 		case COPY_TO_DATA:
542 			bcopy(buf, datap, cur_len);
543 			buf += cur_len;
544 			break;
545 		case COMPARE_TO_DATA:
546 			if (bcmp(datap, buf, cur_len))
547 				return (CRYPTO_SIGNATURE_INVALID);
548 			buf += cur_len;
549 			break;
550 		case SHA1_DIGEST_DATA:
551 			SHA1Update(digest_ctx, datap, cur_len);
552 			break;
553 		}
554 
555 		length -= cur_len;
556 		vec_idx++;
557 		offset = 0;
558 	}
559 
560 	if (vec_idx == uiop->uio_iovcnt && length > 0) {
561 		/*
562 		 * The end of the specified iovec's was reached but
563 		 * the length requested could not be processed.
564 		 */
565 		switch (cmd) {
566 		case COPY_TO_DATA:
567 			data->cd_length = len;
568 			return (CRYPTO_BUFFER_TOO_SMALL);
569 		default:
570 			return (CRYPTO_DATA_LEN_RANGE);
571 		}
572 	}
573 
574 	return (CRYPTO_SUCCESS);
575 }
576 
577 /*
578  * Utility routine to apply the command, 'cmd', to the
579  * data in the mblk structure.
580  */
581 static int
582 process_mblk_data(crypto_data_t *data, uchar_t *buf, int len,
583     cmd_type_t cmd, void *digest_ctx)
584 {
585 	off_t offset = data->cd_offset;
586 	size_t length = len;
587 	mblk_t *mp;
588 	size_t cur_len;
589 	uchar_t *datap;
590 
591 	ASSERT(data->cd_format == CRYPTO_DATA_MBLK);
592 	/*
593 	 * Jump to the first mblk_t containing data to be processed.
594 	 */
595 	for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp);
596 	    offset -= MBLKL(mp), mp = mp->b_cont)
597 		;
598 	if (mp == NULL) {
599 		/*
600 		 * The caller specified an offset that is larger
601 		 * than the total size of the buffers it provided.
602 		 */
603 		return (CRYPTO_DATA_LEN_RANGE);
604 	}
605 
606 	/*
607 	 * Now do the processing on the mblk chain.
608 	 */
609 	while (mp != NULL && length > 0) {
610 		cur_len = MIN(MBLKL(mp) - offset, length);
611 
612 		datap = (uchar_t *)(mp->b_rptr + offset);
613 		switch (cmd) {
614 		case COPY_FROM_DATA:
615 			bcopy(datap, buf, cur_len);
616 			buf += cur_len;
617 			break;
618 		case COPY_TO_DATA:
619 			bcopy(buf, datap, cur_len);
620 			buf += cur_len;
621 			break;
622 		case COMPARE_TO_DATA:
623 			if (bcmp(datap, buf, cur_len))
624 				return (CRYPTO_SIGNATURE_INVALID);
625 			buf += cur_len;
626 			break;
627 		case SHA1_DIGEST_DATA:
628 			SHA1Update(digest_ctx, datap, cur_len);
629 			break;
630 		}
631 
632 		length -= cur_len;
633 		offset = 0;
634 		mp = mp->b_cont;
635 	}
636 
637 	if (mp == NULL && length > 0) {
638 		/*
639 		 * The end of the mblk was reached but the length
640 		 * requested could not be processed.
641 		 */
642 		switch (cmd) {
643 		case COPY_TO_DATA:
644 			data->cd_length = len;
645 			return (CRYPTO_BUFFER_TOO_SMALL);
646 		default:
647 			return (CRYPTO_DATA_LEN_RANGE);
648 		}
649 	}
650 
651 	return (CRYPTO_SUCCESS);
652 }
653 
654 /*
655  * Utility routine to copy a buffer to a crypto_data structure.
656  */
657 static int
658 put_output_data(uchar_t *buf, crypto_data_t *output, int len)
659 {
660 	switch (output->cd_format) {
661 	case CRYPTO_DATA_RAW:
662 		if (output->cd_raw.iov_len < len) {
663 			output->cd_length = len;
664 			return (CRYPTO_BUFFER_TOO_SMALL);
665 		}
666 		bcopy(buf, (uchar_t *)(output->cd_raw.iov_base +
667 		    output->cd_offset), len);
668 		break;
669 
670 	case CRYPTO_DATA_UIO:
671 		return (process_uio_data(output, buf, len, COPY_TO_DATA, NULL));
672 
673 	case CRYPTO_DATA_MBLK:
674 		return (process_mblk_data(output, buf, len,
675 		    COPY_TO_DATA, NULL));
676 
677 	default:
678 		return (CRYPTO_ARGUMENTS_BAD);
679 	}
680 
681 	return (CRYPTO_SUCCESS);
682 }
683 
684 /*
685  * Utility routine to get data from a crypto_data structure.
686  *
687  * '*dptr' contains a pointer to a buffer on return. 'buf'
688  * is allocated by the caller and is ignored for CRYPTO_DATA_RAW case.
689  */
690 static int
691 get_input_data(crypto_data_t *input, uchar_t **dptr, uchar_t *buf)
692 {
693 	int rv;
694 
695 	switch (input->cd_format) {
696 	case CRYPTO_DATA_RAW:
697 		if (input->cd_raw.iov_len < input->cd_length)
698 			return (CRYPTO_ARGUMENTS_BAD);
699 		*dptr = (uchar_t *)(input->cd_raw.iov_base +
700 		    input->cd_offset);
701 		break;
702 
703 	case CRYPTO_DATA_UIO:
704 		if ((rv = process_uio_data(input, buf, input->cd_length,
705 		    COPY_FROM_DATA, NULL)) != CRYPTO_SUCCESS)
706 			return (rv);
707 		*dptr = buf;
708 		break;
709 
710 	case CRYPTO_DATA_MBLK:
711 		if ((rv = process_mblk_data(input, buf, input->cd_length,
712 		    COPY_FROM_DATA, NULL)) != CRYPTO_SUCCESS)
713 			return (rv);
714 		*dptr = buf;
715 		break;
716 
717 	default:
718 		return (CRYPTO_ARGUMENTS_BAD);
719 	}
720 
721 	return (CRYPTO_SUCCESS);
722 }
723 
724 static int
725 copy_key_to_ctx(crypto_key_t *in_key, ecc_ctx_t *ctx, int kmflag)
726 {
727 	int i, count;
728 	size_t len;
729 	caddr_t attr_val;
730 	crypto_object_attribute_t *k_attrs = NULL;
731 
732 	ASSERT(in_key->ck_format == CRYPTO_KEY_ATTR_LIST);
733 
734 	count = in_key->ck_count;
735 	/* figure out how much memory to allocate for everything */
736 	len = sizeof (crypto_key_t) +
737 	    count * sizeof (crypto_object_attribute_t);
738 	for (i = 0; i < count; i++) {
739 		len += roundup(in_key->ck_attrs[i].oa_value_len,
740 		    sizeof (caddr_t));
741 	}
742 
743 	/* one big allocation for everything */
744 	ctx->key = kmem_alloc(len, kmflag);
745 	if (ctx->key == NULL)
746 		return (CRYPTO_HOST_MEMORY);
747 	/* LINTED: pointer alignment */
748 	k_attrs = (crypto_object_attribute_t *)((caddr_t)(ctx->key) +
749 	    sizeof (crypto_key_t));
750 
751 	attr_val = (caddr_t)k_attrs +
752 	    count * sizeof (crypto_object_attribute_t);
753 	for (i = 0; i < count; i++) {
754 		k_attrs[i].oa_type = in_key->ck_attrs[i].oa_type;
755 		bcopy(in_key->ck_attrs[i].oa_value, attr_val,
756 		    in_key->ck_attrs[i].oa_value_len);
757 		k_attrs[i].oa_value = attr_val;
758 		k_attrs[i].oa_value_len = in_key->ck_attrs[i].oa_value_len;
759 		attr_val += roundup(k_attrs[i].oa_value_len, sizeof (caddr_t));
760 	}
761 
762 	ctx->keychunk_size = len;	/* save the size to be freed */
763 	ctx->key->ck_format = CRYPTO_KEY_ATTR_LIST;
764 	ctx->key->ck_count = count;
765 	ctx->key->ck_attrs = k_attrs;
766 
767 	return (CRYPTO_SUCCESS);
768 }
769 
770 static void
771 ecc_free_context(crypto_ctx_t *ctx)
772 {
773 	ecc_ctx_t *ctxp = ctx->cc_provider_private;
774 
775 	if (ctxp != NULL) {
776 		bzero(ctxp->key, ctxp->keychunk_size);
777 		kmem_free(ctxp->key, ctxp->keychunk_size);
778 
779 		free_ecparams(&ctxp->ecparams, B_FALSE);
780 
781 		if (ctxp->mech_type == ECDSA_MECH_INFO_TYPE)
782 			kmem_free(ctxp, sizeof (ecc_ctx_t));
783 		else
784 			kmem_free(ctxp, sizeof (digest_ecc_ctx_t));
785 
786 		ctx->cc_provider_private = NULL;
787 	}
788 }
789 
790 /* ARGSUSED */
791 static int
792 ecc_sign_verify_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
793     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
794     crypto_req_handle_t req)
795 {
796 	int rv;
797 	int kmflag;
798 	ecc_ctx_t *ctxp;
799 	digest_ecc_ctx_t *dctxp;
800 	ecc_mech_type_t mech_type = mechanism->cm_type;
801 	uchar_t *params;
802 	ssize_t params_len;
803 	ECParams  *ecparams;
804 	SECKEYECParams params_item;
805 
806 	if (get_key_attr(key, CKA_EC_PARAMS, (void *) &params,
807 	    &params_len)) {
808 		return (CRYPTO_ARGUMENTS_BAD);
809 	}
810 
811 	/* ASN1 check */
812 	if (params[0] != 0x06 ||
813 	    params[1] != params_len - 2) {
814 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
815 	}
816 	params_item.data = params;
817 	params_item.len = (uint_t)params_len;
818 	kmflag = crypto_kmflag(req);
819 	if (EC_DecodeParams(&params_item, &ecparams, kmflag) != SECSuccess) {
820 		/* bad curve OID */
821 		return (CRYPTO_ARGUMENTS_BAD);
822 	}
823 
824 	/*
825 	 * Allocate an ECC context.
826 	 */
827 	switch (mech_type) {
828 	case ECDSA_SHA1_MECH_INFO_TYPE:
829 		dctxp = kmem_zalloc(sizeof (digest_ecc_ctx_t), kmflag);
830 		ctxp = (ecc_ctx_t *)dctxp;
831 		break;
832 	default:
833 		ctxp = kmem_zalloc(sizeof (ecc_ctx_t), kmflag);
834 		break;
835 	}
836 
837 	if (ctxp == NULL) {
838 		free_ecparams(ecparams, B_TRUE);
839 		return (CRYPTO_HOST_MEMORY);
840 	}
841 
842 	if ((rv = copy_key_to_ctx(key, ctxp, kmflag)) != CRYPTO_SUCCESS) {
843 		switch (mech_type) {
844 		case ECDSA_SHA1_MECH_INFO_TYPE:
845 			kmem_free(dctxp, sizeof (digest_ecc_ctx_t));
846 			break;
847 		default:
848 			kmem_free(ctxp, sizeof (ecc_ctx_t));
849 			break;
850 		}
851 		free_ecparams(ecparams, B_TRUE);
852 		return (rv);
853 	}
854 	ctxp->mech_type = mech_type;
855 	ctxp->ecparams = *ecparams;
856 	kmem_free(ecparams, sizeof (ECParams));
857 
858 	switch (mech_type) {
859 	case ECDSA_SHA1_MECH_INFO_TYPE:
860 		SHA1Init(&(dctxp->sha1_ctx));
861 		break;
862 	}
863 
864 	ctx->cc_provider_private = ctxp;
865 
866 	return (CRYPTO_SUCCESS);
867 }
868 
869 /* ARGSUSED */
870 static int
871 ecc_sign_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
872     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
873     crypto_req_handle_t req)
874 {
875 	int rv;
876 
877 	ecc_mech_type_t mech_type = mechanism->cm_type;
878 
879 	if ((rv = check_mech_and_key(mech_type, key,
880 	    CKO_PRIVATE_KEY)) != CRYPTO_SUCCESS)
881 		return (rv);
882 
883 	rv = ecc_sign_verify_common_init(ctx, mechanism, key,
884 	    ctx_template, req);
885 
886 	return (rv);
887 }
888 
889 /* ARGSUSED */
890 static int
891 ecc_verify_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
892     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
893     crypto_req_handle_t req)
894 {
895 	int rv;
896 
897 	ecc_mech_type_t mech_type = mechanism->cm_type;
898 
899 	if ((rv = check_mech_and_key(mech_type, key,
900 	    CKO_PUBLIC_KEY)) != CRYPTO_SUCCESS)
901 		return (rv);
902 
903 	rv = ecc_sign_verify_common_init(ctx, mechanism, key,
904 	    ctx_template, req);
905 
906 	return (rv);
907 }
908 
909 #define	SHA1_DIGEST_SIZE 20
910 
911 #define	INIT_RAW_CRYPTO_DATA(data, base, len, cd_len)	\
912 	(data).cd_format = CRYPTO_DATA_RAW;		\
913 	(data).cd_offset = 0;				\
914 	(data).cd_raw.iov_base = (char *)base;		\
915 	(data).cd_raw.iov_len = len;			\
916 	(data).cd_length = cd_len;
917 
918 #define	DO_UPDATE	0x01
919 #define	DO_FINAL	0x02
920 #define	DO_SHA1		0x08
921 #define	DO_SIGN		0x10
922 #define	DO_VERIFY	0x20
923 
924 static int
925 digest_data(crypto_data_t *data, void *dctx, uchar_t *digest,
926     uchar_t flag)
927 {
928 	int rv, dlen;
929 	uchar_t *dptr;
930 
931 	ASSERT(flag & DO_SHA1);
932 	if (data == NULL) {
933 		ASSERT((flag & DO_UPDATE) == 0);
934 		goto dofinal;
935 	}
936 
937 	dlen = data->cd_length;
938 
939 	if (flag & DO_UPDATE) {
940 
941 		switch (data->cd_format) {
942 		case CRYPTO_DATA_RAW:
943 			dptr = (uchar_t *)(data->cd_raw.iov_base +
944 			    data->cd_offset);
945 
946 			if (flag & DO_SHA1)
947 				SHA1Update(dctx, dptr, dlen);
948 
949 		break;
950 
951 		case CRYPTO_DATA_UIO:
952 			if (flag & DO_SHA1)
953 				rv = process_uio_data(data, NULL, dlen,
954 				    SHA1_DIGEST_DATA, dctx);
955 
956 			if (rv != CRYPTO_SUCCESS)
957 				return (rv);
958 
959 			break;
960 
961 		case CRYPTO_DATA_MBLK:
962 			if (flag & DO_SHA1)
963 				rv = process_mblk_data(data, NULL, dlen,
964 				    SHA1_DIGEST_DATA, dctx);
965 
966 			if (rv != CRYPTO_SUCCESS)
967 				return (rv);
968 
969 			break;
970 		}
971 	}
972 
973 dofinal:
974 	if (flag & DO_FINAL) {
975 		if (flag & DO_SHA1)
976 			SHA1Final(digest, dctx);
977 	}
978 
979 	return (CRYPTO_SUCCESS);
980 }
981 
982 static int
983 ecc_digest_svrfy_common(digest_ecc_ctx_t *ctxp, crypto_data_t *data,
984     crypto_data_t *signature, uchar_t flag, crypto_req_handle_t req)
985 {
986 	int rv = CRYPTO_FAILED;
987 	uchar_t digest[SHA1_DIGEST_LENGTH];
988 	crypto_data_t der_cd;
989 	ecc_mech_type_t mech_type;
990 
991 	ASSERT(flag & DO_SIGN || flag & DO_VERIFY);
992 	ASSERT(data != NULL || (flag & DO_FINAL));
993 
994 	mech_type = ctxp->mech_type;
995 	if (mech_type != ECDSA_SHA1_MECH_INFO_TYPE)
996 		return (CRYPTO_MECHANISM_INVALID);
997 
998 	/* Don't digest if only returning length of signature. */
999 	if (signature->cd_length > 0) {
1000 		if (mech_type == ECDSA_SHA1_MECH_INFO_TYPE) {
1001 			rv = digest_data(data, &(ctxp->sha1_ctx),
1002 			    digest, flag | DO_SHA1);
1003 			if (rv != CRYPTO_SUCCESS)
1004 				return (rv);
1005 		}
1006 	}
1007 
1008 	INIT_RAW_CRYPTO_DATA(der_cd, digest, SHA1_DIGEST_SIZE,
1009 	    SHA1_DIGEST_SIZE);
1010 
1011 	if (flag & DO_SIGN) {
1012 		rv = ecc_sign_common((ecc_ctx_t *)ctxp, &der_cd, signature,
1013 		    req);
1014 	} else
1015 		rv = ecc_verify_common((ecc_ctx_t *)ctxp, &der_cd, signature,
1016 		    req);
1017 
1018 	return (rv);
1019 }
1020 
1021 /*
1022  * This is a single-part signing routine. It does not
1023  * compute a hash before signing.
1024  */
1025 static int
1026 ecc_sign_common(ecc_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
1027     crypto_req_handle_t req)
1028 {
1029 	int rv = CRYPTO_FAILED;
1030 	SECStatus ss;
1031 	uchar_t *param;
1032 	uchar_t *private;
1033 	ssize_t param_len;
1034 	ssize_t private_len;
1035 	uchar_t tmp_data[EC_MAX_DIGEST_LEN];
1036 	uchar_t signed_data[EC_MAX_SIG_LEN];
1037 	ECPrivateKey ECkey;
1038 	SECItem signature_item;
1039 	SECItem digest_item;
1040 	crypto_key_t *key = ctx->key;
1041 	int kmflag;
1042 
1043 	if ((rv = get_key_attr(key, CKA_EC_PARAMS, &param,
1044 	    &param_len)) != CRYPTO_SUCCESS) {
1045 		return (rv);
1046 	}
1047 
1048 	if (data->cd_length > sizeof (tmp_data))
1049 		return (CRYPTO_DATA_LEN_RANGE);
1050 
1051 	if ((rv = get_input_data(data, &digest_item.data, tmp_data))
1052 	    != CRYPTO_SUCCESS) {
1053 		return (rv);
1054 	}
1055 	digest_item.len = data->cd_length;
1056 
1057 	/* structure assignment */
1058 	ECkey.ecParams = ctx->ecparams;
1059 
1060 	if ((rv = get_key_attr(key, CKA_VALUE, &private,
1061 	    &private_len)) != CRYPTO_SUCCESS) {
1062 		return (rv);
1063 	}
1064 	ECkey.privateValue.data = private;
1065 	ECkey.privateValue.len = (uint_t)private_len;
1066 
1067 	signature_item.data = signed_data;
1068 	signature_item.len = sizeof (signed_data);
1069 
1070 	kmflag = crypto_kmflag(req);
1071 	if ((ss = ECDSA_SignDigest(&ECkey, &signature_item, &digest_item,
1072 	    kmflag)) != SECSuccess) {
1073 		if (ss == SECBufferTooSmall)
1074 			return (CRYPTO_BUFFER_TOO_SMALL);
1075 
1076 		return (CRYPTO_FAILED);
1077 	}
1078 
1079 	if (rv == CRYPTO_SUCCESS) {
1080 		/* copy out the signature */
1081 		if ((rv = put_output_data(signed_data,
1082 		    signature, signature_item.len)) != CRYPTO_SUCCESS)
1083 			return (rv);
1084 
1085 		signature->cd_length = signature_item.len;
1086 	}
1087 
1088 	return (rv);
1089 }
1090 
1091 /* ARGSUSED */
1092 static int
1093 ecc_sign(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
1094     crypto_req_handle_t req)
1095 {
1096 	int rv;
1097 	ecc_ctx_t *ctxp;
1098 
1099 	ASSERT(ctx->cc_provider_private != NULL);
1100 	ctxp = ctx->cc_provider_private;
1101 
1102 	switch (ctxp->mech_type) {
1103 	case ECDSA_SHA1_MECH_INFO_TYPE:
1104 		rv = ecc_digest_svrfy_common((digest_ecc_ctx_t *)ctxp, data,
1105 		    signature, DO_SIGN | DO_UPDATE | DO_FINAL, req);
1106 		break;
1107 	default:
1108 		rv = ecc_sign_common(ctxp, data, signature, req);
1109 		break;
1110 	}
1111 
1112 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
1113 		ecc_free_context(ctx);
1114 
1115 	return (rv);
1116 }
1117 
1118 /* ARGSUSED */
1119 static int
1120 ecc_sign_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req)
1121 {
1122 	int rv;
1123 	digest_ecc_ctx_t *ctxp;
1124 	ecc_mech_type_t mech_type;
1125 
1126 	ASSERT(ctx->cc_provider_private != NULL);
1127 	ctxp = ctx->cc_provider_private;
1128 	mech_type = ctxp->mech_type;
1129 
1130 	if (mech_type == ECDSA_MECH_INFO_TYPE) {
1131 		ecc_free_context(ctx);
1132 		return (CRYPTO_MECHANISM_INVALID);
1133 	}
1134 
1135 	if (mech_type == ECDSA_SHA1_MECH_INFO_TYPE)
1136 		rv = digest_data(data, &(ctxp->sha1_ctx),
1137 		    NULL, DO_SHA1 | DO_UPDATE);
1138 
1139 	if (rv != CRYPTO_SUCCESS)
1140 		ecc_free_context(ctx);
1141 
1142 	return (rv);
1143 }
1144 
1145 /* ARGSUSED */
1146 static int
1147 ecc_sign_final(crypto_ctx_t *ctx, crypto_data_t *signature,
1148     crypto_req_handle_t req)
1149 {
1150 	int rv;
1151 	digest_ecc_ctx_t *ctxp;
1152 
1153 	ASSERT(ctx->cc_provider_private != NULL);
1154 	ctxp = ctx->cc_provider_private;
1155 
1156 	rv = ecc_digest_svrfy_common(ctxp, NULL, signature, DO_SIGN | DO_FINAL,
1157 	    req);
1158 	if (rv != CRYPTO_BUFFER_TOO_SMALL)
1159 		ecc_free_context(ctx);
1160 
1161 	return (rv);
1162 }
1163 
1164 /* ARGSUSED */
1165 static int
1166 ecc_sign_atomic(crypto_provider_handle_t provider,
1167     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1168     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
1169     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
1170 {
1171 	int rv;
1172 	ecc_mech_type_t mech_type = mechanism->cm_type;
1173 	uchar_t *params;
1174 	ssize_t params_len;
1175 	ECParams  *ecparams;
1176 	SECKEYECParams params_item;
1177 	int kmflag;
1178 
1179 	if ((rv = check_mech_and_key(mech_type, key,
1180 	    CKO_PRIVATE_KEY)) != CRYPTO_SUCCESS)
1181 		return (rv);
1182 
1183 	if (get_key_attr(key, CKA_EC_PARAMS, (void *) &params,
1184 	    &params_len)) {
1185 		return (CRYPTO_ARGUMENTS_BAD);
1186 	}
1187 
1188 	/* ASN1 check */
1189 	if (params[0] != 0x06 ||
1190 	    params[1] != params_len - 2) {
1191 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
1192 	}
1193 	params_item.data = params;
1194 	params_item.len = (uint_t)params_len;
1195 	kmflag = crypto_kmflag(req);
1196 	if (EC_DecodeParams(&params_item, &ecparams, kmflag) != SECSuccess) {
1197 		/* bad curve OID */
1198 		return (CRYPTO_ARGUMENTS_BAD);
1199 	}
1200 
1201 	if (mechanism->cm_type == ECDSA_MECH_INFO_TYPE) {
1202 		ecc_ctx_t ctx;
1203 
1204 		ctx.mech_type = mech_type;
1205 		/* structure assignment */
1206 		ctx.ecparams = *ecparams;
1207 		ctx.key = key;
1208 		rv = ecc_sign_common(&ctx, data, signature, req);
1209 	} else {
1210 		digest_ecc_ctx_t dctx;
1211 
1212 		dctx.mech_type = mech_type;
1213 		/* structure assignment */
1214 		dctx.ecparams = *ecparams;
1215 		dctx.key = key;
1216 		SHA1Init(&(dctx.sha1_ctx));
1217 
1218 		rv = ecc_digest_svrfy_common(&dctx, data, signature,
1219 		    DO_SIGN | DO_UPDATE | DO_FINAL, req);
1220 	}
1221 	free_ecparams(ecparams, B_TRUE);
1222 
1223 	return (rv);
1224 }
1225 
1226 static int
1227 ecc_verify_common(ecc_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
1228     crypto_req_handle_t req)
1229 {
1230 	int rv = CRYPTO_FAILED;
1231 	uchar_t *param;
1232 	uchar_t *public;
1233 	ssize_t param_len;
1234 	ssize_t public_len;
1235 	uchar_t tmp_data[EC_MAX_DIGEST_LEN];
1236 	uchar_t signed_data[EC_MAX_SIG_LEN];
1237 	ECPublicKey ECkey;
1238 	SECItem signature_item;
1239 	SECItem digest_item;
1240 	crypto_key_t *key = ctx->key;
1241 	int kmflag;
1242 
1243 	if ((rv = get_key_attr(key, CKA_EC_PARAMS, &param,
1244 	    &param_len)) != CRYPTO_SUCCESS) {
1245 		return (rv);
1246 	}
1247 
1248 	if (signature->cd_length > sizeof (signed_data)) {
1249 		return (CRYPTO_SIGNATURE_LEN_RANGE);
1250 	}
1251 
1252 	if ((rv = get_input_data(signature, &signature_item.data,
1253 	    signed_data)) != CRYPTO_SUCCESS) {
1254 		return (rv);
1255 	}
1256 	signature_item.len = signature->cd_length;
1257 
1258 	if (data->cd_length > sizeof (tmp_data))
1259 		return (CRYPTO_DATA_LEN_RANGE);
1260 
1261 	if ((rv = get_input_data(data, &digest_item.data, tmp_data))
1262 	    != CRYPTO_SUCCESS) {
1263 		return (rv);
1264 	}
1265 	digest_item.len = data->cd_length;
1266 
1267 	/* structure assignment */
1268 	ECkey.ecParams = ctx->ecparams;
1269 
1270 	if ((rv = get_key_attr(key, CKA_EC_POINT, &public,
1271 	    &public_len)) != CRYPTO_SUCCESS) {
1272 		return (rv);
1273 	}
1274 	ECkey.publicValue.data = public;
1275 	ECkey.publicValue.len = (uint_t)public_len;
1276 
1277 	kmflag = crypto_kmflag(req);
1278 	if (ECDSA_VerifyDigest(&ECkey, &signature_item, &digest_item, kmflag)
1279 	    != SECSuccess) {
1280 		rv = CRYPTO_SIGNATURE_INVALID;
1281 	} else {
1282 		rv = CRYPTO_SUCCESS;
1283 	}
1284 
1285 	return (rv);
1286 }
1287 
1288 /* ARGSUSED */
1289 static int
1290 ecc_verify(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *signature,
1291     crypto_req_handle_t req)
1292 {
1293 	int rv;
1294 	ecc_ctx_t *ctxp;
1295 
1296 	ASSERT(ctx->cc_provider_private != NULL);
1297 	ctxp = ctx->cc_provider_private;
1298 
1299 	switch (ctxp->mech_type) {
1300 	case ECDSA_SHA1_MECH_INFO_TYPE:
1301 		rv = ecc_digest_svrfy_common((digest_ecc_ctx_t *)ctxp, data,
1302 		    signature, DO_VERIFY | DO_UPDATE | DO_FINAL, req);
1303 		break;
1304 	default:
1305 		rv = ecc_verify_common(ctxp, data, signature, req);
1306 		break;
1307 	}
1308 
1309 	ecc_free_context(ctx);
1310 	return (rv);
1311 }
1312 
1313 /* ARGSUSED */
1314 static int
1315 ecc_verify_update(crypto_ctx_t *ctx, crypto_data_t *data,
1316     crypto_req_handle_t req)
1317 {
1318 	int rv;
1319 	digest_ecc_ctx_t *ctxp;
1320 
1321 	ASSERT(ctx->cc_provider_private != NULL);
1322 	ctxp = ctx->cc_provider_private;
1323 
1324 	switch (ctxp->mech_type) {
1325 	case ECDSA_SHA1_MECH_INFO_TYPE:
1326 		rv = digest_data(data, &(ctxp->sha1_ctx),
1327 		    NULL, DO_SHA1 | DO_UPDATE);
1328 		break;
1329 	default:
1330 		rv = CRYPTO_MECHANISM_INVALID;
1331 	}
1332 
1333 	if (rv != CRYPTO_SUCCESS)
1334 		ecc_free_context(ctx);
1335 
1336 	return (rv);
1337 }
1338 
1339 /* ARGSUSED */
1340 static int
1341 ecc_verify_final(crypto_ctx_t *ctx, crypto_data_t *signature,
1342     crypto_req_handle_t req)
1343 {
1344 	int rv;
1345 	digest_ecc_ctx_t *ctxp;
1346 
1347 	ASSERT(ctx->cc_provider_private != NULL);
1348 	ctxp = ctx->cc_provider_private;
1349 
1350 	rv = ecc_digest_svrfy_common(ctxp, NULL, signature,
1351 	    DO_VERIFY | DO_FINAL, req);
1352 
1353 	ecc_free_context(ctx);
1354 
1355 	return (rv);
1356 }
1357 
1358 
1359 /* ARGSUSED */
1360 static int
1361 ecc_verify_atomic(crypto_provider_handle_t provider,
1362     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1363     crypto_key_t *key, crypto_data_t *data, crypto_data_t *signature,
1364     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
1365 {
1366 	int rv;
1367 	ecc_mech_type_t mech_type = mechanism->cm_type;
1368 	uchar_t *params;
1369 	ssize_t params_len;
1370 	ECParams  *ecparams;
1371 	SECKEYECParams params_item;
1372 	int kmflag;
1373 
1374 	if ((rv = check_mech_and_key(mech_type, key,
1375 	    CKO_PUBLIC_KEY)) != CRYPTO_SUCCESS)
1376 		return (rv);
1377 
1378 	if (get_key_attr(key, CKA_EC_PARAMS, (void *) &params,
1379 	    &params_len)) {
1380 		return (CRYPTO_ARGUMENTS_BAD);
1381 	}
1382 
1383 	/* ASN1 check */
1384 	if (params[0] != 0x06 ||
1385 	    params[1] != params_len - 2) {
1386 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
1387 	}
1388 	params_item.data = params;
1389 	params_item.len = (uint_t)params_len;
1390 	kmflag = crypto_kmflag(req);
1391 	if (EC_DecodeParams(&params_item, &ecparams, kmflag) != SECSuccess) {
1392 		/* bad curve OID */
1393 		return (CRYPTO_ARGUMENTS_BAD);
1394 	}
1395 
1396 	if (mechanism->cm_type == ECDSA_MECH_INFO_TYPE) {
1397 		ecc_ctx_t ctx;
1398 
1399 		ctx.mech_type = mech_type;
1400 		/* structure assignment */
1401 		ctx.ecparams = *ecparams;
1402 		ctx.key = key;
1403 		rv = ecc_verify_common(&ctx, data, signature, req);
1404 	} else {
1405 		digest_ecc_ctx_t dctx;
1406 
1407 		dctx.mech_type = mech_type;
1408 		/* structure assignment */
1409 		dctx.ecparams = *ecparams;
1410 		dctx.key = key;
1411 		SHA1Init(&(dctx.sha1_ctx));
1412 
1413 		rv = ecc_digest_svrfy_common(&dctx, data, signature,
1414 		    DO_VERIFY | DO_UPDATE | DO_FINAL, req);
1415 	}
1416 	free_ecparams(ecparams, B_TRUE);
1417 	return (rv);
1418 }
1419 
1420 /* ARGSUSED */
1421 static int
1422 ecc_nostore_key_generate_pair(crypto_provider_handle_t provider,
1423     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1424     crypto_object_attribute_t *pub_template, uint_t pub_attribute_count,
1425     crypto_object_attribute_t *pri_template, uint_t pri_attribute_count,
1426     crypto_object_attribute_t *pub_out_template, uint_t pub_out_attribute_count,
1427     crypto_object_attribute_t *pri_out_template, uint_t pri_out_attribute_count,
1428     crypto_req_handle_t req)
1429 {
1430 	int rv = CRYPTO_SUCCESS;
1431 	ECPrivateKey *privKey;	/* contains both public and private values */
1432 	ECParams *ecparams;
1433 	SECKEYECParams params_item;
1434 	ulong_t pub_key_type = ~0UL, pub_class = ~0UL;
1435 	ulong_t pri_key_type = ~0UL, pri_class = ~0UL;
1436 	int params_idx, value_idx, point_idx;
1437 	uchar_t *params = NULL;
1438 	unsigned params_len;
1439 	uchar_t *value = NULL;
1440 	uchar_t *point = NULL;
1441 	int valuelen;
1442 	int pointlen;
1443 	int xylen;
1444 	int kmflag;
1445 
1446 	if (mechanism->cm_type != EC_KEY_PAIR_GEN_MECH_INFO_TYPE) {
1447 		return (CRYPTO_MECHANISM_INVALID);
1448 	}
1449 
1450 	/* optional */
1451 	(void) get_template_attr_ulong(pub_template,
1452 	    pub_attribute_count, CKA_CLASS, &pub_class);
1453 
1454 	/* optional */
1455 	(void) get_template_attr_ulong(pri_template,
1456 	    pri_attribute_count, CKA_CLASS, &pri_class);
1457 
1458 	/* optional */
1459 	(void) get_template_attr_ulong(pub_template,
1460 	    pub_attribute_count, CKA_KEY_TYPE, &pub_key_type);
1461 
1462 	/* optional */
1463 	(void) get_template_attr_ulong(pri_template,
1464 	    pri_attribute_count, CKA_KEY_TYPE, &pri_key_type);
1465 
1466 	if (pub_class != ~0UL && pub_class != CKO_PUBLIC_KEY) {
1467 		return (CRYPTO_TEMPLATE_INCONSISTENT);
1468 	}
1469 	pub_class = CKO_PUBLIC_KEY;
1470 
1471 	if (pri_class != ~0UL && pri_class != CKO_PRIVATE_KEY) {
1472 		return (CRYPTO_TEMPLATE_INCONSISTENT);
1473 	}
1474 	pri_class = CKO_PRIVATE_KEY;
1475 
1476 	if (pub_key_type != ~0UL && pub_key_type != CKK_EC) {
1477 		return (CRYPTO_TEMPLATE_INCONSISTENT);
1478 	}
1479 	pub_key_type = CKK_EC;
1480 
1481 	if (pri_key_type != ~0UL && pri_key_type != CKK_EC) {
1482 		return (CRYPTO_TEMPLATE_INCONSISTENT);
1483 	}
1484 	pri_key_type = CKK_EC;
1485 
1486 	/* public output template must contain CKA_EC_POINT attribute */
1487 	if ((point_idx = find_attr(pub_out_template, pub_out_attribute_count,
1488 	    CKA_EC_POINT)) == -1) {
1489 		return (CRYPTO_TEMPLATE_INCOMPLETE);
1490 	}
1491 
1492 	/* private output template must contain CKA_VALUE attribute */
1493 	if ((value_idx = find_attr(pri_out_template, pri_out_attribute_count,
1494 	    CKA_VALUE)) == -1) {
1495 		return (CRYPTO_TEMPLATE_INCOMPLETE);
1496 	}
1497 
1498 	if ((params_idx = find_attr(pub_template, pub_attribute_count,
1499 	    CKA_EC_PARAMS)) == -1) {
1500 		return (CRYPTO_TEMPLATE_INCOMPLETE);
1501 	}
1502 
1503 	params = (uchar_t *)pub_template[params_idx].oa_value;
1504 	params_len = pub_template[params_idx].oa_value_len;
1505 
1506 	value = (uchar_t *)pri_out_template[value_idx].oa_value;
1507 	valuelen = (int)pri_out_template[value_idx].oa_value_len;
1508 	point = (uchar_t *)pub_out_template[point_idx].oa_value;
1509 	pointlen = (int)pub_out_template[point_idx].oa_value_len;
1510 
1511 	/* ASN1 check */
1512 	if (params[0] != 0x06 ||
1513 	    params[1] != params_len - 2) {
1514 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
1515 	}
1516 	params_item.data = params;
1517 	params_item.len = params_len;
1518 	kmflag = crypto_kmflag(req);
1519 	if (EC_DecodeParams(&params_item, &ecparams, kmflag) != SECSuccess) {
1520 		/* bad curve OID */
1521 		return (CRYPTO_ARGUMENTS_BAD);
1522 	}
1523 
1524 	if (EC_NewKey(ecparams, &privKey, kmflag) != SECSuccess) {
1525 		free_ecparams(ecparams, B_TRUE);
1526 		return (CRYPTO_FAILED);
1527 	}
1528 
1529 	xylen = privKey->publicValue.len;
1530 	/* ASSERT that xylen - 1 is divisible by 2 */
1531 	if (xylen > pointlen) {
1532 		rv = CRYPTO_BUFFER_TOO_SMALL;
1533 		goto out;
1534 	}
1535 
1536 	if (privKey->privateValue.len > valuelen) {
1537 		rv = CRYPTO_BUFFER_TOO_SMALL;
1538 		goto out;
1539 	}
1540 	bcopy(privKey->privateValue.data, value, privKey->privateValue.len);
1541 	pri_out_template[value_idx].oa_value_len = privKey->privateValue.len;
1542 
1543 	bcopy(privKey->publicValue.data, point, xylen);
1544 	pub_out_template[point_idx].oa_value_len = xylen;
1545 
1546 out:
1547 	free_ecprivkey(privKey);
1548 	free_ecparams(ecparams, B_TRUE);
1549 	return (rv);
1550 }
1551 
1552 /* ARGSUSED */
1553 static int
1554 ecc_nostore_key_derive(crypto_provider_handle_t provider,
1555     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1556     crypto_key_t *base_key, crypto_object_attribute_t *in_attrs,
1557     uint_t in_attr_count, crypto_object_attribute_t *out_attrs,
1558     uint_t out_attr_count, crypto_req_handle_t req)
1559 {
1560 	int rv = CRYPTO_SUCCESS;
1561 	int params_idx, value_idx = -1, out_value_idx = -1;
1562 	ulong_t key_type;
1563 	ulong_t key_len;
1564 	crypto_object_attribute_t *attrs;
1565 	ECParams *ecparams;
1566 	SECKEYECParams params_item;
1567 	CK_ECDH1_DERIVE_PARAMS *mech_param;
1568 	SECItem public_value_item, private_value_item, secret_item;
1569 	int kmflag;
1570 
1571 	if (mechanism->cm_type != ECDH1_DERIVE_MECH_INFO_TYPE) {
1572 		return (CRYPTO_MECHANISM_INVALID);
1573 	}
1574 
1575 	ASSERT(IS_P2ALIGNED(mechanism->cm_param, sizeof (uint64_t)));
1576 	/* LINTED: pointer alignment */
1577 	mech_param = (CK_ECDH1_DERIVE_PARAMS *)mechanism->cm_param;
1578 	if (mech_param->kdf != CKD_NULL) {
1579 		return (CRYPTO_MECHANISM_PARAM_INVALID);
1580 	}
1581 
1582 	if ((base_key->ck_format != CRYPTO_KEY_ATTR_LIST) ||
1583 	    (base_key->ck_count == 0)) {
1584 		return (CRYPTO_ARGUMENTS_BAD);
1585 	}
1586 
1587 	if ((rv = get_template_attr_ulong(in_attrs, in_attr_count,
1588 	    CKA_KEY_TYPE, &key_type)) != CRYPTO_SUCCESS) {
1589 		return (rv);
1590 	}
1591 
1592 	switch (key_type) {
1593 	case CKK_DES:
1594 		key_len = DES_KEYSIZE;
1595 		break;
1596 	case CKK_DES2:
1597 		key_len = DES2_KEYSIZE;
1598 		break;
1599 	case CKK_DES3:
1600 		key_len = DES3_KEYSIZE;
1601 		break;
1602 	case CKK_RC4:
1603 	case CKK_AES:
1604 	case CKK_GENERIC_SECRET:
1605 		if ((rv = get_template_attr_ulong(in_attrs, in_attr_count,
1606 		    CKA_VALUE_LEN, &key_len)) != CRYPTO_SUCCESS) {
1607 			return (rv);
1608 		}
1609 		break;
1610 	default:
1611 		key_len = 0;
1612 	}
1613 
1614 	attrs = base_key->ck_attrs;
1615 	if ((value_idx = find_attr(attrs, base_key->ck_count,
1616 	    CKA_VALUE)) == -1) {
1617 		return (CRYPTO_TEMPLATE_INCOMPLETE);
1618 	}
1619 
1620 	if ((params_idx = find_attr(attrs, base_key->ck_count,
1621 	    CKA_EC_PARAMS)) == -1) {
1622 		return (CRYPTO_TEMPLATE_INCOMPLETE);
1623 	}
1624 
1625 	private_value_item.data = (uchar_t *)attrs[value_idx].oa_value;
1626 	private_value_item.len = attrs[value_idx].oa_value_len;
1627 
1628 	params_item.len = attrs[params_idx].oa_value_len;
1629 	params_item.data = (uchar_t *)attrs[params_idx].oa_value;
1630 
1631 	/* ASN1 check */
1632 	if (params_item.data[0] != 0x06 ||
1633 	    params_item.data[1] != params_item.len - 2) {
1634 		return (CRYPTO_ATTRIBUTE_VALUE_INVALID);
1635 	}
1636 	kmflag = crypto_kmflag(req);
1637 	if (EC_DecodeParams(&params_item, &ecparams, kmflag) != SECSuccess) {
1638 		/* bad curve OID */
1639 		return (CRYPTO_ARGUMENTS_BAD);
1640 	}
1641 
1642 	public_value_item.data = (uchar_t *)mech_param->pPublicData;
1643 	public_value_item.len = mech_param->ulPublicDataLen;
1644 
1645 	if ((out_value_idx = find_attr(out_attrs, out_attr_count,
1646 	    CKA_VALUE)) == -1) {
1647 		rv = CRYPTO_TEMPLATE_INCOMPLETE;
1648 		goto out;
1649 	}
1650 	secret_item.data = NULL;
1651 	secret_item.len = 0;
1652 
1653 	if (ECDH_Derive(&public_value_item, ecparams, &private_value_item,
1654 	    B_FALSE, &secret_item, kmflag) != SECSuccess) {
1655 		free_ecparams(ecparams, B_TRUE);
1656 		return (CRYPTO_FAILED);
1657 	} else {
1658 		rv = CRYPTO_SUCCESS;
1659 	}
1660 
1661 	if (key_len == 0)
1662 		key_len = secret_item.len;
1663 
1664 	if (key_len > secret_item.len) {
1665 		rv = CRYPTO_ATTRIBUTE_VALUE_INVALID;
1666 		goto out;
1667 	}
1668 	if (key_len > out_attrs[out_value_idx].oa_value_len) {
1669 		rv = CRYPTO_BUFFER_TOO_SMALL;
1670 		goto out;
1671 	}
1672 	bcopy(secret_item.data + secret_item.len - key_len,
1673 	    (uchar_t *)out_attrs[out_value_idx].oa_value, key_len);
1674 	out_attrs[out_value_idx].oa_value_len = key_len;
1675 out:
1676 	free_ecparams(ecparams, B_TRUE);
1677 	SECITEM_FreeItem(&secret_item, B_FALSE);
1678 	return (rv);
1679 }
1680 
1681 static void
1682 free_ecparams(ECParams *params, boolean_t freeit)
1683 {
1684 	SECITEM_FreeItem(&params->fieldID.u.prime, B_FALSE);
1685 	SECITEM_FreeItem(&params->curve.a, B_FALSE);
1686 	SECITEM_FreeItem(&params->curve.b, B_FALSE);
1687 	SECITEM_FreeItem(&params->curve.seed, B_FALSE);
1688 	SECITEM_FreeItem(&params->base, B_FALSE);
1689 	SECITEM_FreeItem(&params->order, B_FALSE);
1690 	SECITEM_FreeItem(&params->DEREncoding, B_FALSE);
1691 	SECITEM_FreeItem(&params->curveOID, B_FALSE);
1692 	if (freeit)
1693 		kmem_free(params, sizeof (ECParams));
1694 }
1695 
1696 static void
1697 free_ecprivkey(ECPrivateKey *key)
1698 {
1699 	free_ecparams(&key->ecParams, B_FALSE);
1700 	SECITEM_FreeItem(&key->publicValue, B_FALSE);
1701 	bzero(key->privateValue.data, key->privateValue.len);
1702 	SECITEM_FreeItem(&key->privateValue, B_FALSE);
1703 	SECITEM_FreeItem(&key->version, B_FALSE);
1704 	kmem_free(key, sizeof (ECPrivateKey));
1705 }
1706