xref: /illumos-gate/usr/src/uts/common/crypto/core/kcf_prov_lib.c (revision f51469c0ef9945d3870d6c020b715ae2cb2e09da)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  *
25  * Copyright 2023-2026 RackTop Systems, Inc.
26  */
27 
28 #include <sys/strsun.h>
29 #include <sys/systm.h>
30 #include <sys/sysmacros.h>
31 #include <sys/kmem.h>
32 #include <sys/md5.h>
33 #include <sys/sha1.h>
34 #include <sys/sha2.h>
35 #include <modes/modes.h>
36 #include <sys/crypto/common.h>
37 #include <sys/crypto/impl.h>
38 
39 /*
40  * Utility routine to get data from a crypto_data structure.
41  *
42  * '*dptr' contains a pointer to a buffer on return. 'buf'
43  * is allocated by the caller and is ignored for CRYPTO_DATA_RAW case.
44  */
45 int
crypto_get_input_data(crypto_data_t * input,uchar_t ** dptr,uchar_t * buf)46 crypto_get_input_data(crypto_data_t *input, uchar_t **dptr, uchar_t *buf)
47 {
48 	int rv;
49 
50 	switch (input->cd_format) {
51 	case CRYPTO_DATA_RAW:
52 		if (input->cd_raw.iov_len < input->cd_length)
53 			return (CRYPTO_ARGUMENTS_BAD);
54 		*dptr = (uchar_t *)(input->cd_raw.iov_base +
55 		    input->cd_offset);
56 		break;
57 
58 	case CRYPTO_DATA_UIO:
59 		if ((rv = crypto_uio_data(input, buf, input->cd_length,
60 		    COPY_FROM_DATA, NULL, NULL)) != CRYPTO_SUCCESS)
61 			return (rv);
62 		*dptr = buf;
63 		break;
64 
65 	case CRYPTO_DATA_MBLK:
66 		if ((rv = crypto_mblk_data(input, buf, input->cd_length,
67 		    COPY_FROM_DATA, NULL, NULL)) != CRYPTO_SUCCESS)
68 			return (rv);
69 		*dptr = buf;
70 		break;
71 
72 	default:
73 		return (CRYPTO_ARGUMENTS_BAD);
74 	}
75 
76 	return (CRYPTO_SUCCESS);
77 }
78 
79 int
crypto_compare_data(crypto_data_t * data,uchar_t * buf,size_t len)80 crypto_compare_data(crypto_data_t *data, uchar_t *buf, size_t len)
81 {
82 	uchar_t *dptr;
83 
84 	if (len > INT32_MAX)
85 		return (CRYPTO_DATA_LEN_RANGE);
86 
87 	switch (data->cd_format) {
88 	case CRYPTO_DATA_RAW:
89 		dptr = (uchar_t *)(data->cd_raw.iov_base +
90 		    data->cd_offset);
91 
92 		if (data->cd_raw.iov_len < data->cd_length ||
93 		    data->cd_length < len)
94 			return (CRYPTO_DATA_LEN_RANGE);
95 
96 		return (bcmp(dptr, buf, len));
97 
98 	case CRYPTO_DATA_UIO:
99 		return (crypto_uio_data(data, buf, len,
100 		    COMPARE_TO_DATA, NULL, NULL));
101 
102 	case CRYPTO_DATA_MBLK:
103 		return (crypto_mblk_data(data, buf, len,
104 		    COMPARE_TO_DATA, NULL, NULL));
105 	}
106 
107 	return (CRYPTO_FAILED);
108 }
109 
110 int
crypto_copy_key_to_ctx(crypto_key_t * in_key,crypto_key_t ** out_key,size_t * out_size,int kmflag)111 crypto_copy_key_to_ctx(crypto_key_t *in_key, crypto_key_t **out_key,
112     size_t *out_size, int kmflag)
113 {
114 	int i, count;
115 	size_t len;
116 	caddr_t attr_val;
117 	crypto_object_attribute_t *k_attrs = NULL;
118 	crypto_key_t *key;
119 
120 	ASSERT(in_key->ck_format == CRYPTO_KEY_ATTR_LIST);
121 
122 	count = in_key->ck_count;
123 	/* figure out how much memory to allocate for everything */
124 	len = sizeof (crypto_key_t) +
125 	    count * sizeof (crypto_object_attribute_t);
126 	for (i = 0; i < count; i++) {
127 		len += roundup(in_key->ck_attrs[i].oa_value_len,
128 		    sizeof (caddr_t));
129 	}
130 
131 	/* one big allocation for everything */
132 	key = kmem_alloc(len, kmflag);
133 	if (key == NULL)
134 		return (CRYPTO_HOST_MEMORY);
135 	k_attrs = (crypto_object_attribute_t *)(void *)((caddr_t)key +
136 	    sizeof (crypto_key_t));
137 
138 	attr_val = (caddr_t)k_attrs +
139 	    count * sizeof (crypto_object_attribute_t);
140 	for (i = 0; i < count; i++) {
141 		k_attrs[i].oa_type = in_key->ck_attrs[i].oa_type;
142 		bcopy(in_key->ck_attrs[i].oa_value, attr_val,
143 		    in_key->ck_attrs[i].oa_value_len);
144 		k_attrs[i].oa_value = attr_val;
145 		k_attrs[i].oa_value_len = in_key->ck_attrs[i].oa_value_len;
146 		attr_val += roundup(k_attrs[i].oa_value_len, sizeof (caddr_t));
147 	}
148 
149 	key->ck_format = CRYPTO_KEY_ATTR_LIST;
150 	key->ck_count = count;
151 	key->ck_attrs = k_attrs;
152 	*out_key = key;
153 	*out_size = len;		/* save the size to be freed */
154 
155 	return (CRYPTO_SUCCESS);
156 }
157 
158 int
crypto_digest_data(crypto_data_t * data,void * dctx,uchar_t * digest,void (* update)(),void (* final)(),uchar_t flag)159 crypto_digest_data(crypto_data_t *data, void *dctx, uchar_t *digest,
160     void (*update)(), void (*final)(), uchar_t flag)
161 {
162 	int rv, dlen;
163 	uchar_t *dptr;
164 
165 	ASSERT(flag & CRYPTO_DO_MD5 || flag & CRYPTO_DO_SHA1 ||
166 	    flag & CRYPTO_DO_SHA2);
167 	if (data == NULL) {
168 		ASSERT((flag & CRYPTO_DO_UPDATE) == 0);
169 		goto dofinal;
170 	}
171 
172 	dlen = data->cd_length;
173 
174 	if (flag & CRYPTO_DO_UPDATE) {
175 
176 		switch (data->cd_format) {
177 		case CRYPTO_DATA_RAW:
178 			dptr = (uchar_t *)(data->cd_raw.iov_base +
179 			    data->cd_offset);
180 
181 			update(dctx, dptr, dlen);
182 
183 		break;
184 
185 		case CRYPTO_DATA_UIO:
186 			if (flag & CRYPTO_DO_MD5)
187 				rv = crypto_uio_data(data, NULL, dlen,
188 				    MD5_DIGEST_DATA, dctx, update);
189 
190 			else if (flag & CRYPTO_DO_SHA1)
191 				rv = crypto_uio_data(data, NULL, dlen,
192 				    SHA1_DIGEST_DATA, dctx, update);
193 
194 			else
195 				rv = crypto_uio_data(data, NULL, dlen,
196 				    SHA2_DIGEST_DATA, dctx, update);
197 
198 			if (rv != CRYPTO_SUCCESS)
199 				return (rv);
200 
201 			break;
202 
203 		case CRYPTO_DATA_MBLK:
204 			if (flag & CRYPTO_DO_MD5)
205 				rv = crypto_mblk_data(data, NULL, dlen,
206 				    MD5_DIGEST_DATA, dctx, update);
207 
208 			else if (flag & CRYPTO_DO_SHA1)
209 				rv = crypto_mblk_data(data, NULL, dlen,
210 				    SHA1_DIGEST_DATA, dctx, update);
211 
212 			else
213 				rv = crypto_mblk_data(data, NULL, dlen,
214 				    SHA2_DIGEST_DATA, dctx, update);
215 
216 			if (rv != CRYPTO_SUCCESS)
217 				return (rv);
218 
219 			break;
220 		}
221 	}
222 
223 dofinal:
224 	if (flag & CRYPTO_DO_FINAL) {
225 		final(digest, dctx);
226 	}
227 
228 	return (CRYPTO_SUCCESS);
229 }
230 
231 int
crypto_update_iov(void * ctx,crypto_data_t * input,crypto_data_t * output,int (* cipher)(void *,caddr_t,size_t,crypto_data_t *),void (* copy_block)(uint8_t *,uint64_t *))232 crypto_update_iov(void *ctx, crypto_data_t *input, crypto_data_t *output,
233     int (*cipher)(void *, caddr_t, size_t, crypto_data_t *),
234     void (*copy_block)(uint8_t *, uint64_t *))
235 {
236 	common_ctx_t *common_ctx = ctx;
237 	int rv;
238 
239 	if (input->cd_miscdata != NULL) {
240 		copy_block((uint8_t *)input->cd_miscdata,
241 		    &common_ctx->cc_iv[0]);
242 	}
243 
244 	if (input->cd_raw.iov_len < input->cd_length)
245 		return (CRYPTO_ARGUMENTS_BAD);
246 
247 	rv = (cipher)(ctx, input->cd_raw.iov_base + input->cd_offset,
248 	    input->cd_length, (input == output) ? NULL : output);
249 
250 	return (rv);
251 }
252 
253 int
crypto_update_uio(void * ctx,crypto_data_t * input,crypto_data_t * output,int (* cipher)(void *,caddr_t,size_t,crypto_data_t *),void (* copy_block)(uint8_t *,uint64_t *))254 crypto_update_uio(void *ctx, crypto_data_t *input, crypto_data_t *output,
255     int (*cipher)(void *, caddr_t, size_t, crypto_data_t *),
256     void (*copy_block)(uint8_t *, uint64_t *))
257 {
258 	common_ctx_t *common_ctx = ctx;
259 	uio_t *uiop = input->cd_uio;
260 	off_t offset = input->cd_offset;
261 	size_t length = input->cd_length;
262 	uint_t vec_idx;
263 	size_t cur_len;
264 
265 	if (input->cd_miscdata != NULL) {
266 		copy_block((uint8_t *)input->cd_miscdata,
267 		    &common_ctx->cc_iv[0]);
268 	}
269 
270 	if (input->cd_uio->uio_segflg != UIO_SYSSPACE) {
271 		return (CRYPTO_ARGUMENTS_BAD);
272 	}
273 
274 	/*
275 	 * Jump to the first iovec containing data to be
276 	 * processed.
277 	 */
278 	for (vec_idx = 0; vec_idx < uiop->uio_iovcnt &&
279 	    offset >= uiop->uio_iov[vec_idx].iov_len;
280 	    offset -= uiop->uio_iov[vec_idx++].iov_len)
281 		;
282 	if (vec_idx == uiop->uio_iovcnt && length > 0) {
283 		/*
284 		 * The caller specified an offset that is larger than the
285 		 * total size of the buffers it provided.
286 		 */
287 		return (CRYPTO_DATA_LEN_RANGE);
288 	}
289 
290 	/*
291 	 * Now process the iovecs.
292 	 */
293 	while (vec_idx < uiop->uio_iovcnt && length > 0) {
294 		cur_len = MIN(uiop->uio_iov[vec_idx].iov_len -
295 		    offset, length);
296 
297 		(cipher)(ctx, uiop->uio_iov[vec_idx].iov_base + offset,
298 		    cur_len, (input == output) ? NULL : output);
299 
300 		length -= cur_len;
301 		vec_idx++;
302 		offset = 0;
303 	}
304 
305 	if (vec_idx == uiop->uio_iovcnt && length > 0) {
306 		/*
307 		 * The end of the specified iovec's was reached but
308 		 * the length requested could not be processed, i.e.
309 		 * The caller requested to digest more data than it provided.
310 		 */
311 
312 		return (CRYPTO_DATA_LEN_RANGE);
313 	}
314 
315 	return (CRYPTO_SUCCESS);
316 }
317 
318 int
crypto_update_mp(void * ctx,crypto_data_t * input,crypto_data_t * output,int (* cipher)(void *,caddr_t,size_t,crypto_data_t *),void (* copy_block)(uint8_t *,uint64_t *))319 crypto_update_mp(void *ctx, crypto_data_t *input, crypto_data_t *output,
320     int (*cipher)(void *, caddr_t, size_t, crypto_data_t *),
321     void (*copy_block)(uint8_t *, uint64_t *))
322 {
323 	common_ctx_t *common_ctx = ctx;
324 	off_t offset = input->cd_offset;
325 	size_t length = input->cd_length;
326 	mblk_t *mp;
327 	size_t cur_len;
328 
329 	if (input->cd_miscdata != NULL) {
330 		copy_block((uint8_t *)input->cd_miscdata,
331 		    &common_ctx->cc_iv[0]);
332 	}
333 
334 	/*
335 	 * Jump to the first mblk_t containing data to be processed.
336 	 */
337 	for (mp = input->cd_mp; mp != NULL && offset >= MBLKL(mp);
338 	    offset -= MBLKL(mp), mp = mp->b_cont)
339 		;
340 	if (mp == NULL) {
341 		/*
342 		 * The caller specified an offset that is larger than the
343 		 * total size of the buffers it provided.
344 		 */
345 		return (CRYPTO_DATA_LEN_RANGE);
346 	}
347 
348 	/*
349 	 * Now do the processing on the mblk chain.
350 	 */
351 	while (mp != NULL && length > 0) {
352 		cur_len = MIN(MBLKL(mp) - offset, length);
353 		(cipher)(ctx, (char *)(mp->b_rptr + offset), cur_len,
354 		    (input == output) ? NULL : output);
355 
356 		length -= cur_len;
357 		offset = 0;
358 		mp = mp->b_cont;
359 	}
360 
361 	if (mp == NULL && length > 0) {
362 		/*
363 		 * The end of the mblk was reached but the length requested
364 		 * could not be processed, i.e. The caller requested
365 		 * to digest more data than it provided.
366 		 */
367 		return (CRYPTO_DATA_LEN_RANGE);
368 	}
369 
370 	return (CRYPTO_SUCCESS);
371 }
372 
373 /*
374  * Utility routine to look up a attribute of type, 'type',
375  * in the key.
376  */
377 int
crypto_get_key_attr(crypto_key_t * key,crypto_attr_type_t type,uchar_t ** value,ssize_t * value_len)378 crypto_get_key_attr(crypto_key_t *key, crypto_attr_type_t type,
379     uchar_t **value, ssize_t *value_len)
380 {
381 	int i;
382 
383 	ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
384 	for (i = 0; i < key->ck_count; i++) {
385 		if (key->ck_attrs[i].oa_type == type) {
386 			*value = (uchar_t *)key->ck_attrs[i].oa_value;
387 			*value_len = key->ck_attrs[i].oa_value_len;
388 			return (CRYPTO_SUCCESS);
389 		}
390 	}
391 
392 	return (CRYPTO_FAILED);
393 }
394 
395 /*
396  * Sanity limit for param copyin size.
397  * Actual sizes are typically tens or maybe a hundred.
398  */
399 size_t kcf_param_copyin_max = 0x4000; /* 16K */
400 
401 /*
402  * Generic functions to copyin/free mechanisms whose parameters need more work
403  * than a simple flat copyin. Similar to dprov_copyin_mechanism().
404  * This is designed to protect against hardware providers that implement these
405  * mechanisms, but do not implement the copyin_mechanism operation, which would
406  * let user pointers be accessed by providers that have no way to detect them.
407  *
408  * The internal form of parameters is always "flattened" here so if the
409  * top level param struct has pointers, they point to later parts of the
410  * same (single) allocation for the entire parameters object.  This sets
411  * out_mech->cm_param_len to the size of that entire (flattened) object
412  * so the later kmem_free(mech->cm_param, mech->cm_param_len) is correct.
413  * All params are limited in size (kcf_param_copyin_max) and since param
414  * copyin happens early in a crypto session lifetime, it's unlikely this
415  * ever runs into resource constraints while doing copyin of parameters.
416  * There are still resource checks, but in the caller after this returns.
417  */
418 int
kcf_copyin_aes_ccm_param(caddr_t in_addr,size_t param_len,crypto_mechanism_t * mech,int mode,int kmflags)419 kcf_copyin_aes_ccm_param(caddr_t in_addr, size_t param_len,
420     crypto_mechanism_t *mech, int mode, int kmflags)
421 {
422 	STRUCT_DECL(CK_AES_CCM_PARAMS, in_param);
423 	CK_AES_CCM_PARAMS *out_param;
424 	size_t out_len;
425 	ulong_t mac_len;
426 	ulong_t nonce_len;
427 	ulong_t authd_len;
428 	size_t s0, s1, s2;
429 	uchar_t *p, *nonce, *authd;
430 	void *uptr;
431 
432 	STRUCT_INIT(in_param, mode);
433 	if (param_len != STRUCT_SIZE(in_param))
434 		return (CRYPTO_ARGUMENTS_BAD);
435 
436 	/*
437 	 * Copyin top-level param struct
438 	 */
439 	if (copyin(in_addr, STRUCT_BUF(in_param), param_len) != 0)
440 		return (CRYPTO_MECHANISM_PARAM_INVALID);
441 
442 	mac_len   = STRUCT_FGET(in_param, ulMACSize);
443 	nonce_len = STRUCT_FGET(in_param, ulNonceSize);
444 	authd_len = STRUCT_FGET(in_param, ulAuthDataSize);
445 
446 	/*
447 	 * Sanity check sizes. See ccm.c:ccm_validate_args
448 	 */
449 	if (mac_len > 16 || nonce_len > 13 ||
450 	    authd_len > kcf_param_copyin_max) {
451 		return (CRYPTO_MECHANISM_PARAM_INVALID);
452 	}
453 
454 	/*
455 	 * Compute size of flattened internal object
456 	 */
457 	s0 = roundup(sizeof (*out_param), sizeof (caddr_t));
458 	s1 = roundup(nonce_len, sizeof (caddr_t));
459 	s2 = roundup(authd_len, sizeof (caddr_t));
460 
461 	/*
462 	 * Allocate and set pointers (out_pram, nonce, authd)
463 	 */
464 	out_len = s0 + s1 + s2;
465 	p = kmem_alloc(out_len, kmflags);
466 	if (p == NULL)
467 		return (CRYPTO_HOST_MEMORY);
468 	out_param = (CK_AES_CCM_PARAMS *)p;
469 	p += s0;
470 	nonce = p;
471 	p += s1;
472 	authd = p;
473 
474 	/*
475 	 * Copyin "inner" param stuff: nonce, authd
476 	 * (pointed to by top-level struct)
477 	 */
478 	uptr = STRUCT_FGETP(in_param, nonce);
479 	if (copyin(uptr, nonce, nonce_len) != 0)
480 		goto badparams;
481 
482 	uptr = STRUCT_FGETP(in_param, authData);
483 	if (copyin(uptr, authd, authd_len) != 0)
484 		goto badparams;
485 
486 	/*
487 	 * Fill out the top-level struct
488 	 */
489 	out_param->ulMACSize = mac_len;
490 	out_param->ulNonceSize = nonce_len;
491 	out_param->ulAuthDataSize = authd_len;
492 	out_param->ulDataSize = STRUCT_FGET(in_param, ulDataSize);
493 	out_param->nonce = nonce;
494 	out_param->authData = authd;
495 
496 	/*
497 	 * Return it.  Free is in crypto_free_mech()
498 	 */
499 	mech->cm_param = (caddr_t)out_param;
500 	mech->cm_param_len = out_len;
501 	return (CRYPTO_SUCCESS);
502 
503 badparams:
504 	kmem_free(out_param, out_len);
505 	return (CRYPTO_MECHANISM_PARAM_INVALID);
506 }
507 
508 int
kcf_copyin_aes_gcm_param(caddr_t in_addr,size_t param_len,crypto_mechanism_t * mech,int mode,int kmflags)509 kcf_copyin_aes_gcm_param(caddr_t in_addr, size_t param_len,
510     crypto_mechanism_t *mech, int mode, int kmflags)
511 {
512 	STRUCT_DECL(CK_AES_GCM_PARAMS, in_param);
513 	CK_AES_GCM_PARAMS *out_param;
514 	size_t out_len;
515 	ulong_t iv_len;
516 	ulong_t ad_len;
517 	size_t s0, s1, s2;
518 	uchar_t *p, *ivp, *adp;
519 	void *uptr;
520 
521 	STRUCT_INIT(in_param, mode);
522 	if (param_len != STRUCT_SIZE(in_param))
523 		return (CRYPTO_ARGUMENTS_BAD);
524 
525 	/*
526 	 * Copyin top-level param struct
527 	 */
528 	if (copyin(in_addr, STRUCT_BUF(in_param), param_len) != 0)
529 		return (CRYPTO_MECHANISM_PARAM_INVALID);
530 
531 	iv_len = STRUCT_FGET(in_param, ulIvLen);
532 	ad_len = STRUCT_FGET(in_param, ulAADLen);
533 
534 	/*
535 	 * Sanity check sizes. See gcm.c:gcm_validate_args
536 	 */
537 	if (iv_len > kcf_param_copyin_max ||
538 	    ad_len > kcf_param_copyin_max) {
539 		return (CRYPTO_MECHANISM_PARAM_INVALID);
540 	}
541 
542 	/*
543 	 * Compute size of flattened internal object
544 	 */
545 	s0 = roundup(sizeof (*out_param), sizeof (caddr_t));
546 	s1 = roundup(iv_len, sizeof (caddr_t));
547 	s2 = roundup(ad_len, sizeof (caddr_t));
548 
549 	/*
550 	 * Allocate and set pointers (out_param, IV, AAD)
551 	 */
552 	out_len = s0 + s1 + s2;
553 	p = kmem_alloc(out_len, kmflags);
554 	if (p == NULL)
555 		return (CRYPTO_HOST_MEMORY);
556 	out_param = (CK_AES_GCM_PARAMS *)p;
557 	p += s0;
558 	ivp = p;
559 	p += s1;
560 	adp = p;
561 
562 	/*
563 	 * Copyin "inner" param stuff: IV, AAD
564 	 * (pointed to by top-level struct)
565 	 */
566 	uptr = STRUCT_FGETP(in_param, pIv);
567 	if (copyin(uptr, ivp, iv_len) != 0)
568 		goto badparams;
569 
570 	uptr = STRUCT_FGETP(in_param, pAAD);
571 	if (copyin(uptr, adp, ad_len) != 0)
572 		goto badparams;
573 
574 	/*
575 	 * Fill out the top-level struct
576 	 */
577 	out_param->pIv = ivp;
578 	out_param->ulIvLen = iv_len;
579 	out_param->ulIvBits = STRUCT_FGET(in_param, ulIvBits);
580 	out_param->pAAD = adp;
581 	out_param->ulAADLen = ad_len;
582 	out_param->ulTagBits = STRUCT_FGET(in_param, ulTagBits);
583 
584 	/*
585 	 * Return it.  Free is in crypto_free_mech()
586 	 */
587 	mech->cm_param = (caddr_t)out_param;
588 	mech->cm_param_len = out_len;
589 	return (CRYPTO_SUCCESS);
590 
591 badparams:
592 	kmem_free(out_param, out_len);
593 	return (CRYPTO_MECHANISM_PARAM_INVALID);
594 }
595 
596 int
kcf_copyin_aes_gmac_param(caddr_t in_addr,size_t param_len,crypto_mechanism_t * mech,int mode,int kmflags)597 kcf_copyin_aes_gmac_param(caddr_t in_addr, size_t param_len,
598     crypto_mechanism_t *mech, int mode, int kmflags)
599 {
600 	STRUCT_DECL(CK_AES_GMAC_PARAMS, in_param);
601 	CK_AES_GMAC_PARAMS *out_param;
602 	size_t out_len;
603 	ulong_t iv_len;
604 	ulong_t ad_len;
605 	size_t s0, s1, s2;
606 	uchar_t *p, *ivp, *adp;
607 	void *uptr;
608 
609 	STRUCT_INIT(in_param, mode);
610 	if (param_len != STRUCT_SIZE(in_param))
611 		return (CRYPTO_ARGUMENTS_BAD);
612 
613 	/*
614 	 * Copyin top-level param struct
615 	 */
616 	if (copyin(in_addr, STRUCT_BUF(in_param), param_len) != 0)
617 		return (CRYPTO_MECHANISM_PARAM_INVALID);
618 
619 	iv_len = AES_GMAC_IV_LEN;
620 	ad_len = STRUCT_FGET(in_param, ulAADLen);
621 
622 	/*
623 	 * Sanity check sizes. See gcm.c:gmac_init_ctx
624 	 */
625 	if (ad_len > kcf_param_copyin_max) {
626 		return (CRYPTO_MECHANISM_PARAM_INVALID);
627 	}
628 
629 	/*
630 	 * Compute size of flattened internal object
631 	 */
632 	s0 = roundup(sizeof (*out_param), sizeof (caddr_t));
633 	s1 = roundup(iv_len, sizeof (caddr_t));
634 	s2 = roundup(ad_len, sizeof (caddr_t));
635 
636 	/*
637 	 * Allocate and set pointers (out_param, IV, AAD)
638 	 */
639 	out_len = s0 + s1 + s2;
640 	p = kmem_alloc(out_len, kmflags);
641 	if (p == NULL)
642 		return (CRYPTO_HOST_MEMORY);
643 	out_param = (CK_AES_GMAC_PARAMS *)p;
644 	p += s0;
645 	ivp = p;
646 	p += s1;
647 	adp = p;
648 
649 	/*
650 	 * Copyin "inner" param stuff: IV, AAD
651 	 * (pointed to by top-level struct)
652 	 */
653 	uptr = STRUCT_FGETP(in_param, pIv);
654 	if (copyin(uptr, ivp, iv_len) != 0)
655 		goto badparams;
656 
657 	uptr = STRUCT_FGETP(in_param, pAAD);
658 	if (copyin(uptr, adp, ad_len) != 0)
659 		goto badparams;
660 
661 	/*
662 	 * Fill out the top-level struct
663 	 */
664 	out_param->pIv = ivp;
665 	out_param->pAAD = adp;
666 	out_param->ulAADLen = ad_len;
667 
668 	/*
669 	 * Return it.  Free is in crypto_free_mech()
670 	 */
671 	mech->cm_param = (caddr_t)out_param;
672 	mech->cm_param_len = out_len;
673 	return (CRYPTO_SUCCESS);
674 
675 badparams:
676 	kmem_free(out_param, out_len);
677 	return (CRYPTO_MECHANISM_PARAM_INVALID);
678 }
679 
680 int
kcf_copyin_ecdh1_param(caddr_t in_addr,size_t param_len,crypto_mechanism_t * mech,int mode,int kmflags)681 kcf_copyin_ecdh1_param(caddr_t in_addr, size_t param_len,
682     crypto_mechanism_t *mech, int mode, int kmflags)
683 {
684 	STRUCT_DECL(CK_ECDH1_DERIVE_PARAMS, in_param);
685 	CK_ECDH1_DERIVE_PARAMS *out_param;
686 	size_t out_len;
687 	ulong_t sd_len;
688 	ulong_t pd_len;
689 	size_t s0, s1, s2;
690 	uchar_t *p, *sdp, *pdp;
691 	void *uptr;
692 
693 	STRUCT_INIT(in_param, mode);
694 	if (param_len != STRUCT_SIZE(in_param))
695 		return (CRYPTO_ARGUMENTS_BAD);
696 
697 	/*
698 	 * Copyin top-level param struct
699 	 */
700 	if (copyin(in_addr, STRUCT_BUF(in_param), param_len) != 0)
701 		return (CRYPTO_MECHANISM_PARAM_INVALID);
702 
703 	sd_len = STRUCT_FGET(in_param, ulSharedDataLen);
704 	pd_len = STRUCT_FGET(in_param, ulPublicDataLen);
705 
706 	/*
707 	 * Sanity check sizes.
708 	 */
709 	if (sd_len > kcf_param_copyin_max ||
710 	    pd_len > kcf_param_copyin_max) {
711 		return (CRYPTO_MECHANISM_PARAM_INVALID);
712 	}
713 
714 	/*
715 	 * Compute size of flattened internal object
716 	 */
717 	s0 = roundup(sizeof (*out_param), sizeof (caddr_t));
718 	s1 = roundup(sd_len, sizeof (caddr_t));
719 	s2 = roundup(pd_len, sizeof (caddr_t));
720 
721 	/*
722 	 * Allocate and set pointers (out_param, SD, PD)
723 	 */
724 	out_len = s0 + s1 + s2;
725 	p = kmem_alloc(out_len, kmflags);
726 	if (p == NULL)
727 		return (CRYPTO_HOST_MEMORY);
728 	out_param = (CK_ECDH1_DERIVE_PARAMS *)p;
729 	p += s0;
730 	sdp = p;
731 	p += s1;
732 	pdp = p;
733 
734 	/*
735 	 * Copyin "inner" param stuff: SD, PD
736 	 * (pointed to by top-level struct)
737 	 */
738 	uptr = STRUCT_FGETP(in_param, pSharedData);
739 	if (copyin(uptr, sdp, sd_len) != 0)
740 		goto badparams;
741 
742 	uptr = STRUCT_FGETP(in_param, pPublicData);
743 	if (copyin(uptr, pdp, pd_len) != 0)
744 		goto badparams;
745 
746 	/*
747 	 * Fill out the top-level struct
748 	 */
749 	out_param->kdf = STRUCT_FGET(in_param, kdf);
750 	out_param->ulSharedDataLen = sd_len;
751 	out_param->pSharedData = sdp;
752 	out_param->ulPublicDataLen = pd_len;
753 	out_param->pPublicData = pdp;
754 
755 	/*
756 	 * Return it.  Free is in crypto_free_mech()
757 	 */
758 	mech->cm_param = (caddr_t)out_param;
759 	mech->cm_param_len = out_len;
760 	return (CRYPTO_SUCCESS);
761 
762 badparams:
763 	kmem_free(out_param, out_len);
764 	return (CRYPTO_MECHANISM_PARAM_INVALID);
765 }
766