1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1808 mcpowers * Common Development and Distribution License (the "License"). 6 1808 mcpowers * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 9505 Bhargava * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel 27 0 stevel /* 28 0 stevel * The ioctl interface for cryptographic commands. 29 0 stevel */ 30 0 stevel 31 0 stevel #include <sys/types.h> 32 0 stevel #include <sys/modctl.h> 33 0 stevel #include <sys/conf.h> 34 0 stevel #include <sys/stat.h> 35 0 stevel #include <sys/ddi.h> 36 0 stevel #include <sys/sunddi.h> 37 0 stevel #include <sys/kmem.h> 38 0 stevel #include <sys/errno.h> 39 0 stevel #include <sys/ksynch.h> 40 0 stevel #include <sys/file.h> 41 0 stevel #include <sys/open.h> 42 0 stevel #include <sys/cred.h> 43 0 stevel #include <sys/proc.h> 44 0 stevel #include <sys/task.h> 45 0 stevel #include <sys/mkdev.h> 46 0 stevel #include <sys/model.h> 47 0 stevel #include <sys/sysmacros.h> 48 0 stevel #include <sys/crypto/common.h> 49 0 stevel #include <sys/crypto/api.h> 50 0 stevel #include <sys/crypto/impl.h> 51 0 stevel #include <sys/crypto/sched_impl.h> 52 0 stevel #include <sys/crypto/ioctl.h> 53 0 stevel 54 4841 haimay extern int kcf_des3_threshold; 55 4841 haimay extern int kcf_aes_threshold; 56 4841 haimay extern int kcf_rc4_threshold; 57 4841 haimay extern int kcf_md5_threshold; 58 4841 haimay extern int kcf_sha1_threshold; 59 4841 haimay 60 0 stevel /* 61 0 stevel * Locking notes: 62 0 stevel * 63 9505 Bhargava * crypto_locks protects the global array of minor structures. 64 9505 Bhargava * crypto_locks is an array of locks indexed by the cpuid. A reader needs 65 9505 Bhargava * to hold a single lock while a writer needs to hold all locks. 66 9505 Bhargava * krwlock_t is not an option here because the hold time 67 9505 Bhargava * is very small for these locks. 68 9505 Bhargava * 69 9505 Bhargava * The fields in the minor structure are protected by the cm_lock member 70 9505 Bhargava * of the minor structure. The cm_cv is used to signal decrements 71 9505 Bhargava * in the cm_refcnt, and is used with the cm_lock. 72 9505 Bhargava * 73 9505 Bhargava * The locking order is crypto_locks followed by cm_lock. 74 0 stevel */ 75 0 stevel 76 0 stevel /* 77 0 stevel * DDI entry points. 78 0 stevel */ 79 0 stevel static int crypto_attach(dev_info_t *, ddi_attach_cmd_t); 80 0 stevel static int crypto_detach(dev_info_t *, ddi_detach_cmd_t); 81 0 stevel static int crypto_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 82 0 stevel static int crypto_open(dev_t *, int, int, cred_t *); 83 0 stevel static int crypto_close(dev_t, int, int, cred_t *); 84 0 stevel static int crypto_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 85 0 stevel 86 904 mcpowers static int cipher_init(dev_t, caddr_t, int, int (*)(crypto_provider_t, 87 0 stevel crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, 88 0 stevel crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *)); 89 0 stevel 90 0 stevel static int common_digest(dev_t, caddr_t, int, int (*)(crypto_context_t, 91 0 stevel crypto_data_t *, crypto_data_t *, crypto_call_req_t *)); 92 0 stevel 93 0 stevel static int cipher(dev_t, caddr_t, int, int (*)(crypto_context_t, 94 0 stevel crypto_data_t *, crypto_data_t *, crypto_call_req_t *)); 95 0 stevel 96 0 stevel static int cipher_update(dev_t, caddr_t, int, int (*)(crypto_context_t, 97 0 stevel crypto_data_t *, crypto_data_t *, crypto_call_req_t *)); 98 0 stevel 99 0 stevel static int common_final(dev_t, caddr_t, int, int (*)(crypto_context_t, 100 0 stevel crypto_data_t *, crypto_call_req_t *)); 101 0 stevel 102 904 mcpowers static int sign_verify_init(dev_t, caddr_t, int, int (*)(crypto_provider_t, 103 0 stevel crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, 104 0 stevel crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *)); 105 0 stevel 106 0 stevel static int sign_verify_update(dev_t dev, caddr_t arg, int mode, 107 0 stevel int (*)(crypto_context_t, crypto_data_t *, crypto_call_req_t *)); 108 0 stevel 109 0 stevel static void crypto_initialize_rctl(void); 110 0 stevel static void crypto_release_provider_session(crypto_minor_t *, 111 0 stevel crypto_provider_session_t *); 112 3916 krishna static int crypto_buffer_check(size_t); 113 0 stevel static int crypto_free_find_ctx(crypto_session_data_t *); 114 0 stevel static int crypto_get_provider_list(crypto_minor_t *, uint_t *, 115 0 stevel crypto_provider_entry_t **, boolean_t); 116 0 stevel 117 0 stevel /* number of minor numbers to allocate at a time */ 118 0 stevel #define CRYPTO_MINOR_CHUNK 16 119 0 stevel 120 0 stevel /* 121 0 stevel * There are two limits associated with kernel memory. The first, 122 0 stevel * CRYPTO_MAX_BUFFER_LEN, is the maximum number of bytes that can be 123 0 stevel * allocated for a single copyin/copyout buffer. The second limit is 124 0 stevel * the total number of bytes that can be allocated by a process 125 0 stevel * for copyin/copyout buffers. The latter is enforced by the 126 0 stevel * project.max-crypto-memory resource control. 127 0 stevel */ 128 0 stevel 129 0 stevel #define CRYPTO_MAX_BUFFER_LEN (2 * 1024 * 1024) 130 0 stevel #define CRYPTO_MAX_FIND_COUNT 512 131 0 stevel 132 0 stevel /* 133 6424 krishna * We preapprove some bytes for each session to avoid making the costly 134 6424 krishna * crypto_buffer_check() calls. The preapproval is done when a new session 135 6424 krishna * is created and that cost is amortized over later crypto calls. 136 6424 krishna * Most applications create a session and then do a bunch of crypto calls 137 6424 krishna * in that session. So, they benefit from this optimization. 138 6424 krishna * 139 6424 krishna * Note that we may hit the project.max-crypto-memory limit a bit sooner 140 6424 krishna * because of this preapproval. But it is acceptable since the preapproved 141 6424 krishna * amount is insignificant compared to the default max-crypto-memory limit 142 6424 krishna * which is quarter of the machine's memory. The preapproved amount is 143 6424 krishna * roughly 2 * 16K(maximum SSL record size). 144 6424 krishna */ 145 6424 krishna #define CRYPTO_PRE_APPROVED_LIMIT (32 * 1024) 146 0 stevel 147 0 stevel /* The session table grows by CRYPTO_SESSION_CHUNK increments */ 148 0 stevel #define CRYPTO_SESSION_CHUNK 100 149 0 stevel 150 0 stevel size_t crypto_max_buffer_len = CRYPTO_MAX_BUFFER_LEN; 151 6424 krishna size_t crypto_pre_approved_limit = CRYPTO_PRE_APPROVED_LIMIT; 152 0 stevel 153 0 stevel #define INIT_RAW_CRYPTO_DATA(data, len) \ 154 0 stevel (data).cd_format = CRYPTO_DATA_RAW; \ 155 0 stevel (data).cd_raw.iov_base = kmem_alloc(len, KM_SLEEP); \ 156 0 stevel (data).cd_raw.iov_len = len; \ 157 0 stevel (data).cd_offset = 0; \ 158 0 stevel (data).cd_length = len; 159 0 stevel 160 0 stevel static struct kmem_cache *crypto_session_cache; 161 0 stevel static crypto_minor_t **crypto_minors = NULL; 162 0 stevel static dev_info_t *crypto_dip = NULL; 163 0 stevel static minor_t crypto_minor_chunk = CRYPTO_MINOR_CHUNK; 164 0 stevel static minor_t crypto_minors_table_count = 0; 165 0 stevel 166 0 stevel /* 167 0 stevel * Minors are started from 1 because vmem_alloc() 168 0 stevel * returns 0 in case of failure. 169 0 stevel */ 170 0 stevel static vmem_t *crypto_arena = NULL; /* Arena for device minors */ 171 0 stevel static minor_t crypto_minors_count = 0; 172 9505 Bhargava static kcf_lock_withpad_t *crypto_locks; 173 9505 Bhargava 174 9505 Bhargava #define CRYPTO_ENTER_ALL_LOCKS() \ 175 9505 Bhargava for (i = 0; i < max_ncpus; i++) \ 176 9505 Bhargava mutex_enter(&crypto_locks[i].kl_lock); 177 9505 Bhargava 178 9505 Bhargava #define CRYPTO_EXIT_ALL_LOCKS() \ 179 9505 Bhargava for (i = 0; i < max_ncpus; i++) \ 180 9505 Bhargava mutex_exit(&crypto_locks[i].kl_lock); 181 0 stevel 182 0 stevel #define RETURN_LIST B_TRUE 183 0 stevel #define DONT_RETURN_LIST B_FALSE 184 0 stevel 185 904 mcpowers #define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f) 186 0 stevel #define CRYPTO_RANDOM_OFFSET(f) offsetof(crypto_random_number_ops_t, f) 187 0 stevel #define CRYPTO_SESSION_OFFSET(f) offsetof(crypto_session_ops_t, f) 188 0 stevel #define CRYPTO_OBJECT_OFFSET(f) offsetof(crypto_object_ops_t, f) 189 0 stevel #define CRYPTO_PROVIDER_OFFSET(f) \ 190 0 stevel offsetof(crypto_provider_management_ops_t, f) 191 0 stevel 192 0 stevel #define CRYPTO_CANCEL_CTX(spp) { \ 193 0 stevel crypto_cancel_ctx(*(spp)); \ 194 0 stevel *(spp) = NULL; \ 195 0 stevel } 196 0 stevel 197 0 stevel #define CRYPTO_CANCEL_ALL_CTX(sp) { \ 198 0 stevel if ((sp)->sd_digest_ctx != NULL) { \ 199 0 stevel crypto_cancel_ctx((sp)->sd_digest_ctx); \ 200 0 stevel (sp)->sd_digest_ctx = NULL; \ 201 0 stevel } \ 202 0 stevel if ((sp)->sd_encr_ctx != NULL) { \ 203 0 stevel crypto_cancel_ctx((sp)->sd_encr_ctx); \ 204 0 stevel (sp)->sd_encr_ctx = NULL; \ 205 0 stevel } \ 206 0 stevel if ((sp)->sd_decr_ctx != NULL) { \ 207 0 stevel crypto_cancel_ctx((sp)->sd_decr_ctx); \ 208 0 stevel (sp)->sd_decr_ctx = NULL; \ 209 0 stevel } \ 210 0 stevel if ((sp)->sd_sign_ctx != NULL) { \ 211 0 stevel crypto_cancel_ctx((sp)->sd_sign_ctx); \ 212 0 stevel (sp)->sd_sign_ctx = NULL; \ 213 0 stevel } \ 214 0 stevel if ((sp)->sd_verify_ctx != NULL) { \ 215 0 stevel crypto_cancel_ctx((sp)->sd_verify_ctx); \ 216 0 stevel (sp)->sd_verify_ctx = NULL; \ 217 0 stevel } \ 218 0 stevel if ((sp)->sd_sign_recover_ctx != NULL) { \ 219 0 stevel crypto_cancel_ctx((sp)->sd_sign_recover_ctx); \ 220 0 stevel (sp)->sd_sign_recover_ctx = NULL; \ 221 0 stevel } \ 222 0 stevel if ((sp)->sd_verify_recover_ctx != NULL) { \ 223 0 stevel crypto_cancel_ctx((sp)->sd_verify_recover_ctx); \ 224 0 stevel (sp)->sd_verify_recover_ctx = NULL; \ 225 0 stevel } \ 226 0 stevel } 227 0 stevel 228 6424 krishna #define CRYPTO_DECREMENT_RCTL(val) if ((val) != 0) { \ 229 3916 krishna kproject_t *projp; \ 230 3916 krishna mutex_enter(&curproc->p_lock); \ 231 3916 krishna projp = curproc->p_task->tk_proj; \ 232 3916 krishna ASSERT(projp != NULL); \ 233 3916 krishna mutex_enter(&(projp->kpj_data.kpd_crypto_lock)); \ 234 3916 krishna projp->kpj_data.kpd_crypto_mem -= (val); \ 235 3916 krishna mutex_exit(&(projp->kpj_data.kpd_crypto_lock)); \ 236 3916 krishna curproc->p_crypto_mem -= (val); \ 237 3916 krishna mutex_exit(&curproc->p_lock); \ 238 0 stevel } 239 6424 krishna 240 6424 krishna /* 241 6424 krishna * We do not need to hold sd_lock in the macros below 242 6424 krishna * as they are called after doing a get_session_ptr() which 243 6424 krishna * sets the CRYPTO_SESSION_IS_BUSY flag. 244 6424 krishna */ 245 6424 krishna #define CRYPTO_DECREMENT_RCTL_SESSION(sp, val, rctl_chk) \ 246 6867 krishna if (((val) != 0) && ((sp) != NULL)) { \ 247 6424 krishna ASSERT(((sp)->sd_flags & CRYPTO_SESSION_IS_BUSY) != 0); \ 248 6424 krishna if (rctl_chk) { \ 249 6424 krishna CRYPTO_DECREMENT_RCTL(val); \ 250 6424 krishna } else { \ 251 6424 krishna (sp)->sd_pre_approved_amount += (val); \ 252 6424 krishna } \ 253 6424 krishna } 254 6424 krishna 255 6424 krishna #define CRYPTO_BUFFER_CHECK(sp, need, rctl_chk) \ 256 6424 krishna ((sp->sd_pre_approved_amount >= need) ? \ 257 6424 krishna (sp->sd_pre_approved_amount -= need, \ 258 6424 krishna rctl_chk = B_FALSE, CRYPTO_SUCCESS) : \ 259 6424 krishna (rctl_chk = B_TRUE, crypto_buffer_check(need))) 260 0 stevel 261 0 stevel /* 262 0 stevel * Module linkage. 263 0 stevel */ 264 0 stevel static struct cb_ops cbops = { 265 0 stevel crypto_open, /* cb_open */ 266 0 stevel crypto_close, /* cb_close */ 267 0 stevel nodev, /* cb_strategy */ 268 0 stevel nodev, /* cb_print */ 269 0 stevel nodev, /* cb_dump */ 270 0 stevel nodev, /* cb_read */ 271 0 stevel nodev, /* cb_write */ 272 0 stevel crypto_ioctl, /* cb_ioctl */ 273 0 stevel nodev, /* cb_devmap */ 274 0 stevel nodev, /* cb_mmap */ 275 0 stevel nodev, /* cb_segmap */ 276 0 stevel nochpoll, /* cb_chpoll */ 277 0 stevel ddi_prop_op, /* cb_prop_op */ 278 0 stevel NULL, /* cb_streamtab */ 279 0 stevel D_MP, /* cb_flag */ 280 0 stevel CB_REV, /* cb_rev */ 281 0 stevel nodev, /* cb_aread */ 282 0 stevel nodev, /* cb_awrite */ 283 0 stevel }; 284 0 stevel 285 0 stevel static struct dev_ops devops = { 286 0 stevel DEVO_REV, /* devo_rev */ 287 0 stevel 0, /* devo_refcnt */ 288 0 stevel crypto_getinfo, /* devo_getinfo */ 289 0 stevel nulldev, /* devo_identify */ 290 0 stevel nulldev, /* devo_probe */ 291 0 stevel crypto_attach, /* devo_attach */ 292 0 stevel crypto_detach, /* devo_detach */ 293 0 stevel nodev, /* devo_reset */ 294 0 stevel &cbops, /* devo_cb_ops */ 295 0 stevel NULL, /* devo_bus_ops */ 296 0 stevel NULL, /* devo_power */ 297 7656 Sherry ddi_quiesce_not_needed, /* devo_quiesce */ 298 0 stevel }; 299 0 stevel 300 0 stevel static struct modldrv modldrv = { 301 0 stevel &mod_driverops, /* drv_modops */ 302 5072 mcpowers "Cryptographic Library Interface", /* drv_linkinfo */ 303 0 stevel &devops, 304 0 stevel }; 305 0 stevel 306 0 stevel static struct modlinkage modlinkage = { 307 0 stevel MODREV_1, /* ml_rev */ 308 0 stevel &modldrv, /* ml_linkage */ 309 0 stevel NULL 310 0 stevel }; 311 0 stevel 312 0 stevel /* 313 0 stevel * DDI entry points. 314 0 stevel */ 315 0 stevel int 316 0 stevel _init(void) 317 0 stevel { 318 0 stevel return (mod_install(&modlinkage)); 319 0 stevel } 320 0 stevel 321 0 stevel int 322 0 stevel _fini(void) 323 0 stevel { 324 0 stevel return (mod_remove(&modlinkage)); 325 0 stevel } 326 0 stevel 327 0 stevel int 328 0 stevel _info(struct modinfo *modinfop) 329 0 stevel { 330 0 stevel return (mod_info(&modlinkage, modinfop)); 331 0 stevel } 332 0 stevel 333 0 stevel /* ARGSUSED */ 334 0 stevel static int 335 0 stevel crypto_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 336 0 stevel { 337 0 stevel switch (cmd) { 338 0 stevel case DDI_INFO_DEVT2DEVINFO: 339 0 stevel *result = crypto_dip; 340 0 stevel return (DDI_SUCCESS); 341 0 stevel 342 0 stevel case DDI_INFO_DEVT2INSTANCE: 343 0 stevel *result = (void *)0; 344 0 stevel return (DDI_SUCCESS); 345 0 stevel } 346 0 stevel return (DDI_FAILURE); 347 0 stevel } 348 0 stevel 349 0 stevel static int 350 0 stevel crypto_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 351 0 stevel { 352 9505 Bhargava int i; 353 9505 Bhargava 354 0 stevel if (cmd != DDI_ATTACH) { 355 0 stevel return (DDI_FAILURE); 356 0 stevel } 357 0 stevel 358 0 stevel if (ddi_get_instance(dip) != 0) { 359 0 stevel /* we only allow instance 0 to attach */ 360 0 stevel return (DDI_FAILURE); 361 0 stevel } 362 0 stevel 363 0 stevel crypto_session_cache = kmem_cache_create("crypto_session_cache", 364 0 stevel sizeof (crypto_session_data_t), 0, NULL, NULL, NULL, NULL, NULL, 0); 365 0 stevel 366 0 stevel if (crypto_session_cache == NULL) 367 0 stevel return (DDI_FAILURE); 368 0 stevel 369 0 stevel /* create the minor node */ 370 0 stevel if (ddi_create_minor_node(dip, "crypto", S_IFCHR, 0, 371 0 stevel DDI_PSEUDO, 0) != DDI_SUCCESS) { 372 0 stevel kmem_cache_destroy(crypto_session_cache); 373 0 stevel crypto_session_cache = NULL; 374 0 stevel cmn_err(CE_WARN, "crypto_attach: failed creating minor node"); 375 0 stevel ddi_remove_minor_node(dip, NULL); 376 0 stevel return (DDI_FAILURE); 377 0 stevel } 378 0 stevel 379 9505 Bhargava crypto_locks = kmem_zalloc(max_ncpus * sizeof (kcf_lock_withpad_t), 380 9505 Bhargava KM_SLEEP); 381 9505 Bhargava for (i = 0; i < max_ncpus; i++) 382 9505 Bhargava mutex_init(&crypto_locks[i].kl_lock, NULL, MUTEX_DRIVER, NULL); 383 9505 Bhargava 384 0 stevel crypto_dip = dip; 385 0 stevel 386 0 stevel /* allocate integer space for minor numbers */ 387 0 stevel crypto_arena = vmem_create("crypto", (void *)1, 388 0 stevel CRYPTO_MINOR_CHUNK, 1, NULL, NULL, NULL, 0, 389 0 stevel VM_SLEEP | VMC_IDENTIFIER); 390 0 stevel 391 0 stevel return (DDI_SUCCESS); 392 0 stevel } 393 0 stevel 394 0 stevel static int 395 0 stevel crypto_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 396 0 stevel { 397 0 stevel minor_t i; 398 9505 Bhargava kcf_lock_withpad_t *mp; 399 0 stevel 400 0 stevel if (cmd != DDI_DETACH) 401 0 stevel return (DDI_FAILURE); 402 0 stevel 403 9505 Bhargava mp = &crypto_locks[CPU_SEQID]; 404 9505 Bhargava mutex_enter(&mp->kl_lock); 405 9505 Bhargava 406 0 stevel /* check if device is open */ 407 0 stevel for (i = 0; i < crypto_minors_table_count; i++) { 408 0 stevel if (crypto_minors[i] != NULL) { 409 9505 Bhargava mutex_exit(&mp->kl_lock); 410 0 stevel return (DDI_FAILURE); 411 0 stevel } 412 0 stevel } 413 9505 Bhargava mutex_exit(&mp->kl_lock); 414 0 stevel 415 0 stevel crypto_dip = NULL; 416 0 stevel ddi_remove_minor_node(dip, NULL); 417 0 stevel 418 0 stevel kmem_cache_destroy(crypto_session_cache); 419 0 stevel crypto_session_cache = NULL; 420 0 stevel 421 0 stevel kmem_free(crypto_minors, 422 0 stevel sizeof (crypto_minor_t *) * crypto_minors_table_count); 423 0 stevel crypto_minors = NULL; 424 0 stevel crypto_minors_table_count = 0; 425 9505 Bhargava for (i = 0; i < max_ncpus; i++) 426 9505 Bhargava mutex_destroy(&crypto_locks[i].kl_lock); 427 9662 Bhargava kmem_free(crypto_locks, max_ncpus * sizeof (kcf_lock_withpad_t)); 428 9662 Bhargava crypto_locks = NULL; 429 9505 Bhargava 430 0 stevel vmem_destroy(crypto_arena); 431 0 stevel crypto_arena = NULL; 432 0 stevel 433 0 stevel return (DDI_SUCCESS); 434 0 stevel } 435 0 stevel 436 0 stevel /* ARGSUSED */ 437 0 stevel static int 438 0 stevel crypto_open(dev_t *devp, int flag, int otyp, cred_t *credp) 439 0 stevel { 440 0 stevel crypto_minor_t *cm = NULL; 441 0 stevel minor_t mn; 442 9505 Bhargava kcf_lock_withpad_t *mp; 443 9505 Bhargava int i; 444 0 stevel 445 0 stevel if (otyp != OTYP_CHR) 446 0 stevel return (ENXIO); 447 0 stevel 448 0 stevel if (crypto_dip == NULL) 449 0 stevel return (ENXIO); 450 0 stevel 451 0 stevel /* exclusive opens are not supported */ 452 0 stevel if (flag & FEXCL) 453 0 stevel return (ENOTSUP); 454 0 stevel 455 0 stevel again: 456 9505 Bhargava mp = &crypto_locks[CPU_SEQID]; 457 9505 Bhargava mutex_enter(&mp->kl_lock); 458 9505 Bhargava 459 0 stevel /* grow the minors table if needed */ 460 0 stevel if (crypto_minors_count >= crypto_minors_table_count) { 461 0 stevel crypto_minor_t **newtable; 462 0 stevel minor_t chunk = crypto_minor_chunk; 463 0 stevel minor_t saved_count; 464 0 stevel size_t new_size; 465 0 stevel ulong_t big_count; 466 0 stevel 467 0 stevel big_count = crypto_minors_count + chunk; 468 0 stevel if (big_count > MAXMIN) { 469 9505 Bhargava mutex_exit(&mp->kl_lock); 470 0 stevel return (ENOMEM); 471 0 stevel } 472 0 stevel 473 0 stevel saved_count = crypto_minors_table_count; 474 0 stevel new_size = sizeof (crypto_minor_t *) * 475 0 stevel (crypto_minors_table_count + chunk); 476 0 stevel 477 9505 Bhargava mutex_exit(&mp->kl_lock); 478 9505 Bhargava 479 0 stevel newtable = kmem_zalloc(new_size, KM_SLEEP); 480 9505 Bhargava CRYPTO_ENTER_ALL_LOCKS(); 481 0 stevel /* 482 0 stevel * Check if table grew while we were sleeping. 483 0 stevel * The minors table never shrinks. 484 0 stevel */ 485 0 stevel if (crypto_minors_table_count > saved_count) { 486 9505 Bhargava CRYPTO_EXIT_ALL_LOCKS(); 487 0 stevel kmem_free(newtable, new_size); 488 0 stevel goto again; 489 0 stevel } 490 0 stevel 491 0 stevel /* we assume that bcopy() will return if count is 0 */ 492 0 stevel bcopy(crypto_minors, newtable, 493 0 stevel sizeof (crypto_minor_t *) * crypto_minors_table_count); 494 0 stevel 495 0 stevel kmem_free(crypto_minors, 496 0 stevel sizeof (crypto_minor_t *) * crypto_minors_table_count); 497 0 stevel 498 0 stevel /* grow the minors number space */ 499 0 stevel if (crypto_minors_table_count != 0) { 500 0 stevel (void) vmem_add(crypto_arena, 501 0 stevel (void *)(uintptr_t)(crypto_minors_table_count + 1), 502 0 stevel crypto_minor_chunk, VM_SLEEP); 503 0 stevel } 504 0 stevel 505 0 stevel crypto_minors = newtable; 506 0 stevel crypto_minors_table_count += chunk; 507 9505 Bhargava CRYPTO_EXIT_ALL_LOCKS(); 508 9505 Bhargava } else { 509 9505 Bhargava mutex_exit(&mp->kl_lock); 510 9505 Bhargava } 511 0 stevel 512 0 stevel /* allocate a new minor number starting with 1 */ 513 0 stevel mn = (minor_t)(uintptr_t)vmem_alloc(crypto_arena, 1, VM_SLEEP); 514 0 stevel 515 0 stevel cm = kmem_zalloc(sizeof (crypto_minor_t), KM_SLEEP); 516 0 stevel mutex_init(&cm->cm_lock, NULL, MUTEX_DRIVER, NULL); 517 0 stevel cv_init(&cm->cm_cv, NULL, CV_DRIVER, NULL); 518 0 stevel 519 9505 Bhargava CRYPTO_ENTER_ALL_LOCKS(); 520 7882 Bhargava cm->cm_refcnt = 1; 521 0 stevel crypto_minors[mn - 1] = cm; 522 0 stevel crypto_minors_count++; 523 9505 Bhargava CRYPTO_EXIT_ALL_LOCKS(); 524 0 stevel 525 0 stevel *devp = makedevice(getmajor(*devp), mn); 526 0 stevel 527 0 stevel return (0); 528 0 stevel } 529 0 stevel 530 0 stevel /* ARGSUSED */ 531 0 stevel static int 532 0 stevel crypto_close(dev_t dev, int flag, int otyp, cred_t *credp) 533 0 stevel { 534 0 stevel crypto_minor_t *cm = NULL; 535 0 stevel crypto_session_data_t *sp; 536 0 stevel minor_t mn = getminor(dev); 537 0 stevel uint_t i; 538 6424 krishna size_t total = 0; 539 9505 Bhargava kcf_lock_withpad_t *mp; 540 9505 Bhargava 541 9505 Bhargava mp = &crypto_locks[CPU_SEQID]; 542 9505 Bhargava mutex_enter(&mp->kl_lock); 543 9505 Bhargava 544 0 stevel if (mn > crypto_minors_table_count) { 545 9505 Bhargava mutex_exit(&mp->kl_lock); 546 0 stevel cmn_err(CE_WARN, "crypto_close: bad minor (too big) %d", mn); 547 0 stevel return (ENODEV); 548 0 stevel } 549 0 stevel 550 7882 Bhargava cm = crypto_minors[mn - 1]; 551 0 stevel if (cm == NULL) { 552 9505 Bhargava mutex_exit(&mp->kl_lock); 553 0 stevel cmn_err(CE_WARN, "crypto_close: duplicate close of minor %d", 554 0 stevel getminor(dev)); 555 0 stevel return (ENODEV); 556 7882 Bhargava } 557 7882 Bhargava 558 9505 Bhargava mutex_exit(&mp->kl_lock); 559 9505 Bhargava 560 9505 Bhargava CRYPTO_ENTER_ALL_LOCKS(); 561 9505 Bhargava /* 562 9505 Bhargava * We free the minor number, mn, from the crypto_arena 563 9505 Bhargava * only later. This ensures that we won't race with another 564 9505 Bhargava * thread in crypto_open with the same minor number. 565 9505 Bhargava */ 566 9505 Bhargava crypto_minors[mn - 1] = NULL; 567 9505 Bhargava crypto_minors_count--; 568 9505 Bhargava CRYPTO_EXIT_ALL_LOCKS(); 569 9505 Bhargava 570 9505 Bhargava mutex_enter(&cm->cm_lock); 571 7882 Bhargava cm->cm_refcnt --; /* decrement refcnt held in open */ 572 7882 Bhargava while (cm->cm_refcnt > 0) { 573 9505 Bhargava cv_wait(&cm->cm_cv, &cm->cm_lock); 574 9505 Bhargava } 575 0 stevel 576 0 stevel vmem_free(crypto_arena, (void *)(uintptr_t)mn, 1); 577 0 stevel 578 0 stevel /* free all session table entries starting with 1 */ 579 0 stevel for (i = 1; i < cm->cm_session_table_count; i++) { 580 0 stevel if (cm->cm_session_table[i] == NULL) 581 0 stevel continue; 582 0 stevel 583 0 stevel sp = cm->cm_session_table[i]; 584 0 stevel ASSERT((sp->sd_flags & CRYPTO_SESSION_IS_BUSY) == 0); 585 6424 krishna ASSERT(sp->sd_pre_approved_amount == 0 || 586 6424 krishna sp->sd_pre_approved_amount == crypto_pre_approved_limit); 587 6424 krishna total += sp->sd_pre_approved_amount; 588 0 stevel if (sp->sd_find_init_cookie != NULL) { 589 0 stevel (void) crypto_free_find_ctx(sp); 590 0 stevel } 591 0 stevel crypto_release_provider_session(cm, sp->sd_provider_session); 592 0 stevel KCF_PROV_REFRELE(sp->sd_provider); 593 0 stevel CRYPTO_CANCEL_ALL_CTX(sp); 594 0 stevel mutex_destroy(&sp->sd_lock); 595 0 stevel cv_destroy(&sp->sd_cv); 596 0 stevel kmem_cache_free(crypto_session_cache, sp); 597 0 stevel cm->cm_session_table[i] = NULL; 598 0 stevel } 599 0 stevel 600 0 stevel /* free the session table */ 601 0 stevel if (cm->cm_session_table != NULL && cm->cm_session_table_count > 0) 602 0 stevel kmem_free(cm->cm_session_table, cm->cm_session_table_count * 603 0 stevel sizeof (void *)); 604 0 stevel 605 6424 krishna total += (cm->cm_session_table_count * sizeof (void *)); 606 6424 krishna CRYPTO_DECREMENT_RCTL(total); 607 0 stevel 608 0 stevel kcf_free_provider_tab(cm->cm_provider_count, 609 0 stevel cm->cm_provider_array); 610 0 stevel 611 9505 Bhargava mutex_exit(&cm->cm_lock); 612 0 stevel mutex_destroy(&cm->cm_lock); 613 0 stevel cv_destroy(&cm->cm_cv); 614 0 stevel kmem_free(cm, sizeof (crypto_minor_t)); 615 0 stevel 616 0 stevel return (0); 617 0 stevel } 618 0 stevel 619 0 stevel static crypto_minor_t * 620 0 stevel crypto_hold_minor(minor_t minor) 621 0 stevel { 622 7882 Bhargava crypto_minor_t *cm; 623 9505 Bhargava kcf_lock_withpad_t *mp; 624 7882 Bhargava 625 7882 Bhargava if (minor > crypto_minors_table_count) 626 7882 Bhargava return (NULL); 627 0 stevel 628 9505 Bhargava mp = &crypto_locks[CPU_SEQID]; 629 9505 Bhargava mutex_enter(&mp->kl_lock); 630 9505 Bhargava 631 7882 Bhargava if ((cm = crypto_minors[minor - 1]) != NULL) { 632 9505 Bhargava atomic_add_32(&cm->cm_refcnt, 1); 633 9505 Bhargava } 634 9505 Bhargava mutex_exit(&mp->kl_lock); 635 0 stevel return (cm); 636 0 stevel } 637 0 stevel 638 0 stevel static void 639 0 stevel crypto_release_minor(crypto_minor_t *cm) 640 0 stevel { 641 9505 Bhargava if (atomic_add_32_nv(&cm->cm_refcnt, -1) == 0) { 642 7882 Bhargava cv_signal(&cm->cm_cv); 643 0 stevel } 644 0 stevel } 645 4072 krishna 646 4072 krishna /* 647 4072 krishna * Build a list of functions and other information for the provider, pd. 648 0 stevel */ 649 0 stevel static void 650 0 stevel crypto_build_function_list(crypto_function_list_t *fl, kcf_provider_desc_t *pd) 651 0 stevel { 652 0 stevel crypto_ops_t *ops; 653 0 stevel crypto_digest_ops_t *digest_ops; 654 0 stevel crypto_cipher_ops_t *cipher_ops; 655 0 stevel crypto_mac_ops_t *mac_ops; 656 0 stevel crypto_sign_ops_t *sign_ops; 657 0 stevel crypto_verify_ops_t *verify_ops; 658 0 stevel crypto_dual_ops_t *dual_ops; 659 0 stevel crypto_random_number_ops_t *random_number_ops; 660 0 stevel crypto_session_ops_t *session_ops; 661 0 stevel crypto_object_ops_t *object_ops; 662 0 stevel crypto_key_ops_t *key_ops; 663 0 stevel crypto_provider_management_ops_t *provider_ops; 664 0 stevel 665 0 stevel if ((ops = pd->pd_ops_vector) == NULL) 666 0 stevel return; 667 0 stevel 668 904 mcpowers if ((digest_ops = ops->co_digest_ops) != NULL) { 669 0 stevel if (digest_ops->digest_init != NULL) 670 0 stevel fl->fl_digest_init = B_TRUE; 671 0 stevel if (digest_ops->digest != NULL) 672 0 stevel fl->fl_digest = B_TRUE; 673 0 stevel if (digest_ops->digest_update != NULL) 674 0 stevel fl->fl_digest_update = B_TRUE; 675 0 stevel if (digest_ops->digest_key != NULL) 676 0 stevel fl->fl_digest_key = B_TRUE; 677 0 stevel if (digest_ops->digest_final != NULL) 678 0 stevel fl->fl_digest_final = B_TRUE; 679 0 stevel } 680 904 mcpowers if ((cipher_ops = ops->co_cipher_ops) != NULL) { 681 0 stevel if (cipher_ops->encrypt_init != NULL) 682 0 stevel fl->fl_encrypt_init = B_TRUE; 683 0 stevel if (cipher_ops->encrypt != NULL) 684 0 stevel fl->fl_encrypt = B_TRUE; 685 0 stevel if (cipher_ops->encrypt_update != NULL) 686 0 stevel fl->fl_encrypt_update = B_TRUE; 687 0 stevel if (cipher_ops->encrypt_final != NULL) 688 0 stevel fl->fl_encrypt_final = B_TRUE; 689 0 stevel if (cipher_ops->decrypt_init != NULL) 690 0 stevel fl->fl_decrypt_init = B_TRUE; 691 0 stevel if (cipher_ops->decrypt != NULL) 692 0 stevel fl->fl_decrypt = B_TRUE; 693 0 stevel if (cipher_ops->decrypt_update != NULL) 694 0 stevel fl->fl_decrypt_update = B_TRUE; 695 0 stevel if (cipher_ops->decrypt_final != NULL) 696 0 stevel fl->fl_decrypt_final = B_TRUE; 697 0 stevel } 698 904 mcpowers if ((mac_ops = ops->co_mac_ops) != NULL) { 699 0 stevel if (mac_ops->mac_init != NULL) 700 0 stevel fl->fl_mac_init = B_TRUE; 701 0 stevel if (mac_ops->mac != NULL) 702 0 stevel fl->fl_mac = B_TRUE; 703 0 stevel if (mac_ops->mac_update != NULL) 704 0 stevel fl->fl_mac_update = B_TRUE; 705 0 stevel if (mac_ops->mac_final != NULL) 706 0 stevel fl->fl_mac_final = B_TRUE; 707 0 stevel } 708 904 mcpowers if ((sign_ops = ops->co_sign_ops) != NULL) { 709 0 stevel if (sign_ops->sign_init != NULL) 710 0 stevel fl->fl_sign_init = B_TRUE; 711 0 stevel if (sign_ops->sign != NULL) 712 0 stevel fl->fl_sign = B_TRUE; 713 0 stevel if (sign_ops->sign_update != NULL) 714 0 stevel fl->fl_sign_update = B_TRUE; 715 0 stevel if (sign_ops->sign_final != NULL) 716 0 stevel fl->fl_sign_final = B_TRUE; 717 0 stevel if (sign_ops->sign_recover_init != NULL) 718 0 stevel fl->fl_sign_recover_init = B_TRUE; 719 0 stevel if (sign_ops->sign_recover != NULL) 720 0 stevel fl->fl_sign_recover = B_TRUE; 721 0 stevel } 722 904 mcpowers if ((verify_ops = ops->co_verify_ops) != NULL) { 723 0 stevel if (verify_ops->verify_init != NULL) 724 0 stevel fl->fl_verify_init = B_TRUE; 725 0 stevel if (verify_ops->verify != NULL) 726 0 stevel fl->fl_verify = B_TRUE; 727 0 stevel if (verify_ops->verify_update != NULL) 728 0 stevel fl->fl_verify_update = B_TRUE; 729 0 stevel if (verify_ops->verify_final != NULL) 730 0 stevel fl->fl_verify_final = B_TRUE; 731 0 stevel if (verify_ops->verify_recover_init != NULL) 732 0 stevel fl->fl_verify_recover_init = B_TRUE; 733 0 stevel if (verify_ops->verify_recover != NULL) 734 0 stevel fl->fl_verify_recover = B_TRUE; 735 0 stevel } 736 904 mcpowers if ((dual_ops = ops->co_dual_ops) != NULL) { 737 0 stevel if (dual_ops->digest_encrypt_update != NULL) 738 0 stevel fl->fl_digest_encrypt_update = B_TRUE; 739 0 stevel if (dual_ops->decrypt_digest_update != NULL) 740 0 stevel fl->fl_decrypt_digest_update = B_TRUE; 741 0 stevel if (dual_ops->sign_encrypt_update != NULL) 742 0 stevel fl->fl_sign_encrypt_update = B_TRUE; 743 0 stevel if (dual_ops->decrypt_verify_update != NULL) 744 0 stevel fl->fl_decrypt_verify_update = B_TRUE; 745 0 stevel } 746 904 mcpowers if ((random_number_ops = ops->co_random_ops) != NULL) { 747 0 stevel if (random_number_ops->seed_random != NULL) 748 0 stevel fl->fl_seed_random = B_TRUE; 749 0 stevel if (random_number_ops->generate_random != NULL) 750 0 stevel fl->fl_generate_random = B_TRUE; 751 0 stevel } 752 904 mcpowers if ((session_ops = ops->co_session_ops) != NULL) { 753 0 stevel if (session_ops->session_open != NULL) 754 0 stevel fl->fl_session_open = B_TRUE; 755 0 stevel if (session_ops->session_close != NULL) 756 0 stevel fl->fl_session_close = B_TRUE; 757 0 stevel if (session_ops->session_login != NULL) 758 0 stevel fl->fl_session_login = B_TRUE; 759 0 stevel if (session_ops->session_logout != NULL) 760 0 stevel fl->fl_session_logout = B_TRUE; 761 0 stevel } 762 904 mcpowers if ((object_ops = ops->co_object_ops) != NULL) { 763 0 stevel if (object_ops->object_create != NULL) 764 0 stevel fl->fl_object_create = B_TRUE; 765 0 stevel if (object_ops->object_copy != NULL) 766 0 stevel fl->fl_object_copy = B_TRUE; 767 0 stevel if (object_ops->object_destroy != NULL) 768 0 stevel fl->fl_object_destroy = B_TRUE; 769 0 stevel if (object_ops->object_get_size != NULL) 770 0 stevel fl->fl_object_get_size = B_TRUE; 771 0 stevel if (object_ops->object_get_attribute_value != NULL) 772 0 stevel fl->fl_object_get_attribute_value = B_TRUE; 773 0 stevel if (object_ops->object_set_attribute_value != NULL) 774 0 stevel fl->fl_object_set_attribute_value = B_TRUE; 775 0 stevel if (object_ops->object_find_init != NULL) 776 0 stevel fl->fl_object_find_init = B_TRUE; 777 0 stevel if (object_ops->object_find != NULL) 778 0 stevel fl->fl_object_find = B_TRUE; 779 0 stevel if (object_ops->object_find_final != NULL) 780 0 stevel fl->fl_object_find_final = B_TRUE; 781 0 stevel } 782 904 mcpowers if ((key_ops = ops->co_key_ops) != NULL) { 783 0 stevel if (key_ops->key_generate != NULL) 784 0 stevel fl->fl_key_generate = B_TRUE; 785 0 stevel if (key_ops->key_generate_pair != NULL) 786 0 stevel fl->fl_key_generate_pair = B_TRUE; 787 0 stevel if (key_ops->key_wrap != NULL) 788 0 stevel fl->fl_key_wrap = B_TRUE; 789 0 stevel if (key_ops->key_unwrap != NULL) 790 0 stevel fl->fl_key_unwrap = B_TRUE; 791 0 stevel if (key_ops->key_derive != NULL) 792 0 stevel fl->fl_key_derive = B_TRUE; 793 0 stevel } 794 904 mcpowers if ((provider_ops = ops->co_provider_ops) != NULL) { 795 0 stevel if (provider_ops->init_token != NULL) 796 0 stevel fl->fl_init_token = B_TRUE; 797 0 stevel if (provider_ops->init_pin != NULL) 798 0 stevel fl->fl_init_pin = B_TRUE; 799 0 stevel if (provider_ops->set_pin != NULL) 800 0 stevel fl->fl_set_pin = B_TRUE; 801 0 stevel } 802 4072 krishna 803 4072 krishna fl->prov_is_limited = pd->pd_flags & CRYPTO_HASH_NO_UPDATE; 804 4072 krishna if (fl->prov_is_limited) { 805 4072 krishna /* 806 4072 krishna * XXX - The threshold should ideally be per hash 807 4072 krishna * mechanism. For now, we use the same value for all 808 4072 krishna * hash mechanisms. Empirical evidence suggests this 809 4072 krishna * is fine. 810 4072 krishna */ 811 4072 krishna fl->prov_hash_threshold = kcf_md5_threshold; 812 4072 krishna fl->prov_hash_limit = min(pd->pd_hash_limit, 813 4072 krishna min(CRYPTO_MAX_BUFFER_LEN, 814 4072 krishna curproc->p_task->tk_proj->kpj_data.kpd_crypto_mem_ctl)); 815 4072 krishna } 816 4841 haimay 817 4841 haimay fl->total_threshold_count = MAX_NUM_THRESHOLD; 818 4841 haimay fl->fl_threshold[0].mech_type = CKM_DES3_CBC; 819 4841 haimay fl->fl_threshold[0].mech_threshold = kcf_des3_threshold; 820 4841 haimay fl->fl_threshold[1].mech_type = CKM_DES3_ECB; 821 4841 haimay fl->fl_threshold[1].mech_threshold = kcf_des3_threshold; 822 4841 haimay fl->fl_threshold[2].mech_type = CKM_AES_CBC; 823 4841 haimay fl->fl_threshold[2].mech_threshold = kcf_aes_threshold; 824 4841 haimay fl->fl_threshold[3].mech_type = CKM_AES_ECB; 825 4841 haimay fl->fl_threshold[3].mech_threshold = kcf_aes_threshold; 826 4841 haimay fl->fl_threshold[4].mech_type = CKM_RC4; 827 4841 haimay fl->fl_threshold[4].mech_threshold = kcf_rc4_threshold; 828 4841 haimay fl->fl_threshold[5].mech_type = CKM_MD5; 829 4841 haimay fl->fl_threshold[5].mech_threshold = kcf_md5_threshold; 830 4841 haimay fl->fl_threshold[6].mech_type = CKM_SHA_1; 831 4841 haimay fl->fl_threshold[6].mech_threshold = kcf_sha1_threshold; 832 0 stevel } 833 0 stevel 834 0 stevel /* ARGSUSED */ 835 0 stevel static int 836 0 stevel get_function_list(dev_t dev, caddr_t arg, int mode, int *rval) 837 0 stevel { 838 0 stevel crypto_get_function_list_t get_function_list; 839 0 stevel crypto_minor_t *cm; 840 0 stevel crypto_provider_id_t provider_id; 841 0 stevel crypto_function_list_t *fl; 842 0 stevel kcf_provider_desc_t *provider; 843 0 stevel int rv; 844 0 stevel 845 0 stevel if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 846 0 stevel cmn_err(CE_WARN, "get_function_list: failed holding minor"); 847 0 stevel return (ENXIO); 848 0 stevel } 849 0 stevel 850 0 stevel if (copyin(arg, &get_function_list, sizeof (get_function_list)) != 0) { 851 0 stevel crypto_release_minor(cm); 852 0 stevel return (EFAULT); 853 0 stevel } 854 0 stevel 855 0 stevel /* initialize provider_array */ 856 0 stevel if (cm->cm_provider_array == NULL) { 857 0 stevel rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST); 858 0 stevel if (rv != CRYPTO_SUCCESS) { 859 0 stevel goto release_minor; 860 0 stevel } 861 0 stevel } 862 0 stevel 863 0 stevel provider_id = get_function_list.fl_provider_id; 864 0 stevel mutex_enter(&cm->cm_lock); 865 0 stevel /* index must be less than count of providers */ 866 0 stevel if (provider_id >= cm->cm_provider_count) { 867 0 stevel mutex_exit(&cm->cm_lock); 868 0 stevel rv = CRYPTO_ARGUMENTS_BAD; 869 0 stevel goto release_minor; 870 0 stevel } 871 0 stevel 872 0 stevel ASSERT(cm->cm_provider_array != NULL); 873 0 stevel provider = cm->cm_provider_array[provider_id]; 874 0 stevel mutex_exit(&cm->cm_lock); 875 0 stevel 876 0 stevel fl = &get_function_list.fl_list; 877 0 stevel bzero(fl, sizeof (crypto_function_list_t)); 878 0 stevel 879 0 stevel if (provider->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) { 880 0 stevel crypto_build_function_list(fl, provider); 881 0 stevel } else { 882 0 stevel kcf_provider_desc_t *prev = NULL, *pd; 883 0 stevel 884 0 stevel mutex_enter(&provider->pd_lock); 885 0 stevel while (kcf_get_next_logical_provider_member(provider, 886 0 stevel prev, &pd)) { 887 0 stevel prev = pd; 888 0 stevel crypto_build_function_list(fl, pd); 889 0 stevel KCF_PROV_REFRELE(pd); 890 0 stevel } 891 0 stevel mutex_exit(&provider->pd_lock); 892 0 stevel } 893 0 stevel 894 0 stevel rv = CRYPTO_SUCCESS; 895 0 stevel 896 0 stevel release_minor: 897 0 stevel crypto_release_minor(cm); 898 0 stevel 899 0 stevel get_function_list.fl_return_value = rv; 900 0 stevel 901 0 stevel if (copyout(&get_function_list, arg, sizeof (get_function_list)) != 0) { 902 0 stevel return (EFAULT); 903 0 stevel } 904 0 stevel return (0); 905 0 stevel } 906 0 stevel 907 0 stevel /* 908 0 stevel * This ioctl maps a PKCS#11 mechanism string into an internal number 909 0 stevel * that is used by the kernel. pn_internal_number is set to the 910 0 stevel * internal number. 911 0 stevel */ 912 0 stevel /* ARGSUSED */ 913 0 stevel static int 914 0 stevel get_mechanism_number(dev_t dev, caddr_t arg, int mode, int *rval) 915 0 stevel { 916 0 stevel STRUCT_DECL(crypto_get_mechanism_number, get_number); 917 0 stevel crypto_mech_type_t number; 918 0 stevel size_t len; 919 0 stevel char *mechanism_name; 920 0 stevel int rv; 921 0 stevel 922 0 stevel STRUCT_INIT(get_number, mode); 923 0 stevel 924 0 stevel if (copyin(arg, STRUCT_BUF(get_number), STRUCT_SIZE(get_number)) != 0) 925 0 stevel return (EFAULT); 926 0 stevel 927 0 stevel len = STRUCT_FGET(get_number, pn_mechanism_len); 928 0 stevel if (len == 0 || len > CRYPTO_MAX_MECH_NAME) { 929 0 stevel rv = CRYPTO_ARGUMENTS_BAD; 930 0 stevel goto out; 931 0 stevel } 932 0 stevel mechanism_name = kmem_alloc(len, KM_SLEEP); 933 0 stevel 934 0 stevel if (copyin(STRUCT_FGETP(get_number, pn_mechanism_string), 935 0 stevel mechanism_name, len) != 0) { 936 0 stevel kmem_free(mechanism_name, len); 937 0 stevel return (EFAULT); 938 0 stevel } 939 0 stevel 940 2935 krishna /* 941 2935 krishna * Get mechanism number from kcf. We set the load_module 942 2935 krishna * flag to false since we use only hardware providers. 943 2935 krishna */ 944 2935 krishna number = crypto_mech2id_common(mechanism_name, B_FALSE); 945 0 stevel kmem_free(mechanism_name, len); 946 0 stevel if (number == CRYPTO_MECH_INVALID) { 947 0 stevel rv = CRYPTO_ARGUMENTS_BAD; 948 0 stevel goto out; 949 0 stevel } 950 0 stevel 951 0 stevel bcopy((char *)&number, (char *)STRUCT_FADDR(get_number, 952 0 stevel pn_internal_number), sizeof (number)); 953 0 stevel 954 0 stevel rv = CRYPTO_SUCCESS; 955 0 stevel out: 956 0 stevel STRUCT_FSET(get_number, pn_return_value, rv); 957 0 stevel 958 0 stevel if (copyout(STRUCT_BUF(get_number), arg, 959 0 stevel STRUCT_SIZE(get_number)) != 0) { 960 0 stevel return (EFAULT); 961 0 stevel } 962 0 stevel return (0); 963 0 stevel } 964 0 stevel 965 0 stevel /* 966 8313 Dina * This ioctl returns an array of crypto_mech_name_t entries. 967 8313 Dina * It lists all the PKCS#11 mechanisms available in the kernel. 968 8313 Dina */ 969 8313 Dina /* ARGSUSED */ 970 8313 Dina static int 971 8313 Dina get_mechanism_list(dev_t dev, caddr_t arg, int mode, int *rval) 972 8313 Dina { 973 8313 Dina STRUCT_DECL(crypto_get_mechanism_list, get_list); 974 8313 Dina crypto_mech_name_t *entries; 975 8313 Dina size_t copyout_size; 976 8313 Dina uint_t req_count; 977 8313 Dina uint_t count; 978 8313 Dina ulong_t offset; 979 8313 Dina int error = 0; 980 8313 Dina 981 8313 Dina STRUCT_INIT(get_list, mode); 982 8313 Dina 983 8313 Dina if (copyin(arg, STRUCT_BUF(get_list), STRUCT_SIZE(get_list)) != 0) { 984 8313 Dina return (EFAULT); 985 8313 Dina } 986 8313 Dina 987 8313 Dina entries = crypto_get_mech_list(&count, KM_SLEEP); 988 8313 Dina 989 8313 Dina /* Number of entries caller thinks we have */ 990 8313 Dina req_count = STRUCT_FGET(get_list, ml_count); 991 8313 Dina 992 8313 Dina STRUCT_FSET(get_list, ml_count, count); 993 8313 Dina STRUCT_FSET(get_list, ml_return_value, CRYPTO_SUCCESS); 994 8313 Dina 995 8313 Dina /* check if buffer is too small */ 996 8313 Dina if (count > req_count) { 997 8313 Dina STRUCT_FSET(get_list, ml_return_value, CRYPTO_BUFFER_TOO_SMALL); 998 8313 Dina } 999 8313 Dina 1000 8313 Dina /* copyout the first stuff */ 1001 8313 Dina if (copyout(STRUCT_BUF(get_list), arg, STRUCT_SIZE(get_list)) != 0) { 1002 8313 Dina error = EFAULT; 1003 8313 Dina } 1004 8313 Dina 1005 8313 Dina /* 1006 8313 Dina * If only requesting number of entries or buffer too small or an 1007 8313 Dina * error occurred, stop here 1008 8313 Dina */ 1009 8313 Dina if (req_count == 0 || count > req_count || error != 0) { 1010 8313 Dina goto out; 1011 8313 Dina } 1012 8313 Dina 1013 8313 Dina copyout_size = count * sizeof (crypto_mech_name_t); 1014 8313 Dina 1015 8313 Dina /* copyout entries */ 1016 8313 Dina offset = (ulong_t)STRUCT_FADDR(get_list, ml_list); 1017 8313 Dina offset -= (ulong_t)STRUCT_BUF(get_list); 1018 8313 Dina if (copyout(entries, arg + offset, copyout_size) != 0) { 1019 8313 Dina error = EFAULT; 1020 8313 Dina } 1021 8313 Dina 1022 8313 Dina out: 1023 8313 Dina crypto_free_mech_list(entries, count); 1024 8313 Dina return (error); 1025 8313 Dina } 1026 8313 Dina 1027 8313 Dina /* 1028 8313 Dina * Copyout kernel array of mech_infos to user space. 1029 8313 Dina */ 1030 8313 Dina /* ARGSUSED */ 1031 8313 Dina static int 1032 8313 Dina copyout_mechinfos(int mode, caddr_t out, uint_t count, 1033 8313 Dina crypto_mechanism_info_t *k_minfos, caddr_t u_minfos) 1034 8313 Dina { 1035 8313 Dina STRUCT_DECL(crypto_mechanism_info, mi); 1036 8313 Dina caddr_t p; 1037 8313 Dina size_t len; 1038 8313 Dina int i; 1039 8313 Dina 1040 8313 Dina if (count == 0) 1041 8313 Dina return (0); 1042 8313 Dina 1043 8313 Dina STRUCT_INIT(mi, mode); 1044 8313 Dina 1045 8313 Dina len = count * STRUCT_SIZE(mi); 1046 8313 Dina 1047 8313 Dina ASSERT(u_minfos != NULL); 1048 8313 Dina p = u_minfos; 1049 8313 Dina for (i = 0; i < count; i++) { 1050 8313 Dina STRUCT_FSET(mi, mi_min_key_size, k_minfos[i].mi_min_key_size); 1051 8313 Dina STRUCT_FSET(mi, mi_max_key_size, k_minfos[i].mi_max_key_size); 1052 8313 Dina STRUCT_FSET(mi, mi_keysize_unit, k_minfos[i].mi_keysize_unit); 1053 8313 Dina STRUCT_FSET(mi, mi_usage, k_minfos[i].mi_usage); 1054 8313 Dina bcopy(STRUCT_BUF(mi), p, STRUCT_SIZE(mi)); 1055 8313 Dina p += STRUCT_SIZE(mi); 1056 8313 Dina } 1057 8313 Dina 1058 8313 Dina if (copyout(u_minfos, out, len) != 0) 1059 8313 Dina return (EFAULT); 1060 8313 Dina 1061 8313 Dina return (0); 1062 8313 Dina } 1063 8313 Dina 1064 8313 Dina /* 1065 8313 Dina * This ioctl returns information for the specified mechanism. 1066 8313 Dina */ 1067 8313 Dina /* ARGSUSED */ 1068 8313 Dina static int 1069 8313 Dina get_all_mechanism_info(dev_t dev, caddr_t arg, int mode, int *rval) 1070 8313 Dina { 1071 8313 Dina STRUCT_DECL(crypto_get_all_mechanism_info, get_all_mech); 1072 8319 Dina /* LINTED E_FUNC_SET_NOT_USED */ 1073 8313 Dina STRUCT_DECL(crypto_mechanism_info, mi); 1074 8313 Dina crypto_mech_name_t mech_name; 1075 8313 Dina crypto_mech_type_t mech_type; 1076 8313 Dina crypto_mechanism_info_t *mech_infos = NULL; 1077 8313 Dina uint_t num_mech_infos = 0; 1078 8313 Dina uint_t req_count; 1079 8313 Dina caddr_t u_minfos; 1080 8313 Dina ulong_t offset; 1081 8313 Dina int error = 0; 1082 8313 Dina int rv; 1083 8313 Dina 1084 8313 Dina STRUCT_INIT(get_all_mech, mode); 1085 8313 Dina STRUCT_INIT(mi, mode); 1086 8313 Dina 1087 8313 Dina if (copyin(arg, STRUCT_BUF(get_all_mech), 1088 8313 Dina STRUCT_SIZE(get_all_mech)) != 0) { 1089 8313 Dina return (EFAULT); 1090 8313 Dina } 1091 8313 Dina 1092 8313 Dina (void) strncpy(mech_name, STRUCT_FGET(get_all_mech, mi_mechanism_name), 1093 8313 Dina CRYPTO_MAX_MECH_NAME); 1094 8313 Dina mech_type = crypto_mech2id(mech_name); 1095 8313 Dina 1096 8313 Dina if (mech_type == CRYPTO_MECH_INVALID) { 1097 8313 Dina rv = CRYPTO_ARGUMENTS_BAD; 1098 8313 Dina goto out1; 1099 8313 Dina } 1100 8313 Dina 1101 8313 Dina rv = crypto_get_all_mech_info(mech_type, &mech_infos, &num_mech_infos, 1102 8313 Dina KM_SLEEP); 1103 8313 Dina if (rv != CRYPTO_SUCCESS) { 1104 8313 Dina goto out1; 1105 8313 Dina } 1106 8313 Dina /* rv is CRYPTO_SUCCESS at this point */ 1107 8313 Dina 1108 8313 Dina /* Number of entries caller thinks we have */ 1109 8313 Dina req_count = STRUCT_FGET(get_all_mech, mi_count); 1110 8313 Dina 1111 8313 Dina STRUCT_FSET(get_all_mech, mi_count, num_mech_infos); 1112 8313 Dina 1113 8313 Dina /* check if buffer is too small */ 1114 8313 Dina if (num_mech_infos > req_count) { 1115 8313 Dina rv = CRYPTO_BUFFER_TOO_SMALL; 1116 8313 Dina } 1117 8313 Dina 1118 8313 Dina out1: 1119 8313 Dina STRUCT_FSET(get_all_mech, mi_return_value, rv); 1120 8313 Dina 1121 8313 Dina /* copy the first part */ 1122 8313 Dina if (copyout(STRUCT_BUF(get_all_mech), arg, 1123 8313 Dina STRUCT_SIZE(get_all_mech)) != 0) { 1124 8313 Dina error = EFAULT; 1125 8313 Dina } 1126 8313 Dina 1127 8313 Dina /* 1128 8313 Dina * If only requesting number of entries, or there are no entries, 1129 8313 Dina * or rv is not CRYPTO_SUCCESS due to buffer too small or some other 1130 8313 Dina * crypto error, or an error occurred with copyout, stop here 1131 8313 Dina */ 1132 8313 Dina if (req_count == 0 || num_mech_infos == 0 || rv != CRYPTO_SUCCESS || 1133 8313 Dina error != 0) { 1134 8313 Dina goto out2; 1135 8313 Dina } 1136 8313 Dina 1137 8313 Dina /* copyout mech_infos */ 1138 8313 Dina offset = (ulong_t)STRUCT_FADDR(get_all_mech, mi_list); 1139 8313 Dina offset -= (ulong_t)STRUCT_BUF(get_all_mech); 1140 8313 Dina 1141 8313 Dina u_minfos = kmem_alloc(num_mech_infos * STRUCT_SIZE(mi), KM_SLEEP); 1142 8313 Dina error = copyout_mechinfos(mode, arg + offset, num_mech_infos, 1143 8313 Dina mech_infos, u_minfos); 1144 8313 Dina kmem_free(u_minfos, num_mech_infos * STRUCT_SIZE(mi)); 1145 8313 Dina out2: 1146 8313 Dina if (mech_infos != NULL) 1147 8313 Dina crypto_free_all_mech_info(mech_infos, num_mech_infos); 1148 8313 Dina return (error); 1149 8313 Dina } 1150 8313 Dina 1151 8313 Dina /* 1152 0 stevel * Side-effects: 1153 0 stevel * 1. This routine stores provider descriptor pointers in an array 1154 0 stevel * and increments each descriptor's reference count. The array 1155 0 stevel * is stored in per-minor number storage. 1156 0 stevel * 2. Destroys the old array and creates a new one every time 1157 0 stevel * this routine is called. 1158 0 stevel */ 1159 0 stevel int 1160 0 stevel crypto_get_provider_list(crypto_minor_t *cm, uint_t *count, 1161 0 stevel crypto_provider_entry_t **array, boolean_t return_slot_list) 1162 0 stevel { 1163 0 stevel kcf_provider_desc_t **provider_array; 1164 0 stevel crypto_provider_entry_t *p = NULL; 1165 0 stevel uint_t provider_count; 1166 0 stevel int rval; 1167 0 stevel int i; 1168 0 stevel 1169 0 stevel /* 1170 0 stevel * Take snapshot of provider table returning only HW entries 1171 0 stevel * that are in a usable state. Also returns logical provider entries. 1172 0 stevel */ 1173 0 stevel rval = kcf_get_slot_list(&provider_count, &provider_array, B_FALSE); 1174 0 stevel if (rval != CRYPTO_SUCCESS) 1175 0 stevel return (rval); 1176 0 stevel 1177 0 stevel /* allocate memory before taking cm->cm_lock */ 1178 0 stevel if (return_slot_list) { 1179 0 stevel if (provider_count != 0) { 1180 0 stevel p = kmem_alloc(provider_count * 1181 0 stevel sizeof (crypto_provider_entry_t), KM_SLEEP); 1182 0 stevel for (i = 0; i < provider_count; i++) { 1183 0 stevel p[i].pe_provider_id = i; 1184 0 stevel p[i].pe_mechanism_count = 1185 0 stevel provider_array[i]->pd_mech_list_count; 1186 0 stevel } 1187 0 stevel } 1188 0 stevel *array = p; 1189 0 stevel *count = provider_count; 1190 0 stevel } 1191 0 stevel 1192 0 stevel /* 1193 0 stevel * Free existing array of providers and replace with new list. 1194 0 stevel */ 1195 0 stevel mutex_enter(&cm->cm_lock); 1196 0 stevel if (cm->cm_provider_array != NULL) { 1197 0 stevel ASSERT(cm->cm_provider_count > 0); 1198 0 stevel kcf_free_provider_tab(cm->cm_provider_count, 1199 0 stevel cm->cm_provider_array); 1200 0 stevel } 1201 0 stevel 1202 0 stevel cm->cm_provider_array = provider_array; 1203 0 stevel cm->cm_provider_count = provider_count; 1204 0 stevel mutex_exit(&cm->cm_lock); 1205 0 stevel 1206 0 stevel return (CRYPTO_SUCCESS); 1207 0 stevel } 1208 0 stevel 1209 0 stevel /* 1210 0 stevel * This ioctl returns an array of crypto_provider_entry_t entries. 1211 0 stevel * This is how consumers learn which hardware providers are available. 1212 0 stevel */ 1213 0 stevel /* ARGSUSED */ 1214 0 stevel static int 1215 0 stevel get_provider_list(dev_t dev, caddr_t arg, int mode, int *rval) 1216 0 stevel { 1217 0 stevel STRUCT_DECL(crypto_get_provider_list, get_list); 1218 0 stevel crypto_provider_entry_t *entries; 1219 0 stevel crypto_minor_t *cm; 1220 0 stevel size_t copyout_size; 1221 0 stevel uint_t req_count; 1222 0 stevel uint_t count; 1223 0 stevel ulong_t offset; 1224 0 stevel int rv; 1225 0 stevel 1226 0 stevel STRUCT_INIT(get_list, mode); 1227 0 stevel 1228 0 stevel if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 1229 0 stevel cmn_err(CE_WARN, "get_provider_list: failed holding minor"); 1230 0 stevel return (ENXIO); 1231 0 stevel } 1232 0 stevel 1233 0 stevel if (copyin(arg, STRUCT_BUF(get_list), STRUCT_SIZE(get_list)) != 0) { 1234 0 stevel crypto_release_minor(cm); 1235 0 stevel return (EFAULT); 1236 0 stevel } 1237 0 stevel 1238 0 stevel rv = crypto_get_provider_list(cm, &count, &entries, RETURN_LIST); 1239 0 stevel if (rv != CRYPTO_SUCCESS) { 1240 0 stevel crypto_release_minor(cm); 1241 0 stevel STRUCT_FSET(get_list, pl_return_value, rv); 1242 0 stevel if (copyout(STRUCT_BUF(get_list), arg, 1243 0 stevel STRUCT_SIZE(get_list)) != 0) { 1244 0 stevel return (EFAULT); 1245 0 stevel } 1246 0 stevel return (0); 1247 0 stevel } 1248 0 stevel crypto_release_minor(cm); 1249 0 stevel 1250 0 stevel /* Number of slots caller thinks we have */ 1251 0 stevel req_count = STRUCT_FGET(get_list, pl_count); 1252 0 stevel 1253 0 stevel /* Check if only requesting number of slots */ 1254 0 stevel if (req_count == 0) { 1255 0 stevel 1256 0 stevel STRUCT_FSET(get_list, pl_count, count); 1257 0 stevel STRUCT_FSET(get_list, pl_return_value, CRYPTO_SUCCESS); 1258 0 stevel 1259 0 stevel crypto_free_provider_list(entries, count); 1260 0 stevel if (copyout(STRUCT_BUF(get_list), arg, 1261 4632 mcpowers STRUCT_SIZE(get_list)) != 0) { 1262 0 stevel return (EFAULT); 1263 0 stevel } 1264 0 stevel return (0); 1265 0 stevel } 1266 0 stevel 1267 0 stevel /* check if buffer is too small */ 1268 0 stevel req_count = STRUCT_FGET(get_list, pl_count); 1269 0 stevel if (count > req_count) { 1270 0 stevel STRUCT_FSET(get_list, pl_count, count); 1271 0 stevel STRUCT_FSET(get_list, pl_return_value, CRYPTO_BUFFER_TOO_SMALL); 1272 0 stevel crypto_free_provider_list(entries, count); 1273 0 stevel if (copyout(STRUCT_BUF(get_list), arg, 1274 0 stevel STRUCT_SIZE(get_list)) != 0) { 1275 0 stevel return (EFAULT); 1276 0 stevel } 1277 0 stevel return (0); 1278 0 stevel } 1279 0 stevel 1280 0 stevel STRUCT_FSET(get_list, pl_count, count); 1281 0 stevel STRUCT_FSET(get_list, pl_return_value, CRYPTO_SUCCESS); 1282 0 stevel 1283 0 stevel copyout_size = count * sizeof (crypto_provider_entry_t); 1284 0 stevel 1285 0 stevel /* copyout the first stuff */ 1286 0 stevel if (copyout(STRUCT_BUF(get_list), arg, STRUCT_SIZE(get_list)) != 0) { 1287 0 stevel crypto_free_provider_list(entries, count); 1288 0 stevel return (EFAULT); 1289 0 stevel } 1290 0 stevel 1291 0 stevel if (count == 0) { 1292 0 stevel crypto_free_provider_list(entries, count); 1293 0 stevel return (0); 1294 0 stevel } 1295 0 stevel 1296 0 stevel /* copyout entries */ 1297 0 stevel offset = (ulong_t)STRUCT_FADDR(get_list, pl_list); 1298 0 stevel offset -= (ulong_t)STRUCT_BUF(get_list); 1299 0 stevel if (copyout(entries, arg + offset, copyout_size) != 0) { 1300 0 stevel crypto_free_provider_list(entries, count); 1301 0 stevel return (EFAULT); 1302 0 stevel } 1303 0 stevel 1304 0 stevel crypto_free_provider_list(entries, count); 1305 0 stevel return (0); 1306 0 stevel } 1307 0 stevel 1308 0 stevel static void 1309 0 stevel ext_to_provider_data(int mode, kcf_provider_desc_t *provider, 1310 0 stevel crypto_provider_ext_info_t *ei, void *out) 1311 0 stevel { 1312 0 stevel STRUCT_DECL(crypto_provider_data, pd); 1313 0 stevel STRUCT_DECL(crypto_version, version); 1314 0 stevel 1315 0 stevel STRUCT_INIT(pd, mode); 1316 0 stevel STRUCT_INIT(version, mode); 1317 0 stevel 1318 0 stevel bcopy(provider->pd_description, STRUCT_FGET(pd, pd_prov_desc), 1319 0 stevel CRYPTO_PROVIDER_DESCR_MAX_LEN); 1320 0 stevel 1321 0 stevel bcopy(ei->ei_label, STRUCT_FGET(pd, pd_label), CRYPTO_EXT_SIZE_LABEL); 1322 0 stevel bcopy(ei->ei_manufacturerID, STRUCT_FGET(pd, pd_manufacturerID), 1323 0 stevel CRYPTO_EXT_SIZE_MANUF); 1324 0 stevel bcopy(ei->ei_model, STRUCT_FGET(pd, pd_model), CRYPTO_EXT_SIZE_MODEL); 1325 0 stevel bcopy(ei->ei_serial_number, STRUCT_FGET(pd, pd_serial_number), 1326 0 stevel CRYPTO_EXT_SIZE_SERIAL); 1327 0 stevel /* 1328 0 stevel * We do not support ioctls for dual-function crypto operations yet. 1329 0 stevel * So, we clear this flag as it might have been set by a provider. 1330 0 stevel */ 1331 0 stevel ei->ei_flags &= ~CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS; 1332 0 stevel 1333 0 stevel STRUCT_FSET(pd, pd_flags, ei->ei_flags); 1334 0 stevel STRUCT_FSET(pd, pd_max_session_count, ei->ei_max_session_count); 1335 0 stevel STRUCT_FSET(pd, pd_session_count, (int)CRYPTO_UNAVAILABLE_INFO); 1336 0 stevel STRUCT_FSET(pd, pd_max_rw_session_count, ei->ei_max_session_count); 1337 0 stevel STRUCT_FSET(pd, pd_rw_session_count, (int)CRYPTO_UNAVAILABLE_INFO); 1338 0 stevel STRUCT_FSET(pd, pd_max_pin_len, ei->ei_max_pin_len); 1339 0 stevel STRUCT_FSET(pd, pd_min_pin_len, ei->ei_min_pin_len); 1340 0 stevel STRUCT_FSET(pd, pd_total_public_memory, ei->ei_total_public_memory); 1341 0 stevel STRUCT_FSET(pd, pd_free_public_memory, ei->ei_free_public_memory); 1342 0 stevel STRUCT_FSET(pd, pd_total_private_memory, ei->ei_total_private_memory); 1343 0 stevel STRUCT_FSET(pd, pd_free_private_memory, ei->ei_free_private_memory); 1344 0 stevel STRUCT_FSET(version, cv_major, ei->ei_hardware_version.cv_major); 1345 0 stevel STRUCT_FSET(version, cv_minor, ei->ei_hardware_version.cv_minor); 1346 0 stevel bcopy(STRUCT_BUF(version), STRUCT_FADDR(pd, pd_hardware_version), 1347 0 stevel STRUCT_SIZE(version)); 1348 10028 wyllys STRUCT_FSET(version, cv_major, ei->ei_firmware_version.cv_major); 1349 10028 wyllys STRUCT_FSET(version, cv_minor, ei->ei_firmware_version.cv_minor); 1350 0 stevel bcopy(STRUCT_BUF(version), STRUCT_FADDR(pd, pd_firmware_version), 1351 0 stevel STRUCT_SIZE(version)); 1352 0 stevel bcopy(ei->ei_time, STRUCT_FGET(pd, pd_time), CRYPTO_EXT_SIZE_TIME); 1353 0 stevel bcopy(STRUCT_BUF(pd), out, STRUCT_SIZE(pd)); 1354 0 stevel } 1355 0 stevel 1356 0 stevel /* 1357 0 stevel * Utility routine to construct a crypto_provider_ext_info structure. Some 1358 0 stevel * of the fields are constructed from information in the provider structure. 1359 0 stevel * The rest of the fields have default values. We need to do this for 1360 0 stevel * providers which do not support crypto_provider_management_ops routines. 1361 0 stevel */ 1362 0 stevel static void 1363 0 stevel fabricate_ext_info(kcf_provider_desc_t *provider, 1364 0 stevel crypto_provider_ext_info_t *ei) 1365 0 stevel { 1366 0 stevel /* empty label */ 1367 0 stevel (void) memset(ei->ei_label, ' ', CRYPTO_EXT_SIZE_LABEL); 1368 0 stevel 1369 0 stevel (void) memset(ei->ei_manufacturerID, ' ', CRYPTO_EXT_SIZE_MANUF); 1370 0 stevel (void) strncpy((char *)ei->ei_manufacturerID, "Unknown", 7); 1371 0 stevel 1372 0 stevel (void) memset(ei->ei_model, ' ', CRYPTO_EXT_SIZE_MODEL); 1373 0 stevel (void) strncpy((char *)ei->ei_model, "Unknown", 7); 1374 0 stevel 1375 0 stevel (void) memset(ei->ei_serial_number, ' ', CRYPTO_EXT_SIZE_SERIAL); 1376 0 stevel (void) strncpy((char *)ei->ei_serial_number, "Unknown", 7); 1377 0 stevel 1378 0 stevel if (KCF_PROV_RANDOM_OPS(provider) != NULL) 1379 0 stevel ei->ei_flags |= CRYPTO_EXTF_RNG; 1380 0 stevel if (KCF_PROV_DUAL_OPS(provider) != NULL) 1381 0 stevel ei->ei_flags |= CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS; 1382 0 stevel 1383 0 stevel ei->ei_max_session_count = CRYPTO_UNAVAILABLE_INFO; 1384 0 stevel ei->ei_max_pin_len = 0; 1385 0 stevel ei->ei_min_pin_len = 0; 1386 0 stevel ei->ei_total_public_memory = CRYPTO_UNAVAILABLE_INFO; 1387 0 stevel ei->ei_free_public_memory = CRYPTO_UNAVAILABLE_INFO; 1388 0 stevel ei->ei_total_private_memory = CRYPTO_UNAVAILABLE_INFO; 1389 0 stevel ei->ei_free_private_memory = CRYPTO_UNAVAILABLE_INFO; 1390 0 stevel ei->ei_hardware_version.cv_major = 1; 1391 0 stevel ei->ei_hardware_version.cv_minor = 0; 1392 0 stevel ei->ei_firmware_version.cv_major = 1; 1393 0 stevel ei->ei_firmware_version.cv_minor = 0; 1394 0 stevel } 1395 0 stevel 1396 0 stevel /* ARGSUSED */ 1397 0 stevel static int 1398 0 stevel get_provider_info(dev_t dev, caddr_t arg, int mode, int *rval) 1399 0 stevel { 1400 0 stevel STRUCT_DECL(crypto_get_provider_info, get_info); 1401 0 stevel crypto_minor_t *cm; 1402 0 stevel crypto_provider_id_t provider_id; 1403 0 stevel kcf_provider_desc_t *provider, *real_provider; 1404 0 stevel crypto_provider_ext_info_t *ext_info = NULL; 1405 0 stevel size_t need; 1406 0 stevel int error = 0; 1407 0 stevel int rv; 1408 0 stevel kcf_req_params_t params; 1409 0 stevel 1410 0 stevel STRUCT_INIT(get_info, mode); 1411 0 stevel 1412 0 stevel if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 1413 0 stevel cmn_err(CE_WARN, "get_provider_info: failed holding minor"); 1414 0 stevel return (ENXIO); 1415 0 stevel } 1416 0 stevel 1417 0 stevel if (copyin(arg, STRUCT_BUF(get_info), STRUCT_SIZE(get_info)) != 0) { 1418 0 stevel crypto_release_minor(cm); 1419 0 stevel return (EFAULT); 1420 0 stevel } 1421 0 stevel 1422 0 stevel need = sizeof (crypto_provider_ext_info_t); 1423 3916 krishna if ((rv = crypto_buffer_check(need)) != CRYPTO_SUCCESS) { 1424 0 stevel need = 0; 1425 0 stevel goto release_minor; 1426 0 stevel } 1427 0 stevel 1428 0 stevel /* initialize provider_array */ 1429 0 stevel if (cm->cm_provider_array == NULL) { 1430 0 stevel rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST); 1431 0 stevel if (rv != CRYPTO_SUCCESS) { 1432 0 stevel goto release_minor; 1433 0 stevel } 1434 0 stevel } 1435 0 stevel 1436 0 stevel ext_info = kmem_zalloc(need, KM_SLEEP); 1437 0 stevel 1438 0 stevel provider_id = STRUCT_FGET(get_info, gi_provider_id); 1439 0 stevel mutex_enter(&cm->cm_lock); 1440 0 stevel /* index must be less than count of providers */ 1441 0 stevel if (provider_id >= cm->cm_provider_count) { 1442 0 stevel mutex_exit(&cm->cm_lock); 1443 0 stevel rv = CRYPTO_ARGUMENTS_BAD; 1444 0 stevel goto release_minor; 1445 0 stevel } 1446 0 stevel 1447 0 stevel ASSERT(cm->cm_provider_array != NULL); 1448 0 stevel provider = cm->cm_provider_array[provider_id]; 1449 0 stevel KCF_PROV_REFHOLD(provider); 1450 0 stevel mutex_exit(&cm->cm_lock); 1451 0 stevel 1452 0 stevel (void) kcf_get_hardware_provider_nomech( 1453 0 stevel CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(ext_info), 1454 904 mcpowers CHECK_RESTRICT_FALSE, provider, &real_provider); 1455 0 stevel 1456 0 stevel if (real_provider != NULL) { 1457 0 stevel ASSERT(real_provider == provider || 1458 0 stevel provider->pd_prov_type == CRYPTO_LOGICAL_PROVIDER); 1459 0 stevel KCF_WRAP_PROVMGMT_OPS_PARAMS(¶ms, KCF_OP_MGMT_EXTINFO, 1460 0 stevel 0, NULL, 0, NULL, 0, NULL, ext_info, provider); 1461 0 stevel rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, 1462 0 stevel B_FALSE); 1463 0 stevel ASSERT(rv != CRYPTO_NOT_SUPPORTED); 1464 904 mcpowers KCF_PROV_REFRELE(real_provider); 1465 0 stevel } else { 1466 0 stevel /* do the best we can */ 1467 0 stevel fabricate_ext_info(provider, ext_info); 1468 0 stevel rv = CRYPTO_SUCCESS; 1469 0 stevel } 1470 0 stevel KCF_PROV_REFRELE(provider); 1471 0 stevel 1472 0 stevel if (rv == CRYPTO_SUCCESS) { 1473 0 stevel ext_to_provider_data(mode, provider, ext_info, 1474 0 stevel STRUCT_FADDR(get_info, gi_provider_data)); 1475 0 stevel } 1476 0 stevel 1477 0 stevel release_minor: 1478 6424 krishna CRYPTO_DECREMENT_RCTL(need); 1479 0 stevel crypto_release_minor(cm); 1480 0 stevel 1481 0 stevel if (ext_info != NULL) 1482 0 stevel kmem_free(ext_info, sizeof (crypto_provider_ext_info_t)); 1483 0 stevel 1484 0 stevel if (error != 0) 1485 0 stevel return (error); 1486 0 stevel 1487 0 stevel STRUCT_FSET(get_info, gi_return_value, rv); 1488 0 stevel if (copyout(STRUCT_BUF(get_info), arg, STRUCT_SIZE(get_info)) != 0) { 1489 0 stevel return (EFAULT); 1490 0 stevel } 1491 0 stevel return (0); 1492 0 stevel } 1493 0 stevel 1494 0 stevel /* 1495 0 stevel * This ioctl returns an array of crypto_mech_name_t entries. 1496 0 stevel * This is how consumers learn which mechanisms are permitted 1497 0 stevel * by a provider. 1498 0 stevel */ 1499 0 stevel /* ARGSUSED */ 1500 0 stevel static int 1501 0 stevel get_provider_mechanisms(dev_t dev, caddr_t arg, int mode, int *rval) 1502 0 stevel { 1503 0 stevel STRUCT_DECL(crypto_get_provider_mechanisms, get_mechanisms); 1504 0 stevel crypto_mech_name_t *entries; 1505 0 stevel crypto_minor_t *cm; 1506 0 stevel size_t copyout_size; 1507 0 stevel uint_t req_count; 1508 0 stevel uint_t count; 1509 0 stevel ulong_t offset; 1510 0 stevel int err; 1511 0 stevel 1512 0 stevel STRUCT_INIT(get_mechanisms, mode); 1513 0 stevel 1514 0 stevel if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 1515 0 stevel cmn_err(CE_WARN, 1516 0 stevel "get_provider_mechanisms: failed holding minor"); 1517 0 stevel return (ENXIO); 1518 0 stevel } 1519 0 stevel 1520 0 stevel if (copyin(arg, STRUCT_BUF(get_mechanisms), 1521 0 stevel STRUCT_SIZE(get_mechanisms)) != 0) { 1522 0 stevel crypto_release_minor(cm); 1523 0 stevel return (EFAULT); 1524 0 stevel } 1525 0 stevel 1526 0 stevel /* get array of mechanisms from the core module */ 1527 0 stevel if ((err = crypto_get_provider_mechanisms(cm, 1528 0 stevel STRUCT_FGET(get_mechanisms, pm_provider_id), 1529 0 stevel &count, &entries)) != 0) { 1530 0 stevel crypto_release_minor(cm); 1531 0 stevel STRUCT_FSET(get_mechanisms, pm_return_value, err); 1532 0 stevel if (copyout(STRUCT_BUF(get_mechanisms), arg, 1533 0 stevel STRUCT_SIZE(get_mechanisms)) != 0) { 1534 0 stevel return (EFAULT); 1535 0 stevel } 1536 0 stevel return (0); 1537 0 stevel } 1538 0 stevel crypto_release_minor(cm); 1539 0 stevel /* Number of mechs caller thinks we have */ 1540 0 stevel req_count = STRUCT_FGET(get_mechanisms, pm_count); 1541 0 stevel 1542 0 stevel /* Check if caller is just requesting a count of mechanisms */ 1543 0 stevel if (req_count == 0) { 1544 0 stevel STRUCT_FSET(get_mechanisms, pm_count, count); 1545 0 stevel STRUCT_FSET(get_mechanisms, pm_return_value, CRYPTO_SUCCESS); 1546 0 stevel 1547 0 stevel crypto_free_mech_list(entries, count); 1548 0 stevel if (copyout(STRUCT_BUF(get_mechanisms), arg, 1549 0 stevel STRUCT_SIZE(get_mechanisms)) != 0) { 1550 0 stevel return (EFAULT); 1551 0 stevel } 1552 0 stevel return (0); 1553 0 stevel } 1554 0 stevel 1555 0 stevel /* check if buffer is too small */ 1556 0 stevel if (count > req_count) { 1557 0 stevel STRUCT_FSET(get_mechanisms, pm_count, count); 1558 0 stevel STRUCT_FSET(get_mechanisms, pm_return_value, 1559 0 stevel CRYPTO_BUFFER_TOO_SMALL); 1560 0 stevel crypto_free_mech_list(entries, count); 1561 0 stevel if (copyout(STRUCT_BUF(get_mechanisms), arg, 1562 0 stevel STRUCT_SIZE(get_mechanisms)) != 0) { 1563 0 stevel return (EFAULT); 1564 0 stevel } 1565 0 stevel return (0); 1566 0 stevel } 1567 0 stevel 1568 0 stevel STRUCT_FSET(get_mechanisms, pm_count, count); 1569 0 stevel STRUCT_FSET(get_mechanisms, pm_return_value, CRYPTO_SUCCESS); 1570 0 stevel 1571 0 stevel copyout_size = count * sizeof (crypto_mech_name_t); 1572 0 stevel 1573 0 stevel /* copyout the first stuff */ 1574 0 stevel if (copyout(STRUCT_BUF(get_mechanisms), arg, 1575 0 stevel STRUCT_SIZE(get_mechanisms)) != 0) { 1576 0 stevel crypto_free_mech_list(entries, count); 1577 0 stevel return (EFAULT); 1578 0 stevel } 1579 0 stevel 1580 0 stevel if (count == 0) { 1581 0 stevel return (0); 1582 0 stevel } 1583 0 stevel 1584 0 stevel /* copyout entries */ 1585 0 stevel offset = (ulong_t)STRUCT_FADDR(get_mechanisms, pm_list); 1586 0 stevel offset -= (ulong_t)STRUCT_BUF(get_mechanisms); 1587 0 stevel if (copyout(entries, arg + offset, copyout_size) != 0) { 1588 0 stevel crypto_free_mech_list(entries, count); 1589 0 stevel return (EFAULT); 1590 0 stevel } 1591 0 stevel 1592 0 stevel crypto_free_mech_list(entries, count); 1593 0 stevel return (0); 1594 0 stevel } 1595 0 stevel 1596 0 stevel /* 1597 0 stevel * This ioctl returns information about a provider's mechanism. 1598 0 stevel */ 1599 0 stevel /* ARGSUSED */ 1600 0 stevel static int 1601 0 stevel get_provider_mechanism_info(dev_t dev, caddr_t arg, int mode, int *rval) 1602 0 stevel { 1603 0 stevel crypto_get_provider_mechanism_info_t mechanism_info; 1604 0 stevel crypto_minor_t *cm; 1605 0 stevel kcf_provider_desc_t *pd; 1606 0 stevel crypto_mech_info_t *mi = NULL; 1607 0 stevel int rv = CRYPTO_SUCCESS; 1608 0 stevel int i; 1609 0 stevel 1610 0 stevel if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 1611 0 stevel cmn_err(CE_WARN, 1612 0 stevel "get_provider_mechanism_info: failed holding minor"); 1613 0 stevel return (ENXIO); 1614 0 stevel } 1615 0 stevel 1616 0 stevel if (copyin(arg, &mechanism_info, sizeof (mechanism_info)) != 0) { 1617 0 stevel crypto_release_minor(cm); 1618 0 stevel return (EFAULT); 1619 0 stevel } 1620 0 stevel 1621 0 stevel /* initialize provider table */ 1622 0 stevel if (cm->cm_provider_array == NULL) { 1623 0 stevel rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST); 1624 0 stevel if (rv != CRYPTO_SUCCESS) { 1625 0 stevel mutex_enter(&cm->cm_lock); 1626 0 stevel goto fail; 1627 0 stevel } 1628 0 stevel } 1629 0 stevel 1630 0 stevel /* 1631 0 stevel * Provider ID must be less than the count of providers 1632 0 stevel * obtained by calling get_provider_list(). 1633 0 stevel */ 1634 0 stevel mutex_enter(&cm->cm_lock); 1635 0 stevel if (mechanism_info.mi_provider_id >= cm->cm_provider_count) { 1636 0 stevel rv = CRYPTO_ARGUMENTS_BAD; 1637 0 stevel goto fail; 1638 0 stevel } 1639 0 stevel 1640 0 stevel pd = cm->cm_provider_array[mechanism_info.mi_provider_id]; 1641 0 stevel 1642 0 stevel for (i = 0; i < pd->pd_mech_list_count; i++) { 1643 0 stevel if (strncmp(pd->pd_mechanisms[i].cm_mech_name, 1644 0 stevel mechanism_info.mi_mechanism_name, 1645 0 stevel CRYPTO_MAX_MECH_NAME) == 0) { 1646 0 stevel mi = &pd->pd_mechanisms[i]; 1647 0 stevel } 1648 0 stevel } 1649 0 stevel 1650 0 stevel if (mi == NULL) { 1651 0 stevel rv = CRYPTO_ARGUMENTS_BAD; 1652 0 stevel goto fail; 1653 0 stevel } 1654 0 stevel 1655 0 stevel mechanism_info.mi_min_key_size = mi->cm_min_key_length; 1656 0 stevel mechanism_info.mi_max_key_size = mi->cm_max_key_length; 1657 0 stevel mechanism_info.mi_flags = mi->cm_func_group_mask; 1658 0 stevel 1659 0 stevel fail: 1660 0 stevel mutex_exit(&cm->cm_lock); 1661 0 stevel crypto_release_minor(cm); 1662 0 stevel mechanism_info.mi_return_value = rv; 1663 0 stevel if (copyout(&mechanism_info, arg, sizeof (mechanism_info)) != 0) { 1664 0 stevel return (EFAULT); 1665 0 stevel } 1666 0 stevel 1667 0 stevel return (0); 1668 0 stevel } 1669 0 stevel 1670 0 stevel /* 1671 0 stevel * Every open of /dev/crypto multiplexes all PKCS#11 sessions across 1672 0 stevel * a single session to each provider. Calls to open and close session 1673 0 stevel * are not made to providers that do not support sessions. For these 1674 0 stevel * providers, a session number of 0 is passed during subsequent operations, 1675 0 stevel * and it is ignored by the provider. 1676 0 stevel */ 1677 0 stevel static int 1678 0 stevel crypto_get_provider_session(crypto_minor_t *cm, 1679 0 stevel crypto_provider_id_t provider_index, crypto_provider_session_t **output_ps) 1680 0 stevel { 1681 0 stevel kcf_provider_desc_t *pd, *real_provider; 1682 0 stevel kcf_req_params_t params; 1683 0 stevel crypto_provider_session_t *ps, *new_ps; 1684 0 stevel crypto_session_id_t provider_session_id = 0; 1685 0 stevel int rv; 1686 0 stevel 1687 0 stevel ASSERT(MUTEX_HELD(&cm->cm_lock)); 1688 0 stevel 1689 0 stevel /* pd may be a logical provider */ 1690 0 stevel pd = cm->cm_provider_array[provider_index]; 1691 0 stevel 1692 0 stevel again: 1693 0 stevel /* 1694 0 stevel * Check if there is already a session to the provider. 1695 0 stevel * Sessions may be to a logical provider or a real provider. 1696 0 stevel */ 1697 0 stevel for (ps = cm->cm_provider_session; ps != NULL; ps = ps->ps_next) { 1698 0 stevel if (ps->ps_provider == pd) 1699 0 stevel break; 1700 0 stevel } 1701 0 stevel 1702 0 stevel /* found existing session */ 1703 0 stevel if (ps != NULL) { 1704 0 stevel ps->ps_refcnt++; 1705 0 stevel *output_ps = ps; 1706 0 stevel return (CRYPTO_SUCCESS); 1707 0 stevel } 1708 0 stevel mutex_exit(&cm->cm_lock); 1709 0 stevel 1710 0 stevel /* find a hardware provider that supports session ops */ 1711 0 stevel (void) kcf_get_hardware_provider_nomech(CRYPTO_OPS_OFFSET(session_ops), 1712 904 mcpowers CRYPTO_SESSION_OFFSET(session_open), CHECK_RESTRICT_FALSE, 1713 904 mcpowers pd, &real_provider); 1714 0 stevel 1715 0 stevel if (real_provider != NULL) { 1716 0 stevel ASSERT(real_provider == pd || 1717 0 stevel pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER); 1718 0 stevel /* open session to provider */ 1719 0 stevel KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_OPEN, 1720 0 stevel &provider_session_id, 0, CRYPTO_USER, NULL, 0, pd); 1721 0 stevel rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms, 1722 0 stevel B_FALSE); 1723 0 stevel if (rv != CRYPTO_SUCCESS) { 1724 0 stevel mutex_enter(&cm->cm_lock); 1725 904 mcpowers KCF_PROV_REFRELE(real_provider); 1726 0 stevel return (rv); 1727 0 stevel } 1728 0 stevel } 1729 0 stevel 1730 0 stevel /* allocate crypto_provider_session structure */ 1731 0 stevel new_ps = kmem_zalloc(sizeof (crypto_provider_session_t), KM_SLEEP); 1732 0 stevel 1733 0 stevel /* 1734 0 stevel * Check if someone opened a session to the provider 1735 0 stevel * while we dropped the lock. 1736 0 stevel */ 1737 0 stevel mutex_enter(&cm->cm_lock); 1738 0 stevel for (ps = cm->cm_provider_session; ps != NULL; ps = ps->ps_next) { 1739 0 stevel if (ps->ps_provider == pd) { 1740 0 stevel mutex_exit(&cm->cm_lock); 1741 0 stevel kmem_free(new_ps, sizeof (crypto_provider_session_t)); 1742 0 stevel if (real_provider != NULL) { 1743 0 stevel KCF_WRAP_SESSION_OPS_PARAMS(¶ms, 1744 0 stevel KCF_OP_SESSION_CLOSE, NULL, 1745 0 stevel provider_session_id, CRYPTO_USER, NULL, 0, 1746 0 stevel pd); 1747 0 stevel (void) kcf_submit_request(real_provider, NULL, 1748 0 stevel NULL, ¶ms, B_FALSE); 1749 904 mcpowers KCF_PROV_REFRELE(real_provider); 1750 0 stevel } 1751 0 stevel mutex_enter(&cm->cm_lock); 1752 0 stevel goto again; 1753 0 stevel 1754 0 stevel } 1755 0 stevel } 1756 0 stevel 1757 0 stevel /* increment refcnt and attach to crypto_minor structure */ 1758 0 stevel new_ps->ps_session = provider_session_id; 1759 0 stevel new_ps->ps_refcnt = 1; 1760 0 stevel KCF_PROV_REFHOLD(pd); 1761 0 stevel new_ps->ps_provider = pd; 1762 0 stevel if (real_provider != NULL) { 1763 0 stevel new_ps->ps_real_provider = real_provider; 1764 0 stevel } 1765 0 stevel new_ps->ps_next = cm->cm_provider_session; 1766 0 stevel cm->cm_provider_session = new_ps; 1767 0 stevel 1768 0 stevel *output_ps = new_ps; 1769 0 stevel return (CRYPTO_SUCCESS); 1770 0 stevel } 1771 0 stevel 1772 0 stevel /* 1773 0 stevel * Release a provider session. 1774 0 stevel * If the reference count goes to zero, then close the session 1775 0 stevel * to the provider. 1776 0 stevel */ 1777 0 stevel static void 1778 0 stevel crypto_release_provider_session(crypto_minor_t *cm, 1779 0 stevel crypto_provider_session_t *provider_session) 1780 0 stevel { 1781 0 stevel kcf_req_params_t params; 1782 0 stevel crypto_provider_session_t *ps = NULL, **prev; 1783 0 stevel 1784 0 stevel ASSERT(MUTEX_HELD(&cm->cm_lock)); 1785 0 stevel 1786 0 stevel /* verify that provider_session is valid */ 1787 0 stevel for (ps = cm->cm_provider_session, prev = &cm->cm_provider_session; 1788 0 stevel ps != NULL; prev = &ps->ps_next, ps = ps->ps_next) { 1789 0 stevel if (ps == provider_session) { 1790 0 stevel break; 1791 0 stevel } 1792 0 stevel } 1793 0 stevel 1794 0 stevel if (ps == NULL) 1795 0 stevel return; 1796 0 stevel 1797 0 stevel ps->ps_refcnt--; 1798 0 stevel 1799 0 stevel if (ps->ps_refcnt > 0) 1800 0 stevel return; 1801 0 stevel 1802 0 stevel if (ps->ps_real_provider != NULL) { 1803 0 stevel /* close session with provider */ 1804 0 stevel KCF_WRAP_SESSION_OPS_PARAMS(¶ms, KCF_OP_SESSION_CLOSE, NULL, 1805 0 stevel ps->ps_session, CRYPTO_USER, NULL, 0, ps->ps_provider); 1806 0 stevel (void) kcf_submit_request(ps->ps_real_provider, 1807 0 stevel NULL, NULL, ¶ms, B_FALSE); 1808 0 stevel KCF_PROV_REFRELE(ps->ps_real_provider); 1809 0 stevel } 1810 0 stevel KCF_PROV_REFRELE(ps->ps_provider); 1811 0 stevel *prev = ps->ps_next; 1812 0 stevel kmem_free(ps, sizeof (*ps)); 1813 0 stevel } 1814 0 stevel 1815 0 stevel static int 1816 0 stevel grow_session_table(crypto_minor_t *cm) 1817 0 stevel { 1818 0 stevel crypto_session_data_t **session_table; 1819 0 stevel crypto_session_data_t **new; 1820 0 stevel uint_t session_table_count; 1821 0 stevel uint_t need; 1822 0 stevel size_t current_allocation; 1823 0 stevel size_t new_allocation; 1824 3916 krishna int rv; 1825 0 stevel 1826 0 stevel ASSERT(MUTEX_HELD(&cm->cm_lock)); 1827 0 stevel 1828 0 stevel session_table_count = cm->cm_session_table_count; 1829 0 stevel session_table = cm->cm_session_table; 1830 0 stevel need = session_table_count + CRYPTO_SESSION_CHUNK; 1831 0 stevel 1832 0 stevel current_allocation = session_table_count * sizeof (void *); 1833 0 stevel new_allocation = need * sizeof (void *); 1834 0 stevel 1835 0 stevel /* 1836 0 stevel * Memory needed to grow the session table is checked 1837 0 stevel * against the project.max-crypto-memory resource control. 1838 0 stevel */ 1839 3916 krishna if ((rv = crypto_buffer_check(new_allocation - current_allocation)) != 1840 3916 krishna CRYPTO_SUCCESS) { 1841 3916 krishna return (rv); 1842 3916 krishna } 1843 0 stevel 1844 0 stevel /* drop lock while we allocate memory */ 1845 0 stevel mutex_exit(&cm->cm_lock); 1846 0 stevel new = kmem_zalloc(new_allocation, KM_SLEEP); 1847 0 stevel mutex_enter(&cm->cm_lock); 1848 0 stevel 1849 0 stevel /* check if another thread increased the table size */ 1850 0 stevel if (session_table_count != cm->cm_session_table_count) { 1851 0 stevel kmem_free(new, new_allocation); 1852 0 stevel return (CRYPTO_SUCCESS); 1853 0 stevel } 1854 0 stevel 1855 0 stevel bcopy(session_table, new, current_allocation); 1856 0 stevel kmem_free(session_table, current_allocation); 1857 0 stevel cm->cm_session_table = new; 1858 0 stevel cm->cm_session_table_count += CRYPTO_SESSION_CHUNK; 1859 0 stevel 1860 0 stevel return (CRYPTO_SUCCESS); 1861 0 stevel } 1862 0 stevel 1863 0 stevel /* 1864 0 stevel * Find unused entry in session table and return it's index. 1865 0 stevel * Initialize session table entry. 1866 0 stevel */ 1867 0 stevel /* ARGSUSED */ 1868 0 stevel static int 1869 0 stevel crypto_open_session(dev_t dev, uint_t flags, crypto_session_id_t *session_index, 1870 0 stevel crypto_provider_id_t provider_id) 1871 0 stevel { 1872 0 stevel crypto_session_data_t **session_table; 1873 0 stevel crypto_session_data_t *sp; 1874 0 stevel crypto_minor_t *cm; 1875 0 stevel uint_t session_table_count; 1876 0 stevel uint_t i; 1877 0 stevel int rv; 1878 0 stevel crypto_provider_session_t *ps; 1879 0 stevel kcf_provider_desc_t *provider; 1880 0 stevel 1881 0 stevel if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 1882 0 stevel cmn_err(CE_WARN, "crypto_open_session: failed holding minor"); 1883 0 stevel return (CRYPTO_FAILED); 1884 0 stevel } 1885 0 stevel 1886 0 stevel /* initialize provider_array */ 1887 0 stevel if (cm->cm_provider_array == NULL) { 1888 0 stevel rv = crypto_get_provider_list(cm, NULL, NULL, DONT_RETURN_LIST); 1889 0 stevel if (rv != 0) { 1890 0 stevel crypto_release_minor(cm); 1891 0 stevel return (rv); 1892 0 stevel } 1893 0 stevel } 1894 0 stevel 1895 0 stevel mutex_enter(&cm->cm_lock); 1896 0 stevel /* index must be less than count of providers */ 1897 0 stevel if (provider_id >= cm->cm_provider_count) { 1898 0 stevel mutex_exit(&cm->cm_lock); 1899 0 stevel crypto_release_minor(cm); 1900 0 stevel return (CRYPTO_INVALID_PROVIDER_ID); 1901 0 stevel } 1902 0 stevel ASSERT(cm->cm_provider_array != NULL); 1903 0 stevel 1904 0 stevel rv = crypto_get_provider_session(cm, provider_id, &ps); 1905 0 stevel if (rv != CRYPTO_SUCCESS) { 1906 0 stevel mutex_exit(&cm->cm_lock); 1907 0 stevel crypto_release_minor(cm); 1908 0 stevel return (rv); 1909 0 stevel } 1910 0 stevel provider = cm->cm_provider_array[provider_id]; 1911 0 stevel 1912 0 stevel again: 1913 0 stevel session_table_count = cm->cm_session_table_count; 1914 0 stevel session_table = cm->cm_session_table; 1915 0 stevel 1916 0 stevel /* session handles start with 1 */ 1917 0 stevel for (i = 1; i < session_table_count; i++) { 1918 0 stevel if (session_table[i] == NULL) 1919 0 stevel break; 1920 0 stevel } 1921 0 stevel 1922 0 stevel if (i == session_table_count || session_table_count == 0) { 1923 0 stevel if ((rv = grow_session_table(cm)) != CRYPTO_SUCCESS) { 1924 0 stevel crypto_release_provider_session(cm, ps); 1925 0 stevel mutex_exit(&cm->cm_lock); 1926 0 stevel crypto_release_minor(cm); 1927 0 stevel return (rv); 1928 0 stevel } 1929 0 stevel goto again; 1930 0 stevel } 1931 0 stevel 1932 0 stevel sp = kmem_cache_alloc(crypto_session_cache, KM_SLEEP); 1933 0 stevel sp->sd_flags = 0; 1934 0 stevel sp->sd_find_init_cookie = NULL; 1935 0 stevel sp->sd_digest_ctx = NULL; 1936 0 stevel sp->sd_encr_ctx = NULL; 1937 0 stevel sp->sd_decr_ctx = NULL; 1938 0 stevel sp->sd_sign_ctx = NULL; 1939 0 stevel sp->sd_verify_ctx = NULL; 1940 0 stevel sp->sd_sign_recover_ctx = NULL; 1941 0 stevel sp->sd_verify_recover_ctx = NULL; 1942 0 stevel mutex_init(&sp->sd_lock, NULL, MUTEX_DRIVER, NULL); 1943 0 stevel cv_init(&sp->sd_cv, NULL, CV_DRIVER, NULL); 1944 0 stevel KCF_PROV_REFHOLD(provider); 1945 0 stevel sp->sd_provider = provider; 1946 0 stevel sp->sd_provider_session = ps; 1947 6424 krishna 1948 6424 krishna /* See the comment for CRYPTO_PRE_APPROVED_LIMIT. */ 1949 6424 krishna if ((rv = crypto_buffer_check(crypto_pre_approved_limit)) != 1950 6424 krishna CRYPTO_SUCCESS) { 1951 6424 krishna sp->sd_pre_approved_amount = 0; 1952 6424 krishna } else { 1953 6424 krishna sp->sd_pre_approved_amount = crypto_pre_approved_limit; 1954 6424 krishna } 1955 6424 krishna 1956 0 stevel cm->cm_session_table[i] = sp; 1957 0 stevel mutex_exit(&cm->cm_lock); 1958 0 stevel crypto_release_minor(cm); 1959 0 stevel *session_index = i; 1960 0 stevel 1961 0 stevel return (CRYPTO_SUCCESS); 1962 0 stevel } 1963 0 stevel 1964 0 stevel /* 1965 0 stevel * Close a session. 1966 0 stevel */ 1967 0 stevel static int 1968 0 stevel crypto_close_session(dev_t dev, crypto_session_id_t session_index) 1969 0 stevel { 1970 0 stevel crypto_session_data_t **session_table; 1971 0 stevel crypto_session_data_t *sp; 1972 0 stevel crypto_minor_t *cm; 1973 0 stevel 1974 0 stevel if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 1975 0 stevel cmn_err(CE_WARN, "crypto_close_session: failed holding minor"); 1976 0 stevel return (CRYPTO_FAILED); 1977 0 stevel } 1978 0 stevel 1979 0 stevel mutex_enter(&cm->cm_lock); 1980 0 stevel session_table = cm->cm_session_table; 1981 0 stevel 1982 0 stevel if ((session_index) == 0 || 1983 0 stevel (session_index >= cm->cm_session_table_count)) { 1984 0 stevel mutex_exit(&cm->cm_lock); 1985 0 stevel crypto_release_minor(cm); 1986 0 stevel return (CRYPTO_SESSION_HANDLE_INVALID); 1987 0 stevel } 1988 0 stevel 1989 0 stevel sp = session_table[session_index]; 1990 0 stevel if (sp == NULL) { 1991 0 stevel mutex_exit(&cm->cm_lock); 1992 0 stevel crypto_release_minor(cm); 1993 0 stevel return (CRYPTO_SESSION_HANDLE_INVALID); 1994 0 stevel } 1995 0 stevel /* 1996 0 stevel * If session is in use, free it when the thread 1997 0 stevel * finishes with the session. 1998 0 stevel */ 1999 0 stevel mutex_enter(&sp->sd_lock); 2000 0 stevel if (sp->sd_flags & CRYPTO_SESSION_IS_BUSY) { 2001 0 stevel sp->sd_flags |= CRYPTO_SESSION_IS_CLOSED; 2002 0 stevel mutex_exit(&sp->sd_lock); 2003 0 stevel } else { 2004 6424 krishna ASSERT(sp->sd_pre_approved_amount == 0 || 2005 6424 krishna sp->sd_pre_approved_amount == crypto_pre_approved_limit); 2006 6424 krishna CRYPTO_DECREMENT_RCTL(sp->sd_pre_approved_amount); 2007 6424 krishna 2008 0 stevel if (sp->sd_find_init_cookie != NULL) { 2009 0 stevel (void) crypto_free_find_ctx(sp); 2010 0 stevel } 2011 0 stevel 2012 0 stevel crypto_release_provider_session(cm, sp->sd_provider_session); 2013 0 stevel KCF_PROV_REFRELE(sp->sd_provider); 2014 0 stevel CRYPTO_CANCEL_ALL_CTX(sp); 2015 0 stevel mutex_destroy(&sp->sd_lock); 2016 0 stevel cv_destroy(&sp->sd_cv); 2017 0 stevel kmem_cache_free(crypto_session_cache, sp); 2018 0 stevel session_table[session_index] = NULL; 2019 0 stevel } 2020 0 stevel 2021 0 stevel mutex_exit(&cm->cm_lock); 2022 0 stevel crypto_release_minor(cm); 2023 0 stevel 2024 0 stevel return (CRYPTO_SUCCESS); 2025 0 stevel } 2026 0 stevel 2027 0 stevel /* 2028 0 stevel * This ioctl opens a session and returns the session ID in os_session. 2029 0 stevel */ 2030 0 stevel /* ARGSUSED */ 2031 0 stevel static int 2032 0 stevel open_session(dev_t dev, caddr_t arg, int mode, int *rval) 2033 0 stevel { 2034 0 stevel crypto_open_session_t open_session; 2035 0 stevel crypto_session_id_t session; 2036 0 stevel int rv; 2037 0 stevel 2038 0 stevel if (copyin(arg, &open_session, sizeof (open_session)) != 0) 2039 0 stevel return (EFAULT); 2040 0 stevel 2041 0 stevel rv = crypto_open_session(dev, open_session.os_flags, 2042 0 stevel &session, open_session.os_provider_id); 2043 0 stevel if (rv != CRYPTO_SUCCESS) { 2044 0 stevel open_session.os_return_value = rv; 2045 0 stevel if (copyout(&open_session, arg, sizeof (open_session)) != 0) { 2046 0 stevel return (EFAULT); 2047 0 stevel } 2048 0 stevel return (0); 2049 0 stevel } 2050 0 stevel 2051 0 stevel open_session.os_session = session; 2052 0 stevel open_session.os_return_value = CRYPTO_SUCCESS; 2053 0 stevel 2054 0 stevel if (copyout(&open_session, arg, sizeof (open_session)) != 0) { 2055 0 stevel return (EFAULT); 2056 0 stevel } 2057 0 stevel return (0); 2058 0 stevel } 2059 0 stevel 2060 0 stevel /* 2061 0 stevel * This ioctl closes a session. 2062 0 stevel */ 2063 0 stevel /* ARGSUSED */ 2064 0 stevel static int 2065 0 stevel close_session(dev_t dev, caddr_t arg, int mode, int *rval) 2066 0 stevel { 2067 0 stevel crypto_close_session_t close_session; 2068 0 stevel int rv; 2069 0 stevel 2070 0 stevel if (copyin(arg, &close_session, sizeof (close_session)) != 0) 2071 0 stevel return (EFAULT); 2072 0 stevel 2073 0 stevel rv = crypto_close_session(dev, close_session.cs_session); 2074 904 mcpowers close_session.cs_return_value = rv; 2075 0 stevel if (copyout(&close_session, arg, sizeof (close_session)) != 0) { 2076 0 stevel return (EFAULT); 2077 0 stevel } 2078 0 stevel return (0); 2079 0 stevel } 2080 0 stevel 2081 0 stevel /* 2082 0 stevel * Copy data model dependent mechanism structure into a kernel mechanism 2083 0 stevel * structure. Allocate param storage if necessary. 2084 0 stevel */ 2085 0 stevel static boolean_t 2086 6424 krishna copyin_mech(int mode, crypto_session_data_t *sp, crypto_mechanism_t *in_mech, 2087 6424 krishna crypto_mechanism_t *out_mech, size_t *out_rctl_bytes, 2088 6424 krishna boolean_t *out_rctl_chk, int *out_rv, int *out_error) 2089 0 stevel { 2090 0 stevel STRUCT_DECL(crypto_mechanism, mech); 2091 0 stevel caddr_t param; 2092 0 stevel size_t param_len; 2093 6424 krishna size_t rctl_bytes = 0; 2094 0 stevel int error = 0; 2095 0 stevel int rv = 0; 2096 0 stevel 2097 0 stevel STRUCT_INIT(mech, mode); 2098 0 stevel bcopy(in_mech, STRUCT_BUF(mech), STRUCT_SIZE(mech)); 2099 0 stevel param = STRUCT_FGETP(mech, cm_param); 2100 0 stevel param_len = STRUCT_FGET(mech, cm_param_len); 2101 0 stevel out_mech->cm_type = STRUCT_FGET(mech, cm_type); 2102 0 stevel out_mech->cm_param = NULL; 2103 0 stevel out_mech->cm_param_len = 0; 2104 0 stevel if (param != NULL && param_len != 0) { 2105 0 stevel if (param_len > crypto_max_buffer_len) { 2106 0 stevel cmn_err(CE_NOTE, "copyin_mech: buffer greater than " 2107 0 stevel "%ld bytes, pid = %d", crypto_max_buffer_len, 2108 0 stevel curproc->p_pid); 2109 0 stevel rv = CRYPTO_ARGUMENTS_BAD; 2110 0 stevel goto out; 2111 0 stevel } 2112 0 stevel 2113 6424 krishna rv = CRYPTO_BUFFER_CHECK(sp, param_len, *out_rctl_chk); 2114 6424 krishna if (rv != CRYPTO_SUCCESS) { 2115 6424 krishna goto out; 2116 6424 krishna } 2117 6424 krishna rctl_bytes = param_len; 2118 6424 krishna 2119 0 stevel out_mech->cm_param = kmem_alloc(param_len, KM_SLEEP); 2120 0 stevel if (copyin((char *)param, out_mech->cm_param, param_len) != 0) { 2121 0 stevel kmem_free(out_mech->cm_param, param_len); 2122 0 stevel out_mech->cm_param = NULL; 2123 0 stevel error = EFAULT; 2124 0 stevel goto out; 2125 0 stevel } 2126 0 stevel out_mech->cm_param_len = param_len; 2127 0 stevel } 2128 0 stevel out: 2129 0 stevel *out_rctl_bytes = rctl_bytes; 2130 0 stevel *out_rv = rv; 2131 0 stevel *out_error = error; 2132 0 stevel return ((rv | error) ? B_FALSE : B_TRUE); 2133 0 stevel } 2134 0 stevel 2135 0 stevel /* 2136 0 stevel * Free key attributes when key type is CRYPTO_KEY_ATTR_LIST. 2137 0 stevel * The crypto_key structure is not freed. 2138 0 stevel */ 2139 0 stevel static void 2140 0 stevel crypto_free_key_attributes(crypto_key_t *key) 2141 0 stevel { 2142 0 stevel crypto_object_attribute_t *attrs; 2143 0 stevel size_t len = 0; 2144 0 stevel int i; 2145 0 stevel 2146 0 stevel ASSERT(key->ck_format == CRYPTO_KEY_ATTR_LIST); 2147 0 stevel if (key->ck_count == 0 || key->ck_attrs == NULL) 2148 0 stevel return; 2149 0 stevel 2150 0 stevel /* compute the size of the container */ 2151 0 stevel len = key->ck_count * sizeof (crypto_object_attribute_t); 2152 0 stevel 2153 0 stevel /* total up the size of all attributes in the container */ 2154 0 stevel for (i = 0; i < key->ck_count; i++) { 2155 0 stevel attrs = &key->ck_attrs[i]; 2156 0 stevel if (attrs->oa_value_len != 0 && 2157 0 stevel attrs->oa_value != NULL) { 2158 0 stevel len += roundup(attrs->oa_value_len, sizeof (caddr_t)); 2159 0 stevel } 2160 0 stevel } 2161 0 stevel 2162 0 stevel bzero(key->ck_attrs, len); 2163 0 stevel kmem_free(key->ck_attrs, len); 2164 0 stevel } 2165 0 stevel 2166 0 stevel /* 2167 0 stevel * Frees allocated storage in the key structure, but doesn't free 2168 0 stevel * the key structure. 2169 0 stevel */ 2170 0 stevel static void 2171 0 stevel free_crypto_key(crypto_key_t *key) 2172 0 stevel { 2173 0 stevel switch (key->ck_format) { 2174 0 stevel case CRYPTO_KEY_RAW: { 2175 0 stevel size_t len; 2176 0 stevel 2177 0 stevel if (key->ck_length == 0 || key->ck_data == NULL) 2178 0 stevel break; 2179 0 stevel 2180 0 stevel len = CRYPTO_BITS2BYTES(key->ck_length); 2181 0 stevel bzero(key->ck_data, len); 2182 0 stevel kmem_free(key->ck_data, len); 2183 0 stevel break; 2184 0 stevel } 2185 0 stevel 2186 0 stevel case CRYPTO_KEY_ATTR_LIST: 2187 0 stevel crypto_free_key_attributes(key); 2188 0 stevel break; 2189 0 stevel 2190 0 stevel default: 2191 0 stevel break; 2192 0 stevel } 2193 0 stevel } 2194 0 stevel 2195 0 stevel /* 2196 0 stevel * Copy in an array of crypto_object_attribute structures from user-space. 2197 0 stevel * Kernel memory is allocated for the array and the value of each attribute 2198 0 stevel * in the array. Since unprivileged users can specify the size of attributes, 2199 0 stevel * the amount of memory needed is charged against the 2200 0 stevel * project.max-crypto-memory resource control. 2201 0 stevel * 2202 0 stevel * Attribute values are copied in from user-space if copyin_value is set to 2203 0 stevel * B_TRUE. This routine returns B_TRUE if the copyin was successful. 2204 0 stevel */ 2205 0 stevel static boolean_t 2206 6424 krishna copyin_attributes(int mode, crypto_session_data_t *sp, 2207 6424 krishna uint_t count, caddr_t oc_attributes, 2208 0 stevel crypto_object_attribute_t **k_attrs_out, size_t *k_attrs_size_out, 2209 0 stevel caddr_t *u_attrs_out, int *out_rv, int *out_error, size_t *out_rctl_bytes, 2210 6424 krishna boolean_t *out_rctl_chk, boolean_t copyin_value) 2211 0 stevel { 2212 0 stevel STRUCT_DECL(crypto_object_attribute, oa); 2213 0 stevel crypto_object_attribute_t *k_attrs = NULL; 2214 0 stevel caddr_t attrs = NULL, ap, p, value; 2215 0 stevel caddr_t k_attrs_buf; 2216 0 stevel size_t k_attrs_len; 2217 0 stevel size_t k_attrs_buf_len = 0; 2218 0 stevel size_t k_attrs_total_len = 0; 2219 0 stevel size_t tmp_len; 2220 0 stevel size_t rctl_bytes = 0; 2221 0 stevel size_t len = 0; 2222 0 stevel size_t value_len; 2223 0 stevel int error = 0; 2224 0 stevel int rv = 0; 2225 0 stevel int i; 2226 0 stevel 2227 0 stevel STRUCT_INIT(oa, mode); 2228 0 stevel 2229 0 stevel if (count == 0) { 2230 0 stevel rv = CRYPTO_SUCCESS; 2231 0 stevel goto out; 2232 0 stevel } 2233 0 stevel 2234 0 stevel if (count > CRYPTO_MAX_ATTRIBUTE_COUNT) { 2235 0 stevel rv = CRYPTO_ARGUMENTS_BAD; 2236 0 stevel goto out; 2237 0 stevel } 2238 0 stevel 2239 0 stevel /* compute size of crypto_object_attribute array */ 2240 0 stevel len = count * STRUCT_SIZE(oa); 2241 0 stevel 2242 0 stevel /* this allocation is not charged against the user's resource limit */ 2243 0 stevel attrs = kmem_alloc(len, KM_SLEEP); 2244 0 stevel if (copyin(oc_attributes, attrs, len) != 0) { 2245 0 stevel error = EFAULT; 2246 0 stevel goto out; 2247 0 stevel } 2248 0 stevel 2249 0 stevel /* figure out how much memory to allocate for all of the attributes */ 2250 0 stevel ap = attrs; 2251 0 stevel for (i = 0; i < count; i++) { 2252 0 stevel bcopy(ap, STRUCT_BUF(oa), STRUCT_SIZE(oa)); 2253 0 stevel tmp_len = roundup(STRUCT_FGET(oa, oa_value_len), 2254 0 stevel sizeof (caddr_t)); 2255 0 stevel if (tmp_len > crypto_max_buffer_len) { 2256 0 stevel cmn_err(CE_NOTE, "copyin_attributes: buffer greater " 2257 0 stevel "than %ld bytes, pid = %d", crypto_max_buffer_len, 2258 0 stevel curproc->p_pid); 2259 0 stevel rv = CRYPTO_ARGUMENTS_BAD; 2260 0 stevel goto out; 2261 0 stevel } 2262 0 stevel if (STRUCT_FGETP(oa, oa_value) != NULL) 2263 0 stevel k_attrs_buf_len += tmp_len; 2264 0 stevel ap += STRUCT_SIZE(oa); 2265 0 stevel } 2266 0 stevel 2267 0 stevel k_attrs_len = count * sizeof (crypto_object_attribute_t); 2268 0 stevel k_attrs_total_len = k_attrs_buf_len + k_attrs_len; 2269 6424 krishna 2270 6424 krishna rv = CRYPTO_BUFFER_CHECK(sp, k_attrs_total_len, *out_rctl_chk); 2271 6424 krishna if (rv != CRYPTO_SUCCESS) { 2272 6424 krishna goto out; 2273 6424 krishna } 2274 6424 krishna rctl_bytes = k_attrs_total_len; 2275 0 stevel 2276 0 stevel /* one big allocation for everything */ 2277 0 stevel k_attrs = kmem_alloc(k_attrs_total_len, KM_SLEEP); 2278 0 stevel k_attrs_buf = (char *)k_attrs + k_attrs_len; 2279 0 stevel 2280 0 stevel ap = attrs; 2281 0 stevel p = k_attrs_buf; 2282 0 stevel for (i = 0; i < count; i++) { 2283 0 stevel bcopy(ap, STRUCT_BUF(oa), STRUCT_SIZE(oa)); 2284 0 stevel k_attrs[i].oa_type = STRUCT_FGET(oa, oa_type); 2285 0 stevel value = STRUCT_FGETP(oa, oa_value); 2286 0 stevel value_len = STRUCT_FGET(oa, oa_value_len); 2287 0 stevel if (value != NULL && value_len != 0 && copyin_value) { 2288 0 stevel if (copyin(value, p, value_len) != 0) { 2289 0 stevel kmem_free(k_attrs, k_attrs_total_len); 2290 0 stevel k_attrs = NULL; 2291 0 stevel error = EFAULT; 2292 0 stevel goto out; 2293 0 stevel } 2294 0 stevel } 2295 0 stevel 2296 292 mcpowers if (value != NULL) { 2297 292 mcpowers k_attrs[i].oa_value = p; 2298 292 mcpowers p += roundup(value_len, sizeof (caddr_t)); 2299 292 mcpowers } else { 2300 292 mcpowers k_attrs[i].oa_value = NULL; 2301 292 mcpowers } 2302 0 stevel k_attrs[i].oa_value_len = value_len; 2303 0 stevel ap += STRUCT_SIZE(oa); 2304 0 stevel } 2305 0 stevel out: 2306 0 stevel if (attrs != NULL) { 2307 0 stevel /* 2308 0 stevel * Free the array if there is a failure or the caller 2309 0 stevel * doesn't want the array to be returned. 2310 0 stevel */ 2311 0 stevel if (error != 0 || rv != CRYPTO_SUCCESS || u_attrs_out == NULL) { 2312 0 stevel kmem_free(attrs, len); 2313 0 stevel attrs = NULL; 2314 0 stevel } 2315 0 stevel } 2316 0 stevel 2317 0 stevel if (u_attrs_out != NULL) 2318 0 stevel *u_attrs_out = attrs; 2319 0 stevel if (k_attrs_size_out != NULL) 2320 0 stevel *k_attrs_size_out = k_attrs_total_len; 2321 0 stevel *k_attrs_out = k_attrs; 2322 0 stevel *out_rctl_bytes = rctl_bytes; 2323 0 stevel *out_rv = rv; 2324 0 stevel *out_error = error; 2325 0 stevel return ((rv | error) ? B_FALSE : B_TRUE); 2326 0 stevel } 2327 0 stevel 2328 0 stevel /* 2329 0 stevel * Copy data model dependent raw key into a kernel key 2330 0 stevel * structure. Checks key length or attribute lengths against 2331 0 stevel * resource controls before allocating memory. Returns B_TRUE 2332 0 stevel * if both error and rv are set to 0. 2333 0 stevel */ 2334 0 stevel static boolean_t 2335 6424 krishna copyin_key(int mode, crypto_session_data_t *sp, crypto_key_t *in_key, 2336 6424 krishna crypto_key_t *out_key, size_t *out_rctl_bytes, 2337 6424 krishna boolean_t *out_rctl_chk, int *out_rv, int *out_error) 2338 0 stevel { 2339 0 stevel STRUCT_DECL(crypto_key, key); 2340 0 stevel crypto_object_attribute_t *k_attrs = NULL; 2341 0 stevel size_t key_bits; 2342 0 stevel size_t key_bytes = 0; 2343 0 stevel size_t rctl_bytes = 0; 2344 0 stevel int count; 2345 0 stevel int error = 0; 2346 0 stevel int rv = CRYPTO_SUCCESS; 2347 0 stevel 2348 0 stevel STRUCT_INIT(key, mode); 2349 0 stevel bcopy(in_key, STRUCT_BUF(key), STRUCT_SIZE(key)); 2350 0 stevel out_key->ck_format = STRUCT_FGET(key, ck_format); 2351 0 stevel switch (out_key->ck_format) { 2352 0 stevel case CRYPTO_KEY_RAW: 2353 0 stevel key_bits = STRUCT_FGET(key, ck_length); 2354 0 stevel if (key_bits != 0) { 2355 0 stevel key_bytes = CRYPTO_BITS2BYTES(key_bits); 2356 0 stevel if (key_bytes > crypto_max_buffer_len) { 2357 0 stevel cmn_err(CE_NOTE, "copyin_key: buffer greater " 2358 0 stevel "than %ld bytes, pid = %d", 2359 0 stevel crypto_max_buffer_len, curproc->p_pid); 2360 0 stevel rv = CRYPTO_ARGUMENTS_BAD; 2361 0 stevel goto out; 2362 0 stevel } 2363 0 stevel 2364 6424 krishna rv = CRYPTO_BUFFER_CHECK(sp, key_bytes, 2365 6424 krishna *out_rctl_chk); 2366 0 stevel if (rv != CRYPTO_SUCCESS) { 2367 0 stevel goto out; 2368 0 stevel } 2369 6424 krishna rctl_bytes = key_bytes; 2370 0 stevel 2371 0 stevel out_key->ck_data = kmem_alloc(key_bytes, KM_SLEEP); 2372 0 stevel 2373 0 stevel if (copyin((char *)STRUCT_FGETP(key, ck_data), 2374 0 stevel out_key->ck_data, key_bytes) != 0) { 2375 0 stevel kmem_free(out_key->ck_data, key_bytes); 2376 0 stevel out_key->ck_data = NULL; 2377 0 stevel out_key->ck_length = 0; 2378 0 stevel error = EFAULT; 2379 0 stevel goto out; 2380 0 stevel } 2381 0 stevel } 2382 0 stevel out_key->ck_length = key_bits; 2383 0 stevel break; 2384 0 stevel 2385 0 stevel case CRYPTO_KEY_ATTR_LIST: 2386 0 stevel count = STRUCT_FGET(key, ck_count); 2387 0 stevel 2388 6424 krishna if (copyin_attributes(mode, sp, count, 2389 0 stevel (caddr_t)STRUCT_FGETP(key, ck_attrs), &k_attrs, NULL, NULL, 2390 6424 krishna &rv, &error, &rctl_bytes, out_rctl_chk, B_TRUE)) { 2391 0 stevel out_key->ck_count = count; 2392 0 stevel out_key->ck_attrs = k_attrs; 2393 0 stevel k_attrs = NULL; 2394 0 stevel } else { 2395 0 stevel out_key->ck_count = 0; 2396 0 stevel out_key->ck_attrs = NULL; 2397 0 stevel } 2398 0 stevel break; 2399 0 stevel 2400 0 stevel case CRYPTO_KEY_REFERENCE: 2401 0 stevel out_key->ck_obj_id = STRUCT_FGET(key, ck_obj_id); 2402 0 stevel break; 2403 0 stevel 2404 0 stevel default: 2405 0 stevel rv = CRYPTO_ARGUMENTS_BAD; 2406 0 stevel } 2407 0 stevel 2408 0 stevel out: 2409 0 stevel *out_rctl_bytes = rctl_bytes; 2410 0 stevel *out_rv = rv; 2411 0 stevel *out_error = error; 2412 0 stevel return ((rv | error) ? B_FALSE : B_TRUE); 2413 0 stevel } 2414 0 stevel 2415 0 stevel /* 2416 0 stevel * This routine does two things: 2417 0 stevel * 1. Given a crypto_minor structure and a session ID, it returns 2418 0 stevel * a valid session pointer. 2419 0 stevel * 2. It checks that the provider, to which the session has been opened, 2420 0 stevel * has not been removed. 2421 0 stevel */ 2422 0 stevel static boolean_t 2423 0 stevel get_session_ptr(crypto_session_id_t i, crypto_minor_t *cm, 2424 0 stevel crypto_session_data_t **session_ptr, int *out_error, int *out_rv) 2425 0 stevel { 2426 0 stevel crypto_session_data_t *sp = NULL; 2427 0 stevel int rv = CRYPTO_SESSION_HANDLE_INVALID; 2428 0 stevel int error = 0; 2429 0 stevel 2430 0 stevel mutex_enter(&cm->cm_lock); 2431 0 stevel if ((i < cm->cm_session_table_count) && 2432 0 stevel (cm->cm_session_table[i] != NULL)) { 2433 0 stevel sp = cm->cm_session_table[i]; 2434 0 stevel mutex_enter(&sp->sd_lock); 2435 0 stevel mutex_exit(&cm->cm_lock); 2436 0 stevel while (sp->sd_flags & CRYPTO_SESSION_IS_BUSY) { 2437 0 stevel if (cv_wait_sig(&sp->sd_cv, &sp->sd_lock) == 0) { 2438 0 stevel mutex_exit(&sp->sd_lock); 2439 0 stevel sp = NULL; 2440 0 stevel error = EINTR; 2441 0 stevel goto out; 2442 0 stevel } 2443 0 stevel } 2444 0 stevel 2445 0 stevel if (sp->sd_flags & CRYPTO_SESSION_IS_CLOSED) { 2446 0 stevel mutex_exit(&sp->sd_lock); 2447 0 stevel sp = NULL; 2448 0 stevel goto out; 2449 0 stevel } 2450 0 stevel 2451 0 stevel if (KCF_IS_PROV_REMOVED(sp->sd_provider)) { 2452 0 stevel mutex_exit(&sp->sd_lock); 2453 0 stevel sp = NULL; 2454 0 stevel rv = CRYPTO_DEVICE_ERROR; 2455 0 stevel goto out; 2456 0 stevel } 2457 0 stevel 2458 0 stevel rv = CRYPTO_SUCCESS; 2459 0 stevel sp->sd_flags |= CRYPTO_SESSION_IS_BUSY; 2460 0 stevel mutex_exit(&sp->sd_lock); 2461 0 stevel } else { 2462 0 stevel mutex_exit(&cm->cm_lock); 2463 0 stevel } 2464 0 stevel out: 2465 0 stevel *session_ptr = sp; 2466 0 stevel *out_error = error; 2467 0 stevel *out_rv = rv; 2468 0 stevel return ((rv == CRYPTO_SUCCESS && error == 0) ? B_TRUE : B_FALSE); 2469 0 stevel } 2470 0 stevel 2471 6424 krishna #define CRYPTO_SESSION_RELE(s) if ((s) != NULL) { \ 2472 0 stevel mutex_enter(&((s)->sd_lock)); \ 2473 0 stevel (s)->sd_flags &= ~CRYPTO_SESSION_IS_BUSY; \ 2474 0 stevel cv_broadcast(&(s)->sd_cv); \ 2475 0 stevel mutex_exit(&((s)->sd_lock)); \ 2476 0 stevel } 2477 0 stevel 2478 0 stevel /* ARGSUSED */ 2479 0 stevel static int 2480 0 stevel encrypt_init(dev_t dev, caddr_t arg, int mode, int *rval) 2481 0 stevel { 2482 0 stevel return (cipher_init(dev, arg, mode, crypto_encrypt_init_prov)); 2483 0 stevel } 2484 0 stevel 2485 0 stevel /* ARGSUSED */ 2486 0 stevel static int 2487 0 stevel decrypt_init(dev_t dev, caddr_t arg, int mode, int *rval) 2488 0 stevel { 2489 0 stevel return (cipher_init(dev, arg, mode, crypto_decrypt_init_prov)); 2490 0 stevel } 2491 0 stevel 2492 0 stevel /* 2493 904 mcpowers * umech is a mechanism structure that has been copied from user address 2494 904 mcpowers * space into kernel address space. Only one copyin has been done. 2495 904 mcpowers * The mechanism parameter, if non-null, still points to user address space. 2496 904 mcpowers * If the mechanism parameter contains pointers, they are pointers into 2497 904 mcpowers * user address space. 2498 904 mcpowers * 2499 904 mcpowers * kmech is a umech with all pointers and structures in kernel address space. 2500 904 mcpowers * 2501 904 mcpowers * This routine calls the provider's entry point to copy a umech parameter 2502 904 mcpowers * into kernel address space. Kernel memory is allocated by the provider. 2503 904 mcpowers */ 2504 904 mcpowers static int 2505 904 mcpowers crypto_provider_copyin_mech_param(kcf_provider_desc_t *pd, 2506 904 mcpowers crypto_mechanism_t *umech, crypto_mechanism_t *kmech, int mode, int *error) 2507 904 mcpowers { 2508 904 mcpowers crypto_mech_type_t provider_mech_type; 2509 904 mcpowers int rv; 2510 904 mcpowers 2511 904 mcpowers /* get the provider's mech number */ 2512 3708 krishna provider_mech_type = KCF_TO_PROV_MECHNUM(pd, umech->cm_type); 2513 904 mcpowers 2514 904 mcpowers kmech->cm_param = NULL; 2515 904 mcpowers kmech->cm_param_len = 0; 2516 904 mcpowers kmech->cm_type = provider_mech_type; 2517 904 mcpowers rv = KCF_PROV_COPYIN_MECH(pd, umech, kmech, error, mode); 2518 904 mcpowers kmech->cm_type = umech->cm_type; 2519 904 mcpowers 2520 904 mcpowers return (rv); 2521 904 mcpowers } 2522 904 mcpowers 2523 904 mcpowers /* 2524 904 mcpowers * umech is a mechanism structure that has been copied from user address 2525 904 mcpowers * space into kernel address space. Only one copyin has been done. 2526 904 mcpowers * The mechanism parameter, if non-null, still points to user address space. 2527 904 mcpowers * If the mechanism parameter contains pointers, they are pointers into 2528 904 mcpowers * user address space. 2529 904 mcpowers * 2530 904 mcpowers * kmech is a umech with all pointers and structures in kernel address space. 2531 904 mcpowers * 2532 904 mcpowers * This routine calls the provider's entry point to copy a kmech parameter 2533 904 mcpowers * into user address space using umech as a template containing 2534 904 mcpowers * user address pointers. 2535 904 mcpowers */ 2536 904 mcpowers static int 2537 904 mcpowers crypto_provider_copyout_mech_param(kcf_provider_desc_t *pd, 2538 904 mcpowers crypto_mechanism_t *kmech, crypto_mechanism_t *umech, int mode, int *error) 2539 904 mcpowers { 2540 904 mcpowers crypto_mech_type_t provider_mech_type; 2541 904 mcpowers int rv; 2542 904 mcpowers 2543 904 mcpowers /* get the provider's mech number */ 2544 3708 krishna provider_mech_type = KCF_TO_PROV_MECHNUM(pd, umech->cm_type); 2545 904 mcpowers 2546 904 mcpowers kmech->cm_type = provider_mech_type; 2547 904 mcpowers rv = KCF_PROV_COPYOUT_MECH(pd, kmech, umech, error, mode); 2548 904 mcpowers kmech->cm_type = umech->cm_type; 2549 904 mcpowers 2550 904 mcpowers return (rv); 2551 904 mcpowers } 2552 904 mcpowers 2553 904 mcpowers /* 2554 904 mcpowers * Call the provider's entry point to free kernel memory that has been 2555 904 mcpowers * allocated for the mechanism's parameter. 2556 904 mcpowers */ 2557 904 mcpowers static void 2558 904 mcpowers crypto_free_mech(kcf_provider_desc_t *pd, boolean_t allocated_by_crypto_module, 2559 904 mcpowers crypto_mechanism_t *mech) 2560 904 mcpowers { 2561 904 mcpowers crypto_mech_type_t provider_mech_type; 2562 904 mcpowers 2563 904 mcpowers if (allocated_by_crypto_module) { 2564 904 mcpowers if (mech->cm_param != NULL) 2565 904 mcpowers kmem_free(mech->cm_param, mech->cm_param_len); 2566 904 mcpowers } else { 2567 904 mcpowers /* get the provider's mech number */ 2568 3708 krishna provider_mech_type = KCF_TO_PROV_MECHNUM(pd, mech->cm_type); 2569 904 mcpowers 2570 904 mcpowers if (mech->cm_param != NULL && mech->cm_param_len != 0) { 2571 904 mcpowers mech->cm_type = provider_mech_type; 2572 904 mcpowers (void) KCF_PROV_FREE_MECH(pd, mech); 2573 904 mcpowers } 2574 904 mcpowers } 2575 904 mcpowers } 2576 904 mcpowers 2577 904 mcpowers /* 2578 0 stevel * ASSUMPTION: crypto_encrypt_init and crypto_decrypt_init 2579 0 stevel * structures are identical except for field names. 2580 0 stevel */ 2581 0 stevel static int 2582 904 mcpowers cipher_init(dev_t dev, caddr_t arg, int mode, int (*init)(crypto_provider_t, 2583 0 stevel crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, 2584 0 stevel crypto_ctx_template_t, crypto_context_t *, crypto_call_req_t *)) 2585 0 stevel { 2586 0 stevel STRUCT_DECL(crypto_encrypt_init, encrypt_init); 2587 904 mcpowers kcf_provider_desc_t *real_provider = NULL; 2588 0 stevel crypto_session_id_t session_id; 2589 0 stevel crypto_mechanism_t mech; 2590 0 stevel crypto_key_t key; 2591 0 stevel crypto_minor_t *cm; 2592 6424 krishna crypto_session_data_t *sp = NULL; 2593 0 stevel crypto_context_t cc; 2594 0 stevel crypto_ctx_t **ctxpp; 2595 0 stevel size_t mech_rctl_bytes = 0; 2596 6424 krishna boolean_t mech_rctl_chk = B_FALSE; 2597 0 stevel size_t key_rctl_bytes = 0; 2598 6424 krishna boolean_t key_rctl_chk = B_FALSE; 2599 1808 mcpowers int error = 0; 2600 1808 mcpowers int rv; 2601 1808 mcpowers boolean_t allocated_by_crypto_module = B_FALSE; 2602 1808 mcpowers crypto_func_group_t fg; 2603 0 stevel 2604 0 stevel STRUCT_INIT(encrypt_init, mode); 2605 0 stevel 2606 0 stevel if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2607 0 stevel cmn_err(CE_WARN, "cipher_init: failed holding minor"); 2608 0 stevel return (ENXIO); 2609 0 stevel } 2610 0 stevel 2611 0 stevel if (copyin(arg, STRUCT_BUF(encrypt_init), 2612 0 stevel STRUCT_SIZE(encrypt_init)) != 0) { 2613 0 stevel crypto_release_minor(cm); 2614 0 stevel return (EFAULT); 2615 0 stevel } 2616 0 stevel 2617 0 stevel mech.cm_param = NULL; 2618 0 stevel bzero(&key, sizeof (crypto_key_t)); 2619 0 stevel 2620 0 stevel session_id = STRUCT_FGET(encrypt_init, ei_session); 2621 0 stevel 2622 0 stevel if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 2623 6424 krishna goto out; 2624 0 stevel } 2625 0 stevel 2626 904 mcpowers bcopy(STRUCT_FADDR(encrypt_init, ei_mech), &mech.cm_type, 2627 904 mcpowers sizeof (crypto_mech_type_t)); 2628 0 stevel 2629 1808 mcpowers if (init == crypto_encrypt_init_prov) { 2630 1808 mcpowers fg = CRYPTO_FG_ENCRYPT; 2631 1808 mcpowers } else { 2632 1808 mcpowers fg = CRYPTO_FG_DECRYPT; 2633 1808 mcpowers } 2634 1808 mcpowers 2635 10444 Vladimir /* We need the key length for provider selection so copy it in now. */ 2636 6424 krishna if (!copyin_key(mode, sp, STRUCT_FADDR(encrypt_init, ei_key), &key, 2637 6424 krishna &key_rctl_bytes, &key_rctl_chk, &rv, &error)) { 2638 0 stevel goto out; 2639 10444 Vladimir } 2640 10444 Vladimir 2641 10444 Vladimir if ((rv = kcf_get_hardware_provider(mech.cm_type, &key, 2642 10444 Vladimir CRYPTO_MECH_INVALID, NULL, CHECK_RESTRICT_FALSE, sp->sd_provider, 2643 10444 Vladimir &real_provider, fg)) 2644 10444 Vladimir != CRYPTO_SUCCESS) { 2645 10444 Vladimir goto out; 2646 10444 Vladimir } 2647 10444 Vladimir 2648 10444 Vladimir rv = crypto_provider_copyin_mech_param(real_provider, 2649 10444 Vladimir STRUCT_FADDR(encrypt_init, ei_mech), &mech, mode, &error); 2650 10444 Vladimir 2651 10444 Vladimir if (rv == CRYPTO_NOT_SUPPORTED) { 2652 10444 Vladimir allocated_by_crypto_module = B_TRUE; 2653 10444 Vladimir if (!copyin_mech(mode, sp, STRUCT_FADDR(encrypt_init, ei_mech), 2654 10444 Vladimir &mech, &mech_rctl_bytes, &mech_rctl_chk, &rv, &error)) { 2655 10444 Vladimir goto out; 2656 10444 Vladimir } 2657 10444 Vladimir } else { 2658 10444 Vladimir if (rv != CRYPTO_SUCCESS) 2659 10444 Vladimir goto out; 2660 0 stevel } 2661 0 stevel 2662 0 stevel rv = (init)(real_provider, sp->sd_provider_session->ps_session, 2663 0 stevel &mech, &key, NULL, &cc, NULL); 2664 0 stevel 2665 0 stevel /* 2666 0 stevel * Check if a context already exists. If so, it means it is being 2667 0 stevel * abandoned. So, cancel it to avoid leaking it. 2668 0 stevel */ 2669 0 stevel ctxpp = (init == crypto_encrypt_init_prov) ? 2670 0 stevel &sp->sd_encr_ctx : &sp->sd_decr_ctx; 2671 0 stevel 2672 0 stevel if (*ctxpp != NULL) 2673 0 stevel CRYPTO_CANCEL_CTX(ctxpp); 2674 0 stevel *ctxpp = (rv == CRYPTO_SUCCESS) ? cc : NULL; 2675 904 mcpowers 2676 0 stevel out: 2677 6424 krishna CRYPTO_DECREMENT_RCTL_SESSION(sp, mech_rctl_bytes, mech_rctl_chk); 2678 6424 krishna CRYPTO_DECREMENT_RCTL_SESSION(sp, key_rctl_bytes, key_rctl_chk); 2679 6424 krishna CRYPTO_SESSION_RELE(sp); 2680 0 stevel crypto_release_minor(cm); 2681 0 stevel 2682 904 mcpowers if (real_provider != NULL) { 2683 904 mcpowers crypto_free_mech(real_provider, 2684 904 mcpowers allocated_by_crypto_module, &mech); 2685 904 mcpowers KCF_PROV_REFRELE(real_provider); 2686 904 mcpowers } 2687 0 stevel 2688 0 stevel free_crypto_key(&key); 2689 0 stevel 2690 0 stevel if (error != 0) 2691 904 mcpowers /* XXX free context */ 2692 0 stevel return (error); 2693 0 stevel 2694 0 stevel STRUCT_FSET(encrypt_init, ei_return_value, rv); 2695 0 stevel if (copyout(STRUCT_BUF(encrypt_init), arg, 2696 0 stevel STRUCT_SIZE(encrypt_init)) != 0) { 2697 904 mcpowers /* XXX free context */ 2698 0 stevel return (EFAULT); 2699 0 stevel } 2700 0 stevel return (0); 2701 0 stevel } 2702 0 stevel 2703 0 stevel /* ARGSUSED */ 2704 0 stevel static int 2705 0 stevel encrypt(dev_t dev, caddr_t arg, int mode, int *rval) 2706 0 stevel { 2707 0 stevel return (cipher(dev, arg, mode, crypto_encrypt_single)); 2708 0 stevel } 2709 0 stevel 2710 0 stevel /* ARGSUSED */ 2711 0 stevel static int 2712 0 stevel decrypt(dev_t dev, caddr_t arg, int mode, int *rval) 2713 0 stevel { 2714 0 stevel return (cipher(dev, arg, mode, crypto_decrypt_single)); 2715 0 stevel } 2716 0 stevel 2717 0 stevel /* 2718 0 stevel * ASSUMPTION: crypto_encrypt and crypto_decrypt structures 2719 0 stevel * are identical except for field names. 2720 0 stevel */ 2721 0 stevel static int 2722 0 stevel cipher(dev_t dev, caddr_t arg, int mode, 2723 0 stevel int (*single)(crypto_context_t, crypto_data_t *, crypto_data_t *, 2724 0 stevel crypto_call_req_t *)) 2725 0 stevel { 2726 0 stevel STRUCT_DECL(crypto_encrypt, encrypt); 2727 0 stevel crypto_session_id_t session_id; 2728 0 stevel crypto_minor_t *cm; 2729 6424 krishna crypto_session_data_t *sp = NULL; 2730 0 stevel crypto_ctx_t **ctxpp; 2731 0 stevel crypto_data_t data, encr; 2732 0 stevel size_t datalen, encrlen, need = 0; 2733 4632 mcpowers boolean_t do_inplace; 2734 0 stevel char *encrbuf; 2735 0 stevel int error = 0; 2736 0 stevel int rv; 2737 6424 krishna boolean_t rctl_chk = B_FALSE; 2738 0 stevel 2739 0 stevel STRUCT_INIT(encrypt, mode); 2740 0 stevel 2741 0 stevel if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2742 0 stevel cmn_err(CE_WARN, "cipher: failed holding minor"); 2743 0 stevel return (ENXIO); 2744 0 stevel } 2745 0 stevel 2746 0 stevel if (copyin(arg, STRUCT_BUF(encrypt), STRUCT_SIZE(encrypt)) != 0) { 2747 0 stevel crypto_release_minor(cm); 2748 0 stevel return (EFAULT); 2749 0 stevel } 2750 0 stevel 2751 0 stevel data.cd_raw.iov_base = NULL; 2752 0 stevel encr.cd_raw.iov_base = NULL; 2753 0 stevel 2754 0 stevel datalen = STRUCT_FGET(encrypt, ce_datalen); 2755 0 stevel encrlen = STRUCT_FGET(encrypt, ce_encrlen); 2756 0 stevel 2757 0 stevel /* 2758 0 stevel * Don't allocate output buffer unless both buffer pointer and 2759 0 stevel * buffer length are not NULL or 0 (length). 2760 0 stevel */ 2761 0 stevel encrbuf = STRUCT_FGETP(encrypt, ce_encrbuf); 2762 0 stevel if (encrbuf == NULL || encrlen == 0) { 2763 0 stevel encrlen = 0; 2764 0 stevel } 2765 0 stevel 2766 0 stevel if (datalen > crypto_max_buffer_len || 2767 0 stevel encrlen > crypto_max_buffer_len) { 2768 0 stevel cmn_err(CE_NOTE, "cipher: buffer greater than %ld bytes, " 2769 0 stevel "pid = %d", crypto_max_buffer_len, curproc->p_pid); 2770 0 stevel rv = CRYPTO_ARGUMENTS_BAD; 2771 0 stevel goto release_minor; 2772 0 stevel } 2773 0 stevel 2774 6867 krishna session_id = STRUCT_FGET(encrypt, ce_session); 2775 6867 krishna 2776 6867 krishna if (!get_session_ptr(session_id, cm, &sp, &error, &rv)) { 2777 6867 krishna goto release_minor; 2778 6867 krishna } 2779 6867 krishna 2780 4632 mcpowers do_inplace = (STRUCT_FGET(encrypt, ce_flags) & 2781 4632 mcpowers CRYPTO_INPLACE_OPERATION) != 0; 2782 4632 mcpowers need = do_inplace ? datalen : datalen + encrlen; 2783 6424 krishna 2784 6424 krishna if ((rv = CRYPTO_BUFFER_CHECK(sp, need, rctl_chk)) != 2785 6424 krishna CRYPTO_SUCCESS) { 2786 0 stevel need = 0; 2787 0 stevel goto release_minor; 2788 0 stevel } 2789 0 stevel 2790 0 stevel INIT_RAW_CRYPTO_DATA(data, datalen); 2791 0 stevel data.cd_miscdata = NULL; 2792 0 stevel 2793 0 stevel if (datalen != 0 && copyin(STRUCT_FGETP(encrypt, ce_databuf), 2794 0 stevel data.cd_raw.iov_base, datalen) != 0) { 2795 0 stevel error = EFAULT; 2796 0 stevel goto release_minor; 2797 0 stevel } 2798 0 stevel 2799 4632 mcpowers if (do_inplace) { 2800 4632 mcpowers /* set out = in for in-place */ 2801 4632 mcpowers encr = data; 2802 4632 mcpowers } else { 2803 4632 mcpowers INIT_RAW_CRYPTO_DATA(encr, encrlen); 2804 0 stevel } 2805 0 stevel 2806 0 stevel ctxpp = (single == crypto_encrypt_single) ? 2807 0 stevel &sp->sd_encr_ctx : &sp->sd_decr_ctx; 2808 0 stevel 2809 4632 mcpowers if (do_inplace) 2810 11030 opensolaris /* specify in-place buffers with output = NULL */ 2811 4632 mcpowers rv = (single)(*ctxpp, &encr, NULL, NULL); 2812 4632 mcpowers else 2813 4632 mcpowers rv = (single)(*ctxpp, &data, &encr, NULL); 2814 11030 opensolaris 2815 0 stevel if (KCF_CONTEXT_DONE(rv)) 2816 0 stevel *ctxpp = NULL; 2817 0 stevel 2818 0 stevel if (rv == CRYPTO_SUCCESS) { 2819 0 stevel ASSERT(encr.cd_length <= encrlen); 2820 0 stevel if (encr.cd_length != 0 && copyout(encr.cd_raw.iov_base, 2821 0 stevel encrbuf, encr.cd_length) != 0) { 2822 0 stevel error = EFAULT; 2823 0 stevel goto release_minor; 2824 0 stevel } 2825 0 stevel STRUCT_FSET(encrypt, ce_encrlen, encr.cd_length); 2826 0 stevel } 2827 0 stevel 2828 0 stevel if (rv == CRYPTO_BUFFER_TOO_SMALL) { 2829 0 stevel /* 2830 0 stevel * The providers return CRYPTO_BUFFER_TOO_SMALL even for case 1 2831 0 stevel * of section 11.2 of the pkcs11 spec. We catch it here and 2832 0 stevel * provide the correct pkcs11 return value. 2833 0 stevel */ 2834 0 stevel if (STRUCT_FGETP(encrypt, ce_encrbuf) == NULL) 2835 0 stevel rv = CRYPTO_SUCCESS; 2836 0 stevel STRUCT_FSET(encrypt, ce_encrlen, encr.cd_length); 2837 0 stevel } 2838 0 stevel 2839 0 stevel release_minor: 2840 6424 krishna CRYPTO_DECREMENT_RCTL_SESSION(sp, need, rctl_chk); 2841 6424 krishna CRYPTO_SESSION_RELE(sp); 2842 0 stevel crypto_release_minor(cm); 2843 0 stevel 2844 0 stevel if (data.cd_raw.iov_base != NULL) 2845 0 stevel kmem_free(data.cd_raw.iov_base, datalen); 2846 0 stevel 2847 4632 mcpowers if (!do_inplace && encr.cd_raw.iov_base != NULL) 2848 0 stevel kmem_free(encr.cd_raw.iov_base, encrlen); 2849 0 stevel 2850 0 stevel if (error != 0) 2851 0 stevel return (error); 2852 0 stevel 2853 0 stevel STRUCT_FSET(encrypt, ce_return_value, rv); 2854 0 stevel if (copyout(STRUCT_BUF(encrypt), arg, STRUCT_SIZE(encrypt)) != 0) { 2855 0 stevel return (EFAULT); 2856 0 stevel } 2857 0 stevel return (0); 2858 0 stevel } 2859 0 stevel 2860 0 stevel /* ARGSUSED */ 2861 0 stevel static int 2862 0 stevel encrypt_update(dev_t dev, caddr_t arg, int mode, int *rval) 2863 0 stevel { 2864 0 stevel return (cipher_update(dev, arg, mode, crypto_encrypt_update)); 2865 0 stevel } 2866 0 stevel 2867 0 stevel /* ARGSUSED */ 2868 0 stevel static int 2869 0 stevel decrypt_update(dev_t dev, caddr_t arg, int mode, int *rval) 2870 0 stevel { 2871 0 stevel return (cipher_update(dev, arg, mode, crypto_decrypt_update)); 2872 0 stevel } 2873 0 stevel 2874 0 stevel /* 2875 0 stevel * ASSUMPTION: crypto_encrypt_update and crypto_decrypt_update 2876 0 stevel * structures are identical except for field names. 2877 0 stevel */ 2878 0 stevel static int 2879 0 stevel cipher_update(dev_t dev, caddr_t arg, int mode, 2880 0 stevel int (*update)(crypto_context_t, crypto_data_t *, crypto_data_t *, 2881 0 stevel crypto_call_req_t *)) 2882 0 stevel { 2883 0 stevel STRUCT_DECL(crypto_encrypt_update, encrypt_update); 2884 0 stevel crypto_session_id_t session_id; 2885 0 stevel crypto_minor_t *cm; 2886 6424 krishna crypto_session_data_t *sp = NULL; 2887 0 stevel crypto_ctx_t **ctxpp; 2888 0 stevel crypto_data_t data, encr; 2889 0 stevel size_t datalen, encrlen, need = 0; 2890 11030 opensolaris boolean_t do_inplace; 2891 0 stevel char *encrbuf; 2892 0 stevel int error = 0; 2893 0 stevel int rv; 2894 6424 krishna boolean_t rctl_chk = B_FALSE; 2895 0 stevel 2896 0 stevel STRUCT_INIT(encrypt_update, mode); 2897 0 stevel 2898 0 stevel if ((cm = crypto_hold_minor(getminor(dev))) == NULL) { 2899 0 stevel cmn_err(CE_WARN, "cipher_update: failed holding minor"); 2900 0 stevel return (ENXIO); 2901 0 stevel } 2902 0 stevel 2903 0 stevel if (copyin(arg, STRUCT_BUF(encrypt_update), 2904 0 stevel STRUCT_SIZE(encrypt_update)) != 0) { 2905 0 stevel crypto_release_minor(cm); 2906 0 stevel return (EFAULT); 2907 0 stevel } 2908 0 stevel 2909 0 stevel data.cd_raw.iov_base = NULL; 2910 0 stevel encr.cd_raw.iov_base = NULL; 2911 0 stevel 2912 0