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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
24 * Copyright 2018, Joyent, Inc.
25 */
26
27
28 /*
29 * The ioctl interface for cryptographic commands.
30 */
31
32 #include <sys/types.h>
33 #include <sys/modctl.h>
34 #include <sys/conf.h>
35 #include <sys/stat.h>
36 #include <sys/ddi.h>
37 #include <sys/sunddi.h>
38 #include <sys/kmem.h>
39 #include <sys/errno.h>
40 #include <sys/ksynch.h>
41 #include <sys/file.h>
42 #include <sys/open.h>
43 #include <sys/cred.h>
44 #include <sys/proc.h>
45 #include <sys/task.h>
46 #include <sys/mkdev.h>
47 #include <sys/model.h>
48 #include <sys/sysmacros.h>
49 #include <sys/crypto/common.h>
50 #include <sys/crypto/api.h>
51 #include <sys/crypto/impl.h>
52 #include <sys/crypto/sched_impl.h>
53 #include <sys/crypto/ioctl.h>
54
55 extern int kcf_des3_threshold;
56 extern int kcf_aes_threshold;
57 extern int kcf_rc4_threshold;
58 extern int kcf_md5_threshold;
59 extern int kcf_sha1_threshold;
60
61 /*
62 * Locking notes:
63 *
64 * crypto_locks protects the global array of minor structures.
65 * crypto_locks is an array of locks indexed by the cpuid. A reader needs
66 * to hold a single lock while a writer needs to hold all locks.
67 * krwlock_t is not an option here because the hold time
68 * is very small for these locks.
69 *
70 * The fields in the minor structure are protected by the cm_lock member
71 * of the minor structure. The cm_cv is used to signal decrements
72 * in the cm_refcnt, and is used with the cm_lock.
73 *
74 * The locking order is crypto_locks followed by cm_lock.
75 */
76
77 /*
78 * DDI entry points.
79 */
80 static int crypto_attach(dev_info_t *, ddi_attach_cmd_t);
81 static int crypto_detach(dev_info_t *, ddi_detach_cmd_t);
82 static int crypto_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
83 static int crypto_open(dev_t *, int, int, cred_t *);
84 static int crypto_close(dev_t, int, int, cred_t *);
85 static int crypto_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
86
87 static int cipher_init(dev_t, caddr_t, int, int (*)(crypto_provider_t,
88 crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
89 crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *));
90
91 static int common_digest(dev_t, caddr_t, int, int (*)(crypto_context_t,
92 crypto_data_t *, crypto_data_t *, crypto_call_req_t *));
93
94 static int cipher(dev_t, caddr_t, int, int (*)(crypto_context_t,
95 crypto_data_t *, crypto_data_t *, crypto_call_req_t *));
96
97 static int cipher_update(dev_t, caddr_t, int, int (*)(crypto_context_t,
98 crypto_data_t *, crypto_data_t *, crypto_call_req_t *));
99
100 static int common_final(dev_t, caddr_t, int, int (*)(crypto_context_t,
101 crypto_data_t *, crypto_call_req_t *));
102
103 static int sign_verify_init(dev_t, caddr_t, int, int (*)(crypto_provider_t,
104 crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
105 crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *));
106
107 static int sign_verify_update(dev_t dev, caddr_t arg, int mode,
108 int (*)(crypto_context_t, crypto_data_t *, crypto_call_req_t *));
109
110 static void crypto_release_provider_session(crypto_minor_t *,
111 crypto_provider_session_t *);
112 static int crypto_buffer_check(size_t);
113 static int crypto_free_find_ctx(crypto_session_data_t *);
114 static int crypto_get_provider_list(crypto_minor_t *, uint_t *,
115 crypto_provider_entry_t **, boolean_t);
116
117 static int crypto_create_provider_session(crypto_minor_t *,
118 kcf_provider_desc_t *, crypto_session_id_t, crypto_provider_session_t **,
119 kcf_provider_desc_t *);
120 static int crypto_create_session_ptr(crypto_minor_t *, kcf_provider_desc_t *,
121 crypto_provider_session_t *, crypto_session_id_t *);
122
123 /* number of minor numbers to allocate at a time */
124 #define CRYPTO_MINOR_CHUNK 16
125
126 /*
127 * There are two limits associated with kernel memory. The first,
128 * CRYPTO_MAX_BUFFER_LEN, is the maximum number of bytes that can be
129 * allocated for a single copyin/copyout buffer. The second limit is
130 * the total number of bytes that can be allocated by a process
131 * for copyin/copyout buffers. The latter is enforced by the
132 * project.max-crypto-memory resource control.
133 */
134
135 #define CRYPTO_MAX_BUFFER_LEN (2 * 1024 * 1024)
136 #define CRYPTO_MAX_FIND_COUNT 512
137
138 /*
139 * We preapprove some bytes for each session to avoid making the costly
140 * crypto_buffer_check() calls. The preapproval is done when a new session
141 * is created and that cost is amortized over later crypto calls.
142 * Most applications create a session and then do a bunch of crypto calls
143 * in that session. So, they benefit from this optimization.
144 *
145 * Note that we may hit the project.max-crypto-memory limit a bit sooner
146 * because of this preapproval. But it is acceptable since the preapproved
147 * amount is insignificant compared to the default max-crypto-memory limit
148 * which is quarter of the machine's memory. The preapproved amount is
149 * roughly 2 * 16K(maximum SSL record size).
150 */
151 #define CRYPTO_PRE_APPROVED_LIMIT (32 * 1024)
152
153 /* The session table grows by CRYPTO_SESSION_CHUNK increments */
154 #define CRYPTO_SESSION_CHUNK 100
155
156 size_t crypto_max_buffer_len = CRYPTO_MAX_BUFFER_LEN;
157 size_t crypto_pre_approved_limit = CRYPTO_PRE_APPROVED_LIMIT;
158
159 #define INIT_RAW_CRYPTO_DATA(data, len) \
160 (data).cd_format = CRYPTO_DATA_RAW; \
161 (data).cd_raw.iov_base = (len > 0) ? kmem_alloc(len, KM_SLEEP) : NULL; \
162 (data).cd_raw.iov_len = len; \
163 (data).cd_offset = 0; \
164 (data).cd_length = len;
165
166 static struct kmem_cache *crypto_session_cache;
167 static crypto_minor_t **crypto_minors = NULL;
168 static dev_info_t *crypto_dip = NULL;
169 static minor_t crypto_minor_chunk = CRYPTO_MINOR_CHUNK;
170 static minor_t crypto_minors_table_count = 0;
171
172 /*
173 * Minors are started from 1 because vmem_alloc()
174 * returns 0 in case of failure.
175 */
176 static vmem_t *crypto_arena = NULL; /* Arena for device minors */
177 static minor_t crypto_minors_count = 0;
178 static kcf_lock_withpad_t *crypto_locks;
179
180 #define CRYPTO_ENTER_ALL_LOCKS() \
181 for (i = 0; i < max_ncpus; i++) \
182 mutex_enter(&crypto_locks[i].kl_lock);
183
184 #define CRYPTO_EXIT_ALL_LOCKS() \
185 for (i = 0; i < max_ncpus; i++) \
186 mutex_exit(&crypto_locks[i].kl_lock);
187
188 #define RETURN_LIST B_TRUE
189 #define DONT_RETURN_LIST B_FALSE
190
191 #define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
192 #define CRYPTO_RANDOM_OFFSET(f) offsetof(crypto_random_number_ops_t, f)
193 #define CRYPTO_SESSION_OFFSET(f) offsetof(crypto_session_ops_t, f)
194 #define CRYPTO_OBJECT_OFFSET(f) offsetof(crypto_object_ops_t, f)
195 #define CRYPTO_PROVIDER_OFFSET(f) \
196 offsetof(crypto_provider_management_ops_t, f)
197
198 #define CRYPTO_CANCEL_CTX(spp) { \
199 crypto_cancel_ctx(*(spp)); \
200 *(spp) = NULL; \
201 }
202
203 #define CRYPTO_CANCEL_ALL_CTX(sp) { \
204 if ((sp)->sd_digest_ctx != NULL) { \
205 crypto_cancel_ctx((sp)->sd_digest_ctx); \
206 (sp)->sd_digest_ctx = NULL; \
207 } \
208 if ((sp)->sd_encr_ctx != NULL) { \
209 crypto_cancel_ctx((sp)->sd_encr_ctx); \
210 (sp)->sd_encr_ctx = NULL; \
211 } \
212 if ((sp)->sd_decr_ctx != NULL) { \
213 crypto_cancel_ctx((sp)->sd_decr_ctx); \
214 (sp)->sd_decr_ctx = NULL; \
215 } \
216 if ((sp)->sd_sign_ctx != NULL) { \
217 crypto_cancel_ctx((sp)->sd_sign_ctx); \
218 (sp)->sd_sign_ctx = NULL; \
219 } \
220 if ((sp)->sd_verify_ctx != NULL) { \
221 crypto_cancel_ctx((sp)->sd_verify_ctx); \
222 (sp)->sd_verify_ctx = NULL; \
223 } \
224 if ((sp)->sd_sign_recover_ctx != NULL) { \
225 crypto_cancel_ctx((sp)->sd_sign_recover_ctx); \
226 (sp)->sd_sign_recover_ctx = NULL; \
227 } \
228 if ((sp)->sd_verify_recover_ctx != NULL) { \
229 crypto_cancel_ctx((sp)->sd_verify_recover_ctx); \
230 (sp)->sd_verify_recover_ctx = NULL; \
231 } \
232 if ((sp)->sd_mac_ctx != NULL) { \
233 crypto_cancel_ctx((sp)->sd_mac_ctx); \
234 (sp)->sd_mac_ctx = NULL; \
235 } \
236 }
237
238 #define CRYPTO_DECREMENT_RCTL(val) if ((val) != 0) { \
239 kproject_t *projp; \
240 mutex_enter(&curproc->p_lock); \
241 projp = curproc->p_task->tk_proj; \
242 ASSERT(projp != NULL); \
243 mutex_enter(&(projp->kpj_data.kpd_crypto_lock)); \
244 projp->kpj_data.kpd_crypto_mem -= (val); \
245 mutex_exit(&(projp->kpj_data.kpd_crypto_lock)); \
246 curproc->p_crypto_mem -= (val); \
247 mutex_exit(&curproc->p_lock); \
248 }
249
250 /*
251 * We do not need to hold sd_lock in the macros below
252 * as they are called after doing a get_session_ptr() which
253 * sets the CRYPTO_SESSION_IS_BUSY flag.
254 */
255 #define CRYPTO_DECREMENT_RCTL_SESSION(sp, val, rctl_chk) \
256 if (((val) != 0) && ((sp) != NULL)) { \
257 ASSERT(((sp)->sd_flags & CRYPTO_SESSION_IS_BUSY) != 0); \
258 if (rctl_chk) { \
259 CRYPTO_DECREMENT_RCTL(val); \
260 } else { \
261 (sp)->sd_pre_approved_amount += (val); \
262 } \
263 }
264
265 #define CRYPTO_BUFFER_CHECK(sp, need, rctl_chk) \
266 ((sp->sd_pre_approved_amount >= need) ? \
267 (sp->sd_pre_approved_amount -= need, \
268 rctl_chk = B_FALSE, CRYPTO_SUCCESS) : \
269 (rctl_chk = B_TRUE, crypto_buffer_check(need)))
270
271 /*
272 * Module linkage.
273 */
274 static struct cb_ops cbops = {
275 crypto_open, /* cb_open */
276 crypto_close, /* cb_close */
277 nodev, /* cb_strategy */
278 nodev, /* cb_print */
279 nodev, /* cb_dump */
280 nodev, /* cb_read */
281 nodev, /* cb_write */
282 crypto_ioctl, /* cb_ioctl */
283 nodev, /* cb_devmap */
284 nodev, /* cb_mmap */
285 nodev, /* cb_segmap */
286 nochpoll, /* cb_chpoll */
287 ddi_prop_op, /* cb_prop_op */
288 NULL, /* cb_streamtab */
289 D_MP, /* cb_flag */
290 CB_REV, /* cb_rev */
291 nodev, /* cb_aread */
292 nodev, /* cb_awrite */
293 };
294
295 static struct dev_ops devops = {
296 DEVO_REV, /* devo_rev */
297 0, /* devo_refcnt */
298 crypto_getinfo, /* devo_getinfo */
299 nulldev, /* devo_identify */
300 nulldev, /* devo_probe */
301 crypto_attach, /* devo_attach */
302 crypto_detach, /* devo_detach */
303 nodev, /* devo_reset */
304 &cbops, /* devo_cb_ops */
305 NULL, /* devo_bus_ops */
306 NULL, /* devo_power */
307 ddi_quiesce_not_needed, /* devo_quiesce */
308 };
309
310 static struct modldrv modldrv = {
311 &mod_driverops, /* drv_modops */
312 "Cryptographic Library Interface", /* drv_linkinfo */
313 &devops,
314 };
315
316 static struct modlinkage modlinkage = {
317 MODREV_1, /* ml_rev */
318 &modldrv, /* ml_linkage */
319 NULL
320 };
321
322 /*
323 * DDI entry points.
324 */
325 int
_init(void)326 _init(void)
327 {
328 return (mod_install(&modlinkage));
329 }
330
331 int
_fini(void)332 _fini(void)
333 {
334 return (mod_remove(&modlinkage));
335 }
336
337 int
_info(struct modinfo * modinfop)338 _info(struct modinfo *modinfop)
339 {
340 return (mod_info(&modlinkage, modinfop));
341 }
342
343 /* ARGSUSED */
344 static int
crypto_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)345 crypto_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
346 {
347 switch (cmd) {
348 case DDI_INFO_DEVT2DEVINFO:
349 *result = crypto_dip;
350 return (DDI_SUCCESS);
351
352 case DDI_INFO_DEVT2INSTANCE:
353 *result = (void *)0;
354 return (DDI_SUCCESS);
355 }
356 return (DDI_FAILURE);
357 }
358
359 static int
crypto_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)360 crypto_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
361 {
362 int i;
363
364 if (cmd != DDI_ATTACH) {
365 return (DDI_FAILURE);
366 }
367
368 if (ddi_get_instance(dip) != 0) {
369 /* we only allow instance 0 to attach */
370 return (DDI_FAILURE);
371 }
372
373 crypto_session_cache = kmem_cache_create("crypto_session_cache",
374 sizeof (crypto_session_data_t), 0, NULL, NULL, NULL, NULL, NULL, 0);
375
376 if (crypto_session_cache == NULL)
377 return (DDI_FAILURE);
378
379 /* create the minor node */
380 if (ddi_create_minor_node(dip, "crypto", S_IFCHR, 0,
381 DDI_PSEUDO, 0) != DDI_SUCCESS) {
382 kmem_cache_destroy(crypto_session_cache);
383 crypto_session_cache = NULL;
384 cmn_err(CE_WARN, "crypto_attach: failed creating minor node");
385 ddi_remove_minor_node(dip, NULL);
386 return (DDI_FAILURE);
387 }
388
389 crypto_locks = kmem_zalloc(max_ncpus * sizeof (kcf_lock_withpad_t),
390 KM_SLEEP);
391 for (i = 0; i < max_ncpus; i++)
392 mutex_init(&crypto_locks[i].kl_lock, NULL, MUTEX_DRIVER, NULL);
393
394 crypto_dip = dip;
395
396 /* allocate integer space for minor numbers */
397 crypto_arena = vmem_create("crypto", (void *)1,
398 CRYPTO_MINOR_CHUNK, 1, NULL, NULL, NULL, 0,
399 VM_SLEEP | VMC_IDENTIFIER);
400
401 return (DDI_SUCCESS);
402 }
403
404 static int
crypto_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)405 crypto_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
406 {
407 minor_t i;
408 kcf_lock_withpad_t *mp;
409
410 if (cmd != DDI_DETACH)
411 return (DDI_FAILURE);
412
413 mp = &crypto_locks[CPU_SEQID];
414 mutex_enter(&mp->kl_lock);
415
416 /* check if device is open */
417 for (i = 0; i < crypto_minors_table_count; i++) {
418 if (crypto_minors[i] != NULL) {
419 mutex_exit(&mp->kl_lock);
420 return (DDI_FAILURE);
421 }
422 }
423 mutex_exit(&mp->kl_lock);
424
425 crypto_dip = NULL;
426 ddi_remove_minor_node(dip, NULL);
427
428 kmem_cache_destroy(crypto_session_cache);
429 crypto_session_cache = NULL;
430
431 kmem_free(crypto_minors,
432 sizeof (crypto_minor_t *) * crypto_minors_table_count);
433 crypto_minors = NULL;
434 crypto_minors_table_count = 0;
435 for (i = 0; i < max_ncpus; i++)
436 mutex_destroy(&crypto_locks[i].kl_lock);
437 kmem_free(crypto_locks, max_ncpus * sizeof (kcf_lock_withpad_t));
438 crypto_locks = NULL;
439
440 vmem_destroy(crypto_arena);
441 crypto_arena = NULL;
442
443 return (DDI_SUCCESS);
444 }
445
446 /* ARGSUSED3 */
447 static int
crypto_open(dev_t * devp,int flag,int otyp,cred_t * credp)448 crypto_open(dev_t *devp, int flag, int otyp, cred_t *credp)
449 {
450 crypto_minor_t *cm = NULL;
451 minor_t mn;
452 kcf_lock_withpad_t *mp;
453 int i;
454
455 if (otyp != OTYP_CHR)
456 return (ENXIO);
457
458 if (crypto_dip == NULL)
459 return (ENXIO);
460
461 /* exclusive opens are not supported */
462 if (flag & FEXCL)
463 return (ENOTSUP);
464
465 again:
466 mp = &crypto_locks[CPU_SEQID];
467 mutex_enter(&mp->kl_lock);
468
469 /* grow the minors table if needed */
470 if (crypto_minors_count >= crypto_minors_table_count) {
471 crypto_minor_t **newtable;
472 minor_t chunk = crypto_minor_chunk;
473 minor_t saved_count;
474 size_t new_size;
475 ulong_t big_count;
476
477 big_count = crypto_minors_count + chunk;
478 if (big_count > MAXMIN) {
479 mutex_exit(&mp->kl_lock);
480 return (ENOMEM);
481 }
482
483 saved_count = crypto_minors_table_count;
484 new_size = sizeof (crypto_minor_t *) *
485 (crypto_minors_table_count + chunk);
486
487 mutex_exit(&mp->kl_lock);
488
489 newtable = kmem_zalloc(new_size, KM_SLEEP);
490 CRYPTO_ENTER_ALL_LOCKS();
491 /*
492 * Check if table grew while we were sleeping.
493 * The minors table never shrinks.
494 */
495 if (crypto_minors_table_count > saved_count) {
496 CRYPTO_EXIT_ALL_LOCKS();
497 kmem_free(newtable, new_size);
498 goto again;
499 }
500
501 /* we assume that bcopy() will return if count is 0 */
502 bcopy(crypto_minors, newtable,
503 sizeof (crypto_minor_t *) * crypto_minors_table_count);
504
505 kmem_free(crypto_minors,
506 sizeof (crypto_minor_t *) * crypto_minors_table_count);
507
508 /* grow the minors number space */
509 if (crypto_minors_table_count != 0) {
510 (void) vmem_add(crypto_arena,
511 (void *)(uintptr_t)(crypto_minors_table_count + 1),
512 crypto_minor_chunk, VM_SLEEP);
513 }
514
515 crypto_minors = newtable;
516 crypto_minors_table_count += chunk;
517 CRYPTO_EXIT_ALL_LOCKS();
518 } else {
519 mutex_exit(&mp->kl_lock);
520 }
521
522 /* allocate a new minor number starting with 1 */
523 mn = (minor_t)(uintptr_t)vmem_alloc(crypto_arena, 1, VM_SLEEP);
524
525 cm = kmem_zalloc(sizeof (crypto_minor_t), KM_SLEEP);
526 mutex_init(&cm->cm_lock, NULL, MUTEX_DRIVER, NULL);
527 cv_init(&cm->cm_cv, NULL, CV_DRIVER, NULL);
528
529 CRYPTO_ENTER_ALL_LOCKS();
530 cm->cm_refcnt = 1;
531 crypto_minors[mn - 1] = cm;
532 crypto_minors_count++;
533 CRYPTO_EXIT_ALL_LOCKS();
534
535 *devp = makedevice(getmajor(*devp), mn);
536
537 return (0);
538 }
539
540 /* ARGSUSED1 */
541 static int
crypto_close(dev_t dev,int flag,int otyp,cred_t * credp)542 crypto_close(dev_t dev, int flag, int otyp, cred_t *credp)
543 {
544 crypto_minor_t *cm = NULL;
545 crypto_session_data_t *sp;
546 minor_t mn = getminor(dev);
547 uint_t i;
548 size_t total = 0;
549 kcf_lock_withpad_t *mp;
550
551 mp = &crypto_locks[CPU_SEQID];
552 mutex_enter(&mp->kl_lock);
553
554 if (mn > crypto_minors_table_count) {
555 mutex_exit(&mp->kl_lock);
556 cmn_err(CE_WARN, "crypto_close: bad minor (too big) %d", mn);
557 return (ENODEV);
558 }
559
560 cm = crypto_minors[mn - 1];
561 if (cm == NULL) {
562 mutex_exit(&mp->kl_lock);
563 cmn_err(CE_WARN, "crypto_close: duplicate close of minor %d",
564 getminor(dev));
565 return (ENODEV);
566 }
567
568 mutex_exit(&mp->kl_lock);
569
570 CRYPTO_ENTER_ALL_LOCKS();
571 /*
572 * We free the minor number, mn, from the crypto_arena
573 * only later. This ensures that we won't race with another
574 * thread in crypto_open with the same minor number.
575 */
576 crypto_minors[mn - 1] = NULL;
577 crypto_minors_count--;
578 CRYPTO_EXIT_ALL_LOCKS();
579
580 mutex_enter(&cm->cm_lock);
581 cm->cm_refcnt --; /* decrement refcnt held in open */
582 while (cm->cm_refcnt > 0) {
583 cv_wait(&cm->cm_cv, &cm->cm_lock);
584 }
585
586 vmem_free(crypto_arena, (void *)(uintptr_t)mn, 1);
587
588 /* free all session table entries starting with 1 */
589 for (i = 1; i < cm->cm_session_table_count; i++) {
590 if (cm->cm_session_table[i] == NULL)
591 continue;
592
593 sp = cm->cm_session_table[i];
594 ASSERT((sp->sd_flags & CRYPTO_SESSION_IS_BUSY) == 0);
595 ASSERT(sp->sd_pre_approved_amount == 0 ||
596 sp->sd_pre_approved_amount == crypto_pre_approved_limit);
597 total += sp->sd_pre_approved_amount;
598 if (sp->sd_find_init_cookie != NULL) {
599 (void) crypto_free_find_ctx(sp);
600 }
601 crypto_release_provider_session(cm, sp->sd_provider_session);
602 KCF_PROV_REFRELE(sp->sd_provider);
603 CRYPTO_CANCEL_ALL_CTX(sp);
604 mutex_destroy(&sp->sd_lock);
605 cv_destroy(&sp->sd_cv);
606 kmem_cache_free(crypto_session_cache, sp);
607 cm->cm_session_table[i] = NULL;
608 }
609
610 /* free the session table */
611 if (cm->cm_session_table != NULL && cm->cm_session_table_count > 0)
612 kmem_free(cm->cm_session_table, cm->cm_session_table_count *
613 sizeof (void *));
614
615 total += (cm->cm_session_table_count * sizeof (void *));
616 CRYPTO_DECREMENT_RCTL(total);
617
618 kcf_free_provider_tab(cm->cm_provider_count,
619 cm->cm_provider_array);
620
621 mutex_exit(&cm->cm_lock);
622 mutex_destroy(&cm->cm_lock);
623 cv_destroy(&cm->cm_cv);
624 kmem_free(cm, sizeof (crypto_minor_t));
625
626 return (0);
627 }
628
629 static crypto_minor_t *
crypto_hold_minor(minor_t minor)630 crypto_hold_minor(minor_t minor)
631 {
632 crypto_minor_t *cm;
633 kcf_lock_withpad_t *mp;
634
635 if (minor > crypto_minors_table_count)
636 return (NULL);
637
638 mp = &crypto_locks[CPU_SEQID];
639 mutex_enter(&mp->kl_lock);
640
641 if ((cm = crypto_minors[minor - 1]) != NULL) {
642 atomic_inc_32(&cm->cm_refcnt);
643 }
644 mutex_exit(&mp->kl_lock);
645 return (cm);
646 }
647
648 static void
crypto_release_minor(crypto_minor_t * cm)649 crypto_release_minor(crypto_minor_t *cm)
650 {
651 if (atomic_dec_32_nv(&cm->cm_refcnt) == 0) {
652 cv_signal(&cm->cm_cv);
653 }
654 }
655
656 /*
657 * Build a list of functions and other information for the provider, pd.
658 */
659 static void
crypto_build_function_list(crypto_function_list_t * fl,kcf_provider_desc_t * pd)660 crypto_build_function_list(crypto_function_list_t *fl, kcf_provider_desc_t *pd)
661 {
662 crypto_ops_t *ops;
663 crypto_digest_ops_t *digest_ops;
664 crypto_cipher_ops_t *cipher_ops;
665 crypto_mac_ops_t *mac_ops;
666 crypto_sign_ops_t *sign_ops;
667 crypto_verify_ops_t *verify_ops;
668 crypto_dual_ops_t *dual_ops;
669 crypto_random_number_ops_t *random_number_ops;
670 crypto_session_ops_t *session_ops;
671 crypto_object_ops_t *object_ops;
672 crypto_key_ops_t *key_ops;
673 crypto_provider_management_ops_t *provider_ops;
674
675 if ((ops = pd->pd_ops_vector) == NULL)
676 return;
677
678 if ((digest_ops = ops->co_digest_ops) != NULL) {
679 if (digest_ops->digest_init != NULL)
680 fl->fl_digest_init = B_TRUE;
681 if (digest_ops->digest != NULL)
682 fl->fl_digest = B_TRUE;
683 if (digest_ops->digest_update != NULL)
684 fl->fl_digest_update = B_TRUE;
685 if (digest_ops->digest_key != NULL)
686 fl->fl_digest_key = B_TRUE;
687 if (digest_ops->digest_final != NULL)
688 fl->fl_digest_final = B_TRUE;
689 }
690 if ((cipher_ops = ops->co_cipher_ops) != NULL) {
691 if (cipher_ops->encrypt_init != NULL)
692 fl->fl_encrypt_init = B_TRUE;
693 if (cipher_ops->encrypt != NULL)
694 fl->fl_encrypt = B_TRUE;
695 if (cipher_ops->encrypt_update != NULL)
696 fl->fl_encrypt_update = B_TRUE;
697 if (cipher_ops->encrypt_final != NULL)
698 fl->fl_encrypt_final = B_TRUE;
699 if (cipher_ops->decrypt_init != NULL)
700 fl->fl_decrypt_init = B_TRUE;
701 if (cipher_ops->decrypt != NULL)
702 fl->fl_decrypt = B_TRUE;
703 if (cipher_ops->decrypt_update != NULL)
704 fl->fl_decrypt_update = B_TRUE;
705 if (cipher_ops->decrypt_final != NULL)
706 fl->fl_decrypt_final = B_TRUE;
707 }
708 if ((mac_ops = ops->co_mac_ops) != NULL) {
709 if (mac_ops->mac_init != NULL)
710 fl->fl_mac_init = B_TRUE;
711 if (mac_ops->mac != NULL)
712 fl->fl_mac = B_TRUE;
713 if (mac_ops->mac_update != NULL)
714 fl->fl_mac_update = B_TRUE;
715 if (mac_ops->mac_final != NULL)
716 fl->fl_mac_final = B_TRUE;
717 }
718 if ((sign_ops = ops->co_sign_ops) != NULL) {
719 if (sign_ops->sign_init != NULL)
720 fl->fl_sign_init = B_TRUE;
721 if (sign_ops->sign != NULL)
722 fl->fl_sign = B_TRUE;
723 if (sign_ops->sign_update != NULL)
724 fl->fl_sign_update = B_TRUE;
725 if (sign_ops->sign_final != NULL)
726 fl->fl_sign_final = B_TRUE;
727 if (sign_ops->sign_recover_init != NULL)
728 fl->fl_sign_recover_init = B_TRUE;
729 if (sign_ops->sign_recover != NULL)
730 fl->fl_sign_recover = B_TRUE;
731 }
732 if ((verify_ops = ops->co_verify_ops) != NULL) {
733 if (verify_ops->verify_init != NULL)
734 fl->fl_verify_init = B_TRUE;
735 if (verify_ops->verify != NULL)
736 fl->fl_verify = B_TRUE;
737 if (verify_ops->verify_update != NULL)
738 fl->fl_verify_update = B_TRUE;
739 if (verify_ops->verify_final != NULL)
740 fl->fl_verify_final = B_TRUE;
741 if (verify_ops->verify_recover_init != NULL)
742 fl->fl_verify_recover_init = B_TRUE;
743 if (verify_ops->verify_recover != NULL)
744 fl->fl_verify_recover = B_TRUE;
745 }
746 if ((dual_ops = ops->co_dual_ops) != NULL) {
747 if (dual_ops->digest_encrypt_update != NULL)
748 fl->fl_digest_encrypt_update = B_TRUE;
749 if (dual_ops->decrypt_digest_update != NULL)
750 fl->fl_decrypt_digest_update = B_TRUE;
751 if (dual_ops->sign_encrypt_update != NULL)
752 fl->fl_sign_encrypt_update = B_TRUE;
753 if (dual_ops->decrypt_verify_update != NULL)
754 fl->fl_decrypt_verify_update = B_TRUE;
755 }
756 if ((random_number_ops = ops->co_random_ops) != NULL) {
757 if (random_number_ops->seed_random != NULL)
758 fl->fl_seed_random = B_TRUE;
759 if (random_number_ops->generate_random != NULL)
760 fl->fl_generate_random = B_TRUE;
761 }
762 if ((session_ops = ops->co_session_ops) != NULL) {
763 if (session_ops->session_open != NULL)
764 fl->fl_session_open = B_TRUE;
765 if (session_ops->session_close != NULL)
766 fl->fl_session_close = B_TRUE;
767 if (session_ops->session_login != NULL)
768 fl->fl_session_login = B_TRUE;
769 if (session_ops->session_logout != NULL)
770 fl->fl_session_logout = B_TRUE;
771 }
772 if ((object_ops = ops->co_object_ops) != NULL) {
773 if (object_ops->object_create != NULL)
774 fl->fl_object_create = B_TRUE;
775 if (object_ops->object_copy != NULL)
776 fl->fl_object_copy = B_TRUE;
777 if (object_ops->object_destroy != NULL)
778 fl->fl_object_destroy = B_TRUE;
779 if (object_ops->object_get_size != NULL)
780 fl->fl_object_get_size = B_TRUE;
781 if (object_ops->object_get_attribute_value != NULL)
782 fl->fl_object_get_attribute_value = B_TRUE;
783 if (object_ops->object_set_attribute_value != NULL)
784 fl->fl_object_set_attribute_value = B_TRUE;
785 if (object_ops->object_find_init != NULL)
786 fl->fl_object_find_init = B_TRUE;
787 if (object_ops->object_find != NULL)
788 fl->fl_object_find = B_TRUE;
789 if (object_ops->object_find_final != NULL)
790 fl->fl_object_find_final = B_TRUE;
791 }
792 if ((key_ops = ops->co_key_ops) != NULL) {
793 if (key_ops->key_generate != NULL)
794 fl->fl_key_generate = B_TRUE;
795 if (key_ops->key_generate_pair != NULL)
796 fl->fl_key_generate_pair = B_TRUE;
797 if (key_ops->key_wrap != NULL)
798 fl->fl_key_wrap = B_TRUE;
799 if (key_ops->key_unwrap != NULL)
800 fl->fl_key_unwrap = B_TRUE;
801 if (key_ops->key_derive != NULL)
802 fl->fl_key_derive = B_TRUE;
803 }
804 if ((provider_ops = ops->co_provider_ops) != NULL) {
805 if (provider_ops->init_token != NULL)
806 fl->fl_init_token = B_TRUE;
807 if (provider_ops->init_pin != NULL)
808 fl->fl_init_pin = B_TRUE;
809 if (provider_ops->set_pin != NULL)
810 fl->fl_set_pin = B_TRUE;
811 }
812
813 fl->prov_is_hash_limited = pd->pd_flags & CRYPTO_HASH_NO_UPDATE;
814 if (fl->prov_is_hash_limited) {
815 fl->prov_hash_limit = min(pd->pd_hash_limit,
816 min(CRYPTO_MAX_BUFFER_LEN,
817 curproc->p_task->tk_proj->kpj_data.kpd_crypto_mem_ctl));
818 }
819
820 fl->prov_is_hmac_limited = pd->pd_flags & CRYPTO_HMAC_NO_UPDATE;
821 if (fl->prov_is_hmac_limited) {
822 fl->prov_hmac_limit = min(pd->pd_hmac_limit,
823 min(CRYPTO_MAX_BUFFER_LEN,
824 curproc->p_task->tk_proj->kpj_data.kpd_crypto_mem_ctl));
825 }
826
827 if (fl->prov_is_hash_limited || fl->prov_is_hmac_limited) {
828 /*
829 * XXX - The threshold should ideally be per hash/HMAC
830 * mechanism. For now, we use the same value for all
831 * hash/HMAC mechanisms. Empirical evidence suggests this
832 * is fine.
833 */
834 fl->prov_hash_threshold = kcf_md5_threshold;
835 }
836
837 fl->total_threshold_count = MAX_NUM_THRESHOLD;
838 fl->fl_threshold[0].mech_type = CKM_DES3_CBC;
839 fl->fl_threshold[0].mech_threshold = kcf_des3_threshold;
840 fl->fl_threshold[1].mech_type = CKM_DES3_ECB;
841 fl->fl_threshold[1].mech_threshold = kcf_des3_threshold;
842 fl->fl_threshold[2].mech_type = CKM_AES_CBC;
843 fl->fl_threshold[2].mech_threshold = kcf_aes_threshold;
844 fl->fl_threshold[3].mech_type = CKM_AES_ECB;
845 fl->fl_threshold[3].mech_threshold = kcf_aes_threshold;
846 fl->fl_threshold[4].mech_type = CKM_RC4;
847 fl->fl_threshold[4].mech_threshold = kcf_rc4_threshold;
848 fl->fl_threshold[5].mech_type = CKM_MD5;
849 fl->fl_threshold[5].mech_threshold = kcf_md5_threshold;
850 fl->fl_threshold[6].mech_type = CKM_SHA_1;
851 fl->fl_threshold[6].mech_threshold = kcf_sha1_threshold;
852 }
853
854 /* ARGSUSED */
855 static int
get_function_list(dev_t dev,caddr_t arg,int mode,int * rval)856 get_function_list(dev_t dev, caddr_t arg, int mode, int *rval)
857 {
858 crypto_get_function_list_t get_function_list;
859 crypto_minor_t *cm;
860 crypto_provider_id_t provider_id;
861 crypto_function_list_t *fl;
862 kcf_provider_desc_t *provider;
863 int rv;
864
865 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
866 cmn_err(CE_WARN, "get_function_list: failed holding minor");
867 return (ENXIO);
868 }
869
870 if (copyin(arg, &get_function_list, sizeof (get_function_list)) != 0) {
871 crypto_release_minor(cm);
872 return (EFAULT);
873 }
874
875 /* initialize provider_array */
876 if (cm->cm_provider_array == NULL) {
877 rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST);
878 if (rv != CRYPTO_SUCCESS) {
879 goto release_minor;
880 }
881 }
882
883 provider_id = get_function_list.fl_provider_id;
884 mutex_enter(&cm->cm_lock);
885 /* index must be less than count of providers */
886 if (provider_id >= cm->cm_provider_count) {
887 mutex_exit(&cm->cm_lock);
888 rv = CRYPTO_ARGUMENTS_BAD;
889 goto release_minor;
890 }
891
892 ASSERT(cm->cm_provider_array != NULL);
893 provider = cm->cm_provider_array[provider_id];
894 mutex_exit(&cm->cm_lock);
895
896 fl = &get_function_list.fl_list;
897 bzero(fl, sizeof (crypto_function_list_t));
898
899 if (provider->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) {
900 crypto_build_function_list(fl, provider);
901 } else {
902 kcf_provider_desc_t *prev = NULL, *pd;
903
904 mutex_enter(&provider->pd_lock);
905 while (kcf_get_next_logical_provider_member(provider,
906 prev, &pd)) {
907 prev = pd;
908 crypto_build_function_list(fl, pd);
909 KCF_PROV_REFRELE(pd);
910 }
911 mutex_exit(&provider->pd_lock);
912 }
913
914 rv = CRYPTO_SUCCESS;
915
916 release_minor:
917 crypto_release_minor(cm);
918
919 get_function_list.fl_return_value = rv;
920
921 if (copyout(&get_function_list, arg, sizeof (get_function_list)) != 0) {
922 return (EFAULT);
923 }
924 return (0);
925 }
926
927 /*
928 * This ioctl maps a PKCS#11 mechanism string into an internal number
929 * that is used by the kernel. pn_internal_number is set to the
930 * internal number.
931 */
932 /* ARGSUSED */
933 static int
get_mechanism_number(dev_t dev,caddr_t arg,int mode,int * rval)934 get_mechanism_number(dev_t dev, caddr_t arg, int mode, int *rval)
935 {
936 STRUCT_DECL(crypto_get_mechanism_number, get_number);
937 crypto_mech_type_t number;
938 size_t len;
939 char *mechanism_name;
940 int rv;
941
942 STRUCT_INIT(get_number, mode);
943
944 if (copyin(arg, STRUCT_BUF(get_number), STRUCT_SIZE(get_number)) != 0)
945 return (EFAULT);
946
947 len = STRUCT_FGET(get_number, pn_mechanism_len);
948 if (len == 0 || len > CRYPTO_MAX_MECH_NAME) {
949 rv = CRYPTO_ARGUMENTS_BAD;
950 goto out;
951 }
952 mechanism_name = kmem_alloc(len, KM_SLEEP);
953
954 if (copyin(STRUCT_FGETP(get_number, pn_mechanism_string),
955 mechanism_name, len) != 0) {
956 kmem_free(mechanism_name, len);
957 return (EFAULT);
958 }
959
960 /*
961 * Get mechanism number from kcf. We set the load_module
962 * flag to false since we use only hardware providers.
963 */
964 number = crypto_mech2id_common(mechanism_name, B_FALSE);
965 kmem_free(mechanism_name, len);
966 if (number == CRYPTO_MECH_INVALID) {
967 rv = CRYPTO_ARGUMENTS_BAD;
968 goto out;
969 }
970
971 bcopy((char *)&number, (char *)STRUCT_FADDR(get_number,
972 pn_internal_number), sizeof (number));
973
974 rv = CRYPTO_SUCCESS;
975 out:
976 STRUCT_FSET(get_number, pn_return_value, rv);
977
978 if (copyout(STRUCT_BUF(get_number), arg,
979 STRUCT_SIZE(get_number)) != 0) {
980 return (EFAULT);
981 }
982 return (0);
983 }
984
985 /*
986 * This ioctl returns an array of crypto_mech_name_t entries.
987 * It lists all the PKCS#11 mechanisms available in the kernel.
988 */
989 /* ARGSUSED */
990 static int
get_mechanism_list(dev_t dev,caddr_t arg,int mode,int * rval)991 get_mechanism_list(dev_t dev, caddr_t arg, int mode, int *rval)
992 {
993 STRUCT_DECL(crypto_get_mechanism_list, get_list);
994 crypto_mech_name_t *entries;
995 size_t copyout_size;
996 uint_t req_count;
997 uint_t count;
998 ulong_t offset;
999 int error = 0;
1000
1001 STRUCT_INIT(get_list, mode);
1002
1003 if (copyin(arg, STRUCT_BUF(get_list), STRUCT_SIZE(get_list)) != 0) {
1004 return (EFAULT);
1005 }
1006
1007 entries = crypto_get_mech_list(&count, KM_SLEEP);
1008
1009 /* Number of entries caller thinks we have */
1010 req_count = STRUCT_FGET(get_list, ml_count);
1011
1012 STRUCT_FSET(get_list, ml_count, count);
1013 STRUCT_FSET(get_list, ml_return_value, CRYPTO_SUCCESS);
1014
1015 /* check if buffer is too small */
1016 if (count > req_count) {
1017 STRUCT_FSET(get_list, ml_return_value, CRYPTO_BUFFER_TOO_SMALL);
1018 }
1019
1020 /* copyout the first stuff */
1021 if (copyout(STRUCT_BUF(get_list), arg, STRUCT_SIZE(get_list)) != 0) {
1022 error = EFAULT;
1023 }
1024
1025 /*
1026 * If only requesting number of entries or buffer too small or an
1027 * error occurred, stop here
1028 */
1029 if (req_count == 0 || count > req_count || error != 0) {
1030 goto out;
1031 }
1032
1033 copyout_size = count * sizeof (crypto_mech_name_t);
1034
1035 /* copyout entries */
1036 offset = (ulong_t)STRUCT_FADDR(get_list, ml_list);
1037 offset -= (ulong_t)STRUCT_BUF(get_list);
1038 if (copyout(entries, arg + offset, copyout_size) != 0) {
1039 error = EFAULT;
1040 }
1041
1042 out:
1043 crypto_free_mech_list(entries, count);
1044 return (error);
1045 }
1046
1047 /*
1048 * Copyout kernel array of mech_infos to user space.
1049 */
1050 /* ARGSUSED */
1051 static int
copyout_mechinfos(int mode,caddr_t out,uint_t count,crypto_mechanism_info_t * k_minfos,caddr_t u_minfos)1052 copyout_mechinfos(int mode, caddr_t out, uint_t count,
1053 crypto_mechanism_info_t *k_minfos, caddr_t u_minfos)
1054 {
1055 STRUCT_DECL(crypto_mechanism_info, mi);
1056 caddr_t p;
1057 size_t len;
1058 int i;
1059
1060 if (count == 0)
1061 return (0);
1062
1063 STRUCT_INIT(mi, mode);
1064
1065 len = count * STRUCT_SIZE(mi);
1066
1067 ASSERT(u_minfos != NULL);
1068 p = u_minfos;
1069 for (i = 0; i < count; i++) {
1070 STRUCT_FSET(mi, mi_min_key_size, k_minfos[i].mi_min_key_size);
1071 STRUCT_FSET(mi, mi_max_key_size, k_minfos[i].mi_max_key_size);
1072 STRUCT_FSET(mi, mi_keysize_unit, k_minfos[i].mi_keysize_unit);
1073 STRUCT_FSET(mi, mi_usage, k_minfos[i].mi_usage);
1074 bcopy(STRUCT_BUF(mi), p, STRUCT_SIZE(mi));
1075 p += STRUCT_SIZE(mi);
1076 }
1077
1078 if (copyout(u_minfos, out, len) != 0)
1079 return (EFAULT);
1080
1081 return (0);
1082 }
1083
1084 /*
1085 * This ioctl returns information for the specified mechanism.
1086 */
1087 /* ARGSUSED */
1088 static int
get_all_mechanism_info(dev_t dev,caddr_t arg,int mode,int * rval)1089 get_all_mechanism_info(dev_t dev, caddr_t arg, int mode, int *rval)
1090 {
1091 STRUCT_DECL(crypto_get_all_mechanism_info, get_all_mech);
1092 #ifdef _LP64
1093 STRUCT_DECL(crypto_mechanism_info, mi);
1094 #else
1095 /* LINTED E_FUNC_SET_NOT_USED */
1096 STRUCT_DECL(crypto_mechanism_info, mi);
1097 #endif
1098 crypto_mech_name_t mech_name;
1099 crypto_mech_type_t mech_type;
1100 crypto_mechanism_info_t *mech_infos = NULL;
1101 uint_t num_mech_infos = 0;
1102 uint_t req_count;
1103 caddr_t u_minfos;
1104 ulong_t offset;
1105 int error = 0;
1106 int rv;
1107
1108 req_count = 0;
1109 STRUCT_INIT(get_all_mech, mode);
1110 STRUCT_INIT(mi, mode);
1111
1112 if (copyin(arg, STRUCT_BUF(get_all_mech),
1113 STRUCT_SIZE(get_all_mech)) != 0) {
1114 return (EFAULT);
1115 }
1116
1117 (void) strncpy(mech_name, STRUCT_FGET(get_all_mech, mi_mechanism_name),
1118 CRYPTO_MAX_MECH_NAME);
1119 mech_type = crypto_mech2id(mech_name);
1120
1121 if (mech_type == CRYPTO_MECH_INVALID) {
1122 rv = CRYPTO_ARGUMENTS_BAD;
1123 goto out1;
1124 }
1125
1126 rv = crypto_get_all_mech_info(mech_type, &mech_infos, &num_mech_infos,
1127 KM_SLEEP);
1128 if (rv != CRYPTO_SUCCESS) {
1129 goto out1;
1130 }
1131 /* rv is CRYPTO_SUCCESS at this point */
1132
1133 /* Number of entries caller thinks we have */
1134 req_count = STRUCT_FGET(get_all_mech, mi_count);
1135
1136 STRUCT_FSET(get_all_mech, mi_count, num_mech_infos);
1137
1138 /* check if buffer is too small */
1139 if (num_mech_infos > req_count) {
1140 rv = CRYPTO_BUFFER_TOO_SMALL;
1141 }
1142
1143 out1:
1144 STRUCT_FSET(get_all_mech, mi_return_value, rv);
1145
1146 /* copy the first part */
1147 if (copyout(STRUCT_BUF(get_all_mech), arg,
1148 STRUCT_SIZE(get_all_mech)) != 0) {
1149 error = EFAULT;
1150 }
1151
1152 /*
1153 * If only requesting number of entries, or there are no entries,
1154 * or rv is not CRYPTO_SUCCESS due to buffer too small or some other
1155 * crypto error, or an error occurred with copyout, stop here
1156 */
1157 if (req_count == 0 || num_mech_infos == 0 || rv != CRYPTO_SUCCESS ||
1158 error != 0) {
1159 goto out2;
1160 }
1161
1162 /* copyout mech_infos */
1163 offset = (ulong_t)STRUCT_FADDR(get_all_mech, mi_list);
1164 offset -= (ulong_t)STRUCT_BUF(get_all_mech);
1165
1166 u_minfos = kmem_alloc(num_mech_infos * STRUCT_SIZE(mi), KM_SLEEP);
1167 error = copyout_mechinfos(mode, arg + offset, num_mech_infos,
1168 mech_infos, u_minfos);
1169 kmem_free(u_minfos, num_mech_infos * STRUCT_SIZE(mi));
1170 out2:
1171 if (mech_infos != NULL)
1172 crypto_free_all_mech_info(mech_infos, num_mech_infos);
1173 return (error);
1174 }
1175
1176 /*
1177 * Side-effects:
1178 * 1. This routine stores provider descriptor pointers in an array
1179 * and increments each descriptor's reference count. The array
1180 * is stored in per-minor number storage.
1181 * 2. Destroys the old array and creates a new one every time
1182 * this routine is called.
1183 */
1184 int
crypto_get_provider_list(crypto_minor_t * cm,uint_t * count,crypto_provider_entry_t ** array,boolean_t return_slot_list)1185 crypto_get_provider_list(crypto_minor_t *cm, uint_t *count,
1186 crypto_provider_entry_t **array, boolean_t return_slot_list)
1187 {
1188 kcf_provider_desc_t **provider_array;
1189 crypto_provider_entry_t *p = NULL;
1190 uint_t provider_count;
1191 int rval;
1192 int i;
1193
1194 /*
1195 * Take snapshot of provider table returning only HW entries
1196 * that are in a usable state. Also returns logical provider entries.
1197 */
1198 rval = kcf_get_slot_list(&provider_count, &provider_array, B_FALSE);
1199 if (rval != CRYPTO_SUCCESS)
1200 return (rval);
1201
1202 /* allocate memory before taking cm->cm_lock */
1203 if (return_slot_list) {
1204 if (provider_count != 0) {
1205 p = kmem_alloc(provider_count *
1206 sizeof (crypto_provider_entry_t), KM_SLEEP);
1207 for (i = 0; i < provider_count; i++) {
1208 p[i].pe_provider_id = i;
1209 p[i].pe_mechanism_count =
1210 provider_array[i]->pd_mech_list_count;
1211 }
1212 }
1213 *array = p;
1214 *count = provider_count;
1215 }
1216
1217 /*
1218 * Free existing array of providers and replace with new list.
1219 */
1220 mutex_enter(&cm->cm_lock);
1221 if (cm->cm_provider_array != NULL) {
1222 ASSERT(cm->cm_provider_count > 0);
1223 kcf_free_provider_tab(cm->cm_provider_count,
1224 cm->cm_provider_array);
1225 }
1226
1227 cm->cm_provider_array = provider_array;
1228 cm->cm_provider_count = provider_count;
1229 mutex_exit(&cm->cm_lock);
1230
1231 return (CRYPTO_SUCCESS);
1232 }
1233
1234 /*
1235 * This ioctl returns an array of crypto_provider_entry_t entries.
1236 * This is how consumers learn which hardware providers are available.
1237 */
1238 /* ARGSUSED */
1239 static int
get_provider_list(dev_t dev,caddr_t arg,int mode,int * rval)1240 get_provider_list(dev_t dev, caddr_t arg, int mode, int *rval)
1241 {
1242 STRUCT_DECL(crypto_get_provider_list, get_list);
1243 crypto_provider_entry_t *entries;
1244 crypto_minor_t *cm;
1245 size_t copyout_size;
1246 uint_t req_count;
1247 uint_t count;
1248 ulong_t offset;
1249 int rv;
1250
1251 STRUCT_INIT(get_list, mode);
1252
1253 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
1254 cmn_err(CE_WARN, "get_provider_list: failed holding minor");
1255 return (ENXIO);
1256 }
1257
1258 if (copyin(arg, STRUCT_BUF(get_list), STRUCT_SIZE(get_list)) != 0) {
1259 crypto_release_minor(cm);
1260 return (EFAULT);
1261 }
1262
1263 rv = crypto_get_provider_list(cm, &count, &entries, RETURN_LIST);
1264 if (rv != CRYPTO_SUCCESS) {
1265 crypto_release_minor(cm);
1266 STRUCT_FSET(get_list, pl_return_value, rv);
1267 if (copyout(STRUCT_BUF(get_list), arg,
1268 STRUCT_SIZE(get_list)) != 0) {
1269 return (EFAULT);
1270 }
1271 return (0);
1272 }
1273 crypto_release_minor(cm);
1274
1275 /* Number of slots caller thinks we have */
1276 req_count = STRUCT_FGET(get_list, pl_count);
1277
1278 /* Check if only requesting number of slots */
1279 if (req_count == 0) {
1280
1281 STRUCT_FSET(get_list, pl_count, count);
1282 STRUCT_FSET(get_list, pl_return_value, CRYPTO_SUCCESS);
1283
1284 crypto_free_provider_list(entries, count);
1285 if (copyout(STRUCT_BUF(get_list), arg,
1286 STRUCT_SIZE(get_list)) != 0) {
1287 return (EFAULT);
1288 }
1289 return (0);
1290 }
1291
1292 /* check if buffer is too small */
1293 req_count = STRUCT_FGET(get_list, pl_count);
1294 if (count > req_count) {
1295 STRUCT_FSET(get_list, pl_count, count);
1296 STRUCT_FSET(get_list, pl_return_value, CRYPTO_BUFFER_TOO_SMALL);
1297 crypto_free_provider_list(entries, count);
1298 if (copyout(STRUCT_BUF(get_list), arg,
1299 STRUCT_SIZE(get_list)) != 0) {
1300 return (EFAULT);
1301 }
1302 return (0);
1303 }
1304
1305 STRUCT_FSET(get_list, pl_count, count);
1306 STRUCT_FSET(get_list, pl_return_value, CRYPTO_SUCCESS);
1307
1308 copyout_size = count * sizeof (crypto_provider_entry_t);
1309
1310 /* copyout the first stuff */
1311 if (copyout(STRUCT_BUF(get_list), arg, STRUCT_SIZE(get_list)) != 0) {
1312 crypto_free_provider_list(entries, count);
1313 return (EFAULT);
1314 }
1315
1316 if (count == 0) {
1317 crypto_free_provider_list(entries, count);
1318 return (0);
1319 }
1320
1321 /* copyout entries */
1322 offset = (ulong_t)STRUCT_FADDR(get_list, pl_list);
1323 offset -= (ulong_t)STRUCT_BUF(get_list);
1324 if (copyout(entries, arg + offset, copyout_size) != 0) {
1325 crypto_free_provider_list(entries, count);
1326 return (EFAULT);
1327 }
1328
1329 crypto_free_provider_list(entries, count);
1330 return (0);
1331 }
1332
1333 static void
ext_to_provider_data(int mode,kcf_provider_desc_t * provider,crypto_provider_ext_info_t * ei,void * out)1334 ext_to_provider_data(int mode, kcf_provider_desc_t *provider,
1335 crypto_provider_ext_info_t *ei, void *out)
1336 {
1337 STRUCT_DECL(crypto_provider_data, pd);
1338 STRUCT_DECL(crypto_version, version);
1339
1340 STRUCT_INIT(pd, mode);
1341 STRUCT_INIT(version, mode);
1342
1343 bcopy(provider->pd_description, STRUCT_FGET(pd, pd_prov_desc),
1344 CRYPTO_PROVIDER_DESCR_MAX_LEN);
1345
1346 bcopy(ei->ei_label, STRUCT_FGET(pd, pd_label), CRYPTO_EXT_SIZE_LABEL);
1347 bcopy(ei->ei_manufacturerID, STRUCT_FGET(pd, pd_manufacturerID),
1348 CRYPTO_EXT_SIZE_MANUF);
1349 bcopy(ei->ei_model, STRUCT_FGET(pd, pd_model), CRYPTO_EXT_SIZE_MODEL);
1350 bcopy(ei->ei_serial_number, STRUCT_FGET(pd, pd_serial_number),
1351 CRYPTO_EXT_SIZE_SERIAL);
1352 /*
1353 * We do not support ioctls for dual-function crypto operations yet.
1354 * So, we clear this flag as it might have been set by a provider.
1355 */
1356 ei->ei_flags &= ~CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS;
1357
1358 STRUCT_FSET(pd, pd_flags, ei->ei_flags);
1359 STRUCT_FSET(pd, pd_max_session_count, ei->ei_max_session_count);
1360 STRUCT_FSET(pd, pd_session_count, (int)CRYPTO_UNAVAILABLE_INFO);
1361 STRUCT_FSET(pd, pd_max_rw_session_count, ei->ei_max_session_count);
1362 STRUCT_FSET(pd, pd_rw_session_count, (int)CRYPTO_UNAVAILABLE_INFO);
1363 STRUCT_FSET(pd, pd_max_pin_len, ei->ei_max_pin_len);
1364 STRUCT_FSET(pd, pd_min_pin_len, ei->ei_min_pin_len);
1365 STRUCT_FSET(pd, pd_total_public_memory, ei->ei_total_public_memory);
1366 STRUCT_FSET(pd, pd_free_public_memory, ei->ei_free_public_memory);
1367 STRUCT_FSET(pd, pd_total_private_memory, ei->ei_total_private_memory);
1368 STRUCT_FSET(pd, pd_free_private_memory, ei->ei_free_private_memory);
1369 STRUCT_FSET(version, cv_major, ei->ei_hardware_version.cv_major);
1370 STRUCT_FSET(version, cv_minor, ei->ei_hardware_version.cv_minor);
1371 bcopy(STRUCT_BUF(version), STRUCT_FADDR(pd, pd_hardware_version),
1372 STRUCT_SIZE(version));
1373 STRUCT_FSET(version, cv_major, ei->ei_firmware_version.cv_major);
1374 STRUCT_FSET(version, cv_minor, ei->ei_firmware_version.cv_minor);
1375 bcopy(STRUCT_BUF(version), STRUCT_FADDR(pd, pd_firmware_version),
1376 STRUCT_SIZE(version));
1377 bcopy(ei->ei_time, STRUCT_FGET(pd, pd_time), CRYPTO_EXT_SIZE_TIME);
1378 bcopy(STRUCT_BUF(pd), out, STRUCT_SIZE(pd));
1379 }
1380
1381 /*
1382 * Utility routine to construct a crypto_provider_ext_info structure. Some
1383 * of the fields are constructed from information in the provider structure.
1384 * The rest of the fields have default values. We need to do this for
1385 * providers which do not support crypto_provider_management_ops routines.
1386 */
1387 static void
fabricate_ext_info(kcf_provider_desc_t * provider,crypto_provider_ext_info_t * ei)1388 fabricate_ext_info(kcf_provider_desc_t *provider,
1389 crypto_provider_ext_info_t *ei)
1390 {
1391 /* empty label */
1392 (void) memset(ei->ei_label, ' ', CRYPTO_EXT_SIZE_LABEL);
1393
1394 (void) memset(ei->ei_manufacturerID, ' ', CRYPTO_EXT_SIZE_MANUF);
1395 (void) strncpy((char *)ei->ei_manufacturerID, "Unknown", 7);
1396
1397 (void) memset(ei->ei_model, ' ', CRYPTO_EXT_SIZE_MODEL);
1398 (void) strncpy((char *)ei->ei_model, "Unknown", 7);
1399
1400 (void) memset(ei->ei_serial_number, ' ', CRYPTO_EXT_SIZE_SERIAL);
1401 (void) strncpy((char *)ei->ei_serial_number, "Unknown", 7);
1402
1403 if (KCF_PROV_RANDOM_OPS(provider) != NULL)
1404 ei->ei_flags |= CRYPTO_EXTF_RNG;
1405 if (KCF_PROV_DUAL_OPS(provider) != NULL)
1406 ei->ei_flags |= CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS;
1407
1408 ei->ei_max_session_count = CRYPTO_UNAVAILABLE_INFO;
1409 ei->ei_max_pin_len = 0;
1410 ei->ei_min_pin_len = 0;
1411 ei->ei_total_public_memory = CRYPTO_UNAVAILABLE_INFO;
1412 ei->ei_free_public_memory = CRYPTO_UNAVAILABLE_INFO;
1413 ei->ei_total_private_memory = CRYPTO_UNAVAILABLE_INFO;
1414 ei->ei_free_private_memory = CRYPTO_UNAVAILABLE_INFO;
1415 ei->ei_hardware_version.cv_major = 1;
1416 ei->ei_hardware_version.cv_minor = 0;
1417 ei->ei_firmware_version.cv_major = 1;
1418 ei->ei_firmware_version.cv_minor = 0;
1419 }
1420
1421 /* ARGSUSED */
1422 static int
get_provider_info(dev_t dev,caddr_t arg,int mode,int * rval)1423 get_provider_info(dev_t dev, caddr_t arg, int mode, int *rval)
1424 {
1425 STRUCT_DECL(crypto_get_provider_info, get_info);
1426 crypto_minor_t *cm;
1427 crypto_provider_id_t provider_id;
1428 kcf_provider_desc_t *provider, *real_provider;
1429 crypto_provider_ext_info_t *ext_info = NULL;
1430 size_t need;
1431 int error = 0;
1432 int rv;
1433 kcf_req_params_t params;
1434
1435 STRUCT_INIT(get_info, mode);
1436
1437 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
1438 cmn_err(CE_WARN, "get_provider_info: failed holding minor");
1439 return (ENXIO);
1440 }
1441
1442 if (copyin(arg, STRUCT_BUF(get_info), STRUCT_SIZE(get_info)) != 0) {
1443 crypto_release_minor(cm);
1444 return (EFAULT);
1445 }
1446
1447 need = sizeof (crypto_provider_ext_info_t);
1448 if ((rv = crypto_buffer_check(need)) != CRYPTO_SUCCESS) {
1449 need = 0;
1450 goto release_minor;
1451 }
1452
1453 /* initialize provider_array */
1454 if (cm->cm_provider_array == NULL) {
1455 rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST);
1456 if (rv != CRYPTO_SUCCESS) {
1457 goto release_minor;
1458 }
1459 }
1460
1461 ext_info = kmem_zalloc(need, KM_SLEEP);
1462
1463 provider_id = STRUCT_FGET(get_info, gi_provider_id);
1464 mutex_enter(&cm->cm_lock);
1465 /* index must be less than count of providers */
1466 if (provider_id >= cm->cm_provider_count) {
1467 mutex_exit(&cm->cm_lock);
1468 rv = CRYPTO_ARGUMENTS_BAD;
1469 goto release_minor;
1470 }
1471
1472 ASSERT(cm->cm_provider_array != NULL);
1473 provider = cm->cm_provider_array[provider_id];
1474 KCF_PROV_REFHOLD(provider);
1475 mutex_exit(&cm->cm_lock);
1476
1477 (void) kcf_get_hardware_provider_nomech(
1478 CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(ext_info),
1479 provider, &real_provider);
1480
1481 if (real_provider != NULL) {
1482 ASSERT(real_provider == provider ||
1483 provider->pd_prov_type == CRYPTO_LOGICAL_PROVIDER);
1484 KCF_WRAP_PROVMGMT_OPS_PARAMS(¶ms, KCF_OP_MGMT_EXTINFO,
1485 0, NULL, 0, NULL, 0, NULL, ext_info, provider);
1486 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms,
1487 B_FALSE);
1488 ASSERT(rv != CRYPTO_NOT_SUPPORTED);
1489 KCF_PROV_REFRELE(real_provider);
1490 } else {
1491 /* do the best we can */
1492 fabricate_ext_info(provider, ext_info);
1493 rv = CRYPTO_SUCCESS;
1494 }
1495 KCF_PROV_REFRELE(provider);
1496
1497 if (rv == CRYPTO_SUCCESS) {
1498 ext_to_provider_data(mode, provider, ext_info,
1499 STRUCT_FADDR(get_info, gi_provider_data));
1500 }
1501
1502 release_minor:
1503 CRYPTO_DECREMENT_RCTL(need);
1504 crypto_release_minor(cm);
1505
1506 if (ext_info != NULL)
1507 kmem_free(ext_info, sizeof (crypto_provider_ext_info_t));
1508
1509 if (error != 0)
1510 return (error);
1511
1512 STRUCT_FSET(get_info, gi_return_value, rv);
1513 if (copyout(STRUCT_BUF(get_info), arg, STRUCT_SIZE(get_info)) != 0) {
1514 return (EFAULT);
1515 }
1516 return (0);
1517 }
1518
1519 /*
1520 * This ioctl returns an array of crypto_mech_name_t entries.
1521 * This is how consumers learn which mechanisms are permitted
1522 * by a provider.
1523 */
1524 /* ARGSUSED */
1525 static int
get_provider_mechanisms(dev_t dev,caddr_t arg,int mode,int * rval)1526 get_provider_mechanisms(dev_t dev, caddr_t arg, int mode, int *rval)
1527 {
1528 STRUCT_DECL(crypto_get_provider_mechanisms, get_mechanisms);
1529 crypto_mech_name_t *entries;
1530 crypto_minor_t *cm;
1531 size_t copyout_size;
1532 uint_t req_count;
1533 uint_t count;
1534 ulong_t offset;
1535 int err;
1536
1537 STRUCT_INIT(get_mechanisms, mode);
1538
1539 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
1540 cmn_err(CE_WARN,
1541 "get_provider_mechanisms: failed holding minor");
1542 return (ENXIO);
1543 }
1544
1545 if (copyin(arg, STRUCT_BUF(get_mechanisms),
1546 STRUCT_SIZE(get_mechanisms)) != 0) {
1547 crypto_release_minor(cm);
1548 return (EFAULT);
1549 }
1550
1551 /* get array of mechanisms from the core module */
1552 if ((err = crypto_get_provider_mechanisms(cm,
1553 STRUCT_FGET(get_mechanisms, pm_provider_id),
1554 &count, &entries)) != 0) {
1555 crypto_release_minor(cm);
1556 STRUCT_FSET(get_mechanisms, pm_return_value, err);
1557 if (copyout(STRUCT_BUF(get_mechanisms), arg,
1558 STRUCT_SIZE(get_mechanisms)) != 0) {
1559 return (EFAULT);
1560 }
1561 return (0);
1562 }
1563 crypto_release_minor(cm);
1564 /* Number of mechs caller thinks we have */
1565 req_count = STRUCT_FGET(get_mechanisms, pm_count);
1566
1567 /* Check if caller is just requesting a count of mechanisms */
1568 if (req_count == 0) {
1569 STRUCT_FSET(get_mechanisms, pm_count, count);
1570 STRUCT_FSET(get_mechanisms, pm_return_value, CRYPTO_SUCCESS);
1571
1572 crypto_free_mech_list(entries, count);
1573 if (copyout(STRUCT_BUF(get_mechanisms), arg,
1574 STRUCT_SIZE(get_mechanisms)) != 0) {
1575 return (EFAULT);
1576 }
1577 return (0);
1578 }
1579
1580 /* check if buffer is too small */
1581 if (count > req_count) {
1582 STRUCT_FSET(get_mechanisms, pm_count, count);
1583 STRUCT_FSET(get_mechanisms, pm_return_value,
1584 CRYPTO_BUFFER_TOO_SMALL);
1585 crypto_free_mech_list(entries, count);
1586 if (copyout(STRUCT_BUF(get_mechanisms), arg,
1587 STRUCT_SIZE(get_mechanisms)) != 0) {
1588 return (EFAULT);
1589 }
1590 return (0);
1591 }
1592
1593 STRUCT_FSET(get_mechanisms, pm_count, count);
1594 STRUCT_FSET(get_mechanisms, pm_return_value, CRYPTO_SUCCESS);
1595
1596 copyout_size = count * sizeof (crypto_mech_name_t);
1597
1598 /* copyout the first stuff */
1599 if (copyout(STRUCT_BUF(get_mechanisms), arg,
1600 STRUCT_SIZE(get_mechanisms)) != 0) {
1601 crypto_free_mech_list(entries, count);
1602 return (EFAULT);
1603 }
1604
1605 if (count == 0) {
1606 return (0);
1607 }
1608
1609 /* copyout entries */
1610 offset = (ulong_t)STRUCT_FADDR(get_mechanisms, pm_list);
1611 offset -= (ulong_t)STRUCT_BUF(get_mechanisms);
1612 if (copyout(entries, arg + offset, copyout_size) != 0) {
1613 crypto_free_mech_list(entries, count);
1614 return (EFAULT);
1615 }
1616
1617 crypto_free_mech_list(entries, count);
1618 return (0);
1619 }
1620
1621 /*
1622 * This ioctl returns information about a provider's mechanism.
1623 */
1624 /* ARGSUSED */
1625 static int
get_provider_mechanism_info(dev_t dev,caddr_t arg,int mode,int * rval)1626 get_provider_mechanism_info(dev_t dev, caddr_t arg, int mode, int *rval)
1627 {
1628 crypto_get_provider_mechanism_info_t mechanism_info;
1629 crypto_minor_t *cm;
1630 kcf_provider_desc_t *pd;
1631 crypto_mech_info_t *mi = NULL;
1632 int rv = CRYPTO_SUCCESS;
1633 int i;
1634
1635 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
1636 cmn_err(CE_WARN,
1637 "get_provider_mechanism_info: failed holding minor");
1638 return (ENXIO);
1639 }
1640
1641 if (copyin(arg, &mechanism_info, sizeof (mechanism_info)) != 0) {
1642 crypto_release_minor(cm);
1643 return (EFAULT);
1644 }
1645
1646 /* initialize provider table */
1647 if (cm->cm_provider_array == NULL) {
1648 rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST);
1649 if (rv != CRYPTO_SUCCESS) {
1650 mutex_enter(&cm->cm_lock);
1651 goto fail;
1652 }
1653 }
1654
1655 /*
1656 * Provider ID must be less than the count of providers
1657 * obtained by calling get_provider_list().
1658 */
1659 mutex_enter(&cm->cm_lock);
1660 if (mechanism_info.mi_provider_id >= cm->cm_provider_count) {
1661 rv = CRYPTO_ARGUMENTS_BAD;
1662 goto fail;
1663 }
1664
1665 pd = cm->cm_provider_array[mechanism_info.mi_provider_id];
1666
1667 /* First check if the provider supports the mechanism. */
1668 for (i = 0; i < pd->pd_mech_list_count; i++) {
1669 if (strncmp(pd->pd_mechanisms[i].cm_mech_name,
1670 mechanism_info.mi_mechanism_name,
1671 CRYPTO_MAX_MECH_NAME) == 0) {
1672 mi = &pd->pd_mechanisms[i];
1673 break;
1674 }
1675 }
1676
1677 if (mi == NULL) {
1678 rv = CRYPTO_ARGUMENTS_BAD;
1679 goto fail;
1680 }
1681
1682 /* Now check if the mechanism is enabled for the provider. */
1683 if (is_mech_disabled(pd, mechanism_info.mi_mechanism_name)) {
1684 rv = CRYPTO_MECHANISM_INVALID;
1685 goto fail;
1686 }
1687
1688 mechanism_info.mi_min_key_size = mi->cm_min_key_length;
1689 mechanism_info.mi_max_key_size = mi->cm_max_key_length;
1690 mechanism_info.mi_flags = mi->cm_func_group_mask;
1691
1692 fail:
1693 mutex_exit(&cm->cm_lock);
1694 crypto_release_minor(cm);
1695 mechanism_info.mi_return_value = rv;
1696 if (copyout(&mechanism_info, arg, sizeof (mechanism_info)) != 0) {
1697 return (EFAULT);
1698 }
1699
1700 return (0);
1701 }
1702
1703 /*
1704 * Every open of /dev/crypto multiplexes all PKCS#11 sessions across
1705 * a single session to each provider. Calls to open and close session
1706 * are not made to providers that do not support sessions. For these
1707 * providers, a session number of 0 is passed during subsequent operations,
1708 * and it is ignored by the provider.
1709 */
1710 static int
crypto_get_provider_session(crypto_minor_t * cm,crypto_provider_id_t provider_index,crypto_provider_session_t ** output_ps)1711 crypto_get_provider_session(crypto_minor_t *cm,
1712 crypto_provider_id_t provider_index, crypto_provider_session_t **output_ps)
1713 {
1714 kcf_provider_desc_t *pd, *real_provider;
1715 kcf_req_params_t params;
1716 crypto_provider_session_t *ps;
1717 crypto_session_id_t provider_session_id = 0;
1718 int rv;
1719
1720 ASSERT(MUTEX_HELD(&cm->cm_lock));
1721
1722 /* pd may be a logical provider */
1723 pd = cm->cm_provider_array[provider_index];
1724
1725 again:
1726 /*
1727 * Check if there is already a session to the provider.
1728 * Sessions may be to a logical provider or a real provider.
1729 */
1730 for (ps = cm->cm_provider_session; ps != NULL; ps = ps->ps_next) {
1731 if (ps->ps_provider == pd)
1732 break;
1733 }
1734
1735 /* found existing session */
1736 if (ps != NULL) {
1737 ps->ps_refcnt++;
1738 *output_ps = ps;
1739 return (CRYPTO_SUCCESS);
1740 }
1741 mutex_exit(&cm->cm_lock);
1742
1743 /* find a hardware provider that supports session ops */
1744 (void) kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(session_ops),
1745 CRYPTO_SESSION_OFFSET(session_open), pd, &real_provider);
1746
1747 if (real_provider != NULL) {
1748 ASSERT(real_provider == pd ||
1749 pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER);
1750 /* open session to provider */
1751 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_OPEN,
1752 &provider_session_id, 0, CRYPTO_USER, NULL, 0, pd);
1753 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms,
1754 B_FALSE);
1755 if (rv != CRYPTO_SUCCESS) {
1756 mutex_enter(&cm->cm_lock);
1757 KCF_PROV_REFRELE(real_provider);
1758 return (rv);
1759 }
1760 }
1761
1762 /*
1763 * Check if someone opened a session to the provider
1764 * while we dropped the lock.
1765 */
1766 mutex_enter(&cm->cm_lock);
1767 for (ps = cm->cm_provider_session; ps != NULL; ps = ps->ps_next) {
1768 if (ps->ps_provider == pd) {
1769 mutex_exit(&cm->cm_lock);
1770 if (real_provider != NULL) {
1771 KCF_WRAP_SESSION_OPS_PARAMS(¶ms,
1772 KCF_OP_SESSION_CLOSE, NULL,
1773 provider_session_id, CRYPTO_USER, NULL, 0,
1774 pd);
1775 (void) kcf_submit_request(real_provider, NULL,
1776 NULL, ¶ms, B_FALSE);
1777 KCF_PROV_REFRELE(real_provider);
1778 }
1779 mutex_enter(&cm->cm_lock);
1780 goto again;
1781
1782 }
1783 }
1784
1785 return (crypto_create_provider_session(cm, pd, provider_session_id,
1786 output_ps, real_provider));
1787 }
1788
1789 static int
crypto_create_provider_session(crypto_minor_t * cm,kcf_provider_desc_t * pd,crypto_session_id_t sid,crypto_provider_session_t ** out_ps,kcf_provider_desc_t * real)1790 crypto_create_provider_session(crypto_minor_t *cm, kcf_provider_desc_t *pd,
1791 crypto_session_id_t sid, crypto_provider_session_t **out_ps,
1792 kcf_provider_desc_t *real)
1793 {
1794 crypto_provider_session_t *ps;
1795
1796 /* allocate crypto_provider_session structure */
1797 ps = kmem_zalloc(sizeof (crypto_provider_session_t), KM_SLEEP);
1798
1799 /* increment refcnt and attach to crypto_minor structure */
1800 ps->ps_session = sid;
1801 ps->ps_refcnt = 1;
1802 KCF_PROV_REFHOLD(pd);
1803 ps->ps_provider = pd;
1804 if (real != NULL) {
1805 ps->ps_real_provider = real;
1806 }
1807 ps->ps_next = cm->cm_provider_session;
1808 cm->cm_provider_session = ps;
1809
1810 *out_ps = ps;
1811 return (CRYPTO_SUCCESS);
1812 }
1813
1814 /*
1815 * Release a provider session.
1816 * If the reference count goes to zero, then close the session
1817 * to the provider.
1818 */
1819 static void
crypto_release_provider_session(crypto_minor_t * cm,crypto_provider_session_t * provider_session)1820 crypto_release_provider_session(crypto_minor_t *cm,
1821 crypto_provider_session_t *provider_session)
1822 {
1823 kcf_req_params_t params;
1824 crypto_provider_session_t *ps = NULL, **prev;
1825
1826 ASSERT(MUTEX_HELD(&cm->cm_lock));
1827
1828 /* verify that provider_session is valid */
1829 for (ps = cm->cm_provider_session, prev = &cm->cm_provider_session;
1830 ps != NULL; prev = &ps->ps_next, ps = ps->ps_next) {
1831 if (ps == provider_session) {
1832 break;
1833 }
1834 }
1835
1836 if (ps == NULL)
1837 return;
1838
1839 ps->ps_refcnt--;
1840
1841 if (ps->ps_refcnt > 0)
1842 return;
1843
1844 if (ps->ps_real_provider != NULL) {
1845 /* close session with provider */
1846 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_CLOSE, NULL,
1847 ps->ps_session, CRYPTO_USER, NULL, 0, ps->ps_provider);
1848 (void) kcf_submit_request(ps->ps_real_provider,
1849 NULL, NULL, ¶ms, B_FALSE);
1850 KCF_PROV_REFRELE(ps->ps_real_provider);
1851 }
1852 KCF_PROV_REFRELE(ps->ps_provider);
1853 *prev = ps->ps_next;
1854 kmem_free(ps, sizeof (*ps));
1855 }
1856
1857 static int
grow_session_table(crypto_minor_t * cm)1858 grow_session_table(crypto_minor_t *cm)
1859 {
1860 crypto_session_data_t **session_table;
1861 crypto_session_data_t **new;
1862 uint_t session_table_count;
1863 uint_t need;
1864 size_t current_allocation;
1865 size_t new_allocation;
1866 int rv;
1867
1868 ASSERT(MUTEX_HELD(&cm->cm_lock));
1869
1870 session_table_count = cm->cm_session_table_count;
1871 session_table = cm->cm_session_table;
1872 need = session_table_count + CRYPTO_SESSION_CHUNK;
1873
1874 current_allocation = session_table_count * sizeof (void *);
1875 new_allocation = need * sizeof (void *);
1876
1877 /*
1878 * Memory needed to grow the session table is checked
1879 * against the project.max-crypto-memory resource control.
1880 */
1881 if ((rv = crypto_buffer_check(new_allocation - current_allocation)) !=
1882 CRYPTO_SUCCESS) {
1883 return (rv);
1884 }
1885
1886 /* drop lock while we allocate memory */
1887 mutex_exit(&cm->cm_lock);
1888 new = kmem_zalloc(new_allocation, KM_SLEEP);
1889 mutex_enter(&cm->cm_lock);
1890
1891 /* check if another thread increased the table size */
1892 if (session_table_count != cm->cm_session_table_count) {
1893 kmem_free(new, new_allocation);
1894 return (CRYPTO_SUCCESS);
1895 }
1896
1897 bcopy(session_table, new, current_allocation);
1898 kmem_free(session_table, current_allocation);
1899 cm->cm_session_table = new;
1900 cm->cm_session_table_count += CRYPTO_SESSION_CHUNK;
1901
1902 return (CRYPTO_SUCCESS);
1903 }
1904
1905 /*
1906 * Find unused entry in session table and return its index.
1907 * Initialize session table entry.
1908 */
1909 /* ARGSUSED */
1910 static int
crypto_open_session(dev_t dev,uint_t flags,crypto_session_id_t * session_index,crypto_provider_id_t provider_id)1911 crypto_open_session(dev_t dev, uint_t flags, crypto_session_id_t *session_index,
1912 crypto_provider_id_t provider_id)
1913 {
1914 crypto_minor_t *cm;
1915 int rv;
1916 crypto_provider_session_t *ps;
1917 kcf_provider_desc_t *provider;
1918
1919 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
1920 cmn_err(CE_WARN, "crypto_open_session: failed holding minor");
1921 return (CRYPTO_FAILED);
1922 }
1923
1924 /* initialize provider_array */
1925 if (cm->cm_provider_array == NULL) {
1926 rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST);
1927 if (rv != 0) {
1928 crypto_release_minor(cm);
1929 return (rv);
1930 }
1931 }
1932
1933 mutex_enter(&cm->cm_lock);
1934 /* index must be less than count of providers */
1935 if (provider_id >= cm->cm_provider_count) {
1936 mutex_exit(&cm->cm_lock);
1937 crypto_release_minor(cm);
1938 return (CRYPTO_INVALID_PROVIDER_ID);
1939 }
1940 ASSERT(cm->cm_provider_array != NULL);
1941
1942 rv = crypto_get_provider_session(cm, provider_id, &ps);
1943 if (rv != CRYPTO_SUCCESS) {
1944 mutex_exit(&cm->cm_lock);
1945 crypto_release_minor(cm);
1946 return (rv);
1947 }
1948 provider = cm->cm_provider_array[provider_id];
1949
1950 rv = crypto_create_session_ptr(cm, provider, ps, session_index);
1951 mutex_exit(&cm->cm_lock);
1952 crypto_release_minor(cm);
1953 return (rv);
1954
1955 }
1956
1957 static int
crypto_create_session_ptr(crypto_minor_t * cm,kcf_provider_desc_t * provider,crypto_provider_session_t * ps,crypto_session_id_t * session_index)1958 crypto_create_session_ptr(crypto_minor_t *cm, kcf_provider_desc_t *provider,
1959 crypto_provider_session_t *ps, crypto_session_id_t *session_index)
1960 {
1961 crypto_session_data_t **session_table;
1962 crypto_session_data_t *sp;
1963 uint_t session_table_count;
1964 uint_t i;
1965 int rv;
1966
1967 ASSERT(MUTEX_HELD(&cm->cm_lock));
1968
1969 again:
1970 session_table_count = cm->cm_session_table_count;
1971 session_table = cm->cm_session_table;
1972
1973 /* session handles start with 1 */
1974 for (i = 1; i < session_table_count; i++) {
1975 if (session_table[i] == NULL)
1976 break;
1977 }
1978
1979 if (i == session_table_count || session_table_count == 0) {
1980 if ((rv = grow_session_table(cm)) != CRYPTO_SUCCESS) {
1981 crypto_release_provider_session(cm, ps);
1982 return (rv);
1983 }
1984 goto again;
1985 }
1986
1987 sp = kmem_cache_alloc(crypto_session_cache, KM_SLEEP);
1988 sp->sd_flags = 0;
1989 sp->sd_find_init_cookie = NULL;
1990 sp->sd_digest_ctx = NULL;
1991 sp->sd_encr_ctx = NULL;
1992 sp->sd_decr_ctx = NULL;
1993 sp->sd_sign_ctx = NULL;
1994 sp->sd_verify_ctx = NULL;
1995 sp->sd_mac_ctx = NULL;
1996 sp->sd_sign_recover_ctx = NULL;
1997 sp->sd_verify_recover_ctx = NULL;
1998 mutex_init(&sp->sd_lock, NULL, MUTEX_DRIVER, NULL);
1999 cv_init(&sp->sd_cv, NULL, CV_DRIVER, NULL);
2000 KCF_PROV_REFHOLD(provider);
2001 sp->sd_provider = provider;
2002 sp->sd_provider_session = ps;
2003
2004 /* See the comment for CRYPTO_PRE_APPROVED_LIMIT. */
2005 if ((rv = crypto_buffer_check(crypto_pre_approved_limit)) !=
2006 CRYPTO_SUCCESS) {
2007 sp->sd_pre_approved_amount = 0;
2008 } else {
2009 sp->sd_pre_approved_amount = (int)crypto_pre_approved_limit;
2010 }
2011
2012 cm->cm_session_table[i] = sp;
2013 if (session_index != NULL)
2014 *session_index = i;
2015
2016 return (CRYPTO_SUCCESS);
2017 }
2018
2019 /*
2020 * Close a session.
2021 */
2022 static int
crypto_close_session(dev_t dev,crypto_session_id_t session_index)2023 crypto_close_session(dev_t dev, crypto_session_id_t session_index)
2024 {
2025 crypto_session_data_t **session_table;
2026 crypto_session_data_t *sp;
2027 crypto_minor_t *cm;
2028
2029 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2030 cmn_err(CE_WARN, "crypto_close_session: failed holding minor");
2031 return (CRYPTO_FAILED);
2032 }
2033
2034 mutex_enter(&cm->cm_lock);
2035 session_table = cm->cm_session_table;
2036
2037 if ((session_index) == 0 ||
2038 (session_index >= cm->cm_session_table_count)) {
2039 mutex_exit(&cm->cm_lock);
2040 crypto_release_minor(cm);
2041 return (CRYPTO_SESSION_HANDLE_INVALID);
2042 }
2043
2044 sp = session_table[session_index];
2045 if (sp == NULL) {
2046 mutex_exit(&cm->cm_lock);
2047 crypto_release_minor(cm);
2048 return (CRYPTO_SESSION_HANDLE_INVALID);
2049 }
2050 /*
2051 * If session is in use, free it when the thread
2052 * finishes with the session.
2053 */
2054 mutex_enter(&sp->sd_lock);
2055 if (sp->sd_flags & CRYPTO_SESSION_IS_BUSY) {
2056 sp->sd_flags |= CRYPTO_SESSION_IS_CLOSED;
2057 mutex_exit(&sp->sd_lock);
2058 } else {
2059 ASSERT(sp->sd_pre_approved_amount == 0 ||
2060 sp->sd_pre_approved_amount == crypto_pre_approved_limit);
2061 CRYPTO_DECREMENT_RCTL(sp->sd_pre_approved_amount);
2062
2063 if (sp->sd_find_init_cookie != NULL) {
2064 (void) crypto_free_find_ctx(sp);
2065 }
2066
2067 crypto_release_provider_session(cm, sp->sd_provider_session);
2068 KCF_PROV_REFRELE(sp->sd_provider);
2069 CRYPTO_CANCEL_ALL_CTX(sp);
2070 mutex_destroy(&sp->sd_lock);
2071 cv_destroy(&sp->sd_cv);
2072 kmem_cache_free(crypto_session_cache, sp);
2073 session_table[session_index] = NULL;
2074 }
2075
2076 mutex_exit(&cm->cm_lock);
2077 crypto_release_minor(cm);
2078
2079 return (CRYPTO_SUCCESS);
2080 }
2081
2082 /*
2083 * This ioctl opens a session and returns the session ID in os_session.
2084 */
2085 /* ARGSUSED */
2086 static int
open_session(dev_t dev,caddr_t arg,int mode,int * rval)2087 open_session(dev_t dev, caddr_t arg, int mode, int *rval)
2088 {
2089 crypto_open_session_t open_session;
2090 crypto_session_id_t session;
2091 int rv;
2092
2093 if (copyin(arg, &open_session, sizeof (open_session)) != 0)
2094 return (EFAULT);
2095
2096 rv = crypto_open_session(dev, open_session.os_flags,
2097 &session, open_session.os_provider_id);
2098 if (rv != CRYPTO_SUCCESS) {
2099 open_session.os_return_value = rv;
2100 if (copyout(&open_session, arg, sizeof (open_session)) != 0) {
2101 return (EFAULT);
2102 }
2103 return (0);
2104 }
2105
2106 open_session.os_session = session;
2107 open_session.os_return_value = CRYPTO_SUCCESS;
2108
2109 if (copyout(&open_session, arg, sizeof (open_session)) != 0) {
2110 return (EFAULT);
2111 }
2112 return (0);
2113 }
2114
2115 /*
2116 * This ioctl closes a session.
2117 */
2118 /* ARGSUSED */
2119 static int
close_session(dev_t dev,caddr_t arg,int mode,int * rval)2120 close_session(dev_t dev, caddr_t arg, int mode, int *rval)
2121 {
2122 crypto_close_session_t close_session;
2123 int rv;
2124
2125 if (copyin(arg, &close_session, sizeof (close_session)) != 0)
2126 return (EFAULT);
2127
2128 rv = crypto_close_session(dev, close_session.cs_session);
2129 close_session.cs_return_value = rv;
2130 if (copyout(&close_session, arg, sizeof (close_session)) != 0) {
2131 return (EFAULT);
2132 }
2133 return (0);
2134 }
2135
2136 /*
2137 * Copy data model dependent mechanism structure into a kernel mechanism
2138 * structure. Allocate param storage if necessary.
2139 */
2140 static boolean_t
copyin_mech(int mode,crypto_session_data_t * sp,crypto_mechanism_t * in_mech,crypto_mechanism_t * out_mech,size_t * out_rctl_bytes,boolean_t * out_rctl_chk,int * out_rv,int * out_error)2141 copyin_mech(int mode, crypto_session_data_t *sp, crypto_mechanism_t *in_mech,
2142 crypto_mechanism_t *out_mech, size_t *out_rctl_bytes,
2143 boolean_t *out_rctl_chk, int *out_rv, int *out_error)
2144 {
2145 STRUCT_DECL(crypto_mechanism, mech);
2146 caddr_t param;
2147 size_t param_len;
2148 size_t rctl_bytes = 0;
2149 int error = 0;
2150 int rv = 0;
2151
2152 STRUCT_INIT(mech, mode);
2153 bcopy(in_mech, STRUCT_BUF(mech), STRUCT_SIZE(mech));
2154 param = STRUCT_FGETP(mech, cm_param);
2155 param_len = STRUCT_FGET(mech, cm_param_len);
2156 out_mech->cm_type = STRUCT_FGET(mech, cm_type);
2157 out_mech->cm_param = NULL;
2158 out_mech->cm_param_len = 0;
2159 if (param != NULL && param_len != 0) {
2160 if (param_len > crypto_max_buffer_len) {
2161 cmn_err(CE_NOTE, "copyin_mech: buffer greater than "
2162 "%ld bytes, pid = %d", crypto_max_buffer_len,
2163 curproc->p_pid);
2164 rv = CRYPTO_ARGUMENTS_BAD;
2165 goto out;
2166 }
2167
2168 rv = CRYPTO_BUFFER_CHECK(sp, param_len, *out_rctl_chk);
2169 if (rv != CRYPTO_SUCCESS) {
2170 goto out;
2171 }
2172 rctl_bytes = param_len;
2173
2174 out_mech->cm_param = kmem_alloc(param_len, KM_SLEEP);
2175 if (copyin((char *)param, out_mech->cm_param, param_len) != 0) {
2176 kmem_free(out_mech->cm_param, param_len);
2177 out_mech->cm_param = NULL;
2178 error = EFAULT;
2179 goto out;
2180 }
2181 out_mech->cm_param_len = param_len;
2182 }
2183 out:
2184 *out_rctl_bytes = rctl_bytes;
2185 *out_rv = rv;
2186 *out_error = error;
2187 return ((rv | error) ? B_FALSE : B_TRUE);
2188 }
2189
2190 /*
2191 * Free key attributes when key type is CRYPTO_KEY_ATTR_LIST.
2192 * The crypto_key structure is not freed.
2193 */
2194 static void
crypto_free_key_attributes(crypto_key_t * key)2195 crypto_free_key_attributes(crypto_key_t *key)
2196 {
2197 crypto_object_attribute_t *attrs;
2198 size_t len = 0;
2199 int i;
2200
2201 ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST);
2202 if (key->ck_count == 0 || key->ck_attrs == NULL)
2203 return;
2204
2205 /* compute the size of the container */
2206 len = key->ck_count * sizeof (crypto_object_attribute_t);
2207
2208 /* total up the size of all attributes in the container */
2209 for (i = 0; i < key->ck_count; i++) {
2210 attrs = &key->ck_attrs[i];
2211 if (attrs->oa_value_len != 0 &&
2212 attrs->oa_value != NULL) {
2213 len += roundup(attrs->oa_value_len, sizeof (caddr_t));
2214 }
2215 }
2216
2217 bzero(key->ck_attrs, len);
2218 kmem_free(key->ck_attrs, len);
2219 }
2220
2221 /*
2222 * Frees allocated storage in the key structure, but doesn't free
2223 * the key structure.
2224 */
2225 static void
free_crypto_key(crypto_key_t * key)2226 free_crypto_key(crypto_key_t *key)
2227 {
2228 switch (key->ck_format) {
2229 case CRYPTO_KEY_RAW: {
2230 size_t len;
2231
2232 if (key->ck_length == 0 || key->ck_data == NULL)
2233 break;
2234
2235 len = CRYPTO_BITS2BYTES(key->ck_length);
2236 bzero(key->ck_data, len);
2237 kmem_free(key->ck_data, len);
2238 break;
2239 }
2240
2241 case CRYPTO_KEY_ATTR_LIST:
2242 crypto_free_key_attributes(key);
2243 break;
2244
2245 default:
2246 break;
2247 }
2248 }
2249
2250 /*
2251 * Copy in an array of crypto_object_attribute structures from user-space.
2252 * Kernel memory is allocated for the array and the value of each attribute
2253 * in the array. Since unprivileged users can specify the size of attributes,
2254 * the amount of memory needed is charged against the
2255 * project.max-crypto-memory resource control.
2256 *
2257 * Attribute values are copied in from user-space if copyin_value is set to
2258 * B_TRUE. This routine returns B_TRUE if the copyin was successful.
2259 */
2260 static boolean_t
copyin_attributes(int mode,crypto_session_data_t * sp,uint_t count,caddr_t oc_attributes,crypto_object_attribute_t ** k_attrs_out,size_t * k_attrs_size_out,caddr_t * u_attrs_out,int * out_rv,int * out_error,size_t * out_rctl_bytes,boolean_t * out_rctl_chk,boolean_t copyin_value)2261 copyin_attributes(int mode, crypto_session_data_t *sp,
2262 uint_t count, caddr_t oc_attributes,
2263 crypto_object_attribute_t **k_attrs_out, size_t *k_attrs_size_out,
2264 caddr_t *u_attrs_out, int *out_rv, int *out_error, size_t *out_rctl_bytes,
2265 boolean_t *out_rctl_chk, boolean_t copyin_value)
2266 {
2267 STRUCT_DECL(crypto_object_attribute, oa);
2268 crypto_object_attribute_t *k_attrs = NULL;
2269 caddr_t attrs = NULL, ap, p, value;
2270 caddr_t k_attrs_buf;
2271 size_t k_attrs_len;
2272 size_t k_attrs_buf_len = 0;
2273 size_t k_attrs_total_len = 0;
2274 size_t tmp_len;
2275 size_t rctl_bytes = 0;
2276 size_t len = 0;
2277 size_t value_len;
2278 int error = 0;
2279 int rv = 0;
2280 int i;
2281
2282 STRUCT_INIT(oa, mode);
2283
2284 if (count == 0) {
2285 rv = CRYPTO_SUCCESS;
2286 goto out;
2287 }
2288
2289 if (count > CRYPTO_MAX_ATTRIBUTE_COUNT) {
2290 rv = CRYPTO_ARGUMENTS_BAD;
2291 goto out;
2292 }
2293
2294 /* compute size of crypto_object_attribute array */
2295 len = count * STRUCT_SIZE(oa);
2296
2297 /* this allocation is not charged against the user's resource limit */
2298 attrs = kmem_alloc(len, KM_SLEEP);
2299 if (copyin(oc_attributes, attrs, len) != 0) {
2300 error = EFAULT;
2301 goto out;
2302 }
2303
2304 /* figure out how much memory to allocate for all of the attributes */
2305 ap = attrs;
2306 for (i = 0; i < count; i++) {
2307 bcopy(ap, STRUCT_BUF(oa), STRUCT_SIZE(oa));
2308 tmp_len = roundup(STRUCT_FGET(oa, oa_value_len),
2309 sizeof (caddr_t));
2310 if (tmp_len > crypto_max_buffer_len) {
2311 cmn_err(CE_NOTE, "copyin_attributes: buffer greater "
2312 "than %ld bytes, pid = %d", crypto_max_buffer_len,
2313 curproc->p_pid);
2314 rv = CRYPTO_ARGUMENTS_BAD;
2315 goto out;
2316 }
2317 if (STRUCT_FGETP(oa, oa_value) != NULL)
2318 k_attrs_buf_len += tmp_len;
2319 ap += STRUCT_SIZE(oa);
2320 }
2321
2322 k_attrs_len = count * sizeof (crypto_object_attribute_t);
2323 k_attrs_total_len = k_attrs_buf_len + k_attrs_len;
2324
2325 rv = CRYPTO_BUFFER_CHECK(sp, k_attrs_total_len, *out_rctl_chk);
2326 if (rv != CRYPTO_SUCCESS) {
2327 goto out;
2328 }
2329 rctl_bytes = k_attrs_total_len;
2330
2331 /* one big allocation for everything */
2332 k_attrs = kmem_alloc(k_attrs_total_len, KM_SLEEP);
2333 k_attrs_buf = (char *)k_attrs + k_attrs_len;
2334
2335 ap = attrs;
2336 p = k_attrs_buf;
2337 for (i = 0; i < count; i++) {
2338 bcopy(ap, STRUCT_BUF(oa), STRUCT_SIZE(oa));
2339 k_attrs[i].oa_type = STRUCT_FGET(oa, oa_type);
2340 value = STRUCT_FGETP(oa, oa_value);
2341 value_len = STRUCT_FGET(oa, oa_value_len);
2342 if (value != NULL && value_len != 0 && copyin_value) {
2343 if (copyin(value, p, value_len) != 0) {
2344 kmem_free(k_attrs, k_attrs_total_len);
2345 k_attrs = NULL;
2346 error = EFAULT;
2347 goto out;
2348 }
2349 }
2350
2351 if (value != NULL) {
2352 k_attrs[i].oa_value = p;
2353 p += roundup(value_len, sizeof (caddr_t));
2354 } else {
2355 k_attrs[i].oa_value = NULL;
2356 }
2357 k_attrs[i].oa_value_len = value_len;
2358 ap += STRUCT_SIZE(oa);
2359 }
2360 out:
2361 if (attrs != NULL) {
2362 /*
2363 * Free the array if there is a failure or the caller
2364 * doesn't want the array to be returned.
2365 */
2366 if (error != 0 || rv != CRYPTO_SUCCESS || u_attrs_out == NULL) {
2367 kmem_free(attrs, len);
2368 attrs = NULL;
2369 }
2370 }
2371
2372 if (u_attrs_out != NULL)
2373 *u_attrs_out = attrs;
2374 if (k_attrs_size_out != NULL)
2375 *k_attrs_size_out = k_attrs_total_len;
2376 *k_attrs_out = k_attrs;
2377 *out_rctl_bytes = rctl_bytes;
2378 *out_rv = rv;
2379 *out_error = error;
2380 return ((rv | error) ? B_FALSE : B_TRUE);
2381 }
2382
2383 /*
2384 * Copy data model dependent raw key into a kernel key
2385 * structure. Checks key length or attribute lengths against
2386 * resource controls before allocating memory. Returns B_TRUE
2387 * if both error and rv are set to 0.
2388 */
2389 static boolean_t
copyin_key(int mode,crypto_session_data_t * sp,crypto_key_t * in_key,crypto_key_t * out_key,size_t * out_rctl_bytes,boolean_t * out_rctl_chk,int * out_rv,int * out_error)2390 copyin_key(int mode, crypto_session_data_t *sp, crypto_key_t *in_key,
2391 crypto_key_t *out_key, size_t *out_rctl_bytes,
2392 boolean_t *out_rctl_chk, int *out_rv, int *out_error)
2393 {
2394 STRUCT_DECL(crypto_key, key);
2395 crypto_object_attribute_t *k_attrs = NULL;
2396 size_t key_bits;
2397 size_t key_bytes = 0;
2398 size_t rctl_bytes = 0;
2399 int count;
2400 int error = 0;
2401 int rv = CRYPTO_SUCCESS;
2402
2403 STRUCT_INIT(key, mode);
2404 bcopy(in_key, STRUCT_BUF(key), STRUCT_SIZE(key));
2405 out_key->ck_format = STRUCT_FGET(key, ck_format);
2406 switch (out_key->ck_format) {
2407 case CRYPTO_KEY_RAW:
2408 key_bits = STRUCT_FGET(key, ck_length);
2409 if (key_bits != 0) {
2410 if (key_bits >
2411 (CRYPTO_BYTES2BITS(crypto_max_buffer_len))) {
2412 cmn_err(CE_NOTE, "copyin_key: buffer greater "
2413 "than %ld bytes, pid = %d",
2414 crypto_max_buffer_len, curproc->p_pid);
2415 rv = CRYPTO_ARGUMENTS_BAD;
2416 goto out;
2417 }
2418 key_bytes = CRYPTO_BITS2BYTES(key_bits);
2419
2420 rv = CRYPTO_BUFFER_CHECK(sp, key_bytes,
2421 *out_rctl_chk);
2422 if (rv != CRYPTO_SUCCESS) {
2423 goto out;
2424 }
2425 rctl_bytes = key_bytes;
2426
2427 out_key->ck_data = kmem_alloc(key_bytes, KM_SLEEP);
2428
2429 if (copyin((char *)STRUCT_FGETP(key, ck_data),
2430 out_key->ck_data, key_bytes) != 0) {
2431 kmem_free(out_key->ck_data, key_bytes);
2432 out_key->ck_data = NULL;
2433 out_key->ck_length = 0;
2434 error = EFAULT;
2435 goto out;
2436 }
2437 }
2438 out_key->ck_length = (ulong_t)key_bits;
2439 break;
2440
2441 case CRYPTO_KEY_ATTR_LIST:
2442 count = STRUCT_FGET(key, ck_count);
2443
2444 if (copyin_attributes(mode, sp, count,
2445 (caddr_t)STRUCT_FGETP(key, ck_attrs), &k_attrs, NULL, NULL,
2446 &rv, &error, &rctl_bytes, out_rctl_chk, B_TRUE)) {
2447 out_key->ck_count = count;
2448 out_key->ck_attrs = k_attrs;
2449 k_attrs = NULL;
2450 } else {
2451 out_key->ck_count = 0;
2452 out_key->ck_attrs = NULL;
2453 }
2454 break;
2455
2456 case CRYPTO_KEY_REFERENCE:
2457 out_key->ck_obj_id = STRUCT_FGET(key, ck_obj_id);
2458 break;
2459
2460 default:
2461 rv = CRYPTO_ARGUMENTS_BAD;
2462 }
2463
2464 out:
2465 *out_rctl_bytes = rctl_bytes;
2466 *out_rv = rv;
2467 *out_error = error;
2468 return ((rv | error) ? B_FALSE : B_TRUE);
2469 }
2470
2471 /*
2472 * This routine does two things:
2473 * 1. Given a crypto_minor structure and a session ID, it returns
2474 * a valid session pointer.
2475 * 2. It checks that the provider, to which the session has been opened,
2476 * has not been removed.
2477 */
2478 static boolean_t
get_session_ptr(crypto_session_id_t i,crypto_minor_t * cm,crypto_session_data_t ** session_ptr,int * out_error,int * out_rv)2479 get_session_ptr(crypto_session_id_t i, crypto_minor_t *cm,
2480 crypto_session_data_t **session_ptr, int *out_error, int *out_rv)
2481 {
2482 crypto_session_data_t *sp = NULL;
2483 int rv = CRYPTO_SESSION_HANDLE_INVALID;
2484 int error = 0;
2485
2486 mutex_enter(&cm->cm_lock);
2487 if ((i < cm->cm_session_table_count) &&
2488 (cm->cm_session_table[i] != NULL)) {
2489 sp = cm->cm_session_table[i];
2490 mutex_enter(&sp->sd_lock);
2491 mutex_exit(&cm->cm_lock);
2492 while (sp->sd_flags & CRYPTO_SESSION_IS_BUSY) {
2493 if (cv_wait_sig(&sp->sd_cv, &sp->sd_lock) == 0) {
2494 mutex_exit(&sp->sd_lock);
2495 sp = NULL;
2496 error = EINTR;
2497 goto out;
2498 }
2499 }
2500
2501 if (sp->sd_flags & CRYPTO_SESSION_IS_CLOSED) {
2502 mutex_exit(&sp->sd_lock);
2503 sp = NULL;
2504 goto out;
2505 }
2506
2507 if (KCF_IS_PROV_REMOVED(sp->sd_provider)) {
2508 mutex_exit(&sp->sd_lock);
2509 sp = NULL;
2510 rv = CRYPTO_DEVICE_ERROR;
2511 goto out;
2512 }
2513
2514 rv = CRYPTO_SUCCESS;
2515 sp->sd_flags |= CRYPTO_SESSION_IS_BUSY;
2516 mutex_exit(&sp->sd_lock);
2517 } else {
2518 mutex_exit(&cm->cm_lock);
2519 }
2520 out:
2521 *session_ptr = sp;
2522 *out_error = error;
2523 *out_rv = rv;
2524 return ((rv == CRYPTO_SUCCESS && error == 0) ? B_TRUE : B_FALSE);
2525 }
2526
2527 #define CRYPTO_SESSION_RELE(s) if ((s) != NULL) { \
2528 mutex_enter(&((s)->sd_lock)); \
2529 (s)->sd_flags &= ~CRYPTO_SESSION_IS_BUSY; \
2530 cv_broadcast(&(s)->sd_cv); \
2531 mutex_exit(&((s)->sd_lock)); \
2532 }
2533
2534 /* ARGSUSED */
2535 static int
encrypt_init(dev_t dev,caddr_t arg,int mode,int * rval)2536 encrypt_init(dev_t dev, caddr_t arg, int mode, int *rval)
2537 {
2538 return (cipher_init(dev, arg, mode, crypto_encrypt_init_prov));
2539 }
2540
2541 /* ARGSUSED */
2542 static int
decrypt_init(dev_t dev,caddr_t arg,int mode,int * rval)2543 decrypt_init(dev_t dev, caddr_t arg, int mode, int *rval)
2544 {
2545 return (cipher_init(dev, arg, mode, crypto_decrypt_init_prov));
2546 }
2547
2548 /*
2549 * umech is a mechanism structure that has been copied from user address
2550 * space into kernel address space. Only one copyin has been done.
2551 * The mechanism parameter, if non-null, still points to user address space.
2552 * If the mechanism parameter contains pointers, they are pointers into
2553 * user address space.
2554 *
2555 * kmech is a umech with all pointers and structures in kernel address space.
2556 *
2557 * This routine calls the provider's entry point to copy a umech parameter
2558 * into kernel address space. Kernel memory is allocated by the provider.
2559 */
2560 static int
crypto_provider_copyin_mech_param(kcf_provider_desc_t * pd,crypto_mechanism_t * umech,crypto_mechanism_t * kmech,int mode,int * error)2561 crypto_provider_copyin_mech_param(kcf_provider_desc_t *pd,
2562 crypto_mechanism_t *umech, crypto_mechanism_t *kmech, int mode, int *error)
2563 {
2564 crypto_mech_type_t provider_mech_type;
2565 int rv;
2566
2567 /* get the provider's mech number */
2568 provider_mech_type = KCF_TO_PROV_MECHNUM(pd, umech->cm_type);
2569
2570 kmech->cm_param = NULL;
2571 kmech->cm_param_len = 0;
2572 kmech->cm_type = provider_mech_type;
2573 rv = KCF_PROV_COPYIN_MECH(pd, umech, kmech, error, mode);
2574 kmech->cm_type = umech->cm_type;
2575
2576 return (rv);
2577 }
2578
2579 /*
2580 * umech is a mechanism structure that has been copied from user address
2581 * space into kernel address space. Only one copyin has been done.
2582 * The mechanism parameter, if non-null, still points to user address space.
2583 * If the mechanism parameter contains pointers, they are pointers into
2584 * user address space.
2585 *
2586 * kmech is a umech with all pointers and structures in kernel address space.
2587 *
2588 * This routine calls the provider's entry point to copy a kmech parameter
2589 * into user address space using umech as a template containing
2590 * user address pointers.
2591 */
2592 static int
crypto_provider_copyout_mech_param(kcf_provider_desc_t * pd,crypto_mechanism_t * kmech,crypto_mechanism_t * umech,int mode,int * error)2593 crypto_provider_copyout_mech_param(kcf_provider_desc_t *pd,
2594 crypto_mechanism_t *kmech, crypto_mechanism_t *umech, int mode, int *error)
2595 {
2596 crypto_mech_type_t provider_mech_type;
2597 int rv;
2598
2599 /* get the provider's mech number */
2600 provider_mech_type = KCF_TO_PROV_MECHNUM(pd, umech->cm_type);
2601
2602 kmech->cm_type = provider_mech_type;
2603 rv = KCF_PROV_COPYOUT_MECH(pd, kmech, umech, error, mode);
2604 kmech->cm_type = umech->cm_type;
2605
2606 return (rv);
2607 }
2608
2609 /*
2610 * Call the provider's entry point to free kernel memory that has been
2611 * allocated for the mechanism's parameter.
2612 */
2613 static void
crypto_free_mech(kcf_provider_desc_t * pd,boolean_t allocated_by_crypto_module,crypto_mechanism_t * mech)2614 crypto_free_mech(kcf_provider_desc_t *pd, boolean_t allocated_by_crypto_module,
2615 crypto_mechanism_t *mech)
2616 {
2617 crypto_mech_type_t provider_mech_type;
2618
2619 if (allocated_by_crypto_module) {
2620 if (mech->cm_param != NULL)
2621 kmem_free(mech->cm_param, mech->cm_param_len);
2622 } else {
2623 /* get the provider's mech number */
2624 provider_mech_type = KCF_TO_PROV_MECHNUM(pd, mech->cm_type);
2625
2626 if (mech->cm_param != NULL && mech->cm_param_len != 0) {
2627 mech->cm_type = provider_mech_type;
2628 (void) KCF_PROV_FREE_MECH(pd, mech);
2629 }
2630 }
2631 }
2632
2633 /*
2634 * ASSUMPTION: crypto_encrypt_init and crypto_decrypt_init
2635 * structures are identical except for field names.
2636 */
2637 static int
cipher_init(dev_t dev,caddr_t arg,int mode,int (* init)(crypto_provider_t,crypto_session_id_t,crypto_mechanism_t *,crypto_key_t *,crypto_ctx_template_t,crypto_context_t *,crypto_call_req_t *))2638 cipher_init(dev_t dev, caddr_t arg, int mode, int (*init)(crypto_provider_t,
2639 crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
2640 crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *))
2641 {
2642 STRUCT_DECL(crypto_encrypt_init, encrypt_init);
2643 kcf_provider_desc_t *real_provider = NULL;
2644 crypto_session_id_t session_id;
2645 crypto_mechanism_t mech;
2646 crypto_key_t key;
2647 crypto_minor_t *cm;
2648 crypto_session_data_t *sp = NULL;
2649 crypto_context_t cc;
2650 crypto_ctx_t **ctxpp;
2651 size_t mech_rctl_bytes = 0;
2652 boolean_t mech_rctl_chk = B_FALSE;
2653 size_t key_rctl_bytes = 0;
2654 boolean_t key_rctl_chk = B_FALSE;
2655 int error = 0;
2656 int rv;
2657 boolean_t allocated_by_crypto_module = B_FALSE;
2658 crypto_func_group_t fg;
2659
2660 STRUCT_INIT(encrypt_init, mode);
2661
2662 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2663 cmn_err(CE_WARN, "cipher_init: failed holding minor");
2664 return (ENXIO);
2665 }
2666
2667 if (copyin(arg, STRUCT_BUF(encrypt_init),
2668 STRUCT_SIZE(encrypt_init)) != 0) {
2669 crypto_release_minor(cm);
2670 return (EFAULT);
2671 }
2672
2673 mech.cm_param = NULL;
2674 bzero(&key, sizeof (crypto_key_t));
2675
2676 session_id = STRUCT_FGET(encrypt_init, ei_session);
2677
2678 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
2679 goto out;
2680 }
2681
2682 bcopy(STRUCT_FADDR(encrypt_init, ei_mech), &mech.cm_type,
2683 sizeof (crypto_mech_type_t));
2684
2685 if (init == crypto_encrypt_init_prov) {
2686 fg = CRYPTO_FG_ENCRYPT;
2687 } else {
2688 fg = CRYPTO_FG_DECRYPT;
2689 }
2690
2691 /* We need the key length for provider selection so copy it in now. */
2692 if (!copyin_key(mode, sp, STRUCT_FADDR(encrypt_init, ei_key), &key,
2693 &key_rctl_bytes, &key_rctl_chk, &rv, &error)) {
2694 goto out;
2695 }
2696
2697 if ((rv = kcf_get_hardware_provider(mech.cm_type, &key,
2698 CRYPTO_MECH_INVALID, NULL, sp->sd_provider, &real_provider, fg))
2699 != CRYPTO_SUCCESS) {
2700 goto out;
2701 }
2702
2703 rv = crypto_provider_copyin_mech_param(real_provider,
2704 STRUCT_FADDR(encrypt_init, ei_mech), &mech, mode, &error);
2705
2706 if (rv == CRYPTO_NOT_SUPPORTED) {
2707 allocated_by_crypto_module = B_TRUE;
2708 if (!copyin_mech(mode, sp, STRUCT_FADDR(encrypt_init, ei_mech),
2709 &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
2710 goto out;
2711 }
2712 } else {
2713 if (rv != CRYPTO_SUCCESS)
2714 goto out;
2715 }
2716
2717 rv = (init)(real_provider, sp->sd_provider_session->ps_session,
2718 &mech, &key, NULL, &cc, NULL);
2719
2720 /*
2721 * Check if a context already exists. If so, it means it is being
2722 * abandoned. So, cancel it to avoid leaking it.
2723 */
2724 ctxpp = (init == crypto_encrypt_init_prov) ?
2725 &sp->sd_encr_ctx : &sp->sd_decr_ctx;
2726
2727 if (*ctxpp != NULL)
2728 CRYPTO_CANCEL_CTX(ctxpp);
2729 *ctxpp = (rv == CRYPTO_SUCCESS) ? cc : NULL;
2730
2731 out:
2732 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
2733 CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
2734 CRYPTO_SESSION_RELE(sp);
2735 crypto_release_minor(cm);
2736
2737 if (real_provider != NULL) {
2738 crypto_free_mech(real_provider,
2739 allocated_by_crypto_module, &mech);
2740 KCF_PROV_REFRELE(real_provider);
2741 }
2742
2743 free_crypto_key(&key);
2744
2745 if (error != 0)
2746 /* XXX free context */
2747 return (error);
2748
2749 STRUCT_FSET(encrypt_init, ei_return_value, rv);
2750 if (copyout(STRUCT_BUF(encrypt_init), arg,
2751 STRUCT_SIZE(encrypt_init)) != 0) {
2752 /* XXX free context */
2753 return (EFAULT);
2754 }
2755 return (0);
2756 }
2757
2758 /* ARGSUSED */
2759 static int
encrypt(dev_t dev,caddr_t arg,int mode,int * rval)2760 encrypt(dev_t dev, caddr_t arg, int mode, int *rval)
2761 {
2762 return (cipher(dev, arg, mode, crypto_encrypt_single));
2763 }
2764
2765 /* ARGSUSED */
2766 static int
decrypt(dev_t dev,caddr_t arg,int mode,int * rval)2767 decrypt(dev_t dev, caddr_t arg, int mode, int *rval)
2768 {
2769 return (cipher(dev, arg, mode, crypto_decrypt_single));
2770 }
2771
2772 /*
2773 * ASSUMPTION: crypto_encrypt and crypto_decrypt structures
2774 * are identical except for field names.
2775 */
2776 static int
cipher(dev_t dev,caddr_t arg,int mode,int (* single)(crypto_context_t,crypto_data_t *,crypto_data_t *,crypto_call_req_t *))2777 cipher(dev_t dev, caddr_t arg, int mode,
2778 int (*single)(crypto_context_t, crypto_data_t *, crypto_data_t *,
2779 crypto_call_req_t *))
2780 {
2781 STRUCT_DECL(crypto_encrypt, encrypt);
2782 crypto_session_id_t session_id;
2783 crypto_minor_t *cm;
2784 crypto_session_data_t *sp = NULL;
2785 crypto_ctx_t **ctxpp;
2786 crypto_data_t data, encr;
2787 size_t datalen, encrlen, need = 0;
2788 boolean_t do_inplace;
2789 char *encrbuf;
2790 int error = 0;
2791 int rv;
2792 boolean_t rctl_chk = B_FALSE;
2793
2794 do_inplace = B_FALSE;
2795 STRUCT_INIT(encrypt, mode);
2796
2797 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2798 cmn_err(CE_WARN, "cipher: failed holding minor");
2799 return (ENXIO);
2800 }
2801
2802 if (copyin(arg, STRUCT_BUF(encrypt), STRUCT_SIZE(encrypt)) != 0) {
2803 crypto_release_minor(cm);
2804 return (EFAULT);
2805 }
2806
2807 data.cd_raw.iov_base = NULL;
2808 encr.cd_raw.iov_base = NULL;
2809
2810 datalen = STRUCT_FGET(encrypt, ce_datalen);
2811 encrlen = STRUCT_FGET(encrypt, ce_encrlen);
2812
2813 /*
2814 * Don't allocate output buffer unless both buffer pointer and
2815 * buffer length are not NULL or 0 (length).
2816 */
2817 encrbuf = STRUCT_FGETP(encrypt, ce_encrbuf);
2818 if (encrbuf == NULL || encrlen == 0) {
2819 encrlen = 0;
2820 }
2821
2822 if (datalen > crypto_max_buffer_len ||
2823 encrlen > crypto_max_buffer_len) {
2824 cmn_err(CE_NOTE, "cipher: buffer greater than %ld bytes, "
2825 "pid = %d", crypto_max_buffer_len, curproc->p_pid);
2826 rv = CRYPTO_ARGUMENTS_BAD;
2827 goto release_minor;
2828 }
2829
2830 session_id = STRUCT_FGET(encrypt, ce_session);
2831
2832 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
2833 goto release_minor;
2834 }
2835
2836 do_inplace = (STRUCT_FGET(encrypt, ce_flags) &
2837 CRYPTO_INPLACE_OPERATION) != 0;
2838 need = do_inplace ? datalen : datalen + encrlen;
2839
2840 if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) !=
2841 CRYPTO_SUCCESS) {
2842 need = 0;
2843 goto release_minor;
2844 }
2845
2846 INIT_RAW_CRYPTO_DATA(data, datalen);
2847 data.cd_miscdata = NULL;
2848
2849 if (datalen != 0 && copyin(STRUCT_FGETP(encrypt, ce_databuf),
2850 data.cd_raw.iov_base, datalen) != 0) {
2851 error = EFAULT;
2852 goto release_minor;
2853 }
2854
2855 if (do_inplace) {
2856 /* set out = in for in-place */
2857 encr = data;
2858 } else {
2859 INIT_RAW_CRYPTO_DATA(encr, encrlen);
2860 }
2861
2862 ctxpp = (single == crypto_encrypt_single) ?
2863 &sp->sd_encr_ctx : &sp->sd_decr_ctx;
2864
2865 if (do_inplace)
2866 /* specify in-place buffers with output = NULL */
2867 rv = (single)(*ctxpp, &encr, NULL, NULL);
2868 else
2869 rv = (single)(*ctxpp, &data, &encr, NULL);
2870
2871 if (KCF_CONTEXT_DONE(rv))
2872 *ctxpp = NULL;
2873
2874 if (rv == CRYPTO_SUCCESS) {
2875 ASSERT(encr.cd_length <= encrlen);
2876 if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base,
2877 encrbuf, encr.cd_length) != 0) {
2878 error = EFAULT;
2879 goto release_minor;
2880 }
2881 STRUCT_FSET(encrypt, ce_encrlen,
2882 (ulong_t)encr.cd_length);
2883 }
2884
2885 if (rv == CRYPTO_BUFFER_TOO_SMALL) {
2886 /*
2887 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
2888 * of section 11.2 of the pkcs11 spec. We catch it here and
2889 * provide the correct pkcs11 return value.
2890 */
2891 if (STRUCT_FGETP(encrypt, ce_encrbuf) == NULL)
2892 rv = CRYPTO_SUCCESS;
2893 STRUCT_FSET(encrypt, ce_encrlen,
2894 (ulong_t)encr.cd_length);
2895 }
2896
2897 release_minor:
2898 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
2899 CRYPTO_SESSION_RELE(sp);
2900 crypto_release_minor(cm);
2901
2902 if (data.cd_raw.iov_base != NULL)
2903 kmem_free(data.cd_raw.iov_base, datalen);
2904
2905 if (!do_inplace && encr.cd_raw.iov_base != NULL)
2906 kmem_free(encr.cd_raw.iov_base, encrlen);
2907
2908 if (error != 0)
2909 return (error);
2910
2911 STRUCT_FSET(encrypt, ce_return_value, rv);
2912 if (copyout(STRUCT_BUF(encrypt), arg, STRUCT_SIZE(encrypt)) != 0) {
2913 return (EFAULT);
2914 }
2915 return (0);
2916 }
2917
2918 /* ARGSUSED */
2919 static int
encrypt_update(dev_t dev,caddr_t arg,int mode,int * rval)2920 encrypt_update(dev_t dev, caddr_t arg, int mode, int *rval)
2921 {
2922 return (cipher_update(dev, arg, mode, crypto_encrypt_update));
2923 }
2924
2925 /* ARGSUSED */
2926 static int
decrypt_update(dev_t dev,caddr_t arg,int mode,int * rval)2927 decrypt_update(dev_t dev, caddr_t arg, int mode, int *rval)
2928 {
2929 return (cipher_update(dev, arg, mode, crypto_decrypt_update));
2930 }
2931
2932 /*
2933 * ASSUMPTION: crypto_encrypt_update and crypto_decrypt_update
2934 * structures are identical except for field names.
2935 */
2936 static int
cipher_update(dev_t dev,caddr_t arg,int mode,int (* update)(crypto_context_t,crypto_data_t *,crypto_data_t *,crypto_call_req_t *))2937 cipher_update(dev_t dev, caddr_t arg, int mode,
2938 int (*update)(crypto_context_t, crypto_data_t *, crypto_data_t *,
2939 crypto_call_req_t *))
2940 {
2941 STRUCT_DECL(crypto_encrypt_update, encrypt_update);
2942 crypto_session_id_t session_id;
2943 crypto_minor_t *cm;
2944 crypto_session_data_t *sp = NULL;
2945 crypto_ctx_t **ctxpp;
2946 crypto_data_t data, encr;
2947 size_t datalen, encrlen, need = 0;
2948 boolean_t do_inplace;
2949 char *encrbuf;
2950 int error = 0;
2951 int rv;
2952 boolean_t rctl_chk = B_FALSE;
2953
2954 do_inplace = B_FALSE;
2955 STRUCT_INIT(encrypt_update, mode);
2956
2957 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
2958 cmn_err(CE_WARN, "cipher_update: failed holding minor");
2959 return (ENXIO);
2960 }
2961
2962 if (copyin(arg, STRUCT_BUF(encrypt_update),
2963 STRUCT_SIZE(encrypt_update)) != 0) {
2964 crypto_release_minor(cm);
2965 return (EFAULT);
2966 }
2967
2968 data.cd_raw.iov_base = NULL;
2969 encr.cd_raw.iov_base = NULL;
2970
2971 datalen = STRUCT_FGET(encrypt_update, eu_datalen);
2972 encrlen = STRUCT_FGET(encrypt_update, eu_encrlen);
2973
2974 /*
2975 * Don't allocate output buffer unless both buffer pointer and
2976 * buffer length are not NULL or 0 (length).
2977 */
2978 encrbuf = STRUCT_FGETP(encrypt_update, eu_encrbuf);
2979 if (encrbuf == NULL || encrlen == 0) {
2980 encrlen = 0;
2981 }
2982
2983 if (datalen > crypto_max_buffer_len ||
2984 encrlen > crypto_max_buffer_len) {
2985 cmn_err(CE_NOTE, "cipher_update: buffer greater than %ld "
2986 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
2987 rv = CRYPTO_ARGUMENTS_BAD;
2988 goto out;
2989 }
2990
2991 session_id = STRUCT_FGET(encrypt_update, eu_session);
2992
2993 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
2994 goto out;
2995 }
2996
2997 do_inplace = (STRUCT_FGET(encrypt_update, eu_flags) &
2998 CRYPTO_INPLACE_OPERATION) != 0;
2999 need = do_inplace ? datalen : datalen + encrlen;
3000
3001 if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) !=
3002 CRYPTO_SUCCESS) {
3003 need = 0;
3004 goto out;
3005 }
3006
3007 INIT_RAW_CRYPTO_DATA(data, datalen);
3008 data.cd_miscdata = NULL;
3009
3010 if (datalen != 0 && copyin(STRUCT_FGETP(encrypt_update, eu_databuf),
3011 data.cd_raw.iov_base, datalen) != 0) {
3012 error = EFAULT;
3013 goto out;
3014 }
3015
3016 if (do_inplace) {
3017 /* specify in-place buffers with output = input */
3018 encr = data;
3019 } else {
3020 INIT_RAW_CRYPTO_DATA(encr, encrlen);
3021 }
3022
3023 ctxpp = (update == crypto_encrypt_update) ?
3024 &sp->sd_encr_ctx : &sp->sd_decr_ctx;
3025
3026 if (do_inplace)
3027 /* specify in-place buffers with output = NULL */
3028 rv = (update)(*ctxpp, &encr, NULL, NULL);
3029 else
3030 rv = (update)(*ctxpp, &data, &encr, NULL);
3031
3032 if (rv == CRYPTO_SUCCESS || rv == CRYPTO_BUFFER_TOO_SMALL) {
3033 if (rv == CRYPTO_SUCCESS) {
3034 ASSERT(encr.cd_length <= encrlen);
3035 if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base,
3036 encrbuf, encr.cd_length) != 0) {
3037 error = EFAULT;
3038 goto out;
3039 }
3040 } else {
3041 /*
3042 * The providers return CRYPTO_BUFFER_TOO_SMALL even
3043 * for case 1 of section 11.2 of the pkcs11 spec.
3044 * We catch it here and provide the correct pkcs11
3045 * return value.
3046 */
3047 if (STRUCT_FGETP(encrypt_update, eu_encrbuf) == NULL)
3048 rv = CRYPTO_SUCCESS;
3049 }
3050 STRUCT_FSET(encrypt_update, eu_encrlen,
3051 (ulong_t)encr.cd_length);
3052 } else {
3053 CRYPTO_CANCEL_CTX(ctxpp);
3054 }
3055 out:
3056 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
3057 CRYPTO_SESSION_RELE(sp);
3058 crypto_release_minor(cm);
3059
3060 if (data.cd_raw.iov_base != NULL)
3061 kmem_free(data.cd_raw.iov_base, datalen);
3062
3063 if (!do_inplace && (encr.cd_raw.iov_base != NULL))
3064 kmem_free(encr.cd_raw.iov_base, encrlen);
3065
3066 if (error != 0)
3067 return (error);
3068
3069 STRUCT_FSET(encrypt_update, eu_return_value, rv);
3070 if (copyout(STRUCT_BUF(encrypt_update), arg,
3071 STRUCT_SIZE(encrypt_update)) != 0) {
3072 return (EFAULT);
3073 }
3074 return (0);
3075 }
3076
3077 /* ARGSUSED */
3078 static int
encrypt_final(dev_t dev,caddr_t arg,int mode,int * rval)3079 encrypt_final(dev_t dev, caddr_t arg, int mode, int *rval)
3080 {
3081 return (common_final(dev, arg, mode, crypto_encrypt_final));
3082 }
3083
3084 /* ARGSUSED */
3085 static int
decrypt_final(dev_t dev,caddr_t arg,int mode,int * rval)3086 decrypt_final(dev_t dev, caddr_t arg, int mode, int *rval)
3087 {
3088 return (common_final(dev, arg, mode, crypto_decrypt_final));
3089 }
3090
3091 /*
3092 * ASSUMPTION: crypto_encrypt_final, crypto_decrypt_final, crypto_sign_final,
3093 * and crypto_digest_final structures are identical except for field names.
3094 */
3095 static int
common_final(dev_t dev,caddr_t arg,int mode,int (* final)(crypto_context_t,crypto_data_t *,crypto_call_req_t *))3096 common_final(dev_t dev, caddr_t arg, int mode,
3097 int (*final)(crypto_context_t, crypto_data_t *, crypto_call_req_t *))
3098 {
3099 STRUCT_DECL(crypto_encrypt_final, encrypt_final);
3100 crypto_session_id_t session_id;
3101 crypto_minor_t *cm;
3102 crypto_session_data_t *sp = NULL;
3103 crypto_ctx_t **ctxpp;
3104 crypto_data_t encr;
3105 size_t encrlen, need = 0;
3106 char *encrbuf;
3107 int error = 0;
3108 int rv;
3109 boolean_t rctl_chk = B_FALSE;
3110
3111 STRUCT_INIT(encrypt_final, mode);
3112
3113 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3114 cmn_err(CE_WARN, "common_final: failed holding minor");
3115 return (ENXIO);
3116 }
3117
3118 if (copyin(arg, STRUCT_BUF(encrypt_final),
3119 STRUCT_SIZE(encrypt_final)) != 0) {
3120 crypto_release_minor(cm);
3121 return (EFAULT);
3122 }
3123
3124 encr.cd_format = CRYPTO_DATA_RAW;
3125 encr.cd_raw.iov_base = NULL;
3126
3127 encrlen = STRUCT_FGET(encrypt_final, ef_encrlen);
3128
3129 /*
3130 * Don't allocate output buffer unless both buffer pointer and
3131 * buffer length are not NULL or 0 (length).
3132 */
3133 encrbuf = STRUCT_FGETP(encrypt_final, ef_encrbuf);
3134 if (encrbuf == NULL || encrlen == 0) {
3135 encrlen = 0;
3136 }
3137
3138 if (encrlen > crypto_max_buffer_len) {
3139 cmn_err(CE_NOTE, "common_final: buffer greater than %ld "
3140 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
3141 rv = CRYPTO_ARGUMENTS_BAD;
3142 goto release_minor;
3143 }
3144
3145 session_id = STRUCT_FGET(encrypt_final, ef_session);
3146
3147 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
3148 goto release_minor;
3149 }
3150
3151 if ((rv = CRYPTO_BUFFER_CHECK(sp, encrlen, rctl_chk)) !=
3152 CRYPTO_SUCCESS) {
3153 goto release_minor;
3154 }
3155 need = encrlen;
3156 encr.cd_raw.iov_base = kmem_alloc(encrlen, KM_SLEEP);
3157 encr.cd_raw.iov_len = encrlen;
3158
3159 encr.cd_offset = 0;
3160 encr.cd_length = encrlen;
3161
3162 ASSERT(final == crypto_encrypt_final ||
3163 final == crypto_decrypt_final || final == crypto_sign_final ||
3164 final == crypto_digest_final || final == crypto_mac_final);
3165
3166 if (final == crypto_encrypt_final) {
3167 ctxpp = &sp->sd_encr_ctx;
3168 } else if (final == crypto_decrypt_final) {
3169 ctxpp = &sp->sd_decr_ctx;
3170 } else if (final == crypto_sign_final) {
3171 ctxpp = &sp->sd_sign_ctx;
3172 } else if (final == crypto_mac_final) {
3173 ctxpp = &sp->sd_mac_ctx;
3174 } else {
3175 ctxpp = &sp->sd_digest_ctx;
3176 }
3177
3178 rv = (final)(*ctxpp, &encr, NULL);
3179 if (KCF_CONTEXT_DONE(rv))
3180 *ctxpp = NULL;
3181
3182 if (rv == CRYPTO_SUCCESS) {
3183 ASSERT(encr.cd_length <= encrlen);
3184 if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base,
3185 encrbuf, encr.cd_length) != 0) {
3186 error = EFAULT;
3187 goto release_minor;
3188 }
3189 STRUCT_FSET(encrypt_final, ef_encrlen,
3190 (ulong_t)encr.cd_length);
3191 }
3192
3193 if (rv == CRYPTO_BUFFER_TOO_SMALL) {
3194 /*
3195 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
3196 * of section 11.2 of the pkcs11 spec. We catch it here and
3197 * provide the correct pkcs11 return value.
3198 */
3199 if (STRUCT_FGETP(encrypt_final, ef_encrbuf) == NULL)
3200 rv = CRYPTO_SUCCESS;
3201 STRUCT_FSET(encrypt_final, ef_encrlen,
3202 (ulong_t)encr.cd_length);
3203 }
3204
3205 release_minor:
3206 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
3207 CRYPTO_SESSION_RELE(sp);
3208 crypto_release_minor(cm);
3209
3210 if (encr.cd_raw.iov_base != NULL)
3211 kmem_free(encr.cd_raw.iov_base, encrlen);
3212
3213 if (error != 0)
3214 return (error);
3215
3216 STRUCT_FSET(encrypt_final, ef_return_value, rv);
3217 if (copyout(STRUCT_BUF(encrypt_final), arg,
3218 STRUCT_SIZE(encrypt_final)) != 0) {
3219 return (EFAULT);
3220 }
3221 return (0);
3222 }
3223
3224 /* ARGSUSED */
3225 static int
digest_init(dev_t dev,caddr_t arg,int mode,int * rval)3226 digest_init(dev_t dev, caddr_t arg, int mode, int *rval)
3227 {
3228 STRUCT_DECL(crypto_digest_init, digest_init);
3229 kcf_provider_desc_t *real_provider = NULL;
3230 crypto_session_id_t session_id;
3231 crypto_mechanism_t mech;
3232 crypto_minor_t *cm;
3233 crypto_session_data_t *sp = NULL;
3234 crypto_context_t cc;
3235 size_t rctl_bytes = 0;
3236 boolean_t rctl_chk = B_FALSE;
3237 int error = 0;
3238 int rv;
3239
3240 STRUCT_INIT(digest_init, mode);
3241
3242 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3243 cmn_err(CE_WARN, "digest_init: failed holding minor");
3244 return (ENXIO);
3245 }
3246
3247 if (copyin(arg, STRUCT_BUF(digest_init),
3248 STRUCT_SIZE(digest_init)) != 0) {
3249 crypto_release_minor(cm);
3250 return (EFAULT);
3251 }
3252
3253 mech.cm_param = NULL;
3254
3255 session_id = STRUCT_FGET(digest_init, di_session);
3256
3257 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
3258 goto out;
3259 }
3260
3261 if (!copyin_mech(mode, sp, STRUCT_FADDR(digest_init, di_mech), &mech,
3262 &rctl_bytes, &rctl_chk, &rv, &error)) {
3263 goto out;
3264 }
3265
3266 if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL,
3267 CRYPTO_MECH_INVALID, NULL, sp->sd_provider, &real_provider,
3268 CRYPTO_FG_DIGEST)) != CRYPTO_SUCCESS) {
3269 goto out;
3270 }
3271
3272 rv = crypto_digest_init_prov(real_provider,
3273 sp->sd_provider_session->ps_session, &mech, &cc, NULL);
3274
3275 /*
3276 * Check if a context already exists. If so, it means it is being
3277 * abandoned. So, cancel it to avoid leaking it.
3278 */
3279 if (sp->sd_digest_ctx != NULL)
3280 CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx);
3281 sp->sd_digest_ctx = (rv == CRYPTO_SUCCESS) ? cc : NULL;
3282 out:
3283 CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
3284 CRYPTO_SESSION_RELE(sp);
3285 crypto_release_minor(cm);
3286
3287 if (real_provider != NULL)
3288 KCF_PROV_REFRELE(real_provider);
3289
3290 if (mech.cm_param != NULL)
3291 kmem_free(mech.cm_param, mech.cm_param_len);
3292
3293 if (error != 0)
3294 return (error);
3295
3296 STRUCT_FSET(digest_init, di_return_value, rv);
3297 if (copyout(STRUCT_BUF(digest_init), arg,
3298 STRUCT_SIZE(digest_init)) != 0) {
3299 return (EFAULT);
3300 }
3301 return (0);
3302 }
3303
3304 /* ARGSUSED */
3305 static int
digest_update(dev_t dev,caddr_t arg,int mode,int * rval)3306 digest_update(dev_t dev, caddr_t arg, int mode, int *rval)
3307 {
3308 STRUCT_DECL(crypto_digest_update, digest_update);
3309 crypto_session_id_t session_id;
3310 crypto_minor_t *cm;
3311 crypto_session_data_t *sp = NULL;
3312 crypto_data_t data;
3313 size_t datalen, need = 0;
3314 int error = 0;
3315 int rv;
3316 boolean_t rctl_chk = B_FALSE;
3317
3318 STRUCT_INIT(digest_update, mode);
3319
3320 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3321 cmn_err(CE_WARN, "digest_update: failed holding minor");
3322 return (ENXIO);
3323 }
3324
3325 if (copyin(arg, STRUCT_BUF(digest_update),
3326 STRUCT_SIZE(digest_update)) != 0) {
3327 crypto_release_minor(cm);
3328 return (EFAULT);
3329 }
3330
3331 data.cd_format = CRYPTO_DATA_RAW;
3332 data.cd_raw.iov_base = NULL;
3333
3334 datalen = STRUCT_FGET(digest_update, du_datalen);
3335 if (datalen > crypto_max_buffer_len) {
3336 cmn_err(CE_NOTE, "digest_update: buffer greater than %ld "
3337 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
3338 rv = CRYPTO_ARGUMENTS_BAD;
3339 goto release_minor;
3340 }
3341
3342 session_id = STRUCT_FGET(digest_update, du_session);
3343
3344 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
3345 goto release_minor;
3346 }
3347
3348 if ((rv = CRYPTO_BUFFER_CHECK(sp, datalen, rctl_chk)) !=
3349 CRYPTO_SUCCESS) {
3350 goto release_minor;
3351 }
3352
3353 need = datalen;
3354 data.cd_raw.iov_base = kmem_alloc(datalen, KM_SLEEP);
3355 data.cd_raw.iov_len = datalen;
3356
3357 if (datalen != 0 && copyin(STRUCT_FGETP(digest_update, du_databuf),
3358 data.cd_raw.iov_base, datalen) != 0) {
3359 error = EFAULT;
3360 goto release_minor;
3361 }
3362
3363 data.cd_offset = 0;
3364 data.cd_length = datalen;
3365
3366 rv = crypto_digest_update(sp->sd_digest_ctx, &data, NULL);
3367 if (rv != CRYPTO_SUCCESS)
3368 CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx);
3369
3370 release_minor:
3371 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
3372 CRYPTO_SESSION_RELE(sp);
3373 crypto_release_minor(cm);
3374
3375 if (data.cd_raw.iov_base != NULL)
3376 kmem_free(data.cd_raw.iov_base, datalen);
3377
3378 if (error != 0)
3379 return (error);
3380
3381 STRUCT_FSET(digest_update, du_return_value, rv);
3382 if (copyout(STRUCT_BUF(digest_update), arg,
3383 STRUCT_SIZE(digest_update)) != 0) {
3384 return (EFAULT);
3385 }
3386 return (0);
3387 }
3388
3389 /* ARGSUSED */
3390 static int
digest_key(dev_t dev,caddr_t arg,int mode,int * rval)3391 digest_key(dev_t dev, caddr_t arg, int mode, int *rval)
3392 {
3393 STRUCT_DECL(crypto_digest_key, digest_key);
3394 crypto_session_id_t session_id;
3395 crypto_key_t key;
3396 crypto_minor_t *cm;
3397 crypto_session_data_t *sp = NULL;
3398 size_t rctl_bytes = 0;
3399 boolean_t key_rctl_chk = B_FALSE;
3400 int error = 0;
3401 int rv;
3402
3403 STRUCT_INIT(digest_key, mode);
3404
3405 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3406 cmn_err(CE_WARN, "digest_key: failed holding minor");
3407 return (ENXIO);
3408 }
3409
3410 if (copyin(arg, STRUCT_BUF(digest_key), STRUCT_SIZE(digest_key)) != 0) {
3411 crypto_release_minor(cm);
3412 return (EFAULT);
3413 }
3414
3415 bzero(&key, sizeof (crypto_key_t));
3416
3417 session_id = STRUCT_FGET(digest_key, dk_session);
3418
3419 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
3420 goto out;
3421 }
3422
3423 if (!copyin_key(mode, sp, STRUCT_FADDR(digest_key, dk_key), &key,
3424 &rctl_bytes, &key_rctl_chk, &rv, &error)) {
3425 goto out;
3426 }
3427
3428 rv = crypto_digest_key_prov(sp->sd_digest_ctx, &key, NULL);
3429 if (rv != CRYPTO_SUCCESS)
3430 CRYPTO_CANCEL_CTX(&sp->sd_digest_ctx);
3431 out:
3432 CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, key_rctl_chk);
3433 CRYPTO_SESSION_RELE(sp);
3434 crypto_release_minor(cm);
3435
3436 free_crypto_key(&key);
3437
3438 if (error != 0)
3439 return (error);
3440
3441 STRUCT_FSET(digest_key, dk_return_value, rv);
3442 if (copyout(STRUCT_BUF(digest_key), arg,
3443 STRUCT_SIZE(digest_key)) != 0) {
3444 return (EFAULT);
3445 }
3446 return (0);
3447 }
3448
3449 /* ARGSUSED */
3450 static int
digest_final(dev_t dev,caddr_t arg,int mode,int * rval)3451 digest_final(dev_t dev, caddr_t arg, int mode, int *rval)
3452 {
3453 return (common_final(dev, arg, mode, crypto_digest_final));
3454 }
3455
3456 /* ARGSUSED */
3457 static int
digest(dev_t dev,caddr_t arg,int mode,int * rval)3458 digest(dev_t dev, caddr_t arg, int mode, int *rval)
3459 {
3460 return (common_digest(dev, arg, mode, crypto_digest_single));
3461 }
3462
3463 static int
mac_init(dev_t dev,caddr_t arg,int mode,int * rval)3464 mac_init(dev_t dev, caddr_t arg, int mode, int *rval)
3465 {
3466 _NOTE(ARGUNUSED(rval))
3467 return (sign_verify_init(dev, arg, mode, crypto_mac_init_prov));
3468 }
3469
3470 static int
mac_update(dev_t dev,caddr_t arg,int mode,int * rval)3471 mac_update(dev_t dev, caddr_t arg, int mode, int *rval)
3472 {
3473 _NOTE(ARGUNUSED(rval))
3474 return (sign_verify_update(dev, arg, mode, crypto_mac_update));
3475 }
3476
3477 static int
mac_final(dev_t dev,caddr_t arg,int mode,int * rval)3478 mac_final(dev_t dev, caddr_t arg, int mode, int *rval)
3479 {
3480 _NOTE(ARGUNUSED(rval))
3481 return (common_final(dev, arg, mode, crypto_mac_final));
3482 }
3483
3484 /* ARGSUSED */
3485 static int
mac(dev_t dev,caddr_t arg,int mode,int * rval)3486 mac(dev_t dev, caddr_t arg, int mode, int *rval)
3487 {
3488 _NOTE(ARGUNUSED(rval))
3489 return (common_digest(dev, arg, mode, crypto_mac_single));
3490 }
3491
3492 /*
3493 * ASSUMPTION: crypto_digest, crypto_sign, crypto_sign_recover,
3494 * and crypto_verify_recover are identical except for field names.
3495 */
3496 static int
common_digest(dev_t dev,caddr_t arg,int mode,int (* single)(crypto_context_t,crypto_data_t *,crypto_data_t *,crypto_call_req_t *))3497 common_digest(dev_t dev, caddr_t arg, int mode,
3498 int (*single)(crypto_context_t, crypto_data_t *, crypto_data_t *,
3499 crypto_call_req_t *))
3500 {
3501 STRUCT_DECL(crypto_digest, crypto_digest);
3502 crypto_session_id_t session_id;
3503 crypto_minor_t *cm;
3504 crypto_session_data_t *sp = NULL;
3505 crypto_data_t data, digest;
3506 crypto_ctx_t **ctxpp;
3507 size_t datalen, digestlen, need = 0;
3508 char *digestbuf;
3509 int error = 0;
3510 int rv;
3511 boolean_t rctl_chk = B_FALSE;
3512
3513 STRUCT_INIT(crypto_digest, mode);
3514
3515 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3516 cmn_err(CE_WARN, "common_digest: failed holding minor");
3517 return (ENXIO);
3518 }
3519
3520 if (copyin(arg, STRUCT_BUF(crypto_digest),
3521 STRUCT_SIZE(crypto_digest)) != 0) {
3522 crypto_release_minor(cm);
3523 return (EFAULT);
3524 }
3525
3526 data.cd_raw.iov_base = NULL;
3527 digest.cd_raw.iov_base = NULL;
3528 data.cd_miscdata = NULL;
3529 digest.cd_miscdata = NULL;
3530
3531 datalen = STRUCT_FGET(crypto_digest, cd_datalen);
3532 digestlen = STRUCT_FGET(crypto_digest, cd_digestlen);
3533
3534 /*
3535 * Don't allocate output buffer unless both buffer pointer and
3536 * buffer length are not NULL or 0 (length).
3537 */
3538 digestbuf = STRUCT_FGETP(crypto_digest, cd_digestbuf);
3539 if (digestbuf == NULL || digestlen == 0) {
3540 digestlen = 0;
3541 }
3542
3543 if (datalen > crypto_max_buffer_len ||
3544 digestlen > crypto_max_buffer_len) {
3545 cmn_err(CE_NOTE, "common_digest: buffer greater than %ld "
3546 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
3547 rv = CRYPTO_ARGUMENTS_BAD;
3548 goto release_minor;
3549 }
3550
3551 session_id = STRUCT_FGET(crypto_digest, cd_session);
3552
3553 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
3554 goto release_minor;
3555 }
3556
3557 need = datalen + digestlen;
3558 if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) !=
3559 CRYPTO_SUCCESS) {
3560 need = 0;
3561 goto release_minor;
3562 }
3563
3564 INIT_RAW_CRYPTO_DATA(data, datalen);
3565
3566 if (datalen != 0 && copyin(STRUCT_FGETP(crypto_digest, cd_databuf),
3567 data.cd_raw.iov_base, datalen) != 0) {
3568 error = EFAULT;
3569 goto release_minor;
3570 }
3571
3572 INIT_RAW_CRYPTO_DATA(digest, digestlen);
3573
3574 ASSERT(single == crypto_digest_single ||
3575 single == crypto_sign_single ||
3576 single == crypto_verify_recover_single ||
3577 single == crypto_sign_recover_single ||
3578 single == crypto_mac_single);
3579
3580 if (single == crypto_digest_single) {
3581 ctxpp = &sp->sd_digest_ctx;
3582 } else if (single == crypto_sign_single) {
3583 ctxpp = &sp->sd_sign_ctx;
3584 } else if (single == crypto_verify_recover_single) {
3585 ctxpp = &sp->sd_verify_recover_ctx;
3586 } else if (single == crypto_mac_single) {
3587 ctxpp = &sp->sd_mac_ctx;
3588 } else {
3589 ctxpp = &sp->sd_sign_recover_ctx;
3590 }
3591 rv = (single)(*ctxpp, &data, &digest, NULL);
3592 if (KCF_CONTEXT_DONE(rv))
3593 *ctxpp = NULL;
3594
3595 if (rv == CRYPTO_SUCCESS) {
3596 ASSERT(digest.cd_length <= digestlen);
3597 if (digest.cd_length != 0 && copyout(digest.cd_raw.iov_base,
3598 digestbuf, digest.cd_length) != 0) {
3599 error = EFAULT;
3600 goto release_minor;
3601 }
3602 STRUCT_FSET(crypto_digest, cd_digestlen,
3603 (ulong_t)digest.cd_length);
3604 }
3605
3606 if (rv == CRYPTO_BUFFER_TOO_SMALL) {
3607 /*
3608 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
3609 * of section 11.2 of the pkcs11 spec. We catch it here and
3610 * provide the correct pkcs11 return value.
3611 */
3612 if (STRUCT_FGETP(crypto_digest, cd_digestbuf) == NULL)
3613 rv = CRYPTO_SUCCESS;
3614 STRUCT_FSET(crypto_digest, cd_digestlen,
3615 (ulong_t)digest.cd_length);
3616 }
3617
3618 release_minor:
3619 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
3620 CRYPTO_SESSION_RELE(sp);
3621 crypto_release_minor(cm);
3622
3623 if (data.cd_raw.iov_base != NULL)
3624 kmem_free(data.cd_raw.iov_base, datalen);
3625
3626 if (digest.cd_raw.iov_base != NULL)
3627 kmem_free(digest.cd_raw.iov_base, digestlen);
3628
3629 if (error != 0)
3630 return (error);
3631
3632 STRUCT_FSET(crypto_digest, cd_return_value, rv);
3633 if (copyout(STRUCT_BUF(crypto_digest), arg,
3634 STRUCT_SIZE(crypto_digest)) != 0) {
3635 return (EFAULT);
3636 }
3637 return (0);
3638 }
3639
3640 /*
3641 * A helper function that does what the name suggests.
3642 * Returns 0 on success and non-zero otherwise.
3643 * On failure, out_pin is set to 0.
3644 */
3645 int
get_pin_and_session_ptr(char * in_pin,char ** out_pin,size_t pin_len,crypto_minor_t * cm,crypto_session_id_t sid,crypto_session_data_t ** sp,int * rv,int * error)3646 get_pin_and_session_ptr(char *in_pin, char **out_pin, size_t pin_len,
3647 crypto_minor_t *cm, crypto_session_id_t sid, crypto_session_data_t **sp,
3648 int *rv, int *error)
3649 {
3650 char *tmp_pin = NULL;
3651 int tmp_error = 0, tmp_rv = 0;
3652
3653 if (pin_len > KCF_MAX_PIN_LEN) {
3654 tmp_rv = CRYPTO_PIN_LEN_RANGE;
3655 goto out;
3656 }
3657 tmp_pin = kmem_alloc(pin_len, KM_SLEEP);
3658
3659 if (pin_len != 0 && copyin(in_pin, tmp_pin, pin_len) != 0) {
3660 tmp_error = EFAULT;
3661 goto out;
3662 }
3663
3664 (void) get_session_ptr(sid, cm, sp, &tmp_error, &tmp_rv);
3665 out:
3666 *out_pin = tmp_pin;
3667 *rv = tmp_rv;
3668 *error = tmp_error;
3669 return (tmp_rv | tmp_error);
3670 }
3671
3672 /* ARGSUSED */
3673 static int
set_pin(dev_t dev,caddr_t arg,int mode,int * rval)3674 set_pin(dev_t dev, caddr_t arg, int mode, int *rval)
3675 {
3676 STRUCT_DECL(crypto_set_pin, set_pin);
3677 kcf_provider_desc_t *real_provider;
3678 kcf_req_params_t params;
3679 crypto_minor_t *cm;
3680 crypto_session_data_t *sp;
3681 char *old_pin = NULL;
3682 char *new_pin = NULL;
3683 size_t old_pin_len;
3684 size_t new_pin_len;
3685 int error = 0;
3686 int rv;
3687
3688 STRUCT_INIT(set_pin, mode);
3689
3690 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3691 cmn_err(CE_WARN, "set_pin: failed holding minor");
3692 return (ENXIO);
3693 }
3694
3695 if (copyin(arg, STRUCT_BUF(set_pin),
3696 STRUCT_SIZE(set_pin)) != 0) {
3697 crypto_release_minor(cm);
3698 return (EFAULT);
3699 }
3700
3701 old_pin_len = STRUCT_FGET(set_pin, sp_old_len);
3702
3703 if (get_pin_and_session_ptr(STRUCT_FGETP(set_pin, sp_old_pin),
3704 &old_pin, old_pin_len, cm, STRUCT_FGET(set_pin, sp_session),
3705 &sp, &rv, &error) != 0)
3706 goto release_minor;
3707
3708 new_pin_len = STRUCT_FGET(set_pin, sp_new_len);
3709 if (new_pin_len > KCF_MAX_PIN_LEN) {
3710 rv = CRYPTO_PIN_LEN_RANGE;
3711 goto out;
3712 }
3713 new_pin = kmem_alloc(new_pin_len, KM_SLEEP);
3714
3715 if (new_pin_len != 0 && copyin(STRUCT_FGETP(set_pin, sp_new_pin),
3716 new_pin, new_pin_len) != 0) {
3717 error = EFAULT;
3718 goto out;
3719 }
3720
3721 if ((rv = kcf_get_hardware_provider_nomech(
3722 CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(set_pin),
3723 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
3724 goto out;
3725 }
3726
3727 KCF_WRAP_PROVMGMT_OPS_PARAMS(¶ms, KCF_OP_MGMT_SETPIN,
3728 sp->sd_provider_session->ps_session, old_pin, old_pin_len,
3729 new_pin, new_pin_len, NULL, NULL, real_provider);
3730
3731 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
3732 KCF_PROV_REFRELE(real_provider);
3733
3734 out:
3735 CRYPTO_SESSION_RELE(sp);
3736
3737 release_minor:
3738 crypto_release_minor(cm);
3739
3740 if (old_pin != NULL) {
3741 bzero(old_pin, old_pin_len);
3742 kmem_free(old_pin, old_pin_len);
3743 }
3744
3745 if (new_pin != NULL) {
3746 bzero(new_pin, new_pin_len);
3747 kmem_free(new_pin, new_pin_len);
3748 }
3749
3750 if (error != 0)
3751 return (error);
3752
3753 STRUCT_FSET(set_pin, sp_return_value, rv);
3754 if (copyout(STRUCT_BUF(set_pin), arg, STRUCT_SIZE(set_pin)) != 0) {
3755 return (EFAULT);
3756 }
3757 return (0);
3758 }
3759
3760 /* ARGSUSED */
3761 static int
login(dev_t dev,caddr_t arg,int mode,int * rval)3762 login(dev_t dev, caddr_t arg, int mode, int *rval)
3763 {
3764 STRUCT_DECL(crypto_login, login);
3765 kcf_provider_desc_t *real_provider;
3766 kcf_req_params_t params;
3767 crypto_minor_t *cm;
3768 crypto_session_data_t *sp;
3769 size_t pin_len;
3770 char *pin;
3771 uint_t user_type;
3772 int error = 0;
3773 int rv;
3774
3775 STRUCT_INIT(login, mode);
3776
3777 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3778 cmn_err(CE_WARN, "login: failed holding minor");
3779 return (ENXIO);
3780 }
3781
3782 if (copyin(arg, STRUCT_BUF(login), STRUCT_SIZE(login)) != 0) {
3783 crypto_release_minor(cm);
3784 return (EFAULT);
3785 }
3786
3787 user_type = STRUCT_FGET(login, co_user_type);
3788
3789 pin_len = STRUCT_FGET(login, co_pin_len);
3790
3791 if (get_pin_and_session_ptr(STRUCT_FGETP(login, co_pin),
3792 &pin, pin_len, cm, STRUCT_FGET(login, co_session),
3793 &sp, &rv, &error) != 0) {
3794 if (rv == CRYPTO_PIN_LEN_RANGE)
3795 rv = CRYPTO_PIN_INCORRECT;
3796 goto release_minor;
3797 }
3798
3799 if ((rv = kcf_get_hardware_provider_nomech(
3800 CRYPTO_OPS_OFFSET(session_ops),
3801 CRYPTO_SESSION_OFFSET(session_login), sp->sd_provider,
3802 &real_provider)) != CRYPTO_SUCCESS) {
3803 goto out;
3804 }
3805
3806 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_LOGIN, NULL,
3807 sp->sd_provider_session->ps_session, user_type, pin, pin_len,
3808 real_provider);
3809
3810 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
3811 KCF_PROV_REFRELE(real_provider);
3812
3813 out:
3814 CRYPTO_SESSION_RELE(sp);
3815
3816 release_minor:
3817 crypto_release_minor(cm);
3818
3819 if (pin != NULL) {
3820 bzero(pin, pin_len);
3821 kmem_free(pin, pin_len);
3822 }
3823
3824 if (error != 0)
3825 return (error);
3826
3827 STRUCT_FSET(login, co_return_value, rv);
3828 if (copyout(STRUCT_BUF(login), arg, STRUCT_SIZE(login)) != 0) {
3829 return (EFAULT);
3830 }
3831 return (0);
3832 }
3833
3834 /* ARGSUSED */
3835 static int
logout(dev_t dev,caddr_t arg,int mode,int * rval)3836 logout(dev_t dev, caddr_t arg, int mode, int *rval)
3837 {
3838 crypto_logout_t logout;
3839 kcf_provider_desc_t *real_provider;
3840 kcf_req_params_t params;
3841 crypto_minor_t *cm;
3842 crypto_session_data_t *sp;
3843 int error = 0;
3844 int rv;
3845
3846 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3847 cmn_err(CE_WARN, "logout: failed holding minor");
3848 return (ENXIO);
3849 }
3850
3851 if (copyin(arg, &logout, sizeof (logout)) != 0) {
3852 crypto_release_minor(cm);
3853 return (EFAULT);
3854 }
3855
3856 if (!get_session_ptr(logout.cl_session, cm, &sp, &error, &rv)) {
3857 goto release_minor;
3858 }
3859
3860 if ((rv = kcf_get_hardware_provider_nomech(
3861 CRYPTO_OPS_OFFSET(session_ops),
3862 CRYPTO_SESSION_OFFSET(session_logout), sp->sd_provider,
3863 &real_provider)) != CRYPTO_SUCCESS) {
3864 goto out;
3865 }
3866
3867 KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_LOGOUT, NULL,
3868 sp->sd_provider_session->ps_session, 0, NULL, 0, real_provider);
3869 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
3870 KCF_PROV_REFRELE(real_provider);
3871
3872 out:
3873 CRYPTO_SESSION_RELE(sp);
3874
3875 release_minor:
3876 crypto_release_minor(cm);
3877
3878 if (error != 0)
3879 return (error);
3880
3881 logout.cl_return_value = rv;
3882 if (copyout(&logout, arg, sizeof (logout)) != 0) {
3883 return (EFAULT);
3884 }
3885 return (0);
3886 }
3887
3888 /* ARGSUSED */
3889 static int
sign_init(dev_t dev,caddr_t arg,int mode,int * rval)3890 sign_init(dev_t dev, caddr_t arg, int mode, int *rval)
3891 {
3892 return (sign_verify_init(dev, arg, mode, crypto_sign_init_prov));
3893 }
3894
3895 /* ARGSUSED */
3896 static int
sign_recover_init(dev_t dev,caddr_t arg,int mode,int * rval)3897 sign_recover_init(dev_t dev, caddr_t arg, int mode, int *rval)
3898 {
3899 return (sign_verify_init(dev, arg, mode,
3900 crypto_sign_recover_init_prov));
3901 }
3902
3903 /* ARGSUSED */
3904 static int
verify_init(dev_t dev,caddr_t arg,int mode,int * rval)3905 verify_init(dev_t dev, caddr_t arg, int mode, int *rval)
3906 {
3907 return (sign_verify_init(dev, arg, mode, crypto_verify_init_prov));
3908 }
3909
3910 /* ARGSUSED */
3911 static int
verify_recover_init(dev_t dev,caddr_t arg,int mode,int * rval)3912 verify_recover_init(dev_t dev, caddr_t arg, int mode, int *rval)
3913 {
3914 return (sign_verify_init(dev, arg, mode,
3915 crypto_verify_recover_init_prov));
3916 }
3917
3918 /*
3919 * ASSUMPTION: crypto_sign_init, crypto_verify_init, crypto_sign_recover_init,
3920 * and crypto_verify_recover_init structures are identical
3921 * except for field names.
3922 */
3923 static int
sign_verify_init(dev_t dev,caddr_t arg,int mode,int (* init)(crypto_provider_t,crypto_session_id_t,crypto_mechanism_t *,crypto_key_t *,crypto_ctx_template_t,crypto_context_t *,crypto_call_req_t *))3924 sign_verify_init(dev_t dev, caddr_t arg, int mode,
3925 int (*init)(crypto_provider_t, crypto_session_id_t,
3926 crypto_mechanism_t *, crypto_key_t *, crypto_ctx_template_t,
3927 crypto_context_t *, crypto_call_req_t *))
3928 {
3929 STRUCT_DECL(crypto_sign_init, sign_init);
3930 kcf_provider_desc_t *real_provider = NULL;
3931 crypto_session_id_t session_id;
3932 crypto_mechanism_t mech;
3933 crypto_key_t key;
3934 crypto_minor_t *cm;
3935 crypto_session_data_t *sp = NULL;
3936 crypto_context_t cc;
3937 crypto_ctx_t **ctxpp;
3938 size_t mech_rctl_bytes = 0;
3939 boolean_t mech_rctl_chk = B_FALSE;
3940 size_t key_rctl_bytes = 0;
3941 boolean_t key_rctl_chk = B_FALSE;
3942 int error = 0;
3943 int rv;
3944 boolean_t allocated_by_crypto_module = B_FALSE;
3945 crypto_func_group_t fg;
3946
3947 STRUCT_INIT(sign_init, mode);
3948
3949 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
3950 cmn_err(CE_WARN, "sign_verify_init: failed holding minor");
3951 return (ENXIO);
3952 }
3953
3954 if (copyin(arg, STRUCT_BUF(sign_init), STRUCT_SIZE(sign_init)) != 0) {
3955 crypto_release_minor(cm);
3956 return (EFAULT);
3957 }
3958
3959 mech.cm_param = NULL;
3960 bzero(&key, sizeof (key));
3961
3962 session_id = STRUCT_FGET(sign_init, si_session);
3963
3964 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
3965 goto out;
3966 }
3967
3968 bcopy(STRUCT_FADDR(sign_init, si_mech), &mech.cm_type,
3969 sizeof (crypto_mech_type_t));
3970
3971 ASSERT(init == crypto_sign_init_prov ||
3972 init == crypto_verify_init_prov ||
3973 init == crypto_sign_recover_init_prov ||
3974 init == crypto_verify_recover_init_prov ||
3975 init == crypto_mac_init_prov);
3976
3977 if (init == crypto_sign_init_prov) {
3978 fg = CRYPTO_FG_SIGN;
3979 ctxpp = &sp->sd_sign_ctx;
3980 } else if (init == crypto_verify_init_prov) {
3981 fg = CRYPTO_FG_VERIFY;
3982 ctxpp = &sp->sd_verify_ctx;
3983 } else if (init == crypto_sign_recover_init_prov) {
3984 fg = CRYPTO_FG_SIGN_RECOVER;
3985 ctxpp = &sp->sd_sign_recover_ctx;
3986 } else if (init == crypto_mac_init_prov) {
3987 fg = CRYPTO_FG_MAC;
3988 ctxpp = &sp->sd_mac_ctx;
3989 } else {
3990 fg = CRYPTO_FG_VERIFY_RECOVER;
3991 ctxpp = &sp->sd_verify_recover_ctx;
3992 }
3993
3994 /* We need the key length for provider selection so copy it in now. */
3995 if (!copyin_key(mode, sp, STRUCT_FADDR(sign_init, si_key), &key,
3996 &key_rctl_bytes, &key_rctl_chk, &rv, &error)) {
3997 goto out;
3998 }
3999
4000 if ((rv = kcf_get_hardware_provider(mech.cm_type, &key,
4001 CRYPTO_MECH_INVALID, NULL, sp->sd_provider, &real_provider,
4002 fg)) != CRYPTO_SUCCESS) {
4003 goto out;
4004 }
4005
4006 rv = crypto_provider_copyin_mech_param(real_provider,
4007 STRUCT_FADDR(sign_init, si_mech), &mech, mode, &error);
4008
4009 if (rv == CRYPTO_NOT_SUPPORTED) {
4010 allocated_by_crypto_module = B_TRUE;
4011 if (!copyin_mech(mode, sp, STRUCT_FADDR(sign_init, si_mech),
4012 &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
4013 goto out;
4014 }
4015 } else {
4016 if (rv != CRYPTO_SUCCESS)
4017 goto out;
4018 }
4019
4020 rv = (init)(real_provider, sp->sd_provider_session->ps_session,
4021 &mech, &key, NULL, &cc, NULL);
4022
4023 /*
4024 * Check if a context already exists. If so, it means it is being
4025 * abandoned. So, cancel it to avoid leaking it.
4026 */
4027 if (*ctxpp != NULL)
4028 CRYPTO_CANCEL_CTX(ctxpp);
4029 *ctxpp = (rv == CRYPTO_SUCCESS) ? cc : NULL;
4030
4031 out:
4032 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
4033 CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
4034 CRYPTO_SESSION_RELE(sp);
4035 crypto_release_minor(cm);
4036
4037 if (real_provider != NULL) {
4038 crypto_free_mech(real_provider,
4039 allocated_by_crypto_module, &mech);
4040 KCF_PROV_REFRELE(real_provider);
4041 }
4042
4043 free_crypto_key(&key);
4044
4045 if (error != 0)
4046 return (error);
4047
4048 STRUCT_FSET(sign_init, si_return_value, rv);
4049 if (copyout(STRUCT_BUF(sign_init), arg, STRUCT_SIZE(sign_init)) != 0) {
4050 return (EFAULT);
4051 }
4052 return (0);
4053 }
4054
4055 /* ARGSUSED */
4056 static int
sign(dev_t dev,caddr_t arg,int mode,int * rval)4057 sign(dev_t dev, caddr_t arg, int mode, int *rval)
4058 {
4059 return (common_digest(dev, arg, mode, crypto_sign_single));
4060 }
4061
4062 /* ARGSUSED */
4063 static int
sign_recover(dev_t dev,caddr_t arg,int mode,int * rval)4064 sign_recover(dev_t dev, caddr_t arg, int mode, int *rval)
4065 {
4066 return (common_digest(dev, arg, mode, crypto_sign_recover_single));
4067 }
4068
4069 /* ARGSUSED */
4070 static int
verify(dev_t dev,caddr_t arg,int mode,int * rval)4071 verify(dev_t dev, caddr_t arg, int mode, int *rval)
4072 {
4073 STRUCT_DECL(crypto_verify, verify);
4074 crypto_session_id_t session_id;
4075 crypto_minor_t *cm;
4076 crypto_session_data_t *sp = NULL;
4077 crypto_data_t data, sign;
4078 size_t datalen, signlen, need = 0;
4079 int error = 0;
4080 int rv;
4081 boolean_t rctl_chk = B_FALSE;
4082
4083 STRUCT_INIT(verify, mode);
4084
4085 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4086 cmn_err(CE_WARN, "verify: failed holding minor");
4087 return (ENXIO);
4088 }
4089
4090 if (copyin(arg, STRUCT_BUF(verify), STRUCT_SIZE(verify)) != 0) {
4091 crypto_release_minor(cm);
4092 return (EFAULT);
4093 }
4094
4095 data.cd_raw.iov_base = NULL;
4096 sign.cd_raw.iov_base = NULL;
4097
4098 datalen = STRUCT_FGET(verify, cv_datalen);
4099 signlen = STRUCT_FGET(verify, cv_signlen);
4100 if (datalen > crypto_max_buffer_len ||
4101 signlen > crypto_max_buffer_len) {
4102 cmn_err(CE_NOTE, "verify: buffer greater than %ld bytes, "
4103 "pid = %d", crypto_max_buffer_len, curproc->p_pid);
4104 rv = CRYPTO_ARGUMENTS_BAD;
4105 goto release_minor;
4106 }
4107
4108 session_id = STRUCT_FGET(verify, cv_session);
4109
4110 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4111 goto release_minor;
4112 }
4113
4114 need = datalen + signlen;
4115 if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) !=
4116 CRYPTO_SUCCESS) {
4117 need = 0;
4118 goto release_minor;
4119 }
4120
4121 INIT_RAW_CRYPTO_DATA(data, datalen);
4122 INIT_RAW_CRYPTO_DATA(sign, signlen);
4123
4124 if (datalen != 0 && copyin(STRUCT_FGETP(verify, cv_databuf),
4125 data.cd_raw.iov_base, datalen) != 0) {
4126 error = EFAULT;
4127 goto release_minor;
4128 }
4129
4130 if (signlen != 0 && copyin(STRUCT_FGETP(verify, cv_signbuf),
4131 sign.cd_raw.iov_base, signlen) != 0) {
4132 error = EFAULT;
4133 goto release_minor;
4134 }
4135
4136 rv = crypto_verify_single(sp->sd_verify_ctx, &data, &sign, NULL);
4137 if (KCF_CONTEXT_DONE(rv))
4138 sp->sd_verify_ctx = NULL;
4139
4140 release_minor:
4141 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
4142 CRYPTO_SESSION_RELE(sp);
4143 crypto_release_minor(cm);
4144
4145 if (data.cd_raw.iov_base != NULL)
4146 kmem_free(data.cd_raw.iov_base, datalen);
4147
4148 if (sign.cd_raw.iov_base != NULL)
4149 kmem_free(sign.cd_raw.iov_base, signlen);
4150
4151 if (error != 0)
4152 return (error);
4153
4154 STRUCT_FSET(verify, cv_return_value, rv);
4155 if (copyout(STRUCT_BUF(verify), arg, STRUCT_SIZE(verify)) != 0) {
4156 return (EFAULT);
4157 }
4158 return (0);
4159 }
4160
4161 /* ARGSUSED */
4162 static int
verify_recover(dev_t dev,caddr_t arg,int mode,int * rval)4163 verify_recover(dev_t dev, caddr_t arg, int mode, int *rval)
4164 {
4165 return (common_digest(dev, arg, mode, crypto_verify_recover_single));
4166 }
4167
4168 /* ARGSUSED */
4169 static int
sign_update(dev_t dev,caddr_t arg,int mode,int * rval)4170 sign_update(dev_t dev, caddr_t arg, int mode, int *rval)
4171 {
4172 return (sign_verify_update(dev, arg, mode, crypto_sign_update));
4173 }
4174
4175 /* ARGSUSED */
4176 static int
verify_update(dev_t dev,caddr_t arg,int mode,int * rval)4177 verify_update(dev_t dev, caddr_t arg, int mode, int *rval)
4178 {
4179 return (sign_verify_update(dev, arg, mode, crypto_verify_update));
4180 }
4181
4182 /*
4183 * ASSUMPTION: crypto_sign_update and crypto_verify_update structures
4184 * are identical except for field names.
4185 */
4186 static int
sign_verify_update(dev_t dev,caddr_t arg,int mode,int (* update)(crypto_context_t,crypto_data_t *,crypto_call_req_t *))4187 sign_verify_update(dev_t dev, caddr_t arg, int mode,
4188 int (*update)(crypto_context_t, crypto_data_t *, crypto_call_req_t *))
4189 {
4190 STRUCT_DECL(crypto_sign_update, sign_update);
4191 crypto_session_id_t session_id;
4192 crypto_minor_t *cm;
4193 crypto_session_data_t *sp = NULL;
4194 crypto_ctx_t **ctxpp;
4195 crypto_data_t data;
4196 size_t datalen, need = 0;
4197 int error = 0;
4198 int rv;
4199 boolean_t rctl_chk = B_FALSE;
4200
4201 STRUCT_INIT(sign_update, mode);
4202
4203 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4204 cmn_err(CE_WARN, "sign_verify_update: failed holding minor");
4205 return (ENXIO);
4206 }
4207
4208 if (copyin(arg, STRUCT_BUF(sign_update),
4209 STRUCT_SIZE(sign_update)) != 0) {
4210 crypto_release_minor(cm);
4211 return (EFAULT);
4212 }
4213
4214 data.cd_raw.iov_base = NULL;
4215 data.cd_miscdata = NULL;
4216
4217 datalen = STRUCT_FGET(sign_update, su_datalen);
4218 if (datalen > crypto_max_buffer_len) {
4219 cmn_err(CE_NOTE, "sign_verify_update: buffer greater than %ld "
4220 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
4221 rv = CRYPTO_ARGUMENTS_BAD;
4222 goto release_minor;
4223 }
4224
4225 session_id = STRUCT_FGET(sign_update, su_session);
4226
4227 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4228 goto release_minor;
4229 }
4230
4231 if ((rv = CRYPTO_BUFFER_CHECK(sp, datalen, rctl_chk)) !=
4232 CRYPTO_SUCCESS) {
4233 goto release_minor;
4234 }
4235 need = datalen;
4236
4237 INIT_RAW_CRYPTO_DATA(data, datalen);
4238
4239 if (datalen != 0 && copyin(STRUCT_FGETP(sign_update, su_databuf),
4240 data.cd_raw.iov_base, datalen) != 0) {
4241 error = EFAULT;
4242 goto release_minor;
4243 }
4244
4245 ASSERT(update == crypto_sign_update ||
4246 update == crypto_verify_update ||
4247 update == crypto_mac_update);
4248
4249 if (update == crypto_sign_update)
4250 ctxpp = &sp->sd_sign_ctx;
4251 else if (update == crypto_verify_update)
4252 ctxpp = &sp->sd_verify_ctx;
4253 else
4254 ctxpp = &sp->sd_mac_ctx;
4255
4256 rv = (update)(*ctxpp, &data, NULL);
4257 if (rv != CRYPTO_SUCCESS)
4258 CRYPTO_CANCEL_CTX(ctxpp);
4259
4260 release_minor:
4261 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
4262 CRYPTO_SESSION_RELE(sp);
4263 crypto_release_minor(cm);
4264
4265 if (data.cd_raw.iov_base != NULL)
4266 kmem_free(data.cd_raw.iov_base, datalen);
4267
4268 if (error != 0)
4269 return (error);
4270
4271 STRUCT_FSET(sign_update, su_return_value, rv);
4272 if (copyout(STRUCT_BUF(sign_update), arg,
4273 STRUCT_SIZE(sign_update)) != 0) {
4274 return (EFAULT);
4275 }
4276 return (0);
4277 }
4278
4279 /* ARGSUSED */
4280 static int
sign_final(dev_t dev,caddr_t arg,int mode,int * rval)4281 sign_final(dev_t dev, caddr_t arg, int mode, int *rval)
4282 {
4283 return (common_final(dev, arg, mode, crypto_sign_final));
4284 }
4285
4286 /*
4287 * Can't use the common final because it does a copyout of
4288 * the final part.
4289 */
4290 /* ARGSUSED */
4291 static int
verify_final(dev_t dev,caddr_t arg,int mode,int * rval)4292 verify_final(dev_t dev, caddr_t arg, int mode, int *rval)
4293 {
4294 STRUCT_DECL(crypto_verify_final, verify_final);
4295 crypto_session_id_t session_id;
4296 crypto_minor_t *cm;
4297 crypto_session_data_t *sp = NULL;
4298 crypto_data_t sign;
4299 size_t signlen, need = 0;
4300 int error = 0;
4301 int rv;
4302 boolean_t rctl_chk = B_FALSE;
4303
4304 STRUCT_INIT(verify_final, mode);
4305
4306 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4307 cmn_err(CE_WARN, "verify_final: failed holding minor");
4308 return (ENXIO);
4309 }
4310
4311 if (copyin(arg, STRUCT_BUF(verify_final),
4312 STRUCT_SIZE(verify_final)) != 0) {
4313 crypto_release_minor(cm);
4314 return (EFAULT);
4315 }
4316
4317 sign.cd_raw.iov_base = NULL;
4318
4319 signlen = STRUCT_FGET(verify_final, vf_signlen);
4320 if (signlen > crypto_max_buffer_len) {
4321 cmn_err(CE_NOTE, "verify_final: buffer greater than %ld "
4322 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
4323 rv = CRYPTO_ARGUMENTS_BAD;
4324 goto release_minor;
4325 }
4326
4327 session_id = STRUCT_FGET(verify_final, vf_session);
4328
4329 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4330 goto release_minor;
4331 }
4332
4333 if ((rv = CRYPTO_BUFFER_CHECK(sp, signlen, rctl_chk)) !=
4334 CRYPTO_SUCCESS) {
4335 goto release_minor;
4336 }
4337 need = signlen;
4338
4339 INIT_RAW_CRYPTO_DATA(sign, signlen);
4340
4341 if (signlen != 0 && copyin(STRUCT_FGETP(verify_final, vf_signbuf),
4342 sign.cd_raw.iov_base, signlen) != 0) {
4343 error = EFAULT;
4344 goto release_minor;
4345 }
4346
4347 rv = crypto_verify_final(sp->sd_verify_ctx, &sign, NULL);
4348 if (KCF_CONTEXT_DONE(rv))
4349 sp->sd_verify_ctx = NULL;
4350
4351 release_minor:
4352 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
4353 CRYPTO_SESSION_RELE(sp);
4354 crypto_release_minor(cm);
4355
4356 if (sign.cd_raw.iov_base != NULL)
4357 kmem_free(sign.cd_raw.iov_base, signlen);
4358
4359 if (error != 0)
4360 return (error);
4361
4362 STRUCT_FSET(verify_final, vf_return_value, rv);
4363 if (copyout(STRUCT_BUF(verify_final), arg,
4364 STRUCT_SIZE(verify_final)) != 0) {
4365 return (EFAULT);
4366 }
4367 return (0);
4368 }
4369
4370 /* ARGSUSED */
4371 static int
seed_random(dev_t dev,caddr_t arg,int mode,int * rval)4372 seed_random(dev_t dev, caddr_t arg, int mode, int *rval)
4373 {
4374 STRUCT_DECL(crypto_seed_random, seed_random);
4375 kcf_provider_desc_t *real_provider = NULL;
4376 kcf_req_params_t params;
4377 crypto_session_id_t session_id;
4378 crypto_minor_t *cm;
4379 crypto_session_data_t *sp = NULL;
4380 uchar_t *seed_buffer = NULL;
4381 size_t seed_len;
4382 size_t need = 0;
4383 int error = 0;
4384 int rv;
4385 boolean_t rctl_chk = B_FALSE;
4386
4387 STRUCT_INIT(seed_random, mode);
4388
4389 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4390 cmn_err(CE_WARN, "seed_random: failed holding minor");
4391 return (ENXIO);
4392 }
4393
4394 if (copyin(arg, STRUCT_BUF(seed_random),
4395 STRUCT_SIZE(seed_random)) != 0) {
4396 crypto_release_minor(cm);
4397 return (EFAULT);
4398 }
4399
4400 seed_len = STRUCT_FGET(seed_random, sr_seedlen);
4401 if (seed_len > crypto_max_buffer_len) {
4402 cmn_err(CE_NOTE, "seed_random: buffer greater than %ld "
4403 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
4404 rv = CRYPTO_ARGUMENTS_BAD;
4405 goto release_minor;
4406 }
4407
4408 session_id = STRUCT_FGET(seed_random, sr_session);
4409
4410 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4411 goto release_minor;
4412 }
4413
4414 if ((rv = CRYPTO_BUFFER_CHECK(sp, seed_len, rctl_chk)) !=
4415 CRYPTO_SUCCESS) {
4416 goto release_minor;
4417 }
4418 need = seed_len;
4419 seed_buffer = kmem_alloc(seed_len, KM_SLEEP);
4420
4421 if (seed_len != 0 && copyin(STRUCT_FGETP(seed_random, sr_seedbuf),
4422 seed_buffer, seed_len) != 0) {
4423 error = EFAULT;
4424 goto release_minor;
4425 }
4426
4427 if ((rv = kcf_get_hardware_provider_nomech(
4428 CRYPTO_OPS_OFFSET(random_ops), CRYPTO_RANDOM_OFFSET(seed_random),
4429 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4430 goto release_minor;
4431 }
4432
4433 KCF_WRAP_RANDOM_OPS_PARAMS(¶ms, KCF_OP_RANDOM_SEED,
4434 sp->sd_provider_session->ps_session, seed_buffer, seed_len, 0,
4435 CRYPTO_SEED_NOW);
4436
4437 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
4438
4439 release_minor:
4440 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
4441 CRYPTO_SESSION_RELE(sp);
4442 crypto_release_minor(cm);
4443
4444 if (real_provider != NULL)
4445 KCF_PROV_REFRELE(real_provider);
4446
4447 if (seed_buffer != NULL)
4448 kmem_free(seed_buffer, seed_len);
4449
4450 if (error != 0)
4451 return (error);
4452
4453 STRUCT_FSET(seed_random, sr_return_value, rv);
4454 if (copyout(STRUCT_BUF(seed_random), arg,
4455 STRUCT_SIZE(seed_random)) != 0) {
4456 return (EFAULT);
4457 }
4458 return (0);
4459 }
4460
4461 /* ARGSUSED */
4462 static int
generate_random(dev_t dev,caddr_t arg,int mode,int * rval)4463 generate_random(dev_t dev, caddr_t arg, int mode, int *rval)
4464 {
4465 STRUCT_DECL(crypto_generate_random, generate_random);
4466 kcf_provider_desc_t *real_provider = NULL;
4467 kcf_req_params_t params;
4468 crypto_session_id_t session_id;
4469 crypto_minor_t *cm;
4470 crypto_session_data_t *sp = NULL;
4471 uchar_t *buffer = NULL;
4472 size_t len;
4473 size_t need = 0;
4474 int error = 0;
4475 int rv;
4476 boolean_t rctl_chk = B_FALSE;
4477
4478 STRUCT_INIT(generate_random, mode);
4479
4480 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4481 cmn_err(CE_WARN, "generate_random: failed holding minor");
4482 return (ENXIO);
4483 }
4484
4485 if (copyin(arg, STRUCT_BUF(generate_random),
4486 STRUCT_SIZE(generate_random)) != 0) {
4487 crypto_release_minor(cm);
4488 return (EFAULT);
4489 }
4490
4491 len = STRUCT_FGET(generate_random, gr_buflen);
4492 if (len > crypto_max_buffer_len) {
4493 cmn_err(CE_NOTE, "generate_random: buffer greater than %ld "
4494 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
4495 rv = CRYPTO_ARGUMENTS_BAD;
4496 goto release_minor;
4497 }
4498
4499 session_id = STRUCT_FGET(generate_random, gr_session);
4500
4501 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4502 goto release_minor;
4503 }
4504
4505 if ((rv = CRYPTO_BUFFER_CHECK(sp, len, rctl_chk)) !=
4506 CRYPTO_SUCCESS) {
4507 goto release_minor;
4508 }
4509 need = len;
4510 buffer = kmem_alloc(len, KM_SLEEP);
4511
4512 if ((rv = kcf_get_hardware_provider_nomech(
4513 CRYPTO_OPS_OFFSET(random_ops),
4514 CRYPTO_RANDOM_OFFSET(generate_random), sp->sd_provider,
4515 &real_provider)) != CRYPTO_SUCCESS) {
4516 goto release_minor;
4517 }
4518
4519 KCF_WRAP_RANDOM_OPS_PARAMS(¶ms, KCF_OP_RANDOM_GENERATE,
4520 sp->sd_provider_session->ps_session, buffer, len, 0, 0);
4521
4522 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
4523
4524 if (rv == CRYPTO_SUCCESS) {
4525 if (len != 0 && copyout(buffer,
4526 STRUCT_FGETP(generate_random, gr_buf), len) != 0) {
4527 error = EFAULT;
4528 }
4529 }
4530
4531 release_minor:
4532 CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk);
4533 CRYPTO_SESSION_RELE(sp);
4534 crypto_release_minor(cm);
4535
4536 if (real_provider != NULL)
4537 KCF_PROV_REFRELE(real_provider);
4538
4539 if (buffer != NULL) {
4540 /* random numbers are often used to create keys */
4541 bzero(buffer, len);
4542 kmem_free(buffer, len);
4543 }
4544
4545 if (error != 0)
4546 return (error);
4547
4548 STRUCT_FSET(generate_random, gr_return_value, rv);
4549 if (copyout(STRUCT_BUF(generate_random), arg,
4550 STRUCT_SIZE(generate_random)) != 0) {
4551 return (EFAULT);
4552 }
4553 return (0);
4554 }
4555
4556 /*
4557 * Copyout a kernel array of attributes to user space.
4558 * u_attrs is the corresponding user space array containing
4559 * user space pointers necessary for the copyout.
4560 */
4561 /* ARGSUSED */
4562 static int
copyout_attributes(int mode,caddr_t out,uint_t count,crypto_object_attribute_t * k_attrs,caddr_t u_attrs)4563 copyout_attributes(int mode, caddr_t out, uint_t count,
4564 crypto_object_attribute_t *k_attrs, caddr_t u_attrs)
4565 {
4566 STRUCT_DECL(crypto_object_attribute, oa);
4567 caddr_t p, valuep;
4568 size_t value_len;
4569 size_t len;
4570 int i;
4571 int error = 0;
4572
4573 if (count == 0)
4574 return (0);
4575
4576 STRUCT_INIT(oa, mode);
4577
4578 len = count * STRUCT_SIZE(oa);
4579
4580 ASSERT(u_attrs != NULL);
4581 p = u_attrs;
4582 for (i = 0; i < count; i++) {
4583 /* can this bcopy be eliminated? */
4584 bcopy(p, STRUCT_BUF(oa), STRUCT_SIZE(oa));
4585 value_len = k_attrs[i].oa_value_len;
4586 STRUCT_FSET(oa, oa_type, k_attrs[i].oa_type);
4587 STRUCT_FSET(oa, oa_value_len, (ssize_t)value_len);
4588 valuep = STRUCT_FGETP(oa, oa_value);
4589 if ((valuep != NULL) && (value_len != (size_t)-1)) {
4590 if (copyout(k_attrs[i].oa_value,
4591 valuep, value_len) != 0) {
4592 error = EFAULT;
4593 goto out;
4594 }
4595 }
4596 bcopy(STRUCT_BUF(oa), p, STRUCT_SIZE(oa));
4597 p += STRUCT_SIZE(oa);
4598 }
4599 if (copyout(u_attrs, out, len)) {
4600 error = EFAULT;
4601 }
4602 out:
4603 return (error);
4604 }
4605
4606
4607 /* ARGSUSED */
4608 static int
object_create(dev_t dev,caddr_t arg,int mode,int * rval)4609 object_create(dev_t dev, caddr_t arg, int mode, int *rval)
4610 {
4611 STRUCT_DECL(crypto_object_create, object_create);
4612 kcf_provider_desc_t *real_provider = NULL;
4613 kcf_req_params_t params;
4614 crypto_object_attribute_t *k_attrs = NULL;
4615 crypto_session_id_t session_id;
4616 crypto_minor_t *cm;
4617 crypto_session_data_t *sp = NULL;
4618 crypto_object_id_t object_handle;
4619 caddr_t oc_attributes;
4620 size_t k_attrs_size;
4621 size_t rctl_bytes = 0;
4622 boolean_t rctl_chk = B_FALSE;
4623 int error = 0;
4624 int rv;
4625 uint_t count;
4626
4627 STRUCT_INIT(object_create, mode);
4628
4629 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4630 cmn_err(CE_WARN, "object_create: failed holding minor");
4631 return (ENXIO);
4632 }
4633
4634 if (copyin(arg, STRUCT_BUF(object_create),
4635 STRUCT_SIZE(object_create)) != 0) {
4636 crypto_release_minor(cm);
4637 return (EFAULT);
4638 }
4639
4640 count = STRUCT_FGET(object_create, oc_count);
4641 oc_attributes = STRUCT_FGETP(object_create, oc_attributes);
4642
4643 session_id = STRUCT_FGET(object_create, oc_session);
4644 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4645 goto release_minor;
4646 }
4647 if (!copyin_attributes(mode, sp, count, oc_attributes, &k_attrs,
4648 &k_attrs_size, NULL, &rv, &error, &rctl_bytes,
4649 &rctl_chk, B_TRUE)) {
4650 goto release_minor;
4651 }
4652
4653 if ((rv = kcf_get_hardware_provider_nomech(
4654 CRYPTO_OPS_OFFSET(object_ops),
4655 CRYPTO_OBJECT_OFFSET(object_create), sp->sd_provider,
4656 &real_provider)) != CRYPTO_SUCCESS) {
4657 goto release_minor;
4658 }
4659
4660 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_CREATE,
4661 sp->sd_provider_session->ps_session, 0, k_attrs, count,
4662 &object_handle, 0, NULL, NULL, 0, NULL);
4663
4664 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
4665
4666 if (rv == CRYPTO_SUCCESS)
4667 STRUCT_FSET(object_create, oc_handle, object_handle);
4668
4669 release_minor:
4670 CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
4671
4672 if (k_attrs != NULL)
4673 kmem_free(k_attrs, k_attrs_size);
4674
4675 if (error != 0)
4676 goto out;
4677
4678 STRUCT_FSET(object_create, oc_return_value, rv);
4679 if (copyout(STRUCT_BUF(object_create), arg,
4680 STRUCT_SIZE(object_create)) != 0) {
4681 if (rv == CRYPTO_SUCCESS) {
4682 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms,
4683 KCF_OP_OBJECT_DESTROY,
4684 sp->sd_provider_session->ps_session, object_handle,
4685 NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
4686
4687 (void) kcf_submit_request(real_provider, NULL,
4688 NULL, ¶ms, B_FALSE);
4689
4690 error = EFAULT;
4691 }
4692 }
4693 out:
4694 CRYPTO_SESSION_RELE(sp);
4695 crypto_release_minor(cm);
4696 if (real_provider != NULL)
4697 KCF_PROV_REFRELE(real_provider);
4698 return (error);
4699 }
4700
4701 /* ARGSUSED */
4702 static int
object_copy(dev_t dev,caddr_t arg,int mode,int * rval)4703 object_copy(dev_t dev, caddr_t arg, int mode, int *rval)
4704 {
4705 STRUCT_DECL(crypto_object_copy, object_copy);
4706 kcf_provider_desc_t *real_provider = NULL;
4707 kcf_req_params_t params;
4708 crypto_object_attribute_t *k_attrs = NULL;
4709 crypto_session_id_t session_id;
4710 crypto_minor_t *cm;
4711 crypto_session_data_t *sp = NULL;
4712 crypto_object_id_t handle, new_handle;
4713 caddr_t oc_new_attributes;
4714 size_t k_attrs_size;
4715 size_t rctl_bytes = 0;
4716 boolean_t rctl_chk = B_FALSE;
4717 int error = 0;
4718 int rv;
4719 uint_t count;
4720
4721 STRUCT_INIT(object_copy, mode);
4722
4723 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4724 cmn_err(CE_WARN, "object_copy: failed holding minor");
4725 return (ENXIO);
4726 }
4727
4728 if (copyin(arg, STRUCT_BUF(object_copy),
4729 STRUCT_SIZE(object_copy)) != 0) {
4730 crypto_release_minor(cm);
4731 return (EFAULT);
4732 }
4733
4734 count = STRUCT_FGET(object_copy, oc_count);
4735 oc_new_attributes = STRUCT_FGETP(object_copy, oc_new_attributes);
4736
4737 session_id = STRUCT_FGET(object_copy, oc_session);
4738
4739 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4740 goto release_minor;
4741 }
4742 if (!copyin_attributes(mode, sp, count, oc_new_attributes, &k_attrs,
4743 &k_attrs_size, NULL, &rv, &error, &rctl_bytes,
4744 &rctl_chk, B_TRUE)) {
4745 goto release_minor;
4746 }
4747
4748 if ((rv = kcf_get_hardware_provider_nomech(
4749 CRYPTO_OPS_OFFSET(object_ops),
4750 CRYPTO_OBJECT_OFFSET(object_copy), sp->sd_provider,
4751 &real_provider)) != CRYPTO_SUCCESS) {
4752 goto release_minor;
4753 }
4754
4755 handle = STRUCT_FGET(object_copy, oc_handle);
4756 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_COPY,
4757 sp->sd_provider_session->ps_session, handle, k_attrs, count,
4758 &new_handle, 0, NULL, NULL, 0, NULL);
4759
4760 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
4761
4762 if (rv == CRYPTO_SUCCESS)
4763 STRUCT_FSET(object_copy, oc_new_handle, new_handle);
4764
4765 release_minor:
4766 CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
4767
4768 if (k_attrs != NULL)
4769 kmem_free(k_attrs, k_attrs_size);
4770
4771 if (error != 0)
4772 goto out;
4773
4774 STRUCT_FSET(object_copy, oc_return_value, rv);
4775 if (copyout(STRUCT_BUF(object_copy), arg,
4776 STRUCT_SIZE(object_copy)) != 0) {
4777 if (rv == CRYPTO_SUCCESS) {
4778 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms,
4779 KCF_OP_OBJECT_DESTROY,
4780 sp->sd_provider_session->ps_session, new_handle,
4781 NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
4782
4783 (void) kcf_submit_request(real_provider, NULL,
4784 NULL, ¶ms, B_FALSE);
4785
4786 error = EFAULT;
4787 }
4788 }
4789 out:
4790 CRYPTO_SESSION_RELE(sp);
4791 crypto_release_minor(cm);
4792 if (real_provider != NULL)
4793 KCF_PROV_REFRELE(real_provider);
4794 return (error);
4795 }
4796
4797 /* ARGSUSED */
4798 static int
object_destroy(dev_t dev,caddr_t arg,int mode,int * rval)4799 object_destroy(dev_t dev, caddr_t arg, int mode, int *rval)
4800 {
4801 STRUCT_DECL(crypto_object_destroy, object_destroy);
4802 kcf_provider_desc_t *real_provider;
4803 kcf_req_params_t params;
4804 crypto_session_id_t session_id;
4805 crypto_minor_t *cm;
4806 crypto_session_data_t *sp;
4807 crypto_object_id_t handle;
4808 int error = 0;
4809 int rv;
4810
4811 STRUCT_INIT(object_destroy, mode);
4812
4813 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4814 cmn_err(CE_WARN, "object_destroy: failed holding minor");
4815 return (ENXIO);
4816 }
4817
4818 if (copyin(arg, STRUCT_BUF(object_destroy),
4819 STRUCT_SIZE(object_destroy)) != 0) {
4820 crypto_release_minor(cm);
4821 return (EFAULT);
4822 }
4823
4824 session_id = STRUCT_FGET(object_destroy, od_session);
4825
4826 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4827 goto release_minor;
4828 }
4829
4830 if ((rv = kcf_get_hardware_provider_nomech(
4831 CRYPTO_OPS_OFFSET(object_ops),
4832 CRYPTO_OBJECT_OFFSET(object_destroy), sp->sd_provider,
4833 &real_provider)) != CRYPTO_SUCCESS) {
4834 goto out;
4835 }
4836
4837 handle = STRUCT_FGET(object_destroy, od_handle);
4838 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_DESTROY,
4839 sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, 0,
4840 NULL, NULL, 0, NULL);
4841
4842 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
4843 KCF_PROV_REFRELE(real_provider);
4844
4845 out:
4846 CRYPTO_SESSION_RELE(sp);
4847
4848 release_minor:
4849 crypto_release_minor(cm);
4850
4851 if (error != 0)
4852 return (error);
4853
4854 STRUCT_FSET(object_destroy, od_return_value, rv);
4855
4856 if (copyout(STRUCT_BUF(object_destroy), arg,
4857 STRUCT_SIZE(object_destroy)) != 0) {
4858 return (EFAULT);
4859 }
4860 return (0);
4861 }
4862
4863 /* ARGSUSED */
4864 static int
object_get_attribute_value(dev_t dev,caddr_t arg,int mode,int * rval)4865 object_get_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval)
4866 {
4867 STRUCT_DECL(crypto_object_get_attribute_value, get_attribute_value);
4868 #ifdef _LP64
4869 STRUCT_DECL(crypto_object_attribute, oa);
4870 #else
4871 /* LINTED E_FUNC_SET_NOT_USED */
4872 STRUCT_DECL(crypto_object_attribute, oa);
4873 #endif
4874 kcf_provider_desc_t *real_provider;
4875 kcf_req_params_t params;
4876 crypto_object_attribute_t *k_attrs = NULL;
4877 crypto_session_id_t session_id;
4878 crypto_minor_t *cm;
4879 crypto_session_data_t *sp = NULL;
4880 crypto_object_id_t handle;
4881 caddr_t og_attributes;
4882 caddr_t u_attrs = NULL;
4883 size_t k_attrs_size;
4884 size_t rctl_bytes = 0;
4885 boolean_t rctl_chk = B_FALSE;
4886 int error = 0;
4887 int rv;
4888 uint_t count;
4889
4890 STRUCT_INIT(get_attribute_value, mode);
4891 STRUCT_INIT(oa, mode);
4892
4893 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4894 cmn_err(CE_WARN,
4895 "object_get_attribute_value: failed holding minor");
4896 return (ENXIO);
4897 }
4898
4899 if (copyin(arg, STRUCT_BUF(get_attribute_value),
4900 STRUCT_SIZE(get_attribute_value)) != 0) {
4901 crypto_release_minor(cm);
4902 return (EFAULT);
4903 }
4904
4905 count = STRUCT_FGET(get_attribute_value, og_count);
4906 og_attributes = STRUCT_FGETP(get_attribute_value, og_attributes);
4907
4908 session_id = STRUCT_FGET(get_attribute_value, og_session);
4909
4910 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4911 goto release_minor;
4912 }
4913 if (!copyin_attributes(mode, sp, count, og_attributes, &k_attrs,
4914 &k_attrs_size, &u_attrs, &rv, &error, &rctl_bytes,
4915 &rctl_chk, B_FALSE)) {
4916 goto release_minor;
4917 }
4918
4919 if ((rv = kcf_get_hardware_provider_nomech(
4920 CRYPTO_OPS_OFFSET(object_ops),
4921 CRYPTO_OBJECT_OFFSET(object_get_attribute_value),
4922 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
4923 goto out;
4924 }
4925
4926 handle = STRUCT_FGET(get_attribute_value, og_handle);
4927 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_GET_ATTRIBUTE_VALUE,
4928 sp->sd_provider_session->ps_session, handle, k_attrs, count, NULL,
4929 0, NULL, NULL, 0, NULL);
4930
4931 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
4932 KCF_PROV_REFRELE(real_provider);
4933
4934 out:
4935 if (rv == CRYPTO_SUCCESS || rv == CRYPTO_ATTRIBUTE_SENSITIVE ||
4936 rv == CRYPTO_ATTRIBUTE_TYPE_INVALID ||
4937 rv == CRYPTO_BUFFER_TOO_SMALL) {
4938 error = copyout_attributes(mode,
4939 STRUCT_FGETP(get_attribute_value, og_attributes),
4940 count, k_attrs, u_attrs);
4941 }
4942
4943 release_minor:
4944 CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
4945 CRYPTO_SESSION_RELE(sp);
4946 crypto_release_minor(cm);
4947
4948 if (k_attrs != NULL)
4949 kmem_free(k_attrs, k_attrs_size);
4950
4951 if (u_attrs != NULL)
4952 kmem_free(u_attrs, count * STRUCT_SIZE(oa));
4953
4954 if (error != 0)
4955 return (error);
4956
4957 STRUCT_FSET(get_attribute_value, og_return_value, rv);
4958 if (copyout(STRUCT_BUF(get_attribute_value), arg,
4959 STRUCT_SIZE(get_attribute_value)) != 0) {
4960 return (EFAULT);
4961 }
4962 return (0);
4963 }
4964
4965 /* ARGSUSED */
4966 static int
object_get_size(dev_t dev,caddr_t arg,int mode,int * rval)4967 object_get_size(dev_t dev, caddr_t arg, int mode, int *rval)
4968 {
4969 STRUCT_DECL(crypto_object_get_size, object_get_size);
4970 kcf_provider_desc_t *real_provider;
4971 kcf_req_params_t params;
4972 crypto_session_id_t session_id;
4973 crypto_minor_t *cm;
4974 crypto_session_data_t *sp = NULL;
4975 crypto_object_id_t handle;
4976 size_t size;
4977 int error = 0;
4978 int rv;
4979
4980 STRUCT_INIT(object_get_size, mode);
4981
4982 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
4983 cmn_err(CE_WARN, "object_get_size: failed holding minor");
4984 return (ENXIO);
4985 }
4986
4987 if (copyin(arg, STRUCT_BUF(object_get_size),
4988 STRUCT_SIZE(object_get_size)) != 0) {
4989 crypto_release_minor(cm);
4990 return (EFAULT);
4991 }
4992
4993 session_id = STRUCT_FGET(object_get_size, gs_session);
4994
4995 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
4996 goto release_minor;
4997 }
4998
4999 if ((rv = kcf_get_hardware_provider_nomech(
5000 CRYPTO_OPS_OFFSET(object_ops),
5001 CRYPTO_OBJECT_OFFSET(object_get_size),
5002 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
5003 goto release_minor;
5004 }
5005
5006 handle = STRUCT_FGET(object_get_size, gs_handle);
5007 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_GET_SIZE,
5008 sp->sd_provider_session->ps_session, handle, NULL, 0, NULL, &size,
5009 NULL, NULL, 0, NULL);
5010
5011 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
5012 KCF_PROV_REFRELE(real_provider);
5013
5014 if (rv == CRYPTO_SUCCESS) {
5015 STRUCT_FSET(object_get_size, gs_size, (ulong_t)size);
5016 }
5017
5018 release_minor:
5019 crypto_release_minor(cm);
5020 CRYPTO_SESSION_RELE(sp);
5021
5022 if (error != 0)
5023 return (error);
5024
5025 STRUCT_FSET(object_get_size, gs_return_value, rv);
5026 if (copyout(STRUCT_BUF(object_get_size), arg,
5027 STRUCT_SIZE(object_get_size)) != 0) {
5028 return (EFAULT);
5029 }
5030 return (0);
5031 }
5032
5033 /* ARGSUSED */
5034 static int
object_set_attribute_value(dev_t dev,caddr_t arg,int mode,int * rval)5035 object_set_attribute_value(dev_t dev, caddr_t arg, int mode, int *rval)
5036 {
5037 STRUCT_DECL(crypto_object_set_attribute_value, set_attribute_value);
5038 kcf_provider_desc_t *real_provider;
5039 kcf_req_params_t params;
5040 crypto_object_attribute_t *k_attrs = NULL;
5041 crypto_session_id_t session_id;
5042 crypto_minor_t *cm;
5043 crypto_session_data_t *sp = NULL;
5044 crypto_object_id_t object_handle;
5045 caddr_t sa_attributes;
5046 size_t k_attrs_size;
5047 size_t rctl_bytes = 0;
5048 boolean_t rctl_chk = B_FALSE;
5049 int error = 0;
5050 int rv;
5051 uint_t count;
5052
5053 STRUCT_INIT(set_attribute_value, mode);
5054
5055 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5056 cmn_err(CE_WARN,
5057 "object_set_attribute_value: failed holding minor");
5058 return (ENXIO);
5059 }
5060
5061 if (copyin(arg, STRUCT_BUF(set_attribute_value),
5062 STRUCT_SIZE(set_attribute_value)) != 0) {
5063 crypto_release_minor(cm);
5064 return (EFAULT);
5065 }
5066
5067 count = STRUCT_FGET(set_attribute_value, sa_count);
5068 sa_attributes = STRUCT_FGETP(set_attribute_value, sa_attributes);
5069
5070 session_id = STRUCT_FGET(set_attribute_value, sa_session);
5071
5072 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5073 goto release_minor;
5074 }
5075 if (!copyin_attributes(mode, sp, count, sa_attributes, &k_attrs,
5076 &k_attrs_size, NULL, &rv, &error, &rctl_bytes,
5077 &rctl_chk, B_TRUE)) {
5078 goto release_minor;
5079 }
5080
5081 if ((rv = kcf_get_hardware_provider_nomech(
5082 CRYPTO_OPS_OFFSET(object_ops),
5083 CRYPTO_OBJECT_OFFSET(object_set_attribute_value),
5084 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
5085 goto release_minor;
5086 }
5087
5088 object_handle = STRUCT_FGET(set_attribute_value, sa_handle);
5089 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_SET_ATTRIBUTE_VALUE,
5090 sp->sd_provider_session->ps_session, object_handle, k_attrs, count,
5091 NULL, 0, NULL, NULL, 0, NULL);
5092
5093 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
5094 KCF_PROV_REFRELE(real_provider);
5095
5096 release_minor:
5097 CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
5098 CRYPTO_SESSION_RELE(sp);
5099 crypto_release_minor(cm);
5100
5101 if (k_attrs != NULL)
5102 kmem_free(k_attrs, k_attrs_size);
5103
5104 if (error != 0)
5105 return (error);
5106
5107 STRUCT_FSET(set_attribute_value, sa_return_value, rv);
5108 if (copyout(STRUCT_BUF(set_attribute_value), arg,
5109 STRUCT_SIZE(set_attribute_value)) != 0) {
5110 return (EFAULT);
5111 }
5112 return (0);
5113 }
5114
5115 /* ARGSUSED */
5116 static int
object_find_init(dev_t dev,caddr_t arg,int mode,int * rval)5117 object_find_init(dev_t dev, caddr_t arg, int mode, int *rval)
5118 {
5119 STRUCT_DECL(crypto_object_find_init, find_init);
5120 kcf_provider_desc_t *real_provider = NULL;
5121 kcf_req_params_t params;
5122 crypto_object_attribute_t *k_attrs = NULL;
5123 crypto_session_id_t session_id;
5124 crypto_minor_t *cm;
5125 crypto_session_data_t *sp = NULL;
5126 caddr_t attributes;
5127 size_t k_attrs_size;
5128 size_t rctl_bytes = 0;
5129 boolean_t rctl_chk = B_FALSE;
5130 int error = 0;
5131 int rv;
5132 uint_t count;
5133 void *cookie;
5134
5135 STRUCT_INIT(find_init, mode);
5136
5137 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5138 cmn_err(CE_WARN, "object_find_init: failed holding minor");
5139 return (ENXIO);
5140 }
5141
5142 if (copyin(arg, STRUCT_BUF(find_init), STRUCT_SIZE(find_init)) != 0) {
5143 crypto_release_minor(cm);
5144 return (EFAULT);
5145 }
5146
5147 count = STRUCT_FGET(find_init, fi_count);
5148 attributes = STRUCT_FGETP(find_init, fi_attributes);
5149
5150 session_id = STRUCT_FGET(find_init, fi_session);
5151
5152 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5153 goto release_minor;
5154 }
5155 if (!copyin_attributes(mode, sp, count, attributes, &k_attrs,
5156 &k_attrs_size, NULL, &rv, &error, &rctl_bytes,
5157 &rctl_chk, B_TRUE)) {
5158 goto release_minor;
5159 }
5160
5161 if ((rv = kcf_get_hardware_provider_nomech(
5162 CRYPTO_OPS_OFFSET(object_ops),
5163 CRYPTO_OBJECT_OFFSET(object_find_init),
5164 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
5165 goto release_minor;
5166 }
5167
5168 /* check for an active find */
5169 if (sp->sd_find_init_cookie != NULL) {
5170 rv = CRYPTO_OPERATION_IS_ACTIVE;
5171 goto release_minor;
5172 }
5173
5174 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_FIND_INIT,
5175 sp->sd_provider_session->ps_session, 0, k_attrs, count, NULL, 0,
5176 &cookie, NULL, 0, NULL);
5177
5178 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
5179
5180 if (rv == CRYPTO_SUCCESS) {
5181 /*
5182 * The cookie is allocated by a provider at the start of an
5183 * object search. It is freed when the search is terminated
5184 * by a final operation, or when the session is closed.
5185 * It contains state information about which object handles
5186 * have been returned to the caller.
5187 */
5188 sp->sd_find_init_cookie = cookie;
5189 }
5190
5191 release_minor:
5192 CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
5193 CRYPTO_SESSION_RELE(sp);
5194 crypto_release_minor(cm);
5195
5196 if (real_provider != NULL)
5197 KCF_PROV_REFRELE(real_provider);
5198
5199 if (k_attrs != NULL)
5200 kmem_free(k_attrs, k_attrs_size);
5201
5202 if (error != 0)
5203 return (error);
5204
5205 STRUCT_FSET(find_init, fi_return_value, rv);
5206 if (copyout(STRUCT_BUF(find_init), arg, STRUCT_SIZE(find_init)) != 0) {
5207 return (EFAULT);
5208 }
5209 return (0);
5210 }
5211
5212 /* ARGSUSED */
5213 static int
object_find_update(dev_t dev,caddr_t arg,int mode,int * rval)5214 object_find_update(dev_t dev, caddr_t arg, int mode, int *rval)
5215 {
5216 STRUCT_DECL(crypto_object_find_update, find_update);
5217 kcf_provider_desc_t *real_provider;
5218 kcf_req_params_t params;
5219 crypto_minor_t *cm;
5220 crypto_session_data_t *sp = NULL;
5221 crypto_object_id_t *buffer = NULL;
5222 crypto_session_id_t session_id;
5223 size_t len, rctl_bytes = 0;
5224 uint_t count, max_count;
5225 int rv, error = 0;
5226 boolean_t rctl_chk = B_FALSE;
5227
5228 STRUCT_INIT(find_update, mode);
5229
5230 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5231 cmn_err(CE_WARN, "object_find_update: failed holding minor");
5232 return (ENXIO);
5233 }
5234
5235 if (copyin(arg, STRUCT_BUF(find_update),
5236 STRUCT_SIZE(find_update)) != 0) {
5237 crypto_release_minor(cm);
5238 return (EFAULT);
5239 }
5240
5241 max_count = STRUCT_FGET(find_update, fu_max_count);
5242 if (max_count > CRYPTO_MAX_FIND_COUNT) {
5243 cmn_err(CE_NOTE, "object_find_update: count greater than %d, "
5244 "pid = %d", CRYPTO_MAX_FIND_COUNT, curproc->p_pid);
5245 rv = CRYPTO_ARGUMENTS_BAD;
5246 goto release_minor;
5247 }
5248 len = max_count * sizeof (crypto_object_id_t);
5249 session_id = STRUCT_FGET(find_update, fu_session);
5250
5251 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5252 goto release_minor;
5253 }
5254 if ((rv = CRYPTO_BUFFER_CHECK(sp, len, rctl_chk)) !=
5255 CRYPTO_SUCCESS) {
5256 goto release_minor;
5257 }
5258 rctl_bytes = len;
5259 buffer = kmem_alloc(len, KM_SLEEP);
5260
5261 if ((rv = kcf_get_hardware_provider_nomech(
5262 CRYPTO_OPS_OFFSET(object_ops),
5263 CRYPTO_OBJECT_OFFSET(object_find), sp->sd_provider,
5264 &real_provider)) != CRYPTO_SUCCESS) {
5265 goto release_minor;
5266 }
5267
5268 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_FIND,
5269 sp->sd_provider_session->ps_session, 0, NULL, 0, buffer, 0,
5270 NULL, sp->sd_find_init_cookie, max_count, &count);
5271
5272 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
5273 KCF_PROV_REFRELE(real_provider);
5274
5275 if (rv == CRYPTO_SUCCESS) {
5276 if (count > max_count) {
5277 /* bad bad provider */
5278 rv = CRYPTO_FAILED;
5279 goto release_minor;
5280 }
5281 if (count != 0) {
5282 /* copyout handles */
5283 if (copyout(buffer,
5284 STRUCT_FGETP(find_update, fu_handles),
5285 count * sizeof (crypto_object_id_t)) != 0) {
5286 error = EFAULT;
5287 }
5288 }
5289 STRUCT_FSET(find_update, fu_count, count);
5290 }
5291
5292 release_minor:
5293 CRYPTO_DECREMENT_RCTL_SESSION(sp, rctl_bytes, rctl_chk);
5294 CRYPTO_SESSION_RELE(sp);
5295 crypto_release_minor(cm);
5296
5297 if (buffer != NULL)
5298 kmem_free(buffer, len);
5299
5300 if (error != 0)
5301 return (error);
5302
5303 STRUCT_FSET(find_update, fu_return_value, rv);
5304 if (copyout(STRUCT_BUF(find_update), arg,
5305 STRUCT_SIZE(find_update)) != 0) {
5306 return (EFAULT);
5307 }
5308
5309 return (0);
5310 }
5311
5312 /*
5313 * Free provider-allocated storage used for find object searches.
5314 */
5315 static int
crypto_free_find_ctx(crypto_session_data_t * sp)5316 crypto_free_find_ctx(crypto_session_data_t *sp)
5317 {
5318 kcf_provider_desc_t *real_provider;
5319 kcf_req_params_t params;
5320 int rv;
5321
5322 if ((rv = kcf_get_hardware_provider_nomech(
5323 CRYPTO_OPS_OFFSET(object_ops),
5324 CRYPTO_OBJECT_OFFSET(object_find_final),
5325 sp->sd_provider, &real_provider)) != CRYPTO_SUCCESS) {
5326 return (rv);
5327 }
5328
5329 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_FIND_FINAL,
5330 sp->sd_provider_session->ps_session, 0, NULL, 0, NULL, 0,
5331 NULL, sp->sd_find_init_cookie, 0, NULL);
5332
5333 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
5334 KCF_PROV_REFRELE(real_provider);
5335 return (rv);
5336 }
5337
5338 /* ARGSUSED */
5339 static int
object_find_final(dev_t dev,caddr_t arg,int mode,int * rval)5340 object_find_final(dev_t dev, caddr_t arg, int mode, int *rval)
5341 {
5342 STRUCT_DECL(crypto_object_find_final, object_find_final);
5343 crypto_session_id_t session_id;
5344 crypto_minor_t *cm;
5345 crypto_session_data_t *sp;
5346 int error = 0;
5347 int rv;
5348
5349 STRUCT_INIT(object_find_final, mode);
5350
5351 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5352 cmn_err(CE_WARN, "object_find_final: failed holding minor");
5353 return (ENXIO);
5354 }
5355
5356 if (copyin(arg, STRUCT_BUF(object_find_final),
5357 STRUCT_SIZE(object_find_final)) != 0) {
5358 crypto_release_minor(cm);
5359 return (EFAULT);
5360 }
5361
5362 session_id = STRUCT_FGET(object_find_final, ff_session);
5363
5364 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5365 goto release_minor;
5366 }
5367
5368 if ((rv = crypto_free_find_ctx(sp)) == CRYPTO_SUCCESS) {
5369 sp->sd_find_init_cookie = NULL;
5370 }
5371
5372 CRYPTO_SESSION_RELE(sp);
5373
5374 release_minor:
5375 crypto_release_minor(cm);
5376
5377 if (error != 0)
5378 return (error);
5379
5380 STRUCT_FSET(object_find_final, ff_return_value, rv);
5381
5382 if (copyout(STRUCT_BUF(object_find_final), arg,
5383 STRUCT_SIZE(object_find_final)) != 0) {
5384 return (EFAULT);
5385 }
5386 return (0);
5387 }
5388
5389 /* ARGSUSED */
5390 static int
object_generate_key(dev_t dev,caddr_t arg,int mode,int * rval)5391 object_generate_key(dev_t dev, caddr_t arg, int mode, int *rval)
5392 {
5393 STRUCT_DECL(crypto_object_generate_key, generate_key);
5394 kcf_provider_desc_t *real_provider = NULL;
5395 kcf_req_params_t params;
5396 crypto_mechanism_t mech;
5397 crypto_object_attribute_t *k_attrs = NULL;
5398 crypto_session_id_t session_id;
5399 crypto_minor_t *cm;
5400 crypto_session_data_t *sp = NULL;
5401 crypto_object_id_t key_handle;
5402 caddr_t attributes;
5403 size_t k_attrs_size;
5404 size_t mech_rctl_bytes = 0, key_rctl_bytes = 0;
5405 boolean_t mech_rctl_chk = B_FALSE;
5406 boolean_t key_rctl_chk = B_FALSE;
5407 uint_t count;
5408 int error = 0;
5409 int rv;
5410 boolean_t allocated_by_crypto_module = B_FALSE;
5411
5412 STRUCT_INIT(generate_key, mode);
5413
5414 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5415 cmn_err(CE_WARN, "object_generate_key: failed holding minor");
5416 return (ENXIO);
5417 }
5418
5419 if (copyin(arg, STRUCT_BUF(generate_key),
5420 STRUCT_SIZE(generate_key)) != 0) {
5421 crypto_release_minor(cm);
5422 return (EFAULT);
5423 }
5424
5425 session_id = STRUCT_FGET(generate_key, gk_session);
5426
5427 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5428 goto release_minor;
5429 }
5430
5431 bcopy(STRUCT_FADDR(generate_key, gk_mechanism), &mech.cm_type,
5432 sizeof (crypto_mech_type_t));
5433
5434 if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL,
5435 CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
5436 &real_provider, CRYPTO_FG_GENERATE)) != CRYPTO_SUCCESS) {
5437 goto release_minor;
5438 }
5439
5440 rv = crypto_provider_copyin_mech_param(real_provider,
5441 STRUCT_FADDR(generate_key, gk_mechanism), &mech, mode, &error);
5442
5443 if (rv == CRYPTO_NOT_SUPPORTED) {
5444 allocated_by_crypto_module = B_TRUE;
5445 if (!copyin_mech(mode, sp,
5446 STRUCT_FADDR(generate_key, gk_mechanism),
5447 &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
5448 goto release_minor;
5449 }
5450 } else {
5451 if (rv != CRYPTO_SUCCESS)
5452 goto release_minor;
5453 }
5454
5455 count = STRUCT_FGET(generate_key, gk_count);
5456 attributes = STRUCT_FGETP(generate_key, gk_attributes);
5457 if (!copyin_attributes(mode, sp, count, attributes, &k_attrs,
5458 &k_attrs_size, NULL, &rv, &error, &key_rctl_bytes,
5459 &key_rctl_chk, B_TRUE)) {
5460 goto release_minor;
5461 }
5462
5463 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE,
5464 sp->sd_provider_session->ps_session, &mech, k_attrs, count,
5465 &key_handle, NULL, 0, NULL, NULL, NULL, 0);
5466
5467 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
5468
5469 if (rv == CRYPTO_SUCCESS)
5470 STRUCT_FSET(generate_key, gk_handle, key_handle);
5471
5472 release_minor:
5473 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
5474 CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
5475
5476 if (k_attrs != NULL)
5477 kmem_free(k_attrs, k_attrs_size);
5478
5479 if (error != 0)
5480 goto out;
5481
5482 STRUCT_FSET(generate_key, gk_return_value, rv);
5483 if (copyout(STRUCT_BUF(generate_key), arg,
5484 STRUCT_SIZE(generate_key)) != 0) {
5485 if (rv == CRYPTO_SUCCESS) {
5486 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms,
5487 KCF_OP_OBJECT_DESTROY,
5488 sp->sd_provider_session->ps_session, key_handle,
5489 NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5490
5491 (void) kcf_submit_request(real_provider, NULL,
5492 NULL, ¶ms, B_FALSE);
5493
5494 error = EFAULT;
5495 }
5496 }
5497 out:
5498 CRYPTO_SESSION_RELE(sp);
5499 crypto_release_minor(cm);
5500
5501 if (real_provider != NULL) {
5502 crypto_free_mech(real_provider,
5503 allocated_by_crypto_module, &mech);
5504 KCF_PROV_REFRELE(real_provider);
5505 }
5506 return (error);
5507 }
5508
5509 /* ARGSUSED */
5510 static int
nostore_generate_key(dev_t dev,caddr_t arg,int mode,int * rval)5511 nostore_generate_key(dev_t dev, caddr_t arg, int mode, int *rval)
5512 {
5513 STRUCT_DECL(crypto_nostore_generate_key, generate_key);
5514 #ifdef _LP64
5515 STRUCT_DECL(crypto_object_attribute, oa);
5516 #else
5517 /* LINTED E_FUNC_SET_NOT_USED */
5518 STRUCT_DECL(crypto_object_attribute, oa);
5519 #endif
5520 kcf_provider_desc_t *real_provider = NULL;
5521 kcf_req_params_t params;
5522 crypto_mechanism_t mech;
5523 crypto_object_attribute_t *k_in_attrs = NULL;
5524 crypto_object_attribute_t *k_out_attrs = NULL;
5525 crypto_session_id_t session_id;
5526 crypto_minor_t *cm;
5527 crypto_session_data_t *sp = NULL;
5528 caddr_t in_attributes;
5529 caddr_t out_attributes;
5530 size_t k_in_attrs_size;
5531 size_t k_out_attrs_size;
5532 size_t mech_rctl_bytes = 0;
5533 boolean_t mech_rctl_chk = B_FALSE;
5534 size_t in_key_rctl_bytes = 0, out_key_rctl_bytes = 0;
5535 boolean_t in_key_rctl_chk = B_FALSE;
5536 boolean_t out_key_rctl_chk = B_FALSE;
5537 uint_t in_count;
5538 uint_t out_count;
5539 int error = 0;
5540 int rv;
5541 boolean_t allocated_by_crypto_module = B_FALSE;
5542 caddr_t u_attrs = NULL;
5543
5544 out_count = 0;
5545 STRUCT_INIT(generate_key, mode);
5546 STRUCT_INIT(oa, mode);
5547
5548 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5549 cmn_err(CE_WARN, "nostore_generate_key: failed holding minor");
5550 return (ENXIO);
5551 }
5552
5553 if (copyin(arg, STRUCT_BUF(generate_key),
5554 STRUCT_SIZE(generate_key)) != 0) {
5555 crypto_release_minor(cm);
5556 return (EFAULT);
5557 }
5558
5559 session_id = STRUCT_FGET(generate_key, ngk_session);
5560
5561 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5562 goto release_minor;
5563 }
5564
5565 bcopy(STRUCT_FADDR(generate_key, ngk_mechanism), &mech.cm_type,
5566 sizeof (crypto_mech_type_t));
5567
5568 if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL,
5569 CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
5570 &real_provider, CRYPTO_FG_GENERATE)) != CRYPTO_SUCCESS) {
5571 goto release_minor;
5572 }
5573
5574 rv = crypto_provider_copyin_mech_param(real_provider,
5575 STRUCT_FADDR(generate_key, ngk_mechanism), &mech, mode, &error);
5576
5577 if (rv == CRYPTO_NOT_SUPPORTED) {
5578 allocated_by_crypto_module = B_TRUE;
5579 if (!copyin_mech(mode, sp, STRUCT_FADDR(generate_key,
5580 ngk_mechanism), &mech, &mech_rctl_bytes,
5581 &mech_rctl_chk, &rv, &error)) {
5582 goto release_minor;
5583 }
5584 } else {
5585 if (rv != CRYPTO_SUCCESS)
5586 goto release_minor;
5587 }
5588
5589 in_count = STRUCT_FGET(generate_key, ngk_in_count);
5590 in_attributes = STRUCT_FGETP(generate_key, ngk_in_attributes);
5591 if (!copyin_attributes(mode, sp, in_count, in_attributes, &k_in_attrs,
5592 &k_in_attrs_size, NULL, &rv, &error, &in_key_rctl_bytes,
5593 &in_key_rctl_chk, B_TRUE)) {
5594 goto release_minor;
5595 }
5596
5597 out_count = STRUCT_FGET(generate_key, ngk_out_count);
5598 out_attributes = STRUCT_FGETP(generate_key, ngk_out_attributes);
5599 if (!copyin_attributes(mode, sp, out_count, out_attributes,
5600 &k_out_attrs,
5601 &k_out_attrs_size, &u_attrs, &rv, &error, &out_key_rctl_bytes,
5602 &out_key_rctl_chk, B_FALSE)) {
5603 goto release_minor;
5604 }
5605
5606 KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE,
5607 sp->sd_provider_session->ps_session, &mech, k_in_attrs, in_count,
5608 NULL, 0, NULL, k_out_attrs, out_count, NULL, 0);
5609
5610 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
5611
5612 if (rv == CRYPTO_SUCCESS) {
5613 error = copyout_attributes(mode, out_attributes,
5614 out_count, k_out_attrs, u_attrs);
5615 }
5616 release_minor:
5617 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
5618 CRYPTO_DECREMENT_RCTL_SESSION(sp, in_key_rctl_bytes, in_key_rctl_chk);
5619 CRYPTO_DECREMENT_RCTL_SESSION(sp, out_key_rctl_bytes,
5620 out_key_rctl_chk);
5621
5622 if (k_in_attrs != NULL)
5623 kmem_free(k_in_attrs, k_in_attrs_size);
5624 if (k_out_attrs != NULL) {
5625 bzero(k_out_attrs, k_out_attrs_size);
5626 kmem_free(k_out_attrs, k_out_attrs_size);
5627 }
5628
5629 if (u_attrs != NULL)
5630 kmem_free(u_attrs, out_count * STRUCT_SIZE(oa));
5631
5632 if (error != 0)
5633 goto out;
5634
5635 STRUCT_FSET(generate_key, ngk_return_value, rv);
5636 if (copyout(STRUCT_BUF(generate_key), arg,
5637 STRUCT_SIZE(generate_key)) != 0) {
5638 error = EFAULT;
5639 }
5640 out:
5641 CRYPTO_SESSION_RELE(sp);
5642 crypto_release_minor(cm);
5643
5644 if (real_provider != NULL) {
5645 crypto_free_mech(real_provider,
5646 allocated_by_crypto_module, &mech);
5647 KCF_PROV_REFRELE(real_provider);
5648 }
5649 return (error);
5650 }
5651
5652 /* ARGSUSED */
5653 static int
object_generate_key_pair(dev_t dev,caddr_t arg,int mode,int * rval)5654 object_generate_key_pair(dev_t dev, caddr_t arg, int mode, int *rval)
5655 {
5656 STRUCT_DECL(crypto_object_generate_key_pair, generate_key_pair);
5657 kcf_provider_desc_t *real_provider = NULL;
5658 kcf_req_params_t params;
5659 crypto_mechanism_t mech;
5660 crypto_object_attribute_t *k_pub_attrs = NULL;
5661 crypto_object_attribute_t *k_pri_attrs = NULL;
5662 crypto_session_id_t session_id;
5663 crypto_minor_t *cm;
5664 crypto_session_data_t *sp = NULL;
5665 crypto_object_id_t pub_handle;
5666 crypto_object_id_t pri_handle;
5667 caddr_t pri_attributes;
5668 caddr_t pub_attributes;
5669 size_t k_pub_attrs_size, k_pri_attrs_size;
5670 size_t mech_rctl_bytes = 0;
5671 boolean_t mech_rctl_chk = B_FALSE;
5672 size_t pub_rctl_bytes = 0;
5673 boolean_t pub_rctl_chk = B_FALSE;
5674 size_t pri_rctl_bytes = 0;
5675 boolean_t pri_rctl_chk = B_FALSE;
5676 uint_t pub_count;
5677 uint_t pri_count;
5678 int error = 0;
5679 int rv;
5680 boolean_t allocated_by_crypto_module = B_FALSE;
5681
5682 STRUCT_INIT(generate_key_pair, mode);
5683
5684 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5685 cmn_err(CE_WARN,
5686 "object_generate_key_pair: failed holding minor");
5687 return (ENXIO);
5688 }
5689
5690 if (copyin(arg, STRUCT_BUF(generate_key_pair),
5691 STRUCT_SIZE(generate_key_pair)) != 0) {
5692 crypto_release_minor(cm);
5693 return (EFAULT);
5694 }
5695
5696 session_id = STRUCT_FGET(generate_key_pair, kp_session);
5697
5698 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5699 goto release_minor;
5700 }
5701
5702 bcopy(STRUCT_FADDR(generate_key_pair, kp_mechanism), &mech.cm_type,
5703 sizeof (crypto_mech_type_t));
5704
5705 if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL,
5706 CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
5707 &real_provider, CRYPTO_FG_GENERATE_KEY_PAIR)) != CRYPTO_SUCCESS) {
5708 goto release_minor;
5709 }
5710
5711 rv = crypto_provider_copyin_mech_param(real_provider,
5712 STRUCT_FADDR(generate_key_pair, kp_mechanism), &mech, mode, &error);
5713
5714 if (rv == CRYPTO_NOT_SUPPORTED) {
5715 allocated_by_crypto_module = B_TRUE;
5716 if (!copyin_mech(mode, sp, STRUCT_FADDR(generate_key_pair,
5717 kp_mechanism), &mech, &mech_rctl_bytes,
5718 &mech_rctl_chk, &rv, &error)) {
5719 goto release_minor;
5720 }
5721 } else {
5722 if (rv != CRYPTO_SUCCESS)
5723 goto release_minor;
5724 }
5725
5726 pub_count = STRUCT_FGET(generate_key_pair, kp_public_count);
5727 pri_count = STRUCT_FGET(generate_key_pair, kp_private_count);
5728
5729 pub_attributes = STRUCT_FGETP(generate_key_pair, kp_public_attributes);
5730 if (!copyin_attributes(mode, sp, pub_count, pub_attributes,
5731 &k_pub_attrs, &k_pub_attrs_size, NULL, &rv, &error, &pub_rctl_bytes,
5732 &pub_rctl_chk, B_TRUE)) {
5733 goto release_minor;
5734 }
5735
5736 pri_attributes = STRUCT_FGETP(generate_key_pair, kp_private_attributes);
5737 if (!copyin_attributes(mode, sp, pri_count, pri_attributes,
5738 &k_pri_attrs, &k_pri_attrs_size, NULL, &rv, &error,
5739 &pri_rctl_bytes, &pri_rctl_chk, B_TRUE)) {
5740 goto release_minor;
5741 }
5742
5743 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE_PAIR,
5744 sp->sd_provider_session->ps_session, &mech, k_pub_attrs,
5745 pub_count, &pub_handle, k_pri_attrs, pri_count, &pri_handle,
5746 NULL, NULL, 0);
5747
5748 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
5749
5750 if (rv == CRYPTO_SUCCESS) {
5751 STRUCT_FSET(generate_key_pair, kp_public_handle, pub_handle);
5752 STRUCT_FSET(generate_key_pair, kp_private_handle, pri_handle);
5753 }
5754
5755 release_minor:
5756 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
5757 CRYPTO_DECREMENT_RCTL_SESSION(sp, pub_rctl_bytes, pub_rctl_chk);
5758 CRYPTO_DECREMENT_RCTL_SESSION(sp, pri_rctl_bytes, pri_rctl_chk);
5759
5760 if (k_pub_attrs != NULL)
5761 kmem_free(k_pub_attrs, k_pub_attrs_size);
5762
5763 if (k_pri_attrs != NULL)
5764 kmem_free(k_pri_attrs, k_pri_attrs_size);
5765
5766 if (error != 0)
5767 goto out;
5768
5769 STRUCT_FSET(generate_key_pair, kp_return_value, rv);
5770 if (copyout(STRUCT_BUF(generate_key_pair), arg,
5771 STRUCT_SIZE(generate_key_pair)) != 0) {
5772 if (rv == CRYPTO_SUCCESS) {
5773 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms,
5774 KCF_OP_OBJECT_DESTROY,
5775 sp->sd_provider_session->ps_session, pub_handle,
5776 NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5777
5778 (void) kcf_submit_request(real_provider, NULL,
5779 NULL, ¶ms, B_FALSE);
5780
5781 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms,
5782 KCF_OP_OBJECT_DESTROY,
5783 sp->sd_provider_session->ps_session, pri_handle,
5784 NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
5785
5786 (void) kcf_submit_request(real_provider, NULL,
5787 NULL, ¶ms, B_FALSE);
5788
5789 error = EFAULT;
5790 }
5791 }
5792 out:
5793 CRYPTO_SESSION_RELE(sp);
5794 crypto_release_minor(cm);
5795
5796 if (real_provider != NULL) {
5797 crypto_free_mech(real_provider,
5798 allocated_by_crypto_module, &mech);
5799 KCF_PROV_REFRELE(real_provider);
5800 }
5801 return (error);
5802 }
5803
5804 /* ARGSUSED */
5805 static int
nostore_generate_key_pair(dev_t dev,caddr_t arg,int mode,int * rval)5806 nostore_generate_key_pair(dev_t dev, caddr_t arg, int mode, int *rval)
5807 {
5808 STRUCT_DECL(crypto_nostore_generate_key_pair, generate_key_pair);
5809 #ifdef _LP64
5810 STRUCT_DECL(crypto_object_attribute, oa);
5811 #else
5812 /* LINTED E_FUNC_SET_NOT_USED */
5813 STRUCT_DECL(crypto_object_attribute, oa);
5814 #endif
5815 kcf_provider_desc_t *real_provider = NULL;
5816 kcf_req_params_t params;
5817 crypto_mechanism_t mech;
5818 crypto_object_attribute_t *k_in_pub_attrs = NULL;
5819 crypto_object_attribute_t *k_in_pri_attrs = NULL;
5820 crypto_object_attribute_t *k_out_pub_attrs = NULL;
5821 crypto_object_attribute_t *k_out_pri_attrs = NULL;
5822 crypto_session_id_t session_id;
5823 crypto_minor_t *cm;
5824 crypto_session_data_t *sp = NULL;
5825 caddr_t in_pri_attributes;
5826 caddr_t in_pub_attributes;
5827 caddr_t out_pri_attributes;
5828 caddr_t out_pub_attributes;
5829 size_t k_in_pub_attrs_size, k_in_pri_attrs_size;
5830 size_t k_out_pub_attrs_size, k_out_pri_attrs_size;
5831 size_t mech_rctl_bytes = 0;
5832 boolean_t mech_rctl_chk = B_FALSE;
5833 size_t in_pub_rctl_bytes = 0;
5834 boolean_t in_pub_rctl_chk = B_FALSE;
5835 size_t in_pri_rctl_bytes = 0;
5836 boolean_t in_pri_rctl_chk = B_FALSE;
5837 size_t out_pub_rctl_bytes = 0;
5838 boolean_t out_pub_rctl_chk = B_FALSE;
5839 size_t out_pri_rctl_bytes = 0;
5840 boolean_t out_pri_rctl_chk = B_FALSE;
5841 uint_t in_pub_count;
5842 uint_t in_pri_count;
5843 uint_t out_pub_count;
5844 uint_t out_pri_count;
5845 int error = 0;
5846 int rv;
5847 boolean_t allocated_by_crypto_module = B_FALSE;
5848 caddr_t u_pub_attrs = NULL;
5849 caddr_t u_pri_attrs = NULL;
5850
5851 out_pub_count = 0;
5852 out_pri_count = 0;
5853 STRUCT_INIT(generate_key_pair, mode);
5854 STRUCT_INIT(oa, mode);
5855
5856 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
5857 cmn_err(CE_WARN,
5858 "nostore_generate_key_pair: failed holding minor");
5859 return (ENXIO);
5860 }
5861
5862 if (copyin(arg, STRUCT_BUF(generate_key_pair),
5863 STRUCT_SIZE(generate_key_pair)) != 0) {
5864 crypto_release_minor(cm);
5865 return (EFAULT);
5866 }
5867
5868 session_id = STRUCT_FGET(generate_key_pair, nkp_session);
5869
5870 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
5871 goto release_minor;
5872 }
5873
5874 bcopy(STRUCT_FADDR(generate_key_pair, nkp_mechanism), &mech.cm_type,
5875 sizeof (crypto_mech_type_t));
5876
5877 if ((rv = kcf_get_hardware_provider(mech.cm_type, NULL,
5878 CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
5879 &real_provider, CRYPTO_FG_GENERATE_KEY_PAIR)) != CRYPTO_SUCCESS) {
5880 goto release_minor;
5881 }
5882
5883 rv = crypto_provider_copyin_mech_param(real_provider,
5884 STRUCT_FADDR(generate_key_pair, nkp_mechanism), &mech, mode,
5885 &error);
5886
5887 if (rv == CRYPTO_NOT_SUPPORTED) {
5888 allocated_by_crypto_module = B_TRUE;
5889 if (!copyin_mech(mode, sp, STRUCT_FADDR(generate_key_pair,
5890 nkp_mechanism), &mech, &mech_rctl_bytes,
5891 &mech_rctl_chk, &rv, &error)) {
5892 goto release_minor;
5893 }
5894 } else {
5895 if (rv != CRYPTO_SUCCESS)
5896 goto release_minor;
5897 }
5898
5899 in_pub_count = STRUCT_FGET(generate_key_pair, nkp_in_public_count);
5900 in_pri_count = STRUCT_FGET(generate_key_pair, nkp_in_private_count);
5901
5902 in_pub_attributes = STRUCT_FGETP(generate_key_pair,
5903 nkp_in_public_attributes);
5904 if (!copyin_attributes(mode, sp, in_pub_count, in_pub_attributes,
5905 &k_in_pub_attrs, &k_in_pub_attrs_size, NULL, &rv, &error,
5906 &in_pub_rctl_bytes, &in_pub_rctl_chk, B_TRUE)) {
5907 goto release_minor;
5908 }
5909
5910 in_pri_attributes = STRUCT_FGETP(generate_key_pair,
5911 nkp_in_private_attributes);
5912 if (!copyin_attributes(mode, sp, in_pri_count, in_pri_attributes,
5913 &k_in_pri_attrs, &k_in_pri_attrs_size, NULL, &rv, &error,
5914 &in_pri_rctl_bytes, &in_pri_rctl_chk, B_TRUE)) {
5915 goto release_minor;
5916 }
5917
5918 out_pub_count = STRUCT_FGET(generate_key_pair, nkp_out_public_count);
5919 out_pri_count = STRUCT_FGET(generate_key_pair, nkp_out_private_count);
5920
5921 out_pub_attributes = STRUCT_FGETP(generate_key_pair,
5922 nkp_out_public_attributes);
5923 if (!copyin_attributes(mode, sp, out_pub_count, out_pub_attributes,
5924 &k_out_pub_attrs, &k_out_pub_attrs_size, &u_pub_attrs, &rv, &error,
5925 &out_pub_rctl_bytes, &out_pub_rctl_chk, B_FALSE)) {
5926 goto release_minor;
5927 }
5928
5929 out_pri_attributes = STRUCT_FGETP(generate_key_pair,
5930 nkp_out_private_attributes);
5931 if (!copyin_attributes(mode, sp, out_pri_count, out_pri_attributes,
5932 &k_out_pri_attrs, &k_out_pri_attrs_size, &u_pri_attrs, &rv, &error,
5933 &out_pri_rctl_bytes, &out_pri_rctl_chk, B_FALSE)) {
5934 goto release_minor;
5935 }
5936
5937 KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_GENERATE_PAIR,
5938 sp->sd_provider_session->ps_session, &mech, k_in_pub_attrs,
5939 in_pub_count, k_in_pri_attrs, in_pri_count, NULL, k_out_pub_attrs,
5940 out_pub_count, k_out_pri_attrs, out_pri_count);
5941
5942 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
5943
5944 if (rv == CRYPTO_SUCCESS) {
5945 error = copyout_attributes(mode, out_pub_attributes,
5946 out_pub_count, k_out_pub_attrs, u_pub_attrs);
5947 if (error != CRYPTO_SUCCESS)
5948 goto release_minor;
5949 error = copyout_attributes(mode, out_pri_attributes,
5950 out_pri_count, k_out_pri_attrs, u_pri_attrs);
5951 }
5952
5953 release_minor:
5954 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
5955 CRYPTO_DECREMENT_RCTL_SESSION(sp, in_pub_rctl_bytes, in_pub_rctl_chk);
5956 CRYPTO_DECREMENT_RCTL_SESSION(sp, in_pri_rctl_bytes, in_pri_rctl_chk);
5957 CRYPTO_DECREMENT_RCTL_SESSION(sp, out_pub_rctl_bytes,
5958 out_pub_rctl_chk);
5959 CRYPTO_DECREMENT_RCTL_SESSION(sp, out_pri_rctl_bytes,
5960 out_pri_rctl_chk);
5961
5962 if (k_in_pub_attrs != NULL)
5963 kmem_free(k_in_pub_attrs, k_in_pub_attrs_size);
5964
5965 if (k_in_pri_attrs != NULL)
5966 kmem_free(k_in_pri_attrs, k_in_pri_attrs_size);
5967
5968 if (k_out_pub_attrs != NULL)
5969 kmem_free(k_out_pub_attrs, k_out_pub_attrs_size);
5970
5971 if (k_out_pri_attrs != NULL) {
5972 bzero(k_out_pri_attrs, k_out_pri_attrs_size);
5973 kmem_free(k_out_pri_attrs, k_out_pri_attrs_size);
5974 }
5975
5976 if (u_pub_attrs != NULL)
5977 kmem_free(u_pub_attrs, out_pub_count * STRUCT_SIZE(oa));
5978
5979 if (u_pri_attrs != NULL)
5980 kmem_free(u_pri_attrs, out_pri_count * STRUCT_SIZE(oa));
5981
5982 if (error != 0)
5983 goto out;
5984
5985 STRUCT_FSET(generate_key_pair, nkp_return_value, rv);
5986 if (copyout(STRUCT_BUF(generate_key_pair), arg,
5987 STRUCT_SIZE(generate_key_pair)) != 0) {
5988 error = EFAULT;
5989 }
5990 out:
5991 CRYPTO_SESSION_RELE(sp);
5992 crypto_release_minor(cm);
5993
5994 if (real_provider != NULL) {
5995 crypto_free_mech(real_provider,
5996 allocated_by_crypto_module, &mech);
5997 KCF_PROV_REFRELE(real_provider);
5998 }
5999 return (error);
6000 }
6001
6002 /* ARGSUSED */
6003 static int
object_wrap_key(dev_t dev,caddr_t arg,int mode,int * rval)6004 object_wrap_key(dev_t dev, caddr_t arg, int mode, int *rval)
6005 {
6006 STRUCT_DECL(crypto_object_wrap_key, wrap_key);
6007 kcf_provider_desc_t *real_provider = NULL;
6008 kcf_req_params_t params;
6009 crypto_mechanism_t mech;
6010 crypto_key_t key;
6011 crypto_session_id_t session_id;
6012 crypto_minor_t *cm;
6013 crypto_session_data_t *sp = NULL;
6014 crypto_object_id_t handle;
6015 size_t mech_rctl_bytes = 0, key_rctl_bytes = 0;
6016 boolean_t mech_rctl_chk = B_FALSE;
6017 boolean_t key_rctl_chk = B_FALSE;
6018 size_t wrapped_key_rctl_bytes = 0;
6019 boolean_t wrapped_key_rctl_chk = B_FALSE;
6020 size_t wrapped_key_len, new_wrapped_key_len;
6021 uchar_t *wrapped_key = NULL;
6022 char *wrapped_key_buffer;
6023 int error = 0;
6024 int rv;
6025 boolean_t allocated_by_crypto_module = B_FALSE;
6026
6027 STRUCT_INIT(wrap_key, mode);
6028
6029 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
6030 cmn_err(CE_WARN, "object_wrap_key: failed holding minor");
6031 return (ENXIO);
6032 }
6033
6034 if (copyin(arg, STRUCT_BUF(wrap_key), STRUCT_SIZE(wrap_key)) != 0) {
6035 crypto_release_minor(cm);
6036 return (EFAULT);
6037 }
6038
6039 bzero(&key, sizeof (crypto_key_t));
6040
6041 session_id = STRUCT_FGET(wrap_key, wk_session);
6042
6043 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
6044 goto out;
6045 }
6046
6047 bcopy(STRUCT_FADDR(wrap_key, wk_mechanism), &mech.cm_type,
6048 sizeof (crypto_mech_type_t));
6049
6050 /* We need the key length for provider selection so copy it in now. */
6051 if (!copyin_key(mode, sp, STRUCT_FADDR(wrap_key, wk_wrapping_key), &key,
6052 &key_rctl_bytes, &key_rctl_chk, &rv, &error)) {
6053 goto out;
6054 }
6055
6056 wrapped_key_len = STRUCT_FGET(wrap_key, wk_wrapped_key_len);
6057
6058 if ((rv = kcf_get_hardware_provider(mech.cm_type, &key,
6059 CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
6060 &real_provider, CRYPTO_FG_WRAP)) != CRYPTO_SUCCESS) {
6061 goto out;
6062 }
6063
6064 rv = crypto_provider_copyin_mech_param(real_provider,
6065 STRUCT_FADDR(wrap_key, wk_mechanism), &mech, mode, &error);
6066
6067 if (rv == CRYPTO_NOT_SUPPORTED) {
6068 allocated_by_crypto_module = B_TRUE;
6069 if (!copyin_mech(mode, sp, STRUCT_FADDR(wrap_key, wk_mechanism),
6070 &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
6071 goto out;
6072 }
6073 } else {
6074 if (rv != CRYPTO_SUCCESS)
6075 goto out;
6076 }
6077
6078 /*
6079 * Don't allocate output buffer unless both buffer pointer and
6080 * buffer length are not NULL or 0 (length).
6081 */
6082 wrapped_key_buffer = STRUCT_FGETP(wrap_key, wk_wrapped_key);
6083 if (wrapped_key_buffer == NULL || wrapped_key_len == 0) {
6084 wrapped_key_len = 0;
6085 }
6086
6087 if (wrapped_key_len > crypto_max_buffer_len) {
6088 cmn_err(CE_NOTE, "object_wrap_key: buffer greater than %ld "
6089 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
6090 rv = CRYPTO_ARGUMENTS_BAD;
6091 goto out;
6092 }
6093
6094 if ((rv = CRYPTO_BUFFER_CHECK(sp, wrapped_key_len,
6095 wrapped_key_rctl_chk)) != CRYPTO_SUCCESS) {
6096 goto out;
6097 }
6098
6099 /* new_wrapped_key_len can be modified by the provider */
6100 wrapped_key_rctl_bytes = new_wrapped_key_len = wrapped_key_len;
6101 wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP);
6102
6103 handle = STRUCT_FGET(wrap_key, wk_object_handle);
6104 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_WRAP,
6105 sp->sd_provider_session->ps_session, &mech, NULL, 0, &handle,
6106 NULL, 0, NULL, &key, wrapped_key, &new_wrapped_key_len);
6107
6108 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
6109
6110 if (rv == CRYPTO_SUCCESS) {
6111 if (wrapped_key_len != 0 && copyout(wrapped_key,
6112 wrapped_key_buffer, new_wrapped_key_len) != 0) {
6113 error = EFAULT;
6114 }
6115 STRUCT_FSET(wrap_key, wk_wrapped_key_len,
6116 (ulong_t)new_wrapped_key_len);
6117 }
6118
6119 if (rv == CRYPTO_BUFFER_TOO_SMALL) {
6120 /*
6121 * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1
6122 * of section 11.2 of the pkcs11 spec. We catch it here and
6123 * provide the correct pkcs11 return value.
6124 */
6125 if (STRUCT_FGETP(wrap_key, wk_wrapped_key) == NULL)
6126 rv = CRYPTO_SUCCESS;
6127 STRUCT_FSET(wrap_key, wk_wrapped_key_len,
6128 (ulong_t)new_wrapped_key_len);
6129 }
6130
6131 out:
6132 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
6133 CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
6134 CRYPTO_DECREMENT_RCTL_SESSION(sp, wrapped_key_rctl_bytes,
6135 wrapped_key_rctl_chk);
6136 CRYPTO_SESSION_RELE(sp);
6137
6138 crypto_release_minor(cm);
6139
6140 if (real_provider != NULL) {
6141 crypto_free_mech(real_provider,
6142 allocated_by_crypto_module, &mech);
6143 KCF_PROV_REFRELE(real_provider);
6144 }
6145
6146 if (wrapped_key != NULL)
6147 kmem_free(wrapped_key, wrapped_key_len);
6148
6149 free_crypto_key(&key);
6150
6151 if (error != 0)
6152 return (error);
6153
6154 STRUCT_FSET(wrap_key, wk_return_value, rv);
6155 if (copyout(STRUCT_BUF(wrap_key), arg, STRUCT_SIZE(wrap_key)) != 0) {
6156 return (EFAULT);
6157 }
6158 return (0);
6159 }
6160
6161 /* ARGSUSED */
6162 static int
object_unwrap_key(dev_t dev,caddr_t arg,int mode,int * rval)6163 object_unwrap_key(dev_t dev, caddr_t arg, int mode, int *rval)
6164 {
6165 STRUCT_DECL(crypto_object_unwrap_key, unwrap_key);
6166 kcf_provider_desc_t *real_provider = NULL;
6167 kcf_req_params_t params;
6168 crypto_mechanism_t mech;
6169 crypto_key_t unwrapping_key;
6170 crypto_session_id_t session_id;
6171 crypto_minor_t *cm;
6172 crypto_session_data_t *sp = NULL;
6173 crypto_object_id_t handle;
6174 crypto_object_attribute_t *k_attrs = NULL;
6175 size_t k_attrs_size;
6176 size_t mech_rctl_bytes = 0, unwrapping_key_rctl_bytes = 0;
6177 boolean_t mech_rctl_chk = B_FALSE;
6178 boolean_t unwrapping_key_rctl_chk = B_FALSE;
6179 size_t wrapped_key_rctl_bytes = 0, k_attrs_rctl_bytes = 0;
6180 boolean_t wrapped_key_rctl_chk = B_FALSE;
6181 boolean_t k_attrs_rctl_chk = B_FALSE;
6182 size_t wrapped_key_len;
6183 uchar_t *wrapped_key = NULL;
6184 int error = 0;
6185 int rv;
6186 uint_t count;
6187 caddr_t uk_attributes;
6188 boolean_t allocated_by_crypto_module = B_FALSE;
6189
6190 STRUCT_INIT(unwrap_key, mode);
6191
6192 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
6193 cmn_err(CE_WARN, "object_unwrap_key: failed holding minor");
6194 return (ENXIO);
6195 }
6196
6197 if (copyin(arg, STRUCT_BUF(unwrap_key), STRUCT_SIZE(unwrap_key)) != 0) {
6198 crypto_release_minor(cm);
6199 return (EFAULT);
6200 }
6201
6202 bzero(&unwrapping_key, sizeof (unwrapping_key));
6203
6204 session_id = STRUCT_FGET(unwrap_key, uk_session);
6205
6206 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
6207 goto release_minor;
6208 }
6209
6210 bcopy(STRUCT_FADDR(unwrap_key, uk_mechanism), &mech.cm_type,
6211 sizeof (crypto_mech_type_t));
6212
6213 /* We need the key length for provider selection so copy it in now. */
6214 if (!copyin_key(mode, sp, STRUCT_FADDR(unwrap_key, uk_unwrapping_key),
6215 &unwrapping_key, &unwrapping_key_rctl_bytes,
6216 &unwrapping_key_rctl_chk, &rv, &error)) {
6217 goto release_minor;
6218 }
6219
6220 if ((rv = kcf_get_hardware_provider(mech.cm_type, &unwrapping_key,
6221 CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
6222 &real_provider, CRYPTO_FG_UNWRAP)) != CRYPTO_SUCCESS) {
6223 goto release_minor;
6224 }
6225
6226 rv = crypto_provider_copyin_mech_param(real_provider,
6227 STRUCT_FADDR(unwrap_key, uk_mechanism), &mech, mode, &error);
6228
6229 if (rv == CRYPTO_NOT_SUPPORTED) {
6230 allocated_by_crypto_module = B_TRUE;
6231 if (!copyin_mech(mode, sp,
6232 STRUCT_FADDR(unwrap_key, uk_mechanism),
6233 &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
6234 goto release_minor;
6235 }
6236 } else {
6237 if (rv != CRYPTO_SUCCESS)
6238 goto release_minor;
6239 }
6240
6241 count = STRUCT_FGET(unwrap_key, uk_count);
6242 uk_attributes = STRUCT_FGETP(unwrap_key, uk_attributes);
6243 if (!copyin_attributes(mode, sp, count, uk_attributes, &k_attrs,
6244 &k_attrs_size, NULL, &rv, &error, &k_attrs_rctl_bytes,
6245 &k_attrs_rctl_chk, B_TRUE)) {
6246 goto release_minor;
6247 }
6248
6249 wrapped_key_len = STRUCT_FGET(unwrap_key, uk_wrapped_key_len);
6250 if (wrapped_key_len > crypto_max_buffer_len) {
6251 cmn_err(CE_NOTE, "object_unwrap_key: buffer greater than %ld "
6252 "bytes, pid = %d", crypto_max_buffer_len, curproc->p_pid);
6253 rv = CRYPTO_ARGUMENTS_BAD;
6254 goto release_minor;
6255 }
6256
6257 if ((rv = CRYPTO_BUFFER_CHECK(sp, wrapped_key_len,
6258 wrapped_key_rctl_chk)) != CRYPTO_SUCCESS) {
6259 goto release_minor;
6260 }
6261 wrapped_key_rctl_bytes = wrapped_key_len;
6262 wrapped_key = kmem_alloc(wrapped_key_len, KM_SLEEP);
6263
6264 if (wrapped_key_len != 0 && copyin(STRUCT_FGETP(unwrap_key,
6265 uk_wrapped_key), wrapped_key, wrapped_key_len) != 0) {
6266 error = EFAULT;
6267 goto release_minor;
6268 }
6269
6270 /* wrapped_key_len is not modified by the unwrap operation */
6271 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_UNWRAP,
6272 sp->sd_provider_session->ps_session, &mech, k_attrs, count, &handle,
6273 NULL, 0, NULL, &unwrapping_key, wrapped_key, &wrapped_key_len);
6274
6275 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
6276
6277 if (rv == CRYPTO_SUCCESS)
6278 STRUCT_FSET(unwrap_key, uk_object_handle, handle);
6279
6280 release_minor:
6281 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
6282 CRYPTO_DECREMENT_RCTL_SESSION(sp, unwrapping_key_rctl_bytes,
6283 unwrapping_key_rctl_chk);
6284 CRYPTO_DECREMENT_RCTL_SESSION(sp, wrapped_key_rctl_bytes,
6285 wrapped_key_rctl_chk);
6286 CRYPTO_DECREMENT_RCTL_SESSION(sp, k_attrs_rctl_bytes,
6287 k_attrs_rctl_chk);
6288
6289 if (k_attrs != NULL)
6290 kmem_free(k_attrs, k_attrs_size);
6291
6292 if (wrapped_key != NULL)
6293 kmem_free(wrapped_key, wrapped_key_len);
6294
6295 free_crypto_key(&unwrapping_key);
6296
6297 if (error != 0)
6298 goto out;
6299
6300 STRUCT_FSET(unwrap_key, uk_return_value, rv);
6301 if (copyout(STRUCT_BUF(unwrap_key), arg,
6302 STRUCT_SIZE(unwrap_key)) != 0) {
6303 if (rv == CRYPTO_SUCCESS) {
6304 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms,
6305 KCF_OP_OBJECT_DESTROY,
6306 sp->sd_provider_session->ps_session, handle,
6307 NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
6308
6309 (void) kcf_submit_request(real_provider, NULL,
6310 NULL, ¶ms, B_FALSE);
6311
6312 error = EFAULT;
6313 }
6314 }
6315 out:
6316 CRYPTO_SESSION_RELE(sp);
6317 crypto_release_minor(cm);
6318
6319 if (real_provider != NULL) {
6320 crypto_free_mech(real_provider,
6321 allocated_by_crypto_module, &mech);
6322 KCF_PROV_REFRELE(real_provider);
6323 }
6324
6325 return (error);
6326 }
6327
6328 /* ARGSUSED */
6329 static int
object_derive_key(dev_t dev,caddr_t arg,int mode,int * rval)6330 object_derive_key(dev_t dev, caddr_t arg, int mode, int *rval)
6331 {
6332 STRUCT_DECL(crypto_derive_key, derive_key);
6333 kcf_provider_desc_t *real_provider = NULL;
6334 kcf_req_params_t params;
6335 crypto_object_attribute_t *k_attrs = NULL;
6336 crypto_mechanism_t mech;
6337 crypto_key_t base_key;
6338 crypto_session_id_t session_id;
6339 crypto_minor_t *cm;
6340 crypto_session_data_t *sp = NULL;
6341 crypto_object_id_t handle;
6342 size_t k_attrs_size;
6343 size_t key_rctl_bytes = 0, mech_rctl_bytes = 0;
6344 boolean_t mech_rctl_chk = B_FALSE;
6345 boolean_t key_rctl_chk = B_FALSE;
6346 size_t attributes_rctl_bytes = 0;
6347 boolean_t attributes_rctl_chk = B_FALSE;
6348 caddr_t attributes;
6349 uint_t count;
6350 int error = 0;
6351 int rv;
6352 boolean_t allocated_by_crypto_module = B_FALSE;
6353 boolean_t please_destroy_object = B_FALSE;
6354
6355 STRUCT_INIT(derive_key, mode);
6356
6357 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
6358 cmn_err(CE_WARN, "object_derive_key: failed holding minor");
6359 return (ENXIO);
6360 }
6361
6362 if (copyin(arg, STRUCT_BUF(derive_key), STRUCT_SIZE(derive_key)) != 0) {
6363 crypto_release_minor(cm);
6364 return (EFAULT);
6365 }
6366
6367 bzero(&base_key, sizeof (base_key));
6368
6369 session_id = STRUCT_FGET(derive_key, dk_session);
6370
6371 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
6372 goto release_minor;
6373 }
6374
6375 bcopy(STRUCT_FADDR(derive_key, dk_mechanism), &mech.cm_type,
6376 sizeof (crypto_mech_type_t));
6377
6378 /* We need the key length for provider selection so copy it in now. */
6379 if (!copyin_key(mode, sp, STRUCT_FADDR(derive_key, dk_base_key),
6380 &base_key, &key_rctl_bytes, &key_rctl_chk, &rv, &error)) {
6381 goto release_minor;
6382 }
6383
6384 if ((rv = kcf_get_hardware_provider(mech.cm_type, &base_key,
6385 CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
6386 &real_provider, CRYPTO_FG_DERIVE)) != CRYPTO_SUCCESS) {
6387 goto release_minor;
6388 }
6389
6390 rv = crypto_provider_copyin_mech_param(real_provider,
6391 STRUCT_FADDR(derive_key, dk_mechanism), &mech, mode, &error);
6392
6393 if (rv == CRYPTO_NOT_SUPPORTED) {
6394 allocated_by_crypto_module = B_TRUE;
6395 if (!copyin_mech(mode, sp,
6396 STRUCT_FADDR(derive_key, dk_mechanism),
6397 &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
6398 goto release_minor;
6399 }
6400 } else {
6401 if (rv != CRYPTO_SUCCESS)
6402 goto release_minor;
6403 }
6404
6405 count = STRUCT_FGET(derive_key, dk_count);
6406
6407 attributes = STRUCT_FGETP(derive_key, dk_attributes);
6408 if (!copyin_attributes(mode, sp, count, attributes, &k_attrs,
6409 &k_attrs_size, NULL, &rv, &error,
6410 &attributes_rctl_bytes, &attributes_rctl_chk, B_TRUE)) {
6411 goto release_minor;
6412 }
6413
6414 KCF_WRAP_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_DERIVE,
6415 sp->sd_provider_session->ps_session, &mech, k_attrs, count,
6416 &handle, NULL, 0, NULL, &base_key, NULL, NULL);
6417
6418 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
6419
6420 if (rv == CRYPTO_SUCCESS) {
6421 STRUCT_FSET(derive_key, dk_object_handle, handle);
6422
6423 rv = crypto_provider_copyout_mech_param(real_provider,
6424 &mech, STRUCT_FADDR(derive_key, dk_mechanism),
6425 mode, &error);
6426
6427 if (rv == CRYPTO_NOT_SUPPORTED) {
6428 rv = CRYPTO_SUCCESS;
6429 goto release_minor;
6430 }
6431
6432 if (rv != CRYPTO_SUCCESS)
6433 please_destroy_object = B_TRUE;
6434 }
6435
6436 release_minor:
6437 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
6438 CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
6439 CRYPTO_DECREMENT_RCTL_SESSION(sp, attributes_rctl_bytes,
6440 attributes_rctl_chk);
6441
6442 if (k_attrs != NULL)
6443 kmem_free(k_attrs, k_attrs_size);
6444
6445 free_crypto_key(&base_key);
6446
6447 if (error != 0)
6448 goto out;
6449
6450 STRUCT_FSET(derive_key, dk_return_value, rv);
6451 if (copyout(STRUCT_BUF(derive_key), arg,
6452 STRUCT_SIZE(derive_key)) != 0) {
6453 if (rv == CRYPTO_SUCCESS) {
6454 please_destroy_object = B_TRUE;
6455 error = EFAULT;
6456 }
6457 }
6458 out:
6459 if (please_destroy_object) {
6460 KCF_WRAP_OBJECT_OPS_PARAMS(¶ms, KCF_OP_OBJECT_DESTROY,
6461 sp->sd_provider_session->ps_session, handle,
6462 NULL, 0, NULL, 0, NULL, NULL, 0, NULL);
6463
6464 (void) kcf_submit_request(real_provider, NULL,
6465 NULL, ¶ms, B_FALSE);
6466 }
6467
6468 CRYPTO_SESSION_RELE(sp);
6469 crypto_release_minor(cm);
6470
6471 if (real_provider != NULL) {
6472 crypto_free_mech(real_provider,
6473 allocated_by_crypto_module, &mech);
6474 KCF_PROV_REFRELE(real_provider);
6475 }
6476 return (error);
6477 }
6478
6479 /* ARGSUSED */
6480 static int
nostore_derive_key(dev_t dev,caddr_t arg,int mode,int * rval)6481 nostore_derive_key(dev_t dev, caddr_t arg, int mode, int *rval)
6482 {
6483 STRUCT_DECL(crypto_nostore_derive_key, derive_key);
6484 #ifdef _LP64
6485 STRUCT_DECL(crypto_object_attribute, oa);
6486 #else
6487 /* LINTED E_FUNC_SET_NOT_USED */
6488 STRUCT_DECL(crypto_object_attribute, oa);
6489 #endif
6490 kcf_provider_desc_t *real_provider = NULL;
6491 kcf_req_params_t params;
6492 crypto_object_attribute_t *k_in_attrs = NULL;
6493 crypto_object_attribute_t *k_out_attrs = NULL;
6494 crypto_mechanism_t mech;
6495 crypto_key_t base_key;
6496 crypto_session_id_t session_id;
6497 crypto_minor_t *cm;
6498 crypto_session_data_t *sp = NULL;
6499 size_t k_in_attrs_size, k_out_attrs_size;
6500 size_t key_rctl_bytes = 0, mech_rctl_bytes = 0;
6501 boolean_t mech_rctl_chk = B_FALSE;
6502 boolean_t key_rctl_chk = B_FALSE;
6503 size_t in_attributes_rctl_bytes = 0;
6504 size_t out_attributes_rctl_bytes = 0;
6505 boolean_t in_attributes_rctl_chk = B_FALSE;
6506 boolean_t out_attributes_rctl_chk = B_FALSE;
6507 caddr_t in_attributes, out_attributes;
6508 uint_t in_count, out_count;
6509 int error = 0;
6510 int rv;
6511 boolean_t allocated_by_crypto_module = B_FALSE;
6512 caddr_t u_attrs = NULL;
6513
6514 out_count = 0;
6515 STRUCT_INIT(derive_key, mode);
6516 STRUCT_INIT(oa, mode);
6517
6518 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
6519 cmn_err(CE_WARN, "nostore_derive_key: failed holding minor");
6520 return (ENXIO);
6521 }
6522
6523 if (copyin(arg, STRUCT_BUF(derive_key), STRUCT_SIZE(derive_key)) != 0) {
6524 crypto_release_minor(cm);
6525 return (EFAULT);
6526 }
6527
6528 bzero(&base_key, sizeof (base_key));
6529
6530 session_id = STRUCT_FGET(derive_key, ndk_session);
6531
6532 if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) {
6533 goto release_minor;
6534 }
6535
6536 bcopy(STRUCT_FADDR(derive_key, ndk_mechanism), &mech.cm_type,
6537 sizeof (crypto_mech_type_t));
6538
6539 /* We need the key length for provider selection so copy it in now. */
6540 if (!copyin_key(mode, sp, STRUCT_FADDR(derive_key, ndk_base_key),
6541 &base_key, &key_rctl_bytes, &key_rctl_chk, &rv, &error)) {
6542 goto release_minor;
6543 }
6544
6545 if ((rv = kcf_get_hardware_provider(mech.cm_type, &base_key,
6546 CRYPTO_MECH_INVALID, NULL, sp->sd_provider,
6547 &real_provider, CRYPTO_FG_DERIVE)) != CRYPTO_SUCCESS) {
6548 goto release_minor;
6549 }
6550
6551 rv = crypto_provider_copyin_mech_param(real_provider,
6552 STRUCT_FADDR(derive_key, ndk_mechanism), &mech, mode, &error);
6553
6554 if (rv == CRYPTO_NOT_SUPPORTED) {
6555 allocated_by_crypto_module = B_TRUE;
6556 if (!copyin_mech(mode, sp,
6557 STRUCT_FADDR(derive_key, ndk_mechanism),
6558 &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) {
6559 goto release_minor;
6560 }
6561 } else {
6562 if (rv != CRYPTO_SUCCESS)
6563 goto release_minor;
6564 }
6565
6566 in_count = STRUCT_FGET(derive_key, ndk_in_count);
6567 out_count = STRUCT_FGET(derive_key, ndk_out_count);
6568
6569 in_attributes = STRUCT_FGETP(derive_key, ndk_in_attributes);
6570 if (!copyin_attributes(mode, sp, in_count, in_attributes, &k_in_attrs,
6571 &k_in_attrs_size, NULL, &rv, &error, &in_attributes_rctl_bytes,
6572 &in_attributes_rctl_chk, B_TRUE)) {
6573 goto release_minor;
6574 }
6575
6576 out_attributes = STRUCT_FGETP(derive_key, ndk_out_attributes);
6577 if (!copyin_attributes(mode, sp, out_count, out_attributes,
6578 &k_out_attrs, &k_out_attrs_size, &u_attrs, &rv, &error,
6579 &out_attributes_rctl_bytes,
6580 &out_attributes_rctl_chk, B_FALSE)) {
6581 goto release_minor;
6582 }
6583
6584 KCF_WRAP_NOSTORE_KEY_OPS_PARAMS(¶ms, KCF_OP_KEY_DERIVE,
6585 sp->sd_provider_session->ps_session, &mech, k_in_attrs, in_count,
6586 NULL, 0, &base_key, k_out_attrs, out_count, NULL, 0);
6587
6588 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, B_FALSE);
6589
6590 if (rv == CRYPTO_SUCCESS) {
6591 rv = crypto_provider_copyout_mech_param(real_provider,
6592 &mech, STRUCT_FADDR(derive_key, ndk_mechanism),
6593 mode, &error);
6594
6595 if (rv == CRYPTO_NOT_SUPPORTED) {
6596 rv = CRYPTO_SUCCESS;
6597 }
6598 /* copyout the derived secret */
6599 if (copyout_attributes(mode, out_attributes, out_count,
6600 k_out_attrs, u_attrs) != 0)
6601 error = EFAULT;
6602 }
6603
6604 release_minor:
6605 CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk);
6606 CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk);
6607 CRYPTO_DECREMENT_RCTL_SESSION(sp, in_attributes_rctl_bytes,
6608 in_attributes_rctl_chk);
6609 CRYPTO_DECREMENT_RCTL_SESSION(sp, out_attributes_rctl_bytes,
6610 out_attributes_rctl_chk);
6611
6612 if (k_in_attrs != NULL)
6613 kmem_free(k_in_attrs, k_in_attrs_size);
6614 if (k_out_attrs != NULL) {
6615 bzero(k_out_attrs, k_out_attrs_size);
6616 kmem_free(k_out_attrs, k_out_attrs_size);
6617 }
6618
6619 if (u_attrs != NULL)
6620 kmem_free(u_attrs, out_count * STRUCT_SIZE(oa));
6621
6622 free_crypto_key(&base_key);
6623
6624 if (error != 0)
6625 goto out;
6626
6627 STRUCT_FSET(derive_key, ndk_return_value, rv);
6628 if (copyout(STRUCT_BUF(derive_key), arg,
6629 STRUCT_SIZE(derive_key)) != 0) {
6630 error = EFAULT;
6631 }
6632 out:
6633 CRYPTO_SESSION_RELE(sp);
6634 crypto_release_minor(cm);
6635
6636 if (real_provider != NULL) {
6637 crypto_free_mech(real_provider,
6638 allocated_by_crypto_module, &mech);
6639 KCF_PROV_REFRELE(real_provider);
6640 }
6641 return (error);
6642 }
6643
6644 static int
get_provider_by_mech(dev_t dev,caddr_t arg,int mode,int * rval)6645 get_provider_by_mech(dev_t dev, caddr_t arg, int mode, int *rval)
6646 {
6647 _NOTE(ARGUNUSED(mode, rval))
6648 kcf_mech_entry_t *me;
6649 kcf_provider_desc_t *pd;
6650 crypto_key_t key;
6651 crypto_by_mech_t mech;
6652 crypto_provider_session_t *ps;
6653 crypto_minor_t *cm;
6654 int rv, error;
6655
6656 if ((cm = crypto_hold_minor(getminor(dev))) == NULL) {
6657 cmn_err(CE_WARN, "get_provider_by_mech: failed holding minor");
6658 return (ENXIO);
6659 }
6660
6661 bzero(&key, sizeof (key));
6662 key.ck_format = CRYPTO_KEY_RAW;
6663
6664 if (copyin(arg, &mech, sizeof (mech)) != 0) {
6665 crypto_release_minor(cm);
6666 return (EFAULT);
6667 }
6668
6669 key.ck_length = mech.mech_keylen;
6670 /* pd is returned held */
6671 if ((pd = kcf_get_mech_provider(mech.mech_type, &key, &me, &error,
6672 NULL, mech.mech_fg, 0)) == NULL) {
6673 rv = error;
6674 goto release_minor;
6675 }
6676
6677 /* don't want to allow direct access to software providers */
6678 if (pd->pd_prov_type == CRYPTO_SW_PROVIDER) {
6679 rv = CRYPTO_MECHANISM_INVALID;
6680 KCF_PROV_REFRELE(pd);
6681 cmn_err(CE_WARN, "software mech_type given");
6682 goto release_minor;
6683 }
6684
6685 mutex_enter(&cm->cm_lock);
6686 if ((rv = crypto_create_provider_session(cm, pd, pd->pd_sid, &ps, NULL))
6687 == CRYPTO_SUCCESS)
6688 rv = crypto_create_session_ptr(cm, pd, ps, &mech.session_id);
6689
6690 mutex_exit(&cm->cm_lock);
6691 release_minor:
6692 crypto_release_minor(cm);
6693 mech.rv = rv;
6694 if (copyout(&mech, arg, sizeof (mech)) != 0)
6695 return (EFAULT);
6696
6697 return (rv);
6698 }
6699
6700 /* ARGSUSED */
6701 static int
crypto_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * c,int * rval)6702 crypto_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c,
6703 int *rval)
6704 {
6705 #define ARG ((caddr_t)arg)
6706
6707 switch (cmd) {
6708 case CRYPTO_GET_FUNCTION_LIST:
6709 return (get_function_list(dev, ARG, mode, rval));
6710
6711 case CRYPTO_GET_MECHANISM_NUMBER:
6712 return (get_mechanism_number(dev, ARG, mode, rval));
6713
6714 case CRYPTO_GET_MECHANISM_LIST:
6715 return (get_mechanism_list(dev, ARG, mode, rval));
6716
6717 case CRYPTO_GET_ALL_MECHANISM_INFO:
6718 return (get_all_mechanism_info(dev, ARG, mode, rval));
6719
6720 case CRYPTO_GET_PROVIDER_LIST:
6721 return (get_provider_list(dev, ARG, mode, rval));
6722
6723 case CRYPTO_GET_PROVIDER_BY_MECH:
6724 return (get_provider_by_mech(dev, ARG, mode, rval));
6725
6726 case CRYPTO_GET_PROVIDER_INFO:
6727 return (get_provider_info(dev, ARG, mode, rval));
6728
6729 case CRYPTO_GET_PROVIDER_MECHANISMS:
6730 return (get_provider_mechanisms(dev, ARG, mode, rval));
6731
6732 case CRYPTO_GET_PROVIDER_MECHANISM_INFO:
6733 return (get_provider_mechanism_info(dev, ARG, mode, rval));
6734
6735 case CRYPTO_OPEN_SESSION:
6736 return (open_session(dev, ARG, mode, rval));
6737
6738 case CRYPTO_CLOSE_SESSION:
6739 return (close_session(dev, ARG, mode, rval));
6740
6741 case CRYPTO_ENCRYPT_INIT:
6742 return (encrypt_init(dev, ARG, mode, rval));
6743
6744 case CRYPTO_DECRYPT_INIT:
6745 return (decrypt_init(dev, ARG, mode, rval));
6746
6747 case CRYPTO_ENCRYPT:
6748 return (encrypt(dev, ARG, mode, rval));
6749
6750 case CRYPTO_DECRYPT:
6751 return (decrypt(dev, ARG, mode, rval));
6752
6753 case CRYPTO_ENCRYPT_UPDATE:
6754 return (encrypt_update(dev, ARG, mode, rval));
6755
6756 case CRYPTO_DECRYPT_UPDATE:
6757 return (decrypt_update(dev, ARG, mode, rval));
6758
6759 case CRYPTO_ENCRYPT_FINAL:
6760 return (encrypt_final(dev, ARG, mode, rval));
6761
6762 case CRYPTO_DECRYPT_FINAL:
6763 return (decrypt_final(dev, ARG, mode, rval));
6764
6765 case CRYPTO_DIGEST_INIT:
6766 return (digest_init(dev, ARG, mode, rval));
6767
6768 case CRYPTO_DIGEST:
6769 return (digest(dev, ARG, mode, rval));
6770
6771 case CRYPTO_DIGEST_UPDATE:
6772 return (digest_update(dev, ARG, mode, rval));
6773
6774 case CRYPTO_DIGEST_KEY:
6775 return (digest_key(dev, ARG, mode, rval));
6776
6777 case CRYPTO_DIGEST_FINAL:
6778 return (digest_final(dev, ARG, mode, rval));
6779
6780 case CRYPTO_SIGN_INIT:
6781 return (sign_init(dev, ARG, mode, rval));
6782
6783 case CRYPTO_SIGN:
6784 return (sign(dev, ARG, mode, rval));
6785
6786 case CRYPTO_SIGN_UPDATE:
6787 return (sign_update(dev, ARG, mode, rval));
6788
6789 case CRYPTO_SIGN_FINAL:
6790 return (sign_final(dev, ARG, mode, rval));
6791
6792 case CRYPTO_SIGN_RECOVER_INIT:
6793 return (sign_recover_init(dev, ARG, mode, rval));
6794
6795 case CRYPTO_SIGN_RECOVER:
6796 return (sign_recover(dev, ARG, mode, rval));
6797
6798 case CRYPTO_VERIFY_INIT:
6799 return (verify_init(dev, ARG, mode, rval));
6800
6801 case CRYPTO_VERIFY:
6802 return (verify(dev, ARG, mode, rval));
6803
6804 case CRYPTO_VERIFY_UPDATE:
6805 return (verify_update(dev, ARG, mode, rval));
6806
6807 case CRYPTO_VERIFY_FINAL:
6808 return (verify_final(dev, ARG, mode, rval));
6809
6810 case CRYPTO_VERIFY_RECOVER_INIT:
6811 return (verify_recover_init(dev, ARG, mode, rval));
6812
6813 case CRYPTO_VERIFY_RECOVER:
6814 return (verify_recover(dev, ARG, mode, rval));
6815
6816 case CRYPTO_MAC_INIT:
6817 return (mac_init(dev, ARG, mode, rval));
6818
6819 case CRYPTO_MAC:
6820 return (mac(dev, ARG, mode, rval));
6821
6822 case CRYPTO_MAC_UPDATE:
6823 return (mac_update(dev, ARG, mode, rval));
6824
6825 case CRYPTO_MAC_FINAL:
6826 return (mac_final(dev, ARG, mode, rval));
6827
6828 case CRYPTO_SET_PIN:
6829 return (set_pin(dev, ARG, mode, rval));
6830
6831 case CRYPTO_LOGIN:
6832 return (login(dev, ARG, mode, rval));
6833
6834 case CRYPTO_LOGOUT:
6835 return (logout(dev, ARG, mode, rval));
6836
6837 case CRYPTO_SEED_RANDOM:
6838 return (seed_random(dev, ARG, mode, rval));
6839
6840 case CRYPTO_GENERATE_RANDOM:
6841 return (generate_random(dev, ARG, mode, rval));
6842
6843 case CRYPTO_OBJECT_CREATE:
6844 return (object_create(dev, ARG, mode, rval));
6845
6846 case CRYPTO_OBJECT_COPY:
6847 return (object_copy(dev, ARG, mode, rval));
6848
6849 case CRYPTO_OBJECT_DESTROY:
6850 return (object_destroy(dev, ARG, mode, rval));
6851
6852 case CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE:
6853 return (object_get_attribute_value(dev, ARG, mode, rval));
6854
6855 case CRYPTO_OBJECT_GET_SIZE:
6856 return (object_get_size(dev, ARG, mode, rval));
6857
6858 case CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE:
6859 return (object_set_attribute_value(dev, ARG, mode, rval));
6860
6861 case CRYPTO_OBJECT_FIND_INIT:
6862 return (object_find_init(dev, ARG, mode, rval));
6863
6864 case CRYPTO_OBJECT_FIND_UPDATE:
6865 return (object_find_update(dev, ARG, mode, rval));
6866
6867 case CRYPTO_OBJECT_FIND_FINAL:
6868 return (object_find_final(dev, ARG, mode, rval));
6869
6870 case CRYPTO_GENERATE_KEY:
6871 return (object_generate_key(dev, ARG, mode, rval));
6872
6873 case CRYPTO_GENERATE_KEY_PAIR:
6874 return (object_generate_key_pair(dev, ARG, mode, rval));
6875
6876 case CRYPTO_WRAP_KEY:
6877 return (object_wrap_key(dev, ARG, mode, rval));
6878
6879 case CRYPTO_UNWRAP_KEY:
6880 return (object_unwrap_key(dev, ARG, mode, rval));
6881
6882 case CRYPTO_DERIVE_KEY:
6883 return (object_derive_key(dev, ARG, mode, rval));
6884
6885 case CRYPTO_NOSTORE_GENERATE_KEY:
6886 return (nostore_generate_key(dev, ARG, mode, rval));
6887
6888 case CRYPTO_NOSTORE_GENERATE_KEY_PAIR:
6889 return (nostore_generate_key_pair(dev, ARG, mode, rval));
6890
6891 case CRYPTO_NOSTORE_DERIVE_KEY:
6892 return (nostore_derive_key(dev, ARG, mode, rval));
6893 }
6894 return (EINVAL);
6895 }
6896
6897 /*
6898 * Check for the project.max-crypto-memory resource control.
6899 */
6900 static int
crypto_buffer_check(size_t need)6901 crypto_buffer_check(size_t need)
6902 {
6903 kproject_t *kpj;
6904
6905 if (need == 0)
6906 return (CRYPTO_SUCCESS);
6907
6908 mutex_enter(&curproc->p_lock);
6909 kpj = curproc->p_task->tk_proj;
6910 mutex_enter(&(kpj->kpj_data.kpd_crypto_lock));
6911
6912 if (kpj->kpj_data.kpd_crypto_mem + need >
6913 kpj->kpj_data.kpd_crypto_mem_ctl) {
6914 if (rctl_test(rc_project_crypto_mem,
6915 kpj->kpj_rctls, curproc, need, 0) & RCT_DENY) {
6916 mutex_exit(&(kpj->kpj_data.kpd_crypto_lock));
6917 mutex_exit(&curproc->p_lock);
6918 return (CRYPTO_HOST_MEMORY);
6919 }
6920 }
6921
6922 kpj->kpj_data.kpd_crypto_mem += need;
6923 mutex_exit(&(kpj->kpj_data.kpd_crypto_lock));
6924
6925 curproc->p_crypto_mem += need;
6926 mutex_exit(&curproc->p_lock);
6927
6928 return (CRYPTO_SUCCESS);
6929 }
6930