1 1.126 riastrad /* $NetBSD: cryptodev.c,v 1.126 2025/04/17 12:59:58 riastradh Exp $ */ 2 1.4 jonathan /* $FreeBSD: src/sys/opencrypto/cryptodev.c,v 1.4.2.4 2003/06/03 00:09:02 sam Exp $ */ 3 1.1 jonathan /* $OpenBSD: cryptodev.c,v 1.53 2002/07/10 22:21:30 mickey Exp $ */ 4 1.1 jonathan 5 1.36 tls /*- 6 1.36 tls * Copyright (c) 2008 The NetBSD Foundation, Inc. 7 1.36 tls * All rights reserved. 8 1.36 tls * 9 1.36 tls * This code is derived from software contributed to The NetBSD Foundation 10 1.36 tls * by Coyote Point Systems, Inc. 11 1.36 tls * 12 1.36 tls * Redistribution and use in source and binary forms, with or without 13 1.36 tls * modification, are permitted provided that the following conditions 14 1.36 tls * are met: 15 1.36 tls * 1. Redistributions of source code must retain the above copyright 16 1.36 tls * notice, this list of conditions and the following disclaimer. 17 1.36 tls * 2. Redistributions in binary form must reproduce the above copyright 18 1.36 tls * notice, this list of conditions and the following disclaimer in the 19 1.36 tls * documentation and/or other materials provided with the distribution. 20 1.36 tls * 21 1.36 tls * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22 1.36 tls * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 1.36 tls * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 1.36 tls * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25 1.36 tls * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 1.36 tls * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 1.36 tls * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 1.36 tls * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 1.36 tls * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 1.36 tls * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 1.36 tls * POSSIBILITY OF SUCH DAMAGE. 32 1.36 tls */ 33 1.36 tls 34 1.1 jonathan /* 35 1.1 jonathan * Copyright (c) 2001 Theo de Raadt 36 1.1 jonathan * 37 1.1 jonathan * Redistribution and use in source and binary forms, with or without 38 1.1 jonathan * modification, are permitted provided that the following conditions 39 1.1 jonathan * are met: 40 1.1 jonathan * 41 1.1 jonathan * 1. Redistributions of source code must retain the above copyright 42 1.1 jonathan * notice, this list of conditions and the following disclaimer. 43 1.1 jonathan * 2. Redistributions in binary form must reproduce the above copyright 44 1.1 jonathan * notice, this list of conditions and the following disclaimer in the 45 1.1 jonathan * documentation and/or other materials provided with the distribution. 46 1.1 jonathan * 3. The name of the author may not be used to endorse or promote products 47 1.1 jonathan * derived from this software without specific prior written permission. 48 1.1 jonathan * 49 1.1 jonathan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 50 1.1 jonathan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 51 1.1 jonathan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 52 1.1 jonathan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 53 1.1 jonathan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 54 1.1 jonathan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 55 1.1 jonathan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 56 1.1 jonathan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 57 1.1 jonathan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 58 1.1 jonathan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 59 1.1 jonathan * 60 1.1 jonathan * Effort sponsored in part by the Defense Advanced Research Projects 61 1.1 jonathan * Agency (DARPA) and Air Force Research Laboratory, Air Force 62 1.1 jonathan * Materiel Command, USAF, under agreement number F30602-01-2-0537. 63 1.1 jonathan * 64 1.1 jonathan */ 65 1.1 jonathan 66 1.1 jonathan #include <sys/cdefs.h> 67 1.126 riastrad __KERNEL_RCSID(0, "$NetBSD: cryptodev.c,v 1.126 2025/04/17 12:59:58 riastradh Exp $"); 68 1.1 jonathan 69 1.1 jonathan #include <sys/param.h> 70 1.1 jonathan #include <sys/systm.h> 71 1.36 tls #include <sys/kmem.h> 72 1.1 jonathan #include <sys/malloc.h> 73 1.1 jonathan #include <sys/mbuf.h> 74 1.29 tls #include <sys/pool.h> 75 1.1 jonathan #include <sys/sysctl.h> 76 1.1 jonathan #include <sys/file.h> 77 1.1 jonathan #include <sys/filedesc.h> 78 1.1 jonathan #include <sys/errno.h> 79 1.2 jonathan #include <sys/md5.h> 80 1.1 jonathan #include <sys/sha1.h> 81 1.1 jonathan #include <sys/conf.h> 82 1.1 jonathan #include <sys/device.h> 83 1.21 elad #include <sys/kauth.h> 84 1.36 tls #include <sys/select.h> 85 1.36 tls #include <sys/poll.h> 86 1.37 dogcow #include <sys/atomic.h> 87 1.48 christos #include <sys/stat.h> 88 1.70 pgoyette #include <sys/module.h> 89 1.99 pgoyette #include <sys/compat_stub.h> 90 1.1 jonathan 91 1.70 pgoyette #ifdef _KERNEL_OPT 92 1.33 tls #include "opt_ocf.h" 93 1.55 drochner #include "opt_compat_netbsd.h" 94 1.70 pgoyette #endif 95 1.70 pgoyette 96 1.1 jonathan #include <opencrypto/cryptodev.h> 97 1.99 pgoyette #include <opencrypto/ocryptodev.h> 98 1.55 drochner #include <opencrypto/cryptodev_internal.h> 99 1.1 jonathan #include <opencrypto/xform.h> 100 1.1 jonathan 101 1.84 christos #include "ioconf.h" 102 1.84 christos 103 1.92 knakahar kmutex_t cryptodev_mtx; 104 1.89 knakahar 105 1.1 jonathan struct csession { 106 1.1 jonathan TAILQ_ENTRY(csession) next; 107 1.1 jonathan u_int64_t sid; 108 1.1 jonathan u_int32_t ses; 109 1.1 jonathan 110 1.46 darran u_int32_t cipher; /* note: shares name space in crd_alg */ 111 1.54 drochner const struct enc_xform *txform; 112 1.46 darran u_int32_t mac; /* note: shares name space in crd_alg */ 113 1.54 drochner const struct auth_hash *thash; 114 1.46 darran u_int32_t comp_alg; /* note: shares name space in crd_alg */ 115 1.54 drochner const struct comp_algo *tcomp; 116 1.1 jonathan 117 1.26 christos void * key; 118 1.1 jonathan int keylen; 119 1.1 jonathan u_char tmp_iv[EALG_MAX_BLOCK_LEN]; 120 1.1 jonathan 121 1.26 christos void * mackey; 122 1.1 jonathan int mackeylen; 123 1.1 jonathan u_char tmp_mac[CRYPTO_MAX_MAC_LEN]; 124 1.1 jonathan 125 1.29 tls struct iovec iovec[1]; /* user requests never have more */ 126 1.1 jonathan struct uio uio; 127 1.1 jonathan int error; 128 1.1 jonathan }; 129 1.1 jonathan 130 1.1 jonathan struct fcrypt { 131 1.1 jonathan TAILQ_HEAD(csessionlist, csession) csessions; 132 1.36 tls TAILQ_HEAD(crprethead, cryptop) crp_ret_mq; 133 1.36 tls TAILQ_HEAD(krprethead, cryptkop) crp_ret_mkq; 134 1.1 jonathan int sesn; 135 1.36 tls struct selinfo sinfo; 136 1.36 tls u_int32_t requestid; 137 1.48 christos struct timespec atime; 138 1.48 christos struct timespec mtime; 139 1.48 christos struct timespec btime; 140 1.1 jonathan }; 141 1.1 jonathan 142 1.29 tls /* For our fixed-size allocations */ 143 1.38 rmind static struct pool fcrpl; 144 1.38 rmind static struct pool csepl; 145 1.1 jonathan 146 1.1 jonathan /* Declaration of master device (fd-cloning/ctxt-allocating) entrypoints */ 147 1.16 christos static int cryptoopen(dev_t dev, int flag, int mode, struct lwp *l); 148 1.1 jonathan static int cryptoread(dev_t dev, struct uio *uio, int ioflag); 149 1.1 jonathan static int cryptowrite(dev_t dev, struct uio *uio, int ioflag); 150 1.16 christos static int cryptoselect(dev_t dev, int rw, struct lwp *l); 151 1.1 jonathan 152 1.74 pgoyette static int crypto_refcount = 0; /* Prevent detaching while in use */ 153 1.74 pgoyette 154 1.1 jonathan /* Declaration of cloned-device (per-ctxt) entrypoints */ 155 1.36 tls static int cryptof_read(struct file *, off_t *, struct uio *, 156 1.42 christos kauth_cred_t, int); 157 1.36 tls static int cryptof_write(struct file *, off_t *, struct uio *, 158 1.42 christos kauth_cred_t, int); 159 1.36 tls static int cryptof_ioctl(struct file *, u_long, void *); 160 1.36 tls static int cryptof_close(struct file *); 161 1.36 tls static int cryptof_poll(struct file *, int); 162 1.48 christos static int cryptof_stat(struct file *, struct stat *); 163 1.1 jonathan 164 1.12 christos static const struct fileops cryptofops = { 165 1.97 christos .fo_name = "cryptof", 166 1.47 ad .fo_read = cryptof_read, 167 1.47 ad .fo_write = cryptof_write, 168 1.47 ad .fo_ioctl = cryptof_ioctl, 169 1.47 ad .fo_fcntl = fnullop_fcntl, 170 1.47 ad .fo_poll = cryptof_poll, 171 1.48 christos .fo_stat = cryptof_stat, 172 1.47 ad .fo_close = cryptof_close, 173 1.47 ad .fo_kqfilter = fnullop_kqfilter, 174 1.51 dsl .fo_restart = fnullop_restart, 175 1.1 jonathan }; 176 1.1 jonathan 177 1.46 darran struct csession *cryptodev_csefind(struct fcrypt *, u_int); 178 1.1 jonathan static struct csession *csefind(struct fcrypt *, u_int); 179 1.1 jonathan static int csedelete(struct fcrypt *, struct csession *); 180 1.1 jonathan static struct csession *cseadd(struct fcrypt *, struct csession *); 181 1.42 christos static struct csession *csecreate(struct fcrypt *, u_int64_t, void *, 182 1.46 darran u_int64_t, void *, u_int64_t, u_int32_t, u_int32_t, u_int32_t, 183 1.54 drochner const struct enc_xform *, const struct auth_hash *, 184 1.54 drochner const struct comp_algo *); 185 1.121 riastrad static void csefree(struct csession *); 186 1.1 jonathan 187 1.1 jonathan static int cryptodev_key(struct crypt_kop *); 188 1.36 tls static int cryptodev_mkey(struct fcrypt *, struct crypt_n_kop *, int); 189 1.121 riastrad static void cryptodev_msessionfin(struct fcrypt *, int, u_int32_t *); 190 1.1 jonathan 191 1.117 riastrad static void cryptodev_cb(struct cryptop *); 192 1.117 riastrad static void cryptodevkey_cb(struct cryptkop *); 193 1.1 jonathan 194 1.117 riastrad static void cryptodev_mcb(struct cryptop *); 195 1.117 riastrad static void cryptodevkey_mcb(struct cryptkop *); 196 1.36 tls 197 1.36 tls static int cryptodev_getmstatus(struct fcrypt *, struct crypt_result *, 198 1.42 christos int); 199 1.36 tls static int cryptodev_getstatus(struct fcrypt *, struct crypt_result *); 200 1.36 tls 201 1.9 jonathan /* 202 1.9 jonathan * sysctl-able control variables for /dev/crypto now defined in crypto.c: 203 1.126 riastrad * crypto_usercrypto, crypto_userasymcrypto, crypto_devallowsoft. 204 1.9 jonathan */ 205 1.1 jonathan 206 1.1 jonathan /* ARGSUSED */ 207 1.1 jonathan int 208 1.35 ad cryptof_read(file_t *fp, off_t *poff, 209 1.25 christos struct uio *uio, kauth_cred_t cred, int flags) 210 1.1 jonathan { 211 1.42 christos return EIO; 212 1.1 jonathan } 213 1.1 jonathan 214 1.1 jonathan /* ARGSUSED */ 215 1.1 jonathan int 216 1.35 ad cryptof_write(file_t *fp, off_t *poff, 217 1.25 christos struct uio *uio, kauth_cred_t cred, int flags) 218 1.1 jonathan { 219 1.42 christos return EIO; 220 1.1 jonathan } 221 1.1 jonathan 222 1.1 jonathan /* ARGSUSED */ 223 1.1 jonathan int 224 1.36 tls cryptof_ioctl(struct file *fp, u_long cmd, void *data) 225 1.1 jonathan { 226 1.81 matt struct fcrypt *fcr = fp->f_fcrypt; 227 1.1 jonathan struct csession *cse; 228 1.1 jonathan struct session_op *sop; 229 1.36 tls struct session_n_op *snop; 230 1.1 jonathan struct crypt_op *cop; 231 1.36 tls struct crypt_mop *mop; 232 1.36 tls struct crypt_mkop *mkop; 233 1.36 tls struct crypt_n_op *cnop; 234 1.36 tls struct crypt_n_kop *knop; 235 1.36 tls struct crypt_sgop *sgop; 236 1.36 tls struct crypt_sfop *sfop; 237 1.36 tls struct cryptret *crypt_ret; 238 1.36 tls struct crypt_result *crypt_res; 239 1.1 jonathan u_int32_t ses; 240 1.36 tls u_int32_t *sesid; 241 1.1 jonathan int error = 0; 242 1.36 tls size_t count; 243 1.1 jonathan 244 1.29 tls /* backwards compatibility */ 245 1.35 ad file_t *criofp; 246 1.29 tls struct fcrypt *criofcr; 247 1.29 tls int criofd; 248 1.29 tls 249 1.92 knakahar mutex_enter(&cryptodev_mtx); 250 1.48 christos getnanotime(&fcr->atime); 251 1.92 knakahar mutex_exit(&cryptodev_mtx); 252 1.48 christos 253 1.36 tls switch (cmd) { 254 1.29 tls case CRIOGET: /* XXX deprecated, remove after 5.0 */ 255 1.36 tls if ((error = fd_allocfile(&criofp, &criofd)) != 0) 256 1.36 tls return error; 257 1.36 tls criofcr = pool_get(&fcrpl, PR_WAITOK); 258 1.92 knakahar mutex_enter(&cryptodev_mtx); 259 1.36 tls TAILQ_INIT(&criofcr->csessions); 260 1.36 tls TAILQ_INIT(&criofcr->crp_ret_mq); 261 1.36 tls TAILQ_INIT(&criofcr->crp_ret_mkq); 262 1.36 tls selinit(&criofcr->sinfo); 263 1.36 tls 264 1.29 tls /* 265 1.29 tls * Don't ever return session 0, to allow detection of 266 1.29 tls * failed creation attempts with multi-create ioctl. 267 1.29 tls */ 268 1.36 tls criofcr->sesn = 1; 269 1.36 tls criofcr->requestid = 1; 270 1.74 pgoyette crypto_refcount++; 271 1.92 knakahar mutex_exit(&cryptodev_mtx); 272 1.36 tls (void)fd_clone(criofp, criofd, (FREAD|FWRITE), 273 1.29 tls &cryptofops, criofcr); 274 1.36 tls *(u_int32_t *)data = criofd; 275 1.29 tls return error; 276 1.36 tls break; 277 1.1 jonathan case CIOCGSESSION: 278 1.1 jonathan sop = (struct session_op *)data; 279 1.36 tls error = cryptodev_session(fcr, sop); 280 1.36 tls break; 281 1.36 tls case CIOCNGSESSION: 282 1.36 tls sgop = (struct crypt_sgop *)data; 283 1.93 knakahar if (sgop->count <= 0 284 1.93 knakahar || SIZE_MAX / sizeof(struct session_n_op) <= sgop->count) { 285 1.93 knakahar error = EINVAL; 286 1.93 knakahar break; 287 1.93 knakahar } 288 1.36 tls snop = kmem_alloc((sgop->count * 289 1.36 tls sizeof(struct session_n_op)), KM_SLEEP); 290 1.36 tls error = copyin(sgop->sessions, snop, sgop->count * 291 1.36 tls sizeof(struct session_n_op)); 292 1.36 tls if (error) { 293 1.36 tls goto mbail; 294 1.1 jonathan } 295 1.1 jonathan 296 1.92 knakahar mutex_enter(&cryptodev_mtx); 297 1.48 christos fcr->mtime = fcr->atime; 298 1.92 knakahar mutex_exit(&cryptodev_mtx); 299 1.36 tls error = cryptodev_msession(fcr, snop, sgop->count); 300 1.36 tls if (error) { 301 1.36 tls goto mbail; 302 1.1 jonathan } 303 1.1 jonathan 304 1.36 tls error = copyout(snop, sgop->sessions, sgop->count * 305 1.42 christos sizeof(struct session_n_op)); 306 1.36 tls mbail: 307 1.39 tls kmem_free(snop, sgop->count * sizeof(struct session_n_op)); 308 1.1 jonathan break; 309 1.1 jonathan case CIOCFSESSION: 310 1.92 knakahar mutex_enter(&cryptodev_mtx); 311 1.48 christos fcr->mtime = fcr->atime; 312 1.1 jonathan ses = *(u_int32_t *)data; 313 1.1 jonathan cse = csefind(fcr, ses); 314 1.56 drochner if (cse == NULL) { 315 1.92 knakahar mutex_exit(&cryptodev_mtx); 316 1.42 christos return EINVAL; 317 1.56 drochner } 318 1.1 jonathan csedelete(fcr, cse); 319 1.92 knakahar mutex_exit(&cryptodev_mtx); 320 1.121 riastrad csefree(cse); 321 1.1 jonathan break; 322 1.36 tls case CIOCNFSESSION: 323 1.92 knakahar mutex_enter(&cryptodev_mtx); 324 1.48 christos fcr->mtime = fcr->atime; 325 1.92 knakahar mutex_exit(&cryptodev_mtx); 326 1.36 tls sfop = (struct crypt_sfop *)data; 327 1.93 knakahar if (sfop->count <= 0 328 1.93 knakahar || SIZE_MAX / sizeof(u_int32_t) <= sfop->count) { 329 1.93 knakahar error = EINVAL; 330 1.93 knakahar break; 331 1.93 knakahar } 332 1.36 tls sesid = kmem_alloc((sfop->count * sizeof(u_int32_t)), 333 1.42 christos KM_SLEEP); 334 1.42 christos error = copyin(sfop->sesid, sesid, 335 1.42 christos (sfop->count * sizeof(u_int32_t))); 336 1.36 tls if (!error) { 337 1.121 riastrad cryptodev_msessionfin(fcr, sfop->count, sesid); 338 1.36 tls } 339 1.36 tls kmem_free(sesid, (sfop->count * sizeof(u_int32_t))); 340 1.36 tls break; 341 1.1 jonathan case CIOCCRYPT: 342 1.92 knakahar mutex_enter(&cryptodev_mtx); 343 1.48 christos fcr->mtime = fcr->atime; 344 1.1 jonathan cop = (struct crypt_op *)data; 345 1.1 jonathan cse = csefind(fcr, cop->ses); 346 1.92 knakahar mutex_exit(&cryptodev_mtx); 347 1.18 christos if (cse == NULL) { 348 1.90 knakahar DPRINTF("csefind failed\n"); 349 1.42 christos return EINVAL; 350 1.18 christos } 351 1.35 ad error = cryptodev_op(cse, cop, curlwp); 352 1.90 knakahar DPRINTF("cryptodev_op error = %d\n", error); 353 1.1 jonathan break; 354 1.36 tls case CIOCNCRYPTM: 355 1.92 knakahar mutex_enter(&cryptodev_mtx); 356 1.48 christos fcr->mtime = fcr->atime; 357 1.92 knakahar mutex_exit(&cryptodev_mtx); 358 1.36 tls mop = (struct crypt_mop *)data; 359 1.93 knakahar if (mop->count <= 0 360 1.93 knakahar || SIZE_MAX / sizeof(struct crypt_n_op) <= mop->count) { 361 1.93 knakahar error = EINVAL; 362 1.93 knakahar break; 363 1.93 knakahar } 364 1.36 tls cnop = kmem_alloc((mop->count * sizeof(struct crypt_n_op)), 365 1.42 christos KM_SLEEP); 366 1.42 christos error = copyin(mop->reqs, cnop, 367 1.42 christos (mop->count * sizeof(struct crypt_n_op))); 368 1.36 tls if(!error) { 369 1.42 christos error = cryptodev_mop(fcr, cnop, mop->count, curlwp); 370 1.36 tls if (!error) { 371 1.36 tls error = copyout(cnop, mop->reqs, 372 1.42 christos (mop->count * sizeof(struct crypt_n_op))); 373 1.36 tls } 374 1.36 tls } 375 1.36 tls kmem_free(cnop, (mop->count * sizeof(struct crypt_n_op))); 376 1.85 msaitoh break; 377 1.1 jonathan case CIOCKEY: 378 1.1 jonathan error = cryptodev_key((struct crypt_kop *)data); 379 1.90 knakahar DPRINTF("cryptodev_key error = %d\n", error); 380 1.1 jonathan break; 381 1.36 tls case CIOCNFKEYM: 382 1.92 knakahar mutex_enter(&cryptodev_mtx); 383 1.48 christos fcr->mtime = fcr->atime; 384 1.92 knakahar mutex_exit(&cryptodev_mtx); 385 1.36 tls mkop = (struct crypt_mkop *)data; 386 1.93 knakahar if (mkop->count <= 0 387 1.93 knakahar || SIZE_MAX / sizeof(struct crypt_n_kop) <= mkop->count) { 388 1.93 knakahar error = EINVAL; 389 1.93 knakahar break; 390 1.93 knakahar } 391 1.36 tls knop = kmem_alloc((mkop->count * sizeof(struct crypt_n_kop)), 392 1.42 christos KM_SLEEP); 393 1.36 tls error = copyin(mkop->reqs, knop, 394 1.42 christos (mkop->count * sizeof(struct crypt_n_kop))); 395 1.36 tls if (!error) { 396 1.36 tls error = cryptodev_mkey(fcr, knop, mkop->count); 397 1.36 tls if (!error) 398 1.36 tls error = copyout(knop, mkop->reqs, 399 1.42 christos (mkop->count * sizeof(struct crypt_n_kop))); 400 1.36 tls } 401 1.36 tls kmem_free(knop, (mkop->count * sizeof(struct crypt_n_kop))); 402 1.36 tls break; 403 1.1 jonathan case CIOCASYMFEAT: 404 1.1 jonathan error = crypto_getfeat((int *)data); 405 1.1 jonathan break; 406 1.36 tls case CIOCNCRYPTRETM: 407 1.92 knakahar mutex_enter(&cryptodev_mtx); 408 1.48 christos fcr->mtime = fcr->atime; 409 1.92 knakahar mutex_exit(&cryptodev_mtx); 410 1.36 tls crypt_ret = (struct cryptret *)data; 411 1.36 tls count = crypt_ret->count; 412 1.93 knakahar if (count <= 0 413 1.93 knakahar || SIZE_MAX / sizeof(struct crypt_result) <= count) { 414 1.93 knakahar error = EINVAL; 415 1.93 knakahar break; 416 1.93 knakahar } 417 1.42 christos crypt_res = kmem_alloc((count * sizeof(struct crypt_result)), 418 1.42 christos KM_SLEEP); 419 1.36 tls error = copyin(crypt_ret->results, crypt_res, 420 1.42 christos (count * sizeof(struct crypt_result))); 421 1.36 tls if (error) 422 1.36 tls goto reterr; 423 1.36 tls crypt_ret->count = cryptodev_getmstatus(fcr, crypt_res, 424 1.42 christos crypt_ret->count); 425 1.36 tls /* sanity check count */ 426 1.36 tls if (crypt_ret->count > count) { 427 1.37 dogcow printf("%s.%d: error returned count %zd > original " 428 1.42 christos " count %zd\n", 429 1.42 christos __FILE__, __LINE__, crypt_ret->count, count); 430 1.36 tls crypt_ret->count = count; 431 1.36 tls 432 1.36 tls } 433 1.36 tls error = copyout(crypt_res, crypt_ret->results, 434 1.42 christos (crypt_ret->count * sizeof(struct crypt_result))); 435 1.36 tls reterr: 436 1.42 christos kmem_free(crypt_res, (count * sizeof(struct crypt_result))); 437 1.36 tls break; 438 1.36 tls case CIOCNCRYPTRET: 439 1.85 msaitoh error = cryptodev_getstatus(fcr, (struct crypt_result *)data); 440 1.36 tls break; 441 1.1 jonathan default: 442 1.46 darran /* Check for backward compatible commands */ 443 1.99 pgoyette 444 1.100 pgoyette MODULE_HOOK_CALL(ocryptof_50_hook, (fp, cmd, data), 445 1.99 pgoyette enosys(), error); 446 1.99 pgoyette if (error == ENOSYS) 447 1.99 pgoyette error = EINVAL; 448 1.99 pgoyette return error; 449 1.1 jonathan } 450 1.42 christos return error; 451 1.1 jonathan } 452 1.1 jonathan 453 1.46 darran int 454 1.25 christos cryptodev_op(struct csession *cse, struct crypt_op *cop, struct lwp *l) 455 1.1 jonathan { 456 1.1 jonathan struct cryptop *crp = NULL; 457 1.46 darran struct cryptodesc *crde = NULL, *crda = NULL, *crdc = NULL; 458 1.33 tls int error; 459 1.46 darran int iov_len = cop->len; 460 1.46 darran int flags=0; 461 1.46 darran int dst_len; /* copyout size */ 462 1.1 jonathan 463 1.1 jonathan if (cop->len > 256*1024-4) 464 1.42 christos return E2BIG; 465 1.1 jonathan 466 1.13 jonathan if (cse->txform) { 467 1.58 drochner if (cop->len < cse->txform->blocksize 468 1.58 drochner + (cop->iv ? 0 : cse->txform->ivsize) || 469 1.58 drochner (cop->len - (cop->iv ? 0 : cse->txform->ivsize)) 470 1.58 drochner % cse->txform->blocksize != 0) 471 1.42 christos return EINVAL; 472 1.13 jonathan } 473 1.1 jonathan 474 1.118 riastrad if (cse->tcomp == NULL && cse->txform == NULL && cse->thash == NULL) 475 1.118 riastrad return EINVAL; 476 1.118 riastrad 477 1.90 knakahar DPRINTF("cryptodev_op[%u]: iov_len %d\n", 478 1.90 knakahar CRYPTO_SESID2LID(cse->sid), iov_len); 479 1.46 darran if ((cse->tcomp) && cop->dst_len) { 480 1.46 darran if (iov_len < cop->dst_len) { 481 1.46 darran /* Need larger iov to deal with decompress */ 482 1.46 darran iov_len = cop->dst_len; 483 1.46 darran } 484 1.90 knakahar DPRINTF("cryptodev_op: iov_len -> %d for decompress\n", iov_len); 485 1.46 darran } 486 1.46 darran 487 1.42 christos (void)memset(&cse->uio, 0, sizeof(cse->uio)); 488 1.1 jonathan cse->uio.uio_iovcnt = 1; 489 1.1 jonathan cse->uio.uio_resid = 0; 490 1.1 jonathan cse->uio.uio_rw = UIO_WRITE; 491 1.1 jonathan cse->uio.uio_iov = cse->iovec; 492 1.17 yamt UIO_SETUP_SYSSPACE(&cse->uio); 493 1.29 tls memset(&cse->iovec, 0, sizeof(cse->iovec)); 494 1.46 darran 495 1.46 darran /* the iov needs to be big enough to handle the uncompressed 496 1.46 darran * data.... */ 497 1.46 darran cse->uio.uio_iov[0].iov_len = iov_len; 498 1.64 drochner if (iov_len > 0) 499 1.64 drochner cse->uio.uio_iov[0].iov_base = kmem_alloc(iov_len, KM_SLEEP); 500 1.29 tls cse->uio.uio_resid = cse->uio.uio_iov[0].iov_len; 501 1.90 knakahar DPRINTF("lid[%u]: uio.iov_base %p malloced %d bytes\n", 502 1.53 jakllsch CRYPTO_SESID2LID(cse->sid), 503 1.90 knakahar cse->uio.uio_iov[0].iov_base, iov_len); 504 1.1 jonathan 505 1.46 darran crp = crypto_getreq((cse->tcomp != NULL) + (cse->txform != NULL) + (cse->thash != NULL)); 506 1.1 jonathan if (crp == NULL) { 507 1.1 jonathan error = ENOMEM; 508 1.1 jonathan goto bail; 509 1.1 jonathan } 510 1.90 knakahar DPRINTF("lid[%u]: crp %p\n", CRYPTO_SESID2LID(cse->sid), crp); 511 1.46 darran 512 1.46 darran /* crds are always ordered tcomp, thash, then txform */ 513 1.46 darran /* with optional missing links */ 514 1.46 darran 515 1.46 darran /* XXX: If we're going to compress then hash or encrypt, we need 516 1.46 darran * to be able to pass on the new size of the data. 517 1.46 darran */ 518 1.46 darran 519 1.46 darran if (cse->tcomp) { 520 1.46 darran crdc = crp->crp_desc; 521 1.46 darran } 522 1.1 jonathan 523 1.1 jonathan if (cse->thash) { 524 1.46 darran crda = crdc ? crdc->crd_next : crp->crp_desc; 525 1.44 christos if (cse->txform && crda) 526 1.1 jonathan crde = crda->crd_next; 527 1.1 jonathan } else { 528 1.46 darran if (cse->txform) { 529 1.46 darran crde = crdc ? crdc->crd_next : crp->crp_desc; 530 1.46 darran } else if (!cse->tcomp) { 531 1.1 jonathan error = EINVAL; 532 1.1 jonathan goto bail; 533 1.1 jonathan } 534 1.1 jonathan } 535 1.1 jonathan 536 1.90 knakahar DPRINTF("ocf[%u]: iov_len %zu, cop->len %u\n", 537 1.53 jakllsch CRYPTO_SESID2LID(cse->sid), 538 1.46 darran cse->uio.uio_iov[0].iov_len, 539 1.90 knakahar cop->len); 540 1.46 darran 541 1.1 jonathan if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len))) 542 1.36 tls { 543 1.36 tls printf("copyin failed %s %d \n", (char *)cop->src, error); 544 1.1 jonathan goto bail; 545 1.36 tls } 546 1.1 jonathan 547 1.46 darran if (crdc) { 548 1.46 darran switch (cop->op) { 549 1.46 darran case COP_COMP: 550 1.46 darran crdc->crd_flags |= CRD_F_COMP; 551 1.46 darran break; 552 1.46 darran case COP_DECOMP: 553 1.46 darran crdc->crd_flags &= ~CRD_F_COMP; 554 1.46 darran break; 555 1.46 darran default: 556 1.46 darran break; 557 1.46 darran } 558 1.46 darran /* more data to follow? */ 559 1.46 darran if (cop->flags & COP_F_MORE) { 560 1.46 darran flags |= CRYPTO_F_MORE; 561 1.46 darran } 562 1.46 darran crdc->crd_len = cop->len; 563 1.46 darran crdc->crd_inject = 0; 564 1.46 darran 565 1.46 darran crdc->crd_alg = cse->comp_alg; 566 1.46 darran crdc->crd_key = NULL; 567 1.46 darran crdc->crd_klen = 0; 568 1.90 knakahar DPRINTF("lid[%u]: crdc setup for comp_alg %d.\n", 569 1.90 knakahar CRYPTO_SESID2LID(cse->sid), crdc->crd_alg); 570 1.46 darran } 571 1.46 darran 572 1.1 jonathan if (crda) { 573 1.1 jonathan crda->crd_skip = 0; 574 1.1 jonathan crda->crd_len = cop->len; 575 1.1 jonathan crda->crd_inject = 0; /* ??? */ 576 1.1 jonathan 577 1.1 jonathan crda->crd_alg = cse->mac; 578 1.1 jonathan crda->crd_key = cse->mackey; 579 1.1 jonathan crda->crd_klen = cse->mackeylen * 8; 580 1.90 knakahar DPRINTF("crda setup for mac %d.\n", crda->crd_alg); 581 1.1 jonathan } 582 1.1 jonathan 583 1.1 jonathan if (crde) { 584 1.46 darran switch (cop->op) { 585 1.46 darran case COP_ENCRYPT: 586 1.1 jonathan crde->crd_flags |= CRD_F_ENCRYPT; 587 1.46 darran break; 588 1.46 darran case COP_DECRYPT: 589 1.1 jonathan crde->crd_flags &= ~CRD_F_ENCRYPT; 590 1.46 darran break; 591 1.46 darran default: 592 1.46 darran break; 593 1.46 darran } 594 1.1 jonathan crde->crd_len = cop->len; 595 1.1 jonathan crde->crd_inject = 0; 596 1.1 jonathan 597 1.66 drochner if (cse->cipher == CRYPTO_AES_GCM_16 && crda) 598 1.66 drochner crda->crd_len = 0; 599 1.66 drochner else if (cse->cipher == CRYPTO_AES_GMAC) 600 1.66 drochner crde->crd_len = 0; 601 1.66 drochner 602 1.1 jonathan crde->crd_alg = cse->cipher; 603 1.1 jonathan crde->crd_key = cse->key; 604 1.1 jonathan crde->crd_klen = cse->keylen * 8; 605 1.90 knakahar DPRINTF("crde setup for cipher %d.\n", crde->crd_alg); 606 1.1 jonathan } 607 1.1 jonathan 608 1.46 darran 609 1.1 jonathan crp->crp_ilen = cop->len; 610 1.113 riastrad crp->crp_flags = CRYPTO_F_IOV | (cop->flags & COP_F_BATCH) | flags; 611 1.26 christos crp->crp_buf = (void *)&cse->uio; 612 1.108 riastrad crp->crp_callback = cryptodev_cb; 613 1.1 jonathan crp->crp_sid = cse->sid; 614 1.108 riastrad crp->crp_opaque = cse; 615 1.1 jonathan 616 1.1 jonathan if (cop->iv) { 617 1.1 jonathan if (crde == NULL) { 618 1.1 jonathan error = EINVAL; 619 1.1 jonathan goto bail; 620 1.1 jonathan } 621 1.62 drochner if (cse->txform->ivsize == 0) { 622 1.1 jonathan error = EINVAL; 623 1.1 jonathan goto bail; 624 1.1 jonathan } 625 1.36 tls if ((error = copyin(cop->iv, cse->tmp_iv, 626 1.58 drochner cse->txform->ivsize))) 627 1.1 jonathan goto bail; 628 1.58 drochner (void)memcpy(crde->crd_iv, cse->tmp_iv, cse->txform->ivsize); 629 1.1 jonathan crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; 630 1.1 jonathan crde->crd_skip = 0; 631 1.1 jonathan } else if (crde) { 632 1.62 drochner if (cse->txform->ivsize == 0) { 633 1.20 christos crde->crd_skip = 0; 634 1.20 christos } else { 635 1.61 drochner if (!(crde->crd_flags & CRD_F_ENCRYPT)) 636 1.61 drochner crde->crd_flags |= CRD_F_IV_PRESENT; 637 1.58 drochner crde->crd_skip = cse->txform->ivsize; 638 1.58 drochner crde->crd_len -= cse->txform->ivsize; 639 1.20 christos } 640 1.1 jonathan } 641 1.1 jonathan 642 1.1 jonathan if (cop->mac) { 643 1.1 jonathan if (crda == NULL) { 644 1.1 jonathan error = EINVAL; 645 1.1 jonathan goto bail; 646 1.1 jonathan } 647 1.112 riastrad crp->crp_mac = cse->tmp_mac; 648 1.1 jonathan } 649 1.1 jonathan 650 1.67 drochner cv_init(&crp->crp_cv, "crydev"); 651 1.123 riastrad crypto_dispatch(crp); 652 1.111 riastrad mutex_enter(&cryptodev_mtx); 653 1.95 knakahar while (!(crp->crp_devflags & CRYPTODEV_F_RET)) { 654 1.90 knakahar DPRINTF("cse->sid[%d]: sleeping on cv %p for crp %p\n", 655 1.90 knakahar (uint32_t)cse->sid, &crp->crp_cv, crp); 656 1.92 knakahar cv_wait(&crp->crp_cv, &cryptodev_mtx); /* XXX cv_wait_sig? */ 657 1.33 tls } 658 1.92 knakahar mutex_exit(&cryptodev_mtx); 659 1.67 drochner cv_destroy(&crp->crp_cv); 660 1.1 jonathan 661 1.1 jonathan if (crp->crp_etype != 0) { 662 1.90 knakahar DPRINTF("crp_etype %d\n", crp->crp_etype); 663 1.1 jonathan error = crp->crp_etype; 664 1.1 jonathan goto bail; 665 1.1 jonathan } 666 1.1 jonathan 667 1.1 jonathan if (cse->error) { 668 1.90 knakahar DPRINTF("cse->error %d\n", cse->error); 669 1.1 jonathan error = cse->error; 670 1.1 jonathan goto bail; 671 1.1 jonathan } 672 1.1 jonathan 673 1.46 darran dst_len = crp->crp_ilen; 674 1.46 darran /* let the user know how much data was returned */ 675 1.46 darran if (crp->crp_olen) { 676 1.64 drochner if (crp->crp_olen > (cop->dst_len ? cop->dst_len : cop->len)) { 677 1.82 christos error = ENOSPC; 678 1.64 drochner goto bail; 679 1.64 drochner } 680 1.46 darran dst_len = cop->dst_len = crp->crp_olen; 681 1.46 darran } 682 1.46 darran 683 1.46 darran if (cop->dst) { 684 1.90 knakahar DPRINTF("copyout %d bytes to %p\n", dst_len, cop->dst); 685 1.46 darran } 686 1.1 jonathan if (cop->dst && 687 1.46 darran (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, dst_len))) 688 1.36 tls { 689 1.90 knakahar DPRINTF("copyout error %d\n", error); 690 1.1 jonathan goto bail; 691 1.34 tls } 692 1.1 jonathan 693 1.1 jonathan if (cop->mac && 694 1.34 tls (error = copyout(crp->crp_mac, cop->mac, cse->thash->authsize))) { 695 1.90 knakahar DPRINTF("mac copyout error %d\n", error); 696 1.1 jonathan goto bail; 697 1.34 tls } 698 1.1 jonathan 699 1.46 darran 700 1.1 jonathan bail: 701 1.45 darran if (crp) { 702 1.1 jonathan crypto_freereq(crp); 703 1.45 darran } 704 1.46 darran if (cse->uio.uio_iov[0].iov_base) { 705 1.46 darran kmem_free(cse->uio.uio_iov[0].iov_base,iov_len); 706 1.46 darran } 707 1.1 jonathan 708 1.42 christos return error; 709 1.1 jonathan } 710 1.1 jonathan 711 1.117 riastrad static void 712 1.108 riastrad cryptodev_cb(struct cryptop *crp) 713 1.1 jonathan { 714 1.108 riastrad struct csession *cse = crp->crp_opaque; 715 1.116 riastrad 716 1.116 riastrad mutex_enter(&cryptodev_mtx); 717 1.122 riastrad cse->error = crp->crp_etype; 718 1.116 riastrad crp->crp_devflags |= CRYPTODEV_F_RET; 719 1.116 riastrad cv_signal(&crp->crp_cv); 720 1.92 knakahar mutex_exit(&cryptodev_mtx); 721 1.1 jonathan } 722 1.1 jonathan 723 1.117 riastrad static void 724 1.108 riastrad cryptodev_mcb(struct cryptop *crp) 725 1.36 tls { 726 1.108 riastrad struct csession *cse = crp->crp_opaque; 727 1.36 tls 728 1.116 riastrad mutex_enter(&cryptodev_mtx); 729 1.122 riastrad cse->error = crp->crp_etype; 730 1.36 tls TAILQ_INSERT_TAIL(&crp->fcrp->crp_ret_mq, crp, crp_next); 731 1.38 rmind selnotify(&crp->fcrp->sinfo, 0, 0); 732 1.92 knakahar mutex_exit(&cryptodev_mtx); 733 1.36 tls } 734 1.36 tls 735 1.117 riastrad static void 736 1.108 riastrad cryptodevkey_cb(struct cryptkop *krp) 737 1.1 jonathan { 738 1.108 riastrad 739 1.92 knakahar mutex_enter(&cryptodev_mtx); 740 1.95 knakahar krp->krp_devflags |= CRYPTODEV_F_RET; 741 1.36 tls cv_signal(&krp->krp_cv); 742 1.92 knakahar mutex_exit(&cryptodev_mtx); 743 1.36 tls } 744 1.36 tls 745 1.117 riastrad static void 746 1.108 riastrad cryptodevkey_mcb(struct cryptkop *krp) 747 1.36 tls { 748 1.1 jonathan 749 1.92 knakahar mutex_enter(&cryptodev_mtx); 750 1.33 tls cv_signal(&krp->krp_cv); 751 1.36 tls TAILQ_INSERT_TAIL(&krp->fcrp->crp_ret_mkq, krp, krp_next); 752 1.38 rmind selnotify(&krp->fcrp->sinfo, 0, 0); 753 1.92 knakahar mutex_exit(&cryptodev_mtx); 754 1.1 jonathan } 755 1.1 jonathan 756 1.1 jonathan static int 757 1.1 jonathan cryptodev_key(struct crypt_kop *kop) 758 1.1 jonathan { 759 1.1 jonathan struct cryptkop *krp = NULL; 760 1.1 jonathan int error = EINVAL; 761 1.1 jonathan int in, out, size, i; 762 1.1 jonathan 763 1.42 christos if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) 764 1.42 christos return EFBIG; 765 1.1 jonathan 766 1.1 jonathan in = kop->crk_iparams; 767 1.1 jonathan out = kop->crk_oparams; 768 1.1 jonathan switch (kop->crk_op) { 769 1.1 jonathan case CRK_MOD_EXP: 770 1.1 jonathan if (in == 3 && out == 1) 771 1.1 jonathan break; 772 1.42 christos return EINVAL; 773 1.1 jonathan case CRK_MOD_EXP_CRT: 774 1.1 jonathan if (in == 6 && out == 1) 775 1.1 jonathan break; 776 1.42 christos return EINVAL; 777 1.1 jonathan case CRK_DSA_SIGN: 778 1.1 jonathan if (in == 5 && out == 2) 779 1.1 jonathan break; 780 1.42 christos return EINVAL; 781 1.1 jonathan case CRK_DSA_VERIFY: 782 1.1 jonathan if (in == 7 && out == 0) 783 1.1 jonathan break; 784 1.42 christos return EINVAL; 785 1.1 jonathan case CRK_DH_COMPUTE_KEY: 786 1.1 jonathan if (in == 3 && out == 1) 787 1.1 jonathan break; 788 1.42 christos return EINVAL; 789 1.27 tls case CRK_MOD_ADD: 790 1.27 tls if (in == 3 && out == 1) 791 1.27 tls break; 792 1.42 christos return EINVAL; 793 1.27 tls case CRK_MOD_ADDINV: 794 1.27 tls if (in == 2 && out == 1) 795 1.27 tls break; 796 1.42 christos return EINVAL; 797 1.27 tls case CRK_MOD_SUB: 798 1.27 tls if (in == 3 && out == 1) 799 1.27 tls break; 800 1.42 christos return EINVAL; 801 1.27 tls case CRK_MOD_MULT: 802 1.27 tls if (in == 3 && out == 1) 803 1.27 tls break; 804 1.42 christos return EINVAL; 805 1.27 tls case CRK_MOD_MULTINV: 806 1.27 tls if (in == 2 && out == 1) 807 1.27 tls break; 808 1.42 christos return EINVAL; 809 1.27 tls case CRK_MOD: 810 1.27 tls if (in == 2 && out == 1) 811 1.27 tls break; 812 1.42 christos return EINVAL; 813 1.1 jonathan default: 814 1.42 christos return EINVAL; 815 1.1 jonathan } 816 1.1 jonathan 817 1.91 knakahar krp = crypto_kgetreq(1, PR_WAITOK); 818 1.91 knakahar if (krp == NULL) { 819 1.91 knakahar /* limited by opencrypto.crypto_ret_kq.maxlen */ 820 1.91 knakahar return ENOMEM; 821 1.91 knakahar } 822 1.42 christos (void)memset(krp, 0, sizeof *krp); 823 1.33 tls cv_init(&krp->krp_cv, "crykdev"); 824 1.1 jonathan krp->krp_op = kop->crk_op; 825 1.1 jonathan krp->krp_status = kop->crk_status; 826 1.1 jonathan krp->krp_iparams = kop->crk_iparams; 827 1.1 jonathan krp->krp_oparams = kop->crk_oparams; 828 1.1 jonathan krp->krp_status = 0; 829 1.108 riastrad krp->krp_callback = cryptodevkey_cb; 830 1.1 jonathan 831 1.1 jonathan for (i = 0; i < CRK_MAXPARAM; i++) 832 1.1 jonathan krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits; 833 1.1 jonathan for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) { 834 1.1 jonathan size = (krp->krp_param[i].crp_nbits + 7) / 8; 835 1.1 jonathan if (size == 0) 836 1.1 jonathan continue; 837 1.36 tls krp->krp_param[i].crp_p = kmem_alloc(size, KM_SLEEP); 838 1.1 jonathan if (i >= krp->krp_iparams) 839 1.1 jonathan continue; 840 1.42 christos error = copyin(kop->crk_param[i].crp_p, 841 1.42 christos krp->krp_param[i].crp_p, size); 842 1.1 jonathan if (error) 843 1.1 jonathan goto fail; 844 1.1 jonathan } 845 1.1 jonathan 846 1.123 riastrad crypto_kdispatch(krp); 847 1.33 tls 848 1.92 knakahar mutex_enter(&cryptodev_mtx); 849 1.95 knakahar while (!(krp->krp_devflags & CRYPTODEV_F_RET)) { 850 1.92 knakahar cv_wait(&krp->krp_cv, &cryptodev_mtx); /* XXX cv_wait_sig? */ 851 1.33 tls } 852 1.92 knakahar mutex_exit(&cryptodev_mtx); 853 1.1 jonathan 854 1.1 jonathan if (krp->krp_status != 0) { 855 1.90 knakahar DPRINTF("krp->krp_status 0x%08x\n", krp->krp_status); 856 1.1 jonathan error = krp->krp_status; 857 1.1 jonathan goto fail; 858 1.1 jonathan } 859 1.1 jonathan 860 1.42 christos for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; 861 1.42 christos i++) { 862 1.1 jonathan size = (krp->krp_param[i].crp_nbits + 7) / 8; 863 1.1 jonathan if (size == 0) 864 1.1 jonathan continue; 865 1.42 christos error = copyout(krp->krp_param[i].crp_p, 866 1.42 christos kop->crk_param[i].crp_p, size); 867 1.34 tls if (error) { 868 1.90 knakahar DPRINTF("copyout oparam %d failed, " 869 1.90 knakahar "error=%d\n", i-krp->krp_iparams, error); 870 1.1 jonathan goto fail; 871 1.34 tls } 872 1.1 jonathan } 873 1.1 jonathan 874 1.1 jonathan fail: 875 1.43 christos kop->crk_status = krp->krp_status; 876 1.43 christos for (i = 0; i < CRK_MAXPARAM; i++) { 877 1.43 christos struct crparam *kp = &(krp->krp_param[i]); 878 1.43 christos if (krp->krp_param[i].crp_p) { 879 1.43 christos size = (kp->crp_nbits + 7) / 8; 880 1.43 christos KASSERT(size > 0); 881 1.43 christos (void)memset(kp->crp_p, 0, size); 882 1.43 christos kmem_free(kp->crp_p, size); 883 1.1 jonathan } 884 1.1 jonathan } 885 1.45 darran cv_destroy(&krp->krp_cv); 886 1.91 knakahar crypto_kfreereq(krp); 887 1.90 knakahar DPRINTF("error=0x%08x\n", error); 888 1.42 christos return error; 889 1.1 jonathan } 890 1.1 jonathan 891 1.1 jonathan /* ARGSUSED */ 892 1.1 jonathan static int 893 1.36 tls cryptof_close(struct file *fp) 894 1.1 jonathan { 895 1.81 matt struct fcrypt *fcr = fp->f_fcrypt; 896 1.1 jonathan struct csession *cse; 897 1.1 jonathan 898 1.92 knakahar mutex_enter(&cryptodev_mtx); 899 1.1 jonathan while ((cse = TAILQ_FIRST(&fcr->csessions))) { 900 1.1 jonathan TAILQ_REMOVE(&fcr->csessions, cse, next); 901 1.92 knakahar mutex_exit(&cryptodev_mtx); 902 1.121 riastrad csefree(cse); 903 1.92 knakahar mutex_enter(&cryptodev_mtx); 904 1.1 jonathan } 905 1.36 tls seldestroy(&fcr->sinfo); 906 1.81 matt fp->f_fcrypt = NULL; 907 1.74 pgoyette crypto_refcount--; 908 1.92 knakahar mutex_exit(&cryptodev_mtx); 909 1.1 jonathan 910 1.38 rmind pool_put(&fcrpl, fcr); 911 1.1 jonathan return 0; 912 1.1 jonathan } 913 1.1 jonathan 914 1.46 darran /* needed for compatibility module */ 915 1.46 darran struct csession *cryptodev_csefind(struct fcrypt *fcr, u_int ses) 916 1.46 darran { 917 1.46 darran return csefind(fcr, ses); 918 1.46 darran } 919 1.46 darran 920 1.92 knakahar /* csefind: call with cryptodev_mtx held. */ 921 1.1 jonathan static struct csession * 922 1.1 jonathan csefind(struct fcrypt *fcr, u_int ses) 923 1.1 jonathan { 924 1.45 darran struct csession *cse, *cnext, *ret = NULL; 925 1.1 jonathan 926 1.92 knakahar KASSERT(mutex_owned(&cryptodev_mtx)); 927 1.45 darran TAILQ_FOREACH_SAFE(cse, &fcr->csessions, next, cnext) 928 1.1 jonathan if (cse->ses == ses) 929 1.33 tls ret = cse; 930 1.121 riastrad 931 1.42 christos return ret; 932 1.1 jonathan } 933 1.1 jonathan 934 1.92 knakahar /* csedelete: call with cryptodev_mtx held. */ 935 1.1 jonathan static int 936 1.1 jonathan csedelete(struct fcrypt *fcr, struct csession *cse_del) 937 1.1 jonathan { 938 1.45 darran struct csession *cse, *cnext; 939 1.33 tls int ret = 0; 940 1.1 jonathan 941 1.92 knakahar KASSERT(mutex_owned(&cryptodev_mtx)); 942 1.45 darran TAILQ_FOREACH_SAFE(cse, &fcr->csessions, next, cnext) { 943 1.1 jonathan if (cse == cse_del) { 944 1.1 jonathan TAILQ_REMOVE(&fcr->csessions, cse, next); 945 1.33 tls ret = 1; 946 1.1 jonathan } 947 1.1 jonathan } 948 1.42 christos return ret; 949 1.1 jonathan } 950 1.1 jonathan 951 1.1 jonathan static struct csession * 952 1.1 jonathan cseadd(struct fcrypt *fcr, struct csession *cse) 953 1.1 jonathan { 954 1.92 knakahar mutex_enter(&cryptodev_mtx); 955 1.33 tls /* don't let session ID wrap! */ 956 1.33 tls if (fcr->sesn + 1 == 0) return NULL; 957 1.1 jonathan TAILQ_INSERT_TAIL(&fcr->csessions, cse, next); 958 1.1 jonathan cse->ses = fcr->sesn++; 959 1.92 knakahar mutex_exit(&cryptodev_mtx); 960 1.42 christos return cse; 961 1.1 jonathan } 962 1.1 jonathan 963 1.1 jonathan static struct csession * 964 1.26 christos csecreate(struct fcrypt *fcr, u_int64_t sid, void *key, u_int64_t keylen, 965 1.26 christos void *mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac, 966 1.54 drochner u_int32_t comp_alg, const struct enc_xform *txform, 967 1.54 drochner const struct auth_hash *thash, const struct comp_algo *tcomp) 968 1.1 jonathan { 969 1.1 jonathan struct csession *cse; 970 1.1 jonathan 971 1.29 tls cse = pool_get(&csepl, PR_NOWAIT); 972 1.1 jonathan if (cse == NULL) 973 1.1 jonathan return NULL; 974 1.1 jonathan cse->key = key; 975 1.1 jonathan cse->keylen = keylen/8; 976 1.1 jonathan cse->mackey = mackey; 977 1.1 jonathan cse->mackeylen = mackeylen/8; 978 1.1 jonathan cse->sid = sid; 979 1.1 jonathan cse->cipher = cipher; 980 1.1 jonathan cse->mac = mac; 981 1.46 darran cse->comp_alg = comp_alg; 982 1.1 jonathan cse->txform = txform; 983 1.1 jonathan cse->thash = thash; 984 1.46 darran cse->tcomp = tcomp; 985 1.34 tls cse->error = 0; 986 1.28 tls if (cseadd(fcr, cse)) 987 1.42 christos return cse; 988 1.28 tls else { 989 1.33 tls pool_put(&csepl, cse); 990 1.28 tls return NULL; 991 1.28 tls } 992 1.1 jonathan } 993 1.1 jonathan 994 1.121 riastrad static void 995 1.1 jonathan csefree(struct csession *cse) 996 1.1 jonathan { 997 1.1 jonathan 998 1.120 riastrad crypto_freesession(cse->sid); 999 1.1 jonathan if (cse->key) 1000 1.36 tls free(cse->key, M_XDATA); 1001 1.1 jonathan if (cse->mackey) 1002 1.36 tls free(cse->mackey, M_XDATA); 1003 1.29 tls pool_put(&csepl, cse); 1004 1.1 jonathan } 1005 1.1 jonathan 1006 1.1 jonathan static int 1007 1.25 christos cryptoopen(dev_t dev, int flag, int mode, 1008 1.25 christos struct lwp *l) 1009 1.1 jonathan { 1010 1.35 ad file_t *fp; 1011 1.29 tls struct fcrypt *fcr; 1012 1.29 tls int fd, error; 1013 1.29 tls 1014 1.1 jonathan if (crypto_usercrypto == 0) 1015 1.42 christos return ENXIO; 1016 1.29 tls 1017 1.35 ad if ((error = fd_allocfile(&fp, &fd)) != 0) 1018 1.29 tls return error; 1019 1.29 tls 1020 1.29 tls fcr = pool_get(&fcrpl, PR_WAITOK); 1021 1.48 christos getnanotime(&fcr->btime); 1022 1.48 christos fcr->atime = fcr->mtime = fcr->btime; 1023 1.92 knakahar mutex_enter(&cryptodev_mtx); 1024 1.29 tls TAILQ_INIT(&fcr->csessions); 1025 1.36 tls TAILQ_INIT(&fcr->crp_ret_mq); 1026 1.36 tls TAILQ_INIT(&fcr->crp_ret_mkq); 1027 1.36 tls selinit(&fcr->sinfo); 1028 1.29 tls /* 1029 1.29 tls * Don't ever return session 0, to allow detection of 1030 1.29 tls * failed creation attempts with multi-create ioctl. 1031 1.29 tls */ 1032 1.29 tls fcr->sesn = 1; 1033 1.36 tls fcr->requestid = 1; 1034 1.74 pgoyette crypto_refcount++; 1035 1.92 knakahar mutex_exit(&cryptodev_mtx); 1036 1.35 ad return fd_clone(fp, fd, flag, &cryptofops, fcr); 1037 1.1 jonathan } 1038 1.1 jonathan 1039 1.1 jonathan static int 1040 1.25 christos cryptoread(dev_t dev, struct uio *uio, int ioflag) 1041 1.1 jonathan { 1042 1.42 christos return EIO; 1043 1.1 jonathan } 1044 1.1 jonathan 1045 1.1 jonathan static int 1046 1.25 christos cryptowrite(dev_t dev, struct uio *uio, int ioflag) 1047 1.1 jonathan { 1048 1.42 christos return EIO; 1049 1.1 jonathan } 1050 1.1 jonathan 1051 1.1 jonathan int 1052 1.25 christos cryptoselect(dev_t dev, int rw, struct lwp *l) 1053 1.1 jonathan { 1054 1.42 christos return 0; 1055 1.1 jonathan } 1056 1.1 jonathan 1057 1.1 jonathan /*static*/ 1058 1.1 jonathan struct cdevsw crypto_cdevsw = { 1059 1.78 dholland .d_open = cryptoopen, 1060 1.78 dholland .d_close = noclose, 1061 1.78 dholland .d_read = cryptoread, 1062 1.78 dholland .d_write = cryptowrite, 1063 1.78 dholland .d_ioctl = noioctl, 1064 1.78 dholland .d_stop = nostop, 1065 1.78 dholland .d_tty = notty, 1066 1.78 dholland .d_poll = cryptoselect /*nopoll*/, 1067 1.78 dholland .d_mmap = nommap, 1068 1.78 dholland .d_kqfilter = nokqfilter, 1069 1.79 dholland .d_discard = nodiscard, 1070 1.78 dholland .d_flag = D_OTHER 1071 1.1 jonathan }; 1072 1.1 jonathan 1073 1.46 darran int 1074 1.36 tls cryptodev_mop(struct fcrypt *fcr, 1075 1.36 tls struct crypt_n_op * cnop, 1076 1.36 tls int count, struct lwp *l) 1077 1.36 tls { 1078 1.36 tls struct cryptop *crp = NULL; 1079 1.46 darran struct cryptodesc *crde = NULL, *crda = NULL, *crdc = NULL; 1080 1.36 tls int req, error=0; 1081 1.36 tls struct csession *cse; 1082 1.46 darran int flags=0; 1083 1.46 darran int iov_len; 1084 1.36 tls 1085 1.36 tls for (req = 0; req < count; req++) { 1086 1.92 knakahar mutex_enter(&cryptodev_mtx); 1087 1.36 tls cse = csefind(fcr, cnop[req].ses); 1088 1.36 tls if (cse == NULL) { 1089 1.90 knakahar DPRINTF("csefind failed\n"); 1090 1.36 tls cnop[req].status = EINVAL; 1091 1.92 knakahar mutex_exit(&cryptodev_mtx); 1092 1.36 tls continue; 1093 1.36 tls } 1094 1.92 knakahar mutex_exit(&cryptodev_mtx); 1095 1.36 tls 1096 1.36 tls if (cnop[req].len > 256*1024-4) { 1097 1.90 knakahar DPRINTF("length failed\n"); 1098 1.36 tls cnop[req].status = EINVAL; 1099 1.36 tls continue; 1100 1.36 tls } 1101 1.36 tls if (cse->txform) { 1102 1.58 drochner if (cnop[req].len < cse->txform->blocksize - 1103 1.58 drochner (cnop[req].iv ? 0 : cse->txform->ivsize) || 1104 1.58 drochner (cnop[req].len - 1105 1.58 drochner (cnop[req].iv ? 0 : cse->txform->ivsize)) 1106 1.58 drochner % cse->txform->blocksize) { 1107 1.36 tls cnop[req].status = EINVAL; 1108 1.36 tls continue; 1109 1.36 tls } 1110 1.36 tls } 1111 1.36 tls 1112 1.118 riastrad if (cse->txform == NULL && 1113 1.118 riastrad cse->thash == NULL && 1114 1.118 riastrad cse->tcomp == NULL) { 1115 1.118 riastrad cnop[req].status = EINVAL; 1116 1.118 riastrad goto bail; 1117 1.118 riastrad } 1118 1.118 riastrad 1119 1.94 knakahar /* sanitize */ 1120 1.94 knakahar if (cnop[req].len <= 0) { 1121 1.94 knakahar cnop[req].status = ENOMEM; 1122 1.94 knakahar goto bail; 1123 1.94 knakahar } 1124 1.94 knakahar 1125 1.42 christos crp = crypto_getreq((cse->txform != NULL) + 1126 1.46 darran (cse->thash != NULL) + 1127 1.46 darran (cse->tcomp != NULL)); 1128 1.36 tls if (crp == NULL) { 1129 1.36 tls cnop[req].status = ENOMEM; 1130 1.36 tls goto bail; 1131 1.36 tls } 1132 1.36 tls 1133 1.46 darran iov_len = cnop[req].len; 1134 1.46 darran /* got a compression/decompression max size? */ 1135 1.46 darran if ((cse->tcomp) && cnop[req].dst_len) { 1136 1.46 darran if (iov_len < cnop[req].dst_len) { 1137 1.46 darran /* Need larger iov to deal with decompress */ 1138 1.46 darran iov_len = cnop[req].dst_len; 1139 1.46 darran } 1140 1.90 knakahar DPRINTF("iov_len -> %d for decompress\n", iov_len); 1141 1.46 darran } 1142 1.46 darran 1143 1.42 christos (void)memset(&crp->uio, 0, sizeof(crp->uio)); 1144 1.36 tls crp->uio.uio_iovcnt = 1; 1145 1.36 tls crp->uio.uio_resid = 0; 1146 1.36 tls crp->uio.uio_rw = UIO_WRITE; 1147 1.36 tls crp->uio.uio_iov = crp->iovec; 1148 1.36 tls UIO_SETUP_SYSSPACE(&crp->uio); 1149 1.36 tls memset(&crp->iovec, 0, sizeof(crp->iovec)); 1150 1.46 darran crp->uio.uio_iov[0].iov_len = iov_len; 1151 1.90 knakahar DPRINTF("kmem_alloc(%d) for iov \n", iov_len); 1152 1.46 darran crp->uio.uio_iov[0].iov_base = kmem_alloc(iov_len, KM_SLEEP); 1153 1.36 tls crp->uio.uio_resid = crp->uio.uio_iov[0].iov_len; 1154 1.36 tls 1155 1.46 darran if (cse->tcomp) { 1156 1.46 darran crdc = crp->crp_desc; 1157 1.46 darran } 1158 1.46 darran 1159 1.36 tls if (cse->thash) { 1160 1.46 darran crda = crdc ? crdc->crd_next : crp->crp_desc; 1161 1.44 christos if (cse->txform && crda) 1162 1.36 tls crde = crda->crd_next; 1163 1.36 tls } else { 1164 1.46 darran if (cse->txform) { 1165 1.46 darran crde = crdc ? crdc->crd_next : crp->crp_desc; 1166 1.46 darran } else if (!cse->tcomp) { 1167 1.46 darran error = EINVAL; 1168 1.46 darran goto bail; 1169 1.36 tls } 1170 1.36 tls } 1171 1.36 tls 1172 1.36 tls if ((copyin(cnop[req].src, 1173 1.36 tls crp->uio.uio_iov[0].iov_base, cnop[req].len))) { 1174 1.36 tls cnop[req].status = EINVAL; 1175 1.36 tls goto bail; 1176 1.36 tls } 1177 1.46 darran 1178 1.46 darran if (crdc) { 1179 1.46 darran switch (cnop[req].op) { 1180 1.46 darran case COP_COMP: 1181 1.46 darran crdc->crd_flags |= CRD_F_COMP; 1182 1.46 darran break; 1183 1.46 darran case COP_DECOMP: 1184 1.46 darran crdc->crd_flags &= ~CRD_F_COMP; 1185 1.46 darran break; 1186 1.46 darran default: 1187 1.46 darran break; 1188 1.46 darran } 1189 1.46 darran /* more data to follow? */ 1190 1.46 darran if (cnop[req].flags & COP_F_MORE) { 1191 1.46 darran flags |= CRYPTO_F_MORE; 1192 1.46 darran } 1193 1.46 darran crdc->crd_len = cnop[req].len; 1194 1.46 darran crdc->crd_inject = 0; 1195 1.46 darran 1196 1.46 darran crdc->crd_alg = cse->comp_alg; 1197 1.46 darran crdc->crd_key = NULL; 1198 1.46 darran crdc->crd_klen = 0; 1199 1.90 knakahar DPRINTF("cse->sid[%d]: crdc setup for comp_alg %d" 1200 1.46 darran " len %d.\n", 1201 1.46 darran (uint32_t)cse->sid, crdc->crd_alg, 1202 1.90 knakahar crdc->crd_len); 1203 1.46 darran } 1204 1.36 tls 1205 1.36 tls if (crda) { 1206 1.36 tls crda->crd_skip = 0; 1207 1.36 tls crda->crd_len = cnop[req].len; 1208 1.36 tls crda->crd_inject = 0; /* ??? */ 1209 1.36 tls 1210 1.36 tls crda->crd_alg = cse->mac; 1211 1.36 tls crda->crd_key = cse->mackey; 1212 1.36 tls crda->crd_klen = cse->mackeylen * 8; 1213 1.36 tls } 1214 1.36 tls 1215 1.36 tls if (crde) { 1216 1.36 tls if (cnop[req].op == COP_ENCRYPT) 1217 1.36 tls crde->crd_flags |= CRD_F_ENCRYPT; 1218 1.36 tls else 1219 1.36 tls crde->crd_flags &= ~CRD_F_ENCRYPT; 1220 1.36 tls crde->crd_len = cnop[req].len; 1221 1.36 tls crde->crd_inject = 0; 1222 1.36 tls 1223 1.36 tls crde->crd_alg = cse->cipher; 1224 1.36 tls #ifdef notyet /* XXX must notify h/w driver new key, drain */ 1225 1.36 tls if(cnop[req].key && cnop[req].keylen) { 1226 1.36 tls crde->crd_key = malloc(cnop[req].keylen, 1227 1.36 tls M_XDATA, M_WAITOK); 1228 1.36 tls if((error = copyin(cnop[req].key, 1229 1.36 tls crde->crd_key, cnop[req].keylen))) { 1230 1.36 tls cnop[req].status = EINVAL; 1231 1.36 tls goto bail; 1232 1.36 tls } 1233 1.36 tls crde->crd_klen = cnop[req].keylen * 8; 1234 1.36 tls } else { ... } 1235 1.36 tls #endif 1236 1.36 tls crde->crd_key = cse->key; 1237 1.36 tls crde->crd_klen = cse->keylen * 8; 1238 1.36 tls } 1239 1.36 tls 1240 1.36 tls crp->crp_ilen = cnop[req].len; 1241 1.113 riastrad crp->crp_flags = CRYPTO_F_IOV | 1242 1.46 darran (cnop[req].flags & COP_F_BATCH) | flags; 1243 1.36 tls crp->crp_buf = (void *)&crp->uio; 1244 1.108 riastrad crp->crp_callback = cryptodev_mcb; 1245 1.36 tls crp->crp_sid = cse->sid; 1246 1.108 riastrad crp->crp_opaque = cse; 1247 1.36 tls crp->fcrp = fcr; 1248 1.36 tls crp->dst = cnop[req].dst; 1249 1.46 darran crp->len = cnop[req].len; /* input len, iov may be larger */ 1250 1.36 tls crp->mac = cnop[req].mac; 1251 1.90 knakahar DPRINTF("iov_base %p dst %p len %d mac %p\n", 1252 1.46 darran crp->uio.uio_iov[0].iov_base, crp->dst, crp->len, 1253 1.90 knakahar crp->mac); 1254 1.36 tls 1255 1.36 tls if (cnop[req].iv) { 1256 1.36 tls if (crde == NULL) { 1257 1.36 tls cnop[req].status = EINVAL; 1258 1.36 tls goto bail; 1259 1.36 tls } 1260 1.36 tls if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ 1261 1.36 tls cnop[req].status = EINVAL; 1262 1.36 tls goto bail; 1263 1.36 tls } 1264 1.36 tls if ((error = copyin(cnop[req].iv, crp->tmp_iv, 1265 1.58 drochner cse->txform->ivsize))) { 1266 1.36 tls cnop[req].status = EINVAL; 1267 1.36 tls goto bail; 1268 1.36 tls } 1269 1.42 christos (void)memcpy(crde->crd_iv, crp->tmp_iv, 1270 1.58 drochner cse->txform->ivsize); 1271 1.36 tls crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; 1272 1.36 tls crde->crd_skip = 0; 1273 1.36 tls } else if (crde) { 1274 1.36 tls if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */ 1275 1.36 tls crde->crd_skip = 0; 1276 1.36 tls } else { 1277 1.61 drochner if (!(crde->crd_flags & CRD_F_ENCRYPT)) 1278 1.61 drochner crde->crd_flags |= CRD_F_IV_PRESENT; 1279 1.58 drochner crde->crd_skip = cse->txform->ivsize; 1280 1.58 drochner crde->crd_len -= cse->txform->ivsize; 1281 1.36 tls } 1282 1.36 tls } 1283 1.36 tls 1284 1.36 tls if (cnop[req].mac) { 1285 1.36 tls if (crda == NULL) { 1286 1.36 tls cnop[req].status = EINVAL; 1287 1.36 tls goto bail; 1288 1.36 tls } 1289 1.36 tls crp->crp_mac=cse->tmp_mac; 1290 1.36 tls } 1291 1.36 tls cnop[req].reqid = atomic_inc_32_nv(&(fcr->requestid)); 1292 1.36 tls crp->crp_reqid = cnop[req].reqid; 1293 1.36 tls crp->crp_usropaque = cnop[req].opaque; 1294 1.67 drochner cv_init(&crp->crp_cv, "crydev"); 1295 1.123 riastrad crypto_dispatch(crp); 1296 1.123 riastrad cnop[req].status = 0; 1297 1.67 drochner cv_destroy(&crp->crp_cv); 1298 1.36 tls bail: 1299 1.36 tls if (cnop[req].status) { 1300 1.36 tls if (crp) { 1301 1.46 darran if (crp->uio.uio_iov[0].iov_base) { 1302 1.46 darran kmem_free(crp->uio.uio_iov[0].iov_base, 1303 1.46 darran crp->uio.uio_iov[0].iov_len); 1304 1.46 darran } 1305 1.36 tls crypto_freereq(crp); 1306 1.36 tls } 1307 1.36 tls error = 0; 1308 1.36 tls } 1309 1.36 tls } 1310 1.42 christos return error; 1311 1.36 tls } 1312 1.36 tls 1313 1.36 tls static int 1314 1.36 tls cryptodev_mkey(struct fcrypt *fcr, struct crypt_n_kop *kop, int count) 1315 1.36 tls { 1316 1.36 tls struct cryptkop *krp = NULL; 1317 1.36 tls int error = EINVAL; 1318 1.36 tls int in, out, size, i, req; 1319 1.36 tls 1320 1.36 tls for (req = 0; req < count; req++) { 1321 1.42 christos if (kop[req].crk_iparams + kop[req].crk_oparams > CRK_MAXPARAM) 1322 1.42 christos return EFBIG; 1323 1.36 tls 1324 1.36 tls in = kop[req].crk_iparams; 1325 1.36 tls out = kop[req].crk_oparams; 1326 1.36 tls switch (kop[req].crk_op) { 1327 1.36 tls case CRK_MOD_EXP: 1328 1.36 tls if (in == 3 && out == 1) 1329 1.36 tls break; 1330 1.36 tls kop[req].crk_status = EINVAL; 1331 1.36 tls continue; 1332 1.36 tls case CRK_MOD_EXP_CRT: 1333 1.36 tls if (in == 6 && out == 1) 1334 1.36 tls break; 1335 1.36 tls kop[req].crk_status = EINVAL; 1336 1.36 tls continue; 1337 1.36 tls case CRK_DSA_SIGN: 1338 1.36 tls if (in == 5 && out == 2) 1339 1.36 tls break; 1340 1.36 tls kop[req].crk_status = EINVAL; 1341 1.36 tls continue; 1342 1.36 tls case CRK_DSA_VERIFY: 1343 1.36 tls if (in == 7 && out == 0) 1344 1.36 tls break; 1345 1.36 tls kop[req].crk_status = EINVAL; 1346 1.36 tls continue; 1347 1.36 tls case CRK_DH_COMPUTE_KEY: 1348 1.36 tls if (in == 3 && out == 1) 1349 1.36 tls break; 1350 1.36 tls kop[req].crk_status = EINVAL; 1351 1.36 tls continue; 1352 1.36 tls case CRK_MOD_ADD: 1353 1.36 tls if (in == 3 && out == 1) 1354 1.36 tls break; 1355 1.36 tls kop[req].crk_status = EINVAL; 1356 1.36 tls continue; 1357 1.36 tls case CRK_MOD_ADDINV: 1358 1.36 tls if (in == 2 && out == 1) 1359 1.36 tls break; 1360 1.36 tls kop[req].crk_status = EINVAL; 1361 1.36 tls continue; 1362 1.36 tls case CRK_MOD_SUB: 1363 1.36 tls if (in == 3 && out == 1) 1364 1.36 tls break; 1365 1.36 tls kop[req].crk_status = EINVAL; 1366 1.36 tls continue; 1367 1.36 tls case CRK_MOD_MULT: 1368 1.36 tls if (in == 3 && out == 1) 1369 1.85 msaitoh break; 1370 1.36 tls kop[req].crk_status = EINVAL; 1371 1.36 tls continue; 1372 1.36 tls case CRK_MOD_MULTINV: 1373 1.36 tls if (in == 2 && out == 1) 1374 1.36 tls break; 1375 1.36 tls kop[req].crk_status = EINVAL; 1376 1.36 tls continue; 1377 1.36 tls case CRK_MOD: 1378 1.36 tls if (in == 2 && out == 1) 1379 1.36 tls break; 1380 1.36 tls kop[req].crk_status = EINVAL; 1381 1.36 tls continue; 1382 1.36 tls default: 1383 1.36 tls kop[req].crk_status = EINVAL; 1384 1.36 tls continue; 1385 1.36 tls } 1386 1.36 tls 1387 1.91 knakahar krp = crypto_kgetreq(1, PR_WAITOK); 1388 1.91 knakahar if (krp == NULL) { 1389 1.91 knakahar /* limited by opencrypto.crypto_ret_kq.maxlen */ 1390 1.91 knakahar continue; 1391 1.91 knakahar } 1392 1.42 christos (void)memset(krp, 0, sizeof *krp); 1393 1.36 tls cv_init(&krp->krp_cv, "crykdev"); 1394 1.36 tls krp->krp_op = kop[req].crk_op; 1395 1.36 tls krp->krp_status = kop[req].crk_status; 1396 1.36 tls krp->krp_iparams = kop[req].crk_iparams; 1397 1.36 tls krp->krp_oparams = kop[req].crk_oparams; 1398 1.36 tls krp->krp_status = 0; 1399 1.108 riastrad krp->krp_callback = cryptodevkey_mcb; 1400 1.42 christos (void)memcpy(krp->crk_param, kop[req].crk_param, 1401 1.42 christos sizeof(kop[req].crk_param)); 1402 1.36 tls 1403 1.113 riastrad krp->krp_flags = 0; 1404 1.36 tls 1405 1.36 tls for (i = 0; i < CRK_MAXPARAM; i++) 1406 1.36 tls krp->krp_param[i].crp_nbits = 1407 1.36 tls kop[req].crk_param[i].crp_nbits; 1408 1.36 tls for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) { 1409 1.36 tls size = (krp->krp_param[i].crp_nbits + 7) / 8; 1410 1.36 tls if (size == 0) 1411 1.36 tls continue; 1412 1.36 tls krp->krp_param[i].crp_p = 1413 1.36 tls kmem_alloc(size, KM_SLEEP); 1414 1.36 tls if (i >= krp->krp_iparams) 1415 1.36 tls continue; 1416 1.42 christos kop[req].crk_status = 1417 1.42 christos copyin(kop[req].crk_param[i].crp_p, 1418 1.42 christos krp->krp_param[i].crp_p, size); 1419 1.36 tls if (kop[req].crk_status) 1420 1.36 tls goto fail; 1421 1.36 tls } 1422 1.36 tls krp->fcrp = fcr; 1423 1.36 tls 1424 1.36 tls kop[req].crk_reqid = atomic_inc_32_nv(&(fcr->requestid)); 1425 1.36 tls krp->krp_reqid = kop[req].crk_reqid; 1426 1.36 tls krp->krp_usropaque = kop[req].crk_opaque; 1427 1.36 tls 1428 1.123 riastrad crypto_kdispatch(krp); 1429 1.123 riastrad kop[req].crk_status = 0; 1430 1.36 tls fail: 1431 1.123 riastrad if (kop[req].crk_status) { 1432 1.36 tls if (krp) { 1433 1.36 tls kop[req].crk_status = krp->krp_status; 1434 1.36 tls for (i = 0; i < CRK_MAXPARAM; i++) { 1435 1.36 tls struct crparam *kp = 1436 1.36 tls &(krp->krp_param[i]); 1437 1.36 tls if (kp->crp_p) { 1438 1.36 tls size = (kp->crp_nbits + 7) / 8; 1439 1.36 tls KASSERT(size > 0); 1440 1.36 tls memset(kp->crp_p, 0, size); 1441 1.36 tls kmem_free(kp->crp_p, size); 1442 1.36 tls } 1443 1.36 tls } 1444 1.45 darran cv_destroy(&krp->krp_cv); 1445 1.91 knakahar crypto_kfreereq(krp); 1446 1.36 tls } 1447 1.36 tls } 1448 1.36 tls error = 0; 1449 1.36 tls } 1450 1.90 knakahar DPRINTF("error=0x%08x\n", error); 1451 1.42 christos return error; 1452 1.36 tls } 1453 1.36 tls 1454 1.46 darran int 1455 1.45 darran cryptodev_session(struct fcrypt *fcr, struct session_op *sop) 1456 1.45 darran { 1457 1.36 tls struct cryptoini cria, crie; 1458 1.46 darran struct cryptoini cric; /* compressor */ 1459 1.46 darran struct cryptoini *crihead = NULL; 1460 1.54 drochner const struct enc_xform *txform = NULL; 1461 1.54 drochner const struct auth_hash *thash = NULL; 1462 1.54 drochner const struct comp_algo *tcomp = NULL; 1463 1.36 tls struct csession *cse; 1464 1.36 tls u_int64_t sid; 1465 1.36 tls int error = 0; 1466 1.36 tls 1467 1.90 knakahar DPRINTF("cipher=%d, mac=%d\n", sop->cipher, sop->mac); 1468 1.46 darran 1469 1.36 tls /* XXX there must be a way to not embed the list of xforms here */ 1470 1.36 tls switch (sop->cipher) { 1471 1.36 tls case 0: 1472 1.36 tls break; 1473 1.36 tls case CRYPTO_DES_CBC: 1474 1.36 tls txform = &enc_xform_des; 1475 1.36 tls break; 1476 1.36 tls case CRYPTO_3DES_CBC: 1477 1.36 tls txform = &enc_xform_3des; 1478 1.36 tls break; 1479 1.36 tls case CRYPTO_BLF_CBC: 1480 1.36 tls txform = &enc_xform_blf; 1481 1.36 tls break; 1482 1.36 tls case CRYPTO_CAST_CBC: 1483 1.36 tls txform = &enc_xform_cast5; 1484 1.52 hubertf break; 1485 1.36 tls case CRYPTO_SKIPJACK_CBC: 1486 1.36 tls txform = &enc_xform_skipjack; 1487 1.36 tls break; 1488 1.36 tls case CRYPTO_AES_CBC: 1489 1.106 riastrad txform = &enc_xform_aes; 1490 1.36 tls break; 1491 1.60 drochner case CRYPTO_CAMELLIA_CBC: 1492 1.60 drochner txform = &enc_xform_camellia; 1493 1.60 drochner break; 1494 1.59 drochner case CRYPTO_AES_CTR: 1495 1.59 drochner txform = &enc_xform_aes_ctr; 1496 1.59 drochner break; 1497 1.66 drochner case CRYPTO_AES_GCM_16: 1498 1.66 drochner txform = &enc_xform_aes_gcm; 1499 1.66 drochner break; 1500 1.66 drochner case CRYPTO_AES_GMAC: 1501 1.66 drochner txform = &enc_xform_aes_gmac; 1502 1.66 drochner break; 1503 1.36 tls case CRYPTO_NULL_CBC: 1504 1.36 tls txform = &enc_xform_null; 1505 1.36 tls break; 1506 1.36 tls case CRYPTO_ARC4: 1507 1.36 tls txform = &enc_xform_arc4; 1508 1.36 tls break; 1509 1.36 tls default: 1510 1.90 knakahar DPRINTF("Invalid cipher %d\n", sop->cipher); 1511 1.36 tls return EINVAL; 1512 1.36 tls } 1513 1.36 tls 1514 1.46 darran switch (sop->comp_alg) { 1515 1.46 darran case 0: 1516 1.46 darran break; 1517 1.46 darran case CRYPTO_DEFLATE_COMP: 1518 1.46 darran tcomp = &comp_algo_deflate; 1519 1.46 darran break; 1520 1.46 darran case CRYPTO_GZIP_COMP: 1521 1.46 darran tcomp = &comp_algo_gzip; 1522 1.90 knakahar DPRINTF("tcomp for GZIP\n"); 1523 1.46 darran break; 1524 1.46 darran default: 1525 1.90 knakahar DPRINTF("Invalid compression alg %d\n", sop->comp_alg); 1526 1.46 darran return EINVAL; 1527 1.46 darran } 1528 1.46 darran 1529 1.36 tls switch (sop->mac) { 1530 1.36 tls case 0: 1531 1.36 tls break; 1532 1.36 tls case CRYPTO_MD5_HMAC: 1533 1.36 tls thash = &auth_hash_hmac_md5; 1534 1.36 tls break; 1535 1.36 tls case CRYPTO_SHA1_HMAC: 1536 1.36 tls thash = &auth_hash_hmac_sha1; 1537 1.36 tls break; 1538 1.36 tls case CRYPTO_MD5_HMAC_96: 1539 1.36 tls thash = &auth_hash_hmac_md5_96; 1540 1.36 tls break; 1541 1.36 tls case CRYPTO_SHA1_HMAC_96: 1542 1.36 tls thash = &auth_hash_hmac_sha1_96; 1543 1.36 tls break; 1544 1.36 tls case CRYPTO_SHA2_HMAC: 1545 1.36 tls /* XXX switching on key length seems questionable */ 1546 1.36 tls if (sop->mackeylen == auth_hash_hmac_sha2_256.keysize) { 1547 1.36 tls thash = &auth_hash_hmac_sha2_256; 1548 1.36 tls } else if (sop->mackeylen == auth_hash_hmac_sha2_384.keysize) { 1549 1.36 tls thash = &auth_hash_hmac_sha2_384; 1550 1.36 tls } else if (sop->mackeylen == auth_hash_hmac_sha2_512.keysize) { 1551 1.36 tls thash = &auth_hash_hmac_sha2_512; 1552 1.36 tls } else { 1553 1.90 knakahar DPRINTF("Invalid mackeylen %d\n", sop->mackeylen); 1554 1.36 tls return EINVAL; 1555 1.36 tls } 1556 1.36 tls break; 1557 1.102 hikaru case CRYPTO_SHA2_384_HMAC: 1558 1.102 hikaru thash = &auth_hash_hmac_sha2_384; 1559 1.102 hikaru break; 1560 1.102 hikaru case CRYPTO_SHA2_512_HMAC: 1561 1.102 hikaru thash = &auth_hash_hmac_sha2_512; 1562 1.102 hikaru break; 1563 1.36 tls case CRYPTO_RIPEMD160_HMAC: 1564 1.36 tls thash = &auth_hash_hmac_ripemd_160; 1565 1.36 tls break; 1566 1.36 tls case CRYPTO_RIPEMD160_HMAC_96: 1567 1.36 tls thash = &auth_hash_hmac_ripemd_160_96; 1568 1.36 tls break; 1569 1.36 tls case CRYPTO_MD5: 1570 1.36 tls thash = &auth_hash_md5; 1571 1.36 tls break; 1572 1.36 tls case CRYPTO_SHA1: 1573 1.36 tls thash = &auth_hash_sha1; 1574 1.36 tls break; 1575 1.63 drochner case CRYPTO_AES_XCBC_MAC_96: 1576 1.63 drochner thash = &auth_hash_aes_xcbc_mac_96; 1577 1.63 drochner break; 1578 1.66 drochner case CRYPTO_AES_128_GMAC: 1579 1.66 drochner thash = &auth_hash_gmac_aes_128; 1580 1.66 drochner break; 1581 1.66 drochner case CRYPTO_AES_192_GMAC: 1582 1.66 drochner thash = &auth_hash_gmac_aes_192; 1583 1.66 drochner break; 1584 1.66 drochner case CRYPTO_AES_256_GMAC: 1585 1.66 drochner thash = &auth_hash_gmac_aes_256; 1586 1.66 drochner break; 1587 1.36 tls case CRYPTO_NULL_HMAC: 1588 1.36 tls thash = &auth_hash_null; 1589 1.36 tls break; 1590 1.36 tls default: 1591 1.90 knakahar DPRINTF("Invalid mac %d\n", sop->mac); 1592 1.42 christos return EINVAL; 1593 1.36 tls } 1594 1.36 tls 1595 1.36 tls memset(&crie, 0, sizeof(crie)); 1596 1.36 tls memset(&cria, 0, sizeof(cria)); 1597 1.46 darran memset(&cric, 0, sizeof(cric)); 1598 1.46 darran 1599 1.46 darran if (tcomp) { 1600 1.46 darran cric.cri_alg = tcomp->type; 1601 1.46 darran cric.cri_klen = 0; 1602 1.90 knakahar DPRINTF("tcomp->type = %d\n", tcomp->type); 1603 1.46 darran 1604 1.46 darran crihead = &cric; 1605 1.65 drochner if (txform) { 1606 1.65 drochner cric.cri_next = &crie; 1607 1.65 drochner } else if (thash) { 1608 1.46 darran cric.cri_next = &cria; 1609 1.46 darran } 1610 1.46 darran } 1611 1.36 tls 1612 1.36 tls if (txform) { 1613 1.36 tls crie.cri_alg = txform->type; 1614 1.36 tls crie.cri_klen = sop->keylen * 8; 1615 1.36 tls if (sop->keylen > txform->maxkey || 1616 1.36 tls sop->keylen < txform->minkey) { 1617 1.90 knakahar DPRINTF("keylen %d not in [%d,%d]\n", 1618 1.90 knakahar sop->keylen, txform->minkey, txform->maxkey); 1619 1.42 christos error = EINVAL; 1620 1.36 tls goto bail; 1621 1.36 tls } 1622 1.36 tls 1623 1.36 tls crie.cri_key = malloc(crie.cri_klen / 8, M_XDATA, M_WAITOK); 1624 1.42 christos if ((error = copyin(sop->key, crie.cri_key, crie.cri_klen / 8))) 1625 1.36 tls goto bail; 1626 1.46 darran if (!crihead) { 1627 1.46 darran crihead = &crie; 1628 1.46 darran } 1629 1.65 drochner if (thash) 1630 1.65 drochner crie.cri_next = &cria; 1631 1.46 darran } 1632 1.36 tls 1633 1.36 tls if (thash) { 1634 1.36 tls cria.cri_alg = thash->type; 1635 1.36 tls cria.cri_klen = sop->mackeylen * 8; 1636 1.36 tls if (sop->mackeylen != thash->keysize) { 1637 1.90 knakahar DPRINTF("mackeylen %d != keysize %d\n", 1638 1.90 knakahar sop->mackeylen, thash->keysize); 1639 1.36 tls error = EINVAL; 1640 1.36 tls goto bail; 1641 1.36 tls } 1642 1.36 tls if (cria.cri_klen) { 1643 1.36 tls cria.cri_key = malloc(cria.cri_klen / 8, M_XDATA, 1644 1.42 christos M_WAITOK); 1645 1.36 tls if ((error = copyin(sop->mackey, cria.cri_key, 1646 1.42 christos cria.cri_klen / 8))) { 1647 1.36 tls goto bail; 1648 1.36 tls } 1649 1.36 tls } 1650 1.46 darran if (!crihead) { 1651 1.46 darran crihead = &cria; 1652 1.46 darran } 1653 1.36 tls } 1654 1.46 darran 1655 1.46 darran error = crypto_newsession(&sid, crihead, crypto_devallowsoft); 1656 1.36 tls if (!error) { 1657 1.90 knakahar DPRINTF("got session %d\n", (uint32_t)sid); 1658 1.36 tls cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen, 1659 1.46 darran cria.cri_key, cria.cri_klen, (txform ? sop->cipher : 0), sop->mac, 1660 1.46 darran (tcomp ? sop->comp_alg : 0), txform, thash, tcomp); 1661 1.36 tls if (cse != NULL) { 1662 1.36 tls sop->ses = cse->ses; 1663 1.36 tls } else { 1664 1.90 knakahar DPRINTF("csecreate failed\n"); 1665 1.36 tls crypto_freesession(sid); 1666 1.36 tls error = EINVAL; 1667 1.36 tls } 1668 1.36 tls } else { 1669 1.90 knakahar DPRINTF("SIOCSESSION violates kernel parameters %d\n", error); 1670 1.36 tls } 1671 1.36 tls bail: 1672 1.36 tls if (error) { 1673 1.36 tls if (crie.cri_key) { 1674 1.36 tls memset(crie.cri_key, 0, crie.cri_klen / 8); 1675 1.36 tls free(crie.cri_key, M_XDATA); 1676 1.36 tls } 1677 1.36 tls if (cria.cri_key) { 1678 1.36 tls memset(cria.cri_key, 0, cria.cri_klen / 8); 1679 1.36 tls free(cria.cri_key, M_XDATA); 1680 1.36 tls } 1681 1.36 tls } 1682 1.36 tls return error; 1683 1.36 tls } 1684 1.36 tls 1685 1.46 darran int 1686 1.36 tls cryptodev_msession(struct fcrypt *fcr, struct session_n_op *sn_ops, 1687 1.36 tls int count) 1688 1.36 tls { 1689 1.36 tls int i; 1690 1.36 tls 1691 1.36 tls for (i = 0; i < count; i++, sn_ops++) { 1692 1.36 tls struct session_op s_op; 1693 1.36 tls s_op.cipher = sn_ops->cipher; 1694 1.36 tls s_op.mac = sn_ops->mac; 1695 1.94 knakahar s_op.comp_alg = sn_ops->comp_alg; 1696 1.36 tls s_op.keylen = sn_ops->keylen; 1697 1.36 tls s_op.key = sn_ops->key; 1698 1.36 tls s_op.mackeylen = sn_ops->mackeylen; 1699 1.36 tls s_op.mackey = sn_ops->mackey; 1700 1.103 christos s_op.ses = ~0; 1701 1.36 tls 1702 1.36 tls sn_ops->status = cryptodev_session(fcr, &s_op); 1703 1.94 knakahar 1704 1.36 tls sn_ops->ses = s_op.ses; 1705 1.36 tls } 1706 1.36 tls 1707 1.36 tls return 0; 1708 1.36 tls } 1709 1.36 tls 1710 1.121 riastrad static void 1711 1.36 tls cryptodev_msessionfin(struct fcrypt *fcr, int count, u_int32_t *sesid) 1712 1.36 tls { 1713 1.36 tls struct csession *cse; 1714 1.121 riastrad int req; 1715 1.36 tls 1716 1.92 knakahar mutex_enter(&cryptodev_mtx); 1717 1.36 tls for(req = 0; req < count; req++) { 1718 1.36 tls cse = csefind(fcr, sesid[req]); 1719 1.36 tls if (cse == NULL) 1720 1.36 tls continue; 1721 1.36 tls csedelete(fcr, cse); 1722 1.92 knakahar mutex_exit(&cryptodev_mtx); 1723 1.121 riastrad csefree(cse); 1724 1.92 knakahar mutex_enter(&cryptodev_mtx); 1725 1.36 tls } 1726 1.92 knakahar mutex_exit(&cryptodev_mtx); 1727 1.36 tls } 1728 1.36 tls 1729 1.36 tls /* 1730 1.125 rillig * collect as many completed requests as are available, or count completed 1731 1.125 rillig * requests, whichever is less. 1732 1.36 tls * return the number of requests. 1733 1.36 tls */ 1734 1.36 tls static int 1735 1.36 tls cryptodev_getmstatus(struct fcrypt *fcr, struct crypt_result *crypt_res, 1736 1.42 christos int count) 1737 1.36 tls { 1738 1.36 tls struct cryptop *crp = NULL; 1739 1.36 tls struct cryptkop *krp = NULL; 1740 1.36 tls struct csession *cse; 1741 1.36 tls int i, size, req = 0; 1742 1.36 tls int completed=0; 1743 1.36 tls 1744 1.46 darran /* On queue so nobody else can grab them 1745 1.46 darran * and copyout can be delayed-- no locking */ 1746 1.46 darran TAILQ_HEAD(, cryptop) crp_delfree_q = 1747 1.46 darran TAILQ_HEAD_INITIALIZER(crp_delfree_q); 1748 1.46 darran TAILQ_HEAD(, cryptkop) krp_delfree_q = 1749 1.46 darran TAILQ_HEAD_INITIALIZER(krp_delfree_q); 1750 1.36 tls 1751 1.36 tls /* at this point we do not know which response user is requesting for 1752 1.36 tls * (symmetric or asymmetric) so we copyout one from each i.e if the 1753 1.36 tls * count is 2 then 1 from symmetric and 1 from asymmetric queue and 1754 1.36 tls * if 3 then 2 symmetric and 1 asymmetric and so on */ 1755 1.46 darran 1756 1.46 darran /* pull off a list of requests while protected from changes */ 1757 1.92 knakahar mutex_enter(&cryptodev_mtx); 1758 1.46 darran while (req < count) { 1759 1.36 tls crp = TAILQ_FIRST(&fcr->crp_ret_mq); 1760 1.46 darran if (crp) { 1761 1.46 darran TAILQ_REMOVE(&fcr->crp_ret_mq, crp, crp_next); 1762 1.46 darran TAILQ_INSERT_TAIL(&crp_delfree_q, crp, crp_next); 1763 1.36 tls cse = (struct csession *)crp->crp_opaque; 1764 1.46 darran 1765 1.46 darran /* see if the session is still valid */ 1766 1.36 tls cse = csefind(fcr, cse->ses); 1767 1.46 darran if (cse != NULL) { 1768 1.46 darran crypt_res[req].status = 0; 1769 1.46 darran } else { 1770 1.90 knakahar DPRINTF("csefind failed\n"); 1771 1.36 tls crypt_res[req].status = EINVAL; 1772 1.46 darran } 1773 1.46 darran req++; 1774 1.46 darran } 1775 1.46 darran if(req < count) { 1776 1.46 darran crypt_res[req].status = 0; 1777 1.46 darran krp = TAILQ_FIRST(&fcr->crp_ret_mkq); 1778 1.46 darran if (krp) { 1779 1.46 darran TAILQ_REMOVE(&fcr->crp_ret_mkq, krp, krp_next); 1780 1.46 darran TAILQ_INSERT_TAIL(&krp_delfree_q, krp, krp_next); 1781 1.46 darran req++; 1782 1.46 darran } 1783 1.46 darran } 1784 1.46 darran } 1785 1.92 knakahar mutex_exit(&cryptodev_mtx); 1786 1.46 darran 1787 1.46 darran /* now do all the work outside the mutex */ 1788 1.46 darran for(req=0; req < count ;) { 1789 1.46 darran crp = TAILQ_FIRST(&crp_delfree_q); 1790 1.46 darran if (crp) { 1791 1.46 darran if (crypt_res[req].status != 0) { 1792 1.46 darran /* csefind failed during collection */ 1793 1.36 tls goto bail; 1794 1.36 tls } 1795 1.46 darran cse = (struct csession *)crp->crp_opaque; 1796 1.46 darran crypt_res[req].reqid = crp->crp_reqid; 1797 1.46 darran crypt_res[req].opaque = crp->crp_usropaque; 1798 1.46 darran completed++; 1799 1.36 tls 1800 1.36 tls if (crp->crp_etype != 0) { 1801 1.36 tls crypt_res[req].status = crp->crp_etype; 1802 1.36 tls goto bail; 1803 1.36 tls } 1804 1.36 tls 1805 1.36 tls if (cse->error) { 1806 1.36 tls crypt_res[req].status = cse->error; 1807 1.36 tls goto bail; 1808 1.36 tls } 1809 1.36 tls 1810 1.42 christos if (crp->dst && (crypt_res[req].status = 1811 1.42 christos copyout(crp->uio.uio_iov[0].iov_base, crp->dst, 1812 1.42 christos crp->len))) 1813 1.36 tls goto bail; 1814 1.36 tls 1815 1.42 christos if (crp->mac && (crypt_res[req].status = 1816 1.42 christos copyout(crp->crp_mac, crp->mac, 1817 1.42 christos cse->thash->authsize))) 1818 1.36 tls goto bail; 1819 1.46 darran 1820 1.36 tls bail: 1821 1.46 darran TAILQ_REMOVE(&crp_delfree_q, crp, crp_next); 1822 1.46 darran kmem_free(crp->uio.uio_iov[0].iov_base, 1823 1.46 darran crp->uio.uio_iov[0].iov_len); 1824 1.46 darran crypto_freereq(crp); 1825 1.36 tls req++; 1826 1.36 tls } 1827 1.36 tls 1828 1.46 darran if (req < count) { 1829 1.46 darran krp = TAILQ_FIRST(&krp_delfree_q); 1830 1.36 tls if (krp) { 1831 1.36 tls crypt_res[req].reqid = krp->krp_reqid; 1832 1.36 tls crypt_res[req].opaque = krp->krp_usropaque; 1833 1.36 tls completed++; 1834 1.36 tls if (krp->krp_status != 0) { 1835 1.90 knakahar DPRINTF("krp->krp_status 0x%08x\n", 1836 1.90 knakahar krp->krp_status); 1837 1.42 christos crypt_res[req].status = krp->krp_status; 1838 1.36 tls goto fail; 1839 1.36 tls } 1840 1.36 tls 1841 1.36 tls for (i = krp->krp_iparams; i < krp->krp_iparams 1842 1.42 christos + krp->krp_oparams; i++) { 1843 1.36 tls size = (krp->krp_param[i].crp_nbits 1844 1.42 christos + 7) / 8; 1845 1.36 tls if (size == 0) 1846 1.36 tls continue; 1847 1.36 tls crypt_res[req].status = copyout 1848 1.36 tls (krp->krp_param[i].crp_p, 1849 1.36 tls krp->crk_param[i].crp_p, size); 1850 1.36 tls if (crypt_res[req].status) { 1851 1.90 knakahar DPRINTF("copyout oparam %d failed, " 1852 1.42 christos "error=%d\n", 1853 1.42 christos i - krp->krp_iparams, 1854 1.90 knakahar crypt_res[req].status); 1855 1.36 tls goto fail; 1856 1.36 tls } 1857 1.36 tls } 1858 1.36 tls fail: 1859 1.46 darran TAILQ_REMOVE(&krp_delfree_q, krp, krp_next); 1860 1.36 tls /* not sure what to do for this */ 1861 1.36 tls /* kop[req].crk_status = krp->krp_status; */ 1862 1.46 darran for (i = 0; i < CRK_MAXPARAM; i++) { 1863 1.46 darran struct crparam *kp = &(krp->krp_param[i]); 1864 1.46 darran if (kp->crp_p) { 1865 1.46 darran size = (kp->crp_nbits + 7) / 8; 1866 1.46 darran KASSERT(size > 0); 1867 1.46 darran (void)memset(kp->crp_p, 0, size); 1868 1.46 darran kmem_free(kp->crp_p, size); 1869 1.46 darran } 1870 1.46 darran } 1871 1.46 darran cv_destroy(&krp->krp_cv); 1872 1.91 knakahar crypto_kfreereq(krp); 1873 1.46 darran req++; 1874 1.36 tls } 1875 1.36 tls } 1876 1.36 tls } 1877 1.36 tls 1878 1.85 msaitoh return completed; 1879 1.36 tls } 1880 1.36 tls 1881 1.36 tls static int 1882 1.36 tls cryptodev_getstatus (struct fcrypt *fcr, struct crypt_result *crypt_res) 1883 1.36 tls { 1884 1.45 darran struct cryptop *crp = NULL, *cnext; 1885 1.45 darran struct cryptkop *krp = NULL, *knext; 1886 1.36 tls struct csession *cse; 1887 1.36 tls int i, size, req = 0; 1888 1.36 tls 1889 1.92 knakahar mutex_enter(&cryptodev_mtx); 1890 1.36 tls /* Here we dont know for which request the user is requesting the 1891 1.36 tls * response so checking in both the queues */ 1892 1.45 darran TAILQ_FOREACH_SAFE(crp, &fcr->crp_ret_mq, crp_next, cnext) { 1893 1.36 tls if(crp && (crp->crp_reqid == crypt_res->reqid)) { 1894 1.36 tls cse = (struct csession *)crp->crp_opaque; 1895 1.36 tls crypt_res->opaque = crp->crp_usropaque; 1896 1.36 tls cse = csefind(fcr, cse->ses); 1897 1.36 tls if (cse == NULL) { 1898 1.90 knakahar DPRINTF("csefind failed\n"); 1899 1.36 tls crypt_res->status = EINVAL; 1900 1.36 tls goto bail; 1901 1.36 tls } 1902 1.36 tls 1903 1.36 tls if (crp->crp_etype != 0) { 1904 1.36 tls crypt_res->status = crp->crp_etype; 1905 1.36 tls goto bail; 1906 1.36 tls } 1907 1.36 tls 1908 1.36 tls if (cse->error) { 1909 1.36 tls crypt_res->status = cse->error; 1910 1.36 tls goto bail; 1911 1.36 tls } 1912 1.36 tls 1913 1.42 christos if (crp->dst && (crypt_res->status = 1914 1.42 christos copyout(crp->uio.uio_iov[0].iov_base, 1915 1.42 christos crp->dst, crp->len))) 1916 1.36 tls goto bail; 1917 1.36 tls 1918 1.42 christos if (crp->mac && (crypt_res->status = 1919 1.42 christos copyout(crp->crp_mac, crp->mac, 1920 1.42 christos cse->thash->authsize))) 1921 1.36 tls goto bail; 1922 1.36 tls bail: 1923 1.36 tls TAILQ_REMOVE(&fcr->crp_ret_mq, crp, crp_next); 1924 1.36 tls 1925 1.92 knakahar mutex_exit(&cryptodev_mtx); 1926 1.36 tls crypto_freereq(crp); 1927 1.36 tls return 0; 1928 1.36 tls } 1929 1.36 tls } 1930 1.36 tls 1931 1.45 darran TAILQ_FOREACH_SAFE(krp, &fcr->crp_ret_mkq, krp_next, knext) { 1932 1.36 tls if(krp && (krp->krp_reqid == crypt_res->reqid)) { 1933 1.36 tls crypt_res[req].opaque = krp->krp_usropaque; 1934 1.36 tls if (krp->krp_status != 0) { 1935 1.90 knakahar DPRINTF("krp->krp_status 0x%08x\n", 1936 1.90 knakahar krp->krp_status); 1937 1.36 tls crypt_res[req].status = krp->krp_status; 1938 1.36 tls goto fail; 1939 1.36 tls } 1940 1.36 tls 1941 1.42 christos for (i = krp->krp_iparams; i < krp->krp_iparams + 1942 1.42 christos krp->krp_oparams; i++) { 1943 1.36 tls size = (krp->krp_param[i].crp_nbits + 7) / 8; 1944 1.36 tls if (size == 0) 1945 1.36 tls continue; 1946 1.42 christos crypt_res[req].status = copyout( 1947 1.42 christos krp->krp_param[i].crp_p, 1948 1.42 christos krp->crk_param[i].crp_p, size); 1949 1.36 tls if (crypt_res[req].status) { 1950 1.90 knakahar DPRINTF("copyout oparam " 1951 1.42 christos "%d failed, error=%d\n", 1952 1.42 christos i - krp->krp_iparams, 1953 1.90 knakahar crypt_res[req].status); 1954 1.36 tls goto fail; 1955 1.36 tls } 1956 1.36 tls } 1957 1.36 tls fail: 1958 1.36 tls TAILQ_REMOVE(&fcr->crp_ret_mkq, krp, krp_next); 1959 1.92 knakahar mutex_exit(&cryptodev_mtx); 1960 1.36 tls /* not sure what to do for this */ 1961 1.36 tls /* kop[req].crk_status = krp->krp_status; */ 1962 1.36 tls for (i = 0; i < CRK_MAXPARAM; i++) { 1963 1.36 tls struct crparam *kp = &(krp->krp_param[i]); 1964 1.36 tls if (kp->crp_p) { 1965 1.36 tls size = (kp->crp_nbits + 7) / 8; 1966 1.36 tls KASSERT(size > 0); 1967 1.36 tls memset(kp->crp_p, 0, size); 1968 1.36 tls kmem_free(kp->crp_p, size); 1969 1.36 tls } 1970 1.36 tls } 1971 1.45 darran cv_destroy(&krp->krp_cv); 1972 1.91 knakahar crypto_kfreereq(krp); 1973 1.36 tls return 0; 1974 1.36 tls } 1975 1.36 tls } 1976 1.92 knakahar mutex_exit(&cryptodev_mtx); 1977 1.85 msaitoh return EINPROGRESS; 1978 1.36 tls } 1979 1.36 tls 1980 1.36 tls static int 1981 1.48 christos cryptof_stat(struct file *fp, struct stat *st) 1982 1.48 christos { 1983 1.81 matt struct fcrypt *fcr = fp->f_fcrypt; 1984 1.48 christos 1985 1.68 joerg (void)memset(st, 0, sizeof(*st)); 1986 1.49 christos 1987 1.92 knakahar mutex_enter(&cryptodev_mtx); 1988 1.48 christos st->st_dev = makedev(cdevsw_lookup_major(&crypto_cdevsw), fcr->sesn); 1989 1.48 christos st->st_atimespec = fcr->atime; 1990 1.48 christos st->st_mtimespec = fcr->mtime; 1991 1.48 christos st->st_ctimespec = st->st_birthtimespec = fcr->btime; 1992 1.49 christos st->st_uid = kauth_cred_geteuid(fp->f_cred); 1993 1.49 christos st->st_gid = kauth_cred_getegid(fp->f_cred); 1994 1.92 knakahar mutex_exit(&cryptodev_mtx); 1995 1.49 christos 1996 1.48 christos return 0; 1997 1.48 christos } 1998 1.48 christos 1999 1.48 christos static int 2000 1.36 tls cryptof_poll(struct file *fp, int events) 2001 1.36 tls { 2002 1.81 matt struct fcrypt *fcr = fp->f_fcrypt; 2003 1.38 rmind int revents = 0; 2004 1.36 tls 2005 1.36 tls if (!(events & (POLLIN | POLLRDNORM))) { 2006 1.36 tls /* only support read and POLLIN */ 2007 1.36 tls return 0; 2008 1.36 tls } 2009 1.36 tls 2010 1.92 knakahar mutex_enter(&cryptodev_mtx); 2011 1.36 tls if (TAILQ_EMPTY(&fcr->crp_ret_mq) && TAILQ_EMPTY(&fcr->crp_ret_mkq)) { 2012 1.38 rmind /* no completed requests pending, save the poll for later */ 2013 1.36 tls selrecord(curlwp, &fcr->sinfo); 2014 1.36 tls } else { 2015 1.36 tls /* let the app(s) know that there are completed requests */ 2016 1.38 rmind revents = events & (POLLIN | POLLRDNORM); 2017 1.36 tls } 2018 1.92 knakahar mutex_exit(&cryptodev_mtx); 2019 1.38 rmind 2020 1.38 rmind return revents; 2021 1.36 tls } 2022 1.36 tls 2023 1.15 thorpej /* 2024 1.15 thorpej * Pseudo-device initialization routine for /dev/crypto 2025 1.15 thorpej */ 2026 1.15 thorpej void 2027 1.25 christos cryptoattach(int num) 2028 1.15 thorpej { 2029 1.96 christos 2030 1.80 skrll crypto_init(); 2031 1.80 skrll 2032 1.92 knakahar mutex_init(&cryptodev_mtx, MUTEX_DEFAULT, IPL_NONE); 2033 1.89 knakahar 2034 1.29 tls pool_init(&fcrpl, sizeof(struct fcrypt), 0, 0, 0, "fcrpl", 2035 1.109 riastrad NULL, IPL_NONE); 2036 1.29 tls pool_init(&csepl, sizeof(struct csession), 0, 0, 0, "csepl", 2037 1.109 riastrad NULL, IPL_NONE); 2038 1.29 tls 2039 1.29 tls /* 2040 1.29 tls * Preallocate space for 64 users, with 5 sessions each. 2041 1.29 tls * (consider that a TLS protocol session requires at least 2042 1.29 tls * 3DES, MD5, and SHA1 (both hashes are used in the PRF) for 2043 1.29 tls * the negotiation, plus HMAC_SHA1 for the actual SSL records, 2044 1.29 tls * consuming one session here for each algorithm. 2045 1.29 tls */ 2046 1.105 chs pool_prime(&fcrpl, 64); 2047 1.105 chs pool_prime(&csepl, 64 * 5); 2048 1.15 thorpej } 2049 1.70 pgoyette 2050 1.70 pgoyette void crypto_attach(device_t, device_t, void *); 2051 1.70 pgoyette 2052 1.70 pgoyette void 2053 1.70 pgoyette crypto_attach(device_t parent, device_t self, void * opaque) 2054 1.70 pgoyette { 2055 1.70 pgoyette 2056 1.70 pgoyette cryptoattach(0); 2057 1.70 pgoyette } 2058 1.70 pgoyette 2059 1.70 pgoyette int crypto_detach(device_t, int); 2060 1.70 pgoyette 2061 1.70 pgoyette int 2062 1.70 pgoyette crypto_detach(device_t self, int num) 2063 1.70 pgoyette { 2064 1.73 pgoyette 2065 1.70 pgoyette pool_destroy(&fcrpl); 2066 1.70 pgoyette pool_destroy(&csepl); 2067 1.70 pgoyette 2068 1.92 knakahar mutex_destroy(&cryptodev_mtx); 2069 1.89 knakahar 2070 1.70 pgoyette return 0; 2071 1.70 pgoyette } 2072 1.70 pgoyette 2073 1.70 pgoyette int crypto_match(device_t, cfdata_t, void *); 2074 1.70 pgoyette 2075 1.70 pgoyette int 2076 1.70 pgoyette crypto_match(device_t parent, cfdata_t data, void *opaque) 2077 1.70 pgoyette { 2078 1.70 pgoyette 2079 1.70 pgoyette return 1; 2080 1.70 pgoyette } 2081 1.70 pgoyette 2082 1.71 pgoyette MODULE(MODULE_CLASS_DRIVER, crypto, "opencrypto"); 2083 1.70 pgoyette 2084 1.70 pgoyette CFDRIVER_DECL(crypto, DV_DULL, NULL); 2085 1.70 pgoyette 2086 1.70 pgoyette CFATTACH_DECL2_NEW(crypto, 0, crypto_match, crypto_attach, crypto_detach, 2087 1.70 pgoyette NULL, NULL, NULL); 2088 1.70 pgoyette 2089 1.71 pgoyette #ifdef _MODULE 2090 1.77 pgoyette static int cryptoloc[] = { -1, -1 }; 2091 1.77 pgoyette 2092 1.77 pgoyette static struct cfdata crypto_cfdata[] = { 2093 1.77 pgoyette { 2094 1.77 pgoyette .cf_name = "crypto", 2095 1.77 pgoyette .cf_atname = "crypto", 2096 1.77 pgoyette .cf_unit = 0, 2097 1.77 pgoyette .cf_fstate = 0, 2098 1.77 pgoyette .cf_loc = cryptoloc, 2099 1.77 pgoyette .cf_flags = 0, 2100 1.77 pgoyette .cf_pspec = NULL, 2101 1.77 pgoyette }, 2102 1.77 pgoyette { NULL, NULL, 0, 0, NULL, 0, NULL } 2103 1.77 pgoyette }; 2104 1.71 pgoyette #endif 2105 1.70 pgoyette 2106 1.70 pgoyette static int 2107 1.70 pgoyette crypto_modcmd(modcmd_t cmd, void *arg) 2108 1.70 pgoyette { 2109 1.71 pgoyette int error = 0; 2110 1.71 pgoyette #ifdef _MODULE 2111 1.70 pgoyette devmajor_t cmajor = NODEVMAJOR, bmajor = NODEVMAJOR; 2112 1.71 pgoyette #endif 2113 1.70 pgoyette 2114 1.70 pgoyette switch (cmd) { 2115 1.70 pgoyette case MODULE_CMD_INIT: 2116 1.71 pgoyette #ifdef _MODULE 2117 1.77 pgoyette 2118 1.107 pgoyette error = devsw_attach(crypto_cd.cd_name, NULL, &bmajor, 2119 1.107 pgoyette &crypto_cdevsw, &cmajor); 2120 1.107 pgoyette if (error) { 2121 1.107 pgoyette aprint_error("%s: unable to register devsw, error %d\n", 2122 1.107 pgoyette crypto_cd.cd_name, error); 2123 1.107 pgoyette return error; 2124 1.107 pgoyette } 2125 1.107 pgoyette 2126 1.77 pgoyette error = config_cfdriver_attach(&crypto_cd); 2127 1.77 pgoyette if (error) { 2128 1.107 pgoyette devsw_detach(NULL, &crypto_cdevsw); 2129 1.70 pgoyette return error; 2130 1.77 pgoyette } 2131 1.77 pgoyette 2132 1.77 pgoyette error = config_cfattach_attach(crypto_cd.cd_name, &crypto_ca); 2133 1.77 pgoyette if (error) { 2134 1.77 pgoyette config_cfdriver_detach(&crypto_cd); 2135 1.107 pgoyette devsw_detach(NULL, &crypto_cdevsw); 2136 1.77 pgoyette aprint_error("%s: unable to register cfattach\n", 2137 1.77 pgoyette crypto_cd.cd_name); 2138 1.77 pgoyette 2139 1.77 pgoyette return error; 2140 1.77 pgoyette } 2141 1.77 pgoyette 2142 1.77 pgoyette error = config_cfdata_attach(crypto_cfdata, 1); 2143 1.77 pgoyette if (error) { 2144 1.77 pgoyette config_cfattach_detach(crypto_cd.cd_name, &crypto_ca); 2145 1.77 pgoyette config_cfdriver_detach(&crypto_cd); 2146 1.107 pgoyette devsw_detach(NULL, &crypto_cdevsw); 2147 1.77 pgoyette aprint_error("%s: unable to register cfdata\n", 2148 1.77 pgoyette crypto_cd.cd_name); 2149 1.77 pgoyette 2150 1.77 pgoyette return error; 2151 1.77 pgoyette } 2152 1.70 pgoyette 2153 1.77 pgoyette (void)config_attach_pseudo(crypto_cfdata); 2154 1.71 pgoyette #endif 2155 1.70 pgoyette 2156 1.71 pgoyette return error; 2157 1.70 pgoyette case MODULE_CMD_FINI: 2158 1.71 pgoyette #ifdef _MODULE 2159 1.101 christos if (crypto_refcount != 0) 2160 1.101 christos return EBUSY; 2161 1.77 pgoyette error = config_cfdata_detach(crypto_cfdata); 2162 1.70 pgoyette if (error) { 2163 1.70 pgoyette return error; 2164 1.70 pgoyette } 2165 1.77 pgoyette 2166 1.77 pgoyette config_cfattach_detach(crypto_cd.cd_name, &crypto_ca); 2167 1.77 pgoyette config_cfdriver_detach(&crypto_cd); 2168 1.77 pgoyette devsw_detach(NULL, &crypto_cdevsw); 2169 1.71 pgoyette #endif 2170 1.70 pgoyette 2171 1.71 pgoyette return error; 2172 1.74 pgoyette #ifdef _MODULE 2173 1.74 pgoyette case MODULE_CMD_AUTOUNLOAD: 2174 1.75 pgoyette #if 0 /* 2175 1.75 pgoyette * XXX Completely disable auto-unload for now, since there is still 2176 1.75 pgoyette * XXX a (small) window where in-module ref-counting doesn't help 2177 1.75 pgoyette */ 2178 1.74 pgoyette if (crypto_refcount != 0) 2179 1.75 pgoyette #endif 2180 1.74 pgoyette return EBUSY; 2181 1.74 pgoyette /* FALLTHROUGH */ 2182 1.74 pgoyette #endif 2183 1.70 pgoyette default: 2184 1.70 pgoyette return ENOTTY; 2185 1.70 pgoyette } 2186 1.70 pgoyette } 2187