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