1 /*	$OpenBSD: cryptodev.c,v 1.63 2005/05/25 05:47:53 markus Exp $	*/
2 
3 /*
4  * Copyright (c) 2001 Theo de Raadt
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * Effort sponsored in part by the Defense Advanced Research Projects
28  * Agency (DARPA) and Air Force Research Laboratory, Air Force
29  * Materiel Command, USAF, under agreement number F30602-01-2-0537.
30  *
31  */
32 
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/malloc.h>
36 #include <sys/mbuf.h>
37 #include <sys/sysctl.h>
38 #include <sys/file.h>
39 #include <sys/filedesc.h>
40 #include <sys/errno.h>
41 #include <dev/rndvar.h>
42 #include <sys/conf.h>
43 #include <sys/device.h>
44 #include <syskern/md5.h>
45 #include <crypto/sha1.h>
46 #include <crypto/rmd160.h>
47 #include <crypto/cast.h>
48 #include <crypto/skipjack.h>
49 #include <crypto/blf.h>
50 #include <crypto/cryptodev.h>
51 #include <crypto/xform.h>
52 
53 #include <dev/ic/tpm.h>
54 #if defined(__i386__)
55 #include "tpm.h"
56 #else
57 #define NTPM 0
58 #endif
59 
60 #define MINOR_DIVERT(minorno, num, name, op, ...) do {			\
61 	if (minor(dev) == (minorno))					\
62 		return (num > 0 ? (name ## op (__VA_ARGS__)) : ENXIO);	\
63 } while (/* CONSTCOND */ 0)
64 
65 #define MINOR_DIVERT_TPM(op, ...) MINOR_DIVERT(1, NTPM, tpm, op, __VA_ARGS__)
66 
67 extern struct cryptocap *crypto_drivers;
68 extern int crypto_drivers_num;
69 
70 struct csession {
71 	TAILQ_ENTRY(csession) next;
72 	u_int64_t	sid;
73 	u_int32_t	ses;
74 
75 	u_int32_t	cipher;
76 	struct enc_xform *txform;
77 	u_int32_t	mac;
78 	struct auth_hash *thash;
79 
80 	caddr_t		key;
81 	int		keylen;
82 	u_char		tmp_iv[EALG_MAX_BLOCK_LEN];
83 
84 	caddr_t		mackey;
85 	int		mackeylen;
86 	u_char		tmp_mac[CRYPTO_MAX_MAC_LEN];
87 
88 	struct iovec	iovec[IOV_MAX];
89 	struct uio	uio;
90 	int		error;
91 };
92 
93 struct fcrypt {
94 	TAILQ_HEAD(csessionlist, csession) csessions;
95 	int		sesn;
96 };
97 
98 void	cryptoattach(int);
99 
100 int	cryptof_read(struct file *, off_t *, struct uio *, struct ucred *);
101 int	cryptof_write(struct file *, off_t *, struct uio *, struct ucred *);
102 int	cryptof_ioctl(struct file *, u_long, caddr_t, struct proc *p);
103 int	cryptof_poll(struct file *, int, struct proc *);
104 int	cryptof_kqfilter(struct file *, struct knote *);
105 int	cryptof_stat(struct file *, struct stat *, struct proc *);
106 int	cryptof_close(struct file *, struct proc *);
107 
108 static struct fileops cryptofops = {
109     cryptof_read,
110     cryptof_write,
111     cryptof_ioctl,
112     cryptof_poll,
113     cryptof_kqfilter,
114     cryptof_stat,
115     cryptof_close
116 };
117 
118 struct	csession *csefind(struct fcrypt *, u_int);
119 int	csedelete(struct fcrypt *, struct csession *);
120 struct	csession *cseadd(struct fcrypt *, struct csession *);
121 struct	csession *csecreate(struct fcrypt *, u_int64_t, caddr_t, u_int64_t,
122     caddr_t, u_int64_t, u_int32_t, u_int32_t, struct enc_xform *,
123     struct auth_hash *);
124 int	csefree(struct csession *);
125 
126 int	cryptodev_op(struct csession *, struct crypt_op *, struct proc *);
127 int	cryptodev_key(struct crypt_kop *);
128 int	cryptodev_dokey(struct crypt_kop *kop, struct crparam kvp[]);
129 
130 int	cryptodev_cb(void *);
131 int	cryptodevkey_cb(void *);
132 
133 int	usercrypto = 1;		/* userland may do crypto requests */
134 int	userasymcrypto = 1;	/* userland may do asymmetric crypto reqs */
135 int	cryptodevallowsoft = 0;	/* only use hardware crypto */
136 
137 /* ARGSUSED */
138 int
cryptof_read(struct file * fp,off_t * poff,struct uio * uio,struct ucred * cred)139 cryptof_read(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
140 {
141 	return (EIO);
142 }
143 
144 /* ARGSUSED */
145 int
cryptof_write(struct file * fp,off_t * poff,struct uio * uio,struct ucred * cred)146 cryptof_write(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
147 {
148 	return (EIO);
149 }
150 
151 /* ARGSUSED */
152 int
cryptof_ioctl(struct file * fp,u_long cmd,caddr_t data,struct proc * p)153 cryptof_ioctl(struct file *fp, u_long cmd, caddr_t data, struct proc *p)
154 {
155 	struct cryptoini cria, crie;
156 	struct fcrypt *fcr = (struct fcrypt *)fp->f_data;
157 	struct csession *cse;
158 	struct session_op *sop;
159 	struct crypt_op *cop;
160 	struct enc_xform *txform = NULL;
161 	struct auth_hash *thash = NULL;
162 	u_int64_t sid;
163 	u_int32_t ses;
164 	int error = 0;
165 
166 	switch (cmd) {
167 	case CIOCGSESSION:
168 		sop = (struct session_op *)data;
169 		switch (sop->cipher) {
170 		case 0:
171 			break;
172 		case CRYPTO_DES_CBC:
173 			txform = &enc_xform_des;
174 			break;
175 		case CRYPTO_3DES_CBC:
176 			txform = &enc_xform_3des;
177 			break;
178 		case CRYPTO_BLF_CBC:
179 			txform = &enc_xform_blf;
180 			break;
181 		case CRYPTO_CAST_CBC:
182 			txform = &enc_xform_cast5;
183 			break;
184 		case CRYPTO_SKIPJACK_CBC:
185 			txform = &enc_xform_skipjack;
186 			break;
187 		case CRYPTO_AES_CBC:
188 			txform = &enc_xform_rijndael128;
189 			break;
190 		case CRYPTO_AES_CTR:
191 			txform = &enc_xform_aes_ctr;
192 			break;
193 		case CRYPTO_ARC4:
194 			txform = &enc_xform_arc4;
195 			break;
196 		case CRYPTO_NULL:
197 			txform = &enc_xform_null;
198 			break;
199 		default:
200 			return (EINVAL);
201 		}
202 
203 		switch (sop->mac) {
204 		case 0:
205 			break;
206 #if 0
207 		case CRYPTO_MD5_HMAC:
208 			thash = &auth_hash_hmac_md5_96;
209 			break;
210 		case CRYPTO_SHA1_HMAC:
211 			thash = &auth_hash_hmac_sha1_96;
212 			break;
213 		case CRYPTO_RIPEMD160_HMAC:
214 			thash = &auth_hash_hmac_ripemd_160_96;
215 			break;
216 		case CRYPTO_MD5:
217 			thash = &auth_hash_md5;
218 			break;
219 		case CRYPTO_SHA1:
220 			thash = &auth_hash_sha1;
221 			break;
222 #endif
223 		default:
224 			return (EINVAL);
225 		}
226 
227 		bzero(&crie, sizeof(crie));
228 		bzero(&cria, sizeof(cria));
229 
230 		if (txform) {
231 			crie.cri_alg = txform->type;
232 			crie.cri_klen = sop->keylen * 8;
233 			if (sop->keylen > txform->maxkey ||
234 			    sop->keylen < txform->minkey) {
235 				error = EINVAL;
236 				goto bail;
237 			}
238 
239 			MALLOC(crie.cri_key, u_int8_t *,
240 			    crie.cri_klen / 8, M_XDATA, M_WAITOK);
241 			if ((error = copyin(sop->key, crie.cri_key,
242 			    crie.cri_klen / 8)))
243 				goto bail;
244 			if (thash)
245 				crie.cri_next = &cria;
246 		}
247 
248 		if (thash) {
249 			cria.cri_alg = thash->type;
250 			cria.cri_klen = sop->mackeylen * 8;
251 			if (sop->mackeylen != thash->keysize) {
252 				error = EINVAL;
253 				goto bail;
254 			}
255 
256 			if (cria.cri_klen) {
257 				MALLOC(cria.cri_key, u_int8_t *,
258 				    cria.cri_klen / 8, M_XDATA, M_WAITOK);
259 				if ((error = copyin(sop->mackey, cria.cri_key,
260 				    cria.cri_klen / 8)))
261 					goto bail;
262 			}
263 		}
264 
265 		error = crypto_newsession(&sid, (txform ? &crie : &cria),
266 		    !cryptodevallowsoft);
267 
268 		if (error)
269 			goto bail;
270 
271 		cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen,
272 		    cria.cri_key, cria.cri_klen, sop->cipher, sop->mac, txform,
273 		    thash);
274 
275 		if (cse == NULL) {
276 			crypto_freesession(sid);
277 			error = EINVAL;
278 			goto bail;
279 		}
280 		sop->ses = cse->ses;
281 
282 bail:
283 		if (error) {
284 			if (crie.cri_key)
285 				FREE(crie.cri_key, M_XDATA);
286 			if (cria.cri_key)
287 				FREE(cria.cri_key, M_XDATA);
288 		}
289 		break;
290 	case CIOCFSESSION:
291 		ses = *(u_int32_t *)data;
292 		cse = csefind(fcr, ses);
293 		if (cse == NULL)
294 			return (EINVAL);
295 		csedelete(fcr, cse);
296 		error = csefree(cse);
297 		break;
298 	case CIOCCRYPT:
299 		cop = (struct crypt_op *)data;
300 		cse = csefind(fcr, cop->ses);
301 		if (cse == NULL)
302 			return (EINVAL);
303 		error = cryptodev_op(cse, cop, p);
304 		break;
305 	case CIOCKEY:
306 		error = cryptodev_key((struct crypt_kop *)data);
307 		break;
308 	case CIOCASYMFEAT:
309 		error = crypto_getfeat((int *)data);
310 		break;
311 	default:
312 		error = EINVAL;
313 	}
314 	return (error);
315 }
316 
317 int
cryptodev_op(struct csession * cse,struct crypt_op * cop,struct proc * p)318 cryptodev_op(struct csession *cse, struct crypt_op *cop, struct proc *p)
319 {
320 	struct cryptop *crp= NULL;
321 	struct cryptodesc *crde = NULL, *crda = NULL;
322 	int i, s, error;
323 	u_int32_t hid;
324 
325 	if (cop->len > 64*1024-4)
326 		return (E2BIG);
327 
328 	if (cse->txform && (cop->len % cse->txform->blocksize) != 0) {
329 		return (EINVAL);
330 	}
331 
332 	bzero(&cse->uio, sizeof(cse->uio));
333 	cse->uio.uio_iovcnt = 1;
334 	cse->uio.uio_resid = 0;
335 	cse->uio.uio_segflg = UIO_SYSSPACE;
336 	cse->uio.uio_rw = UIO_WRITE;
337 	cse->uio.uio_procp = p;
338 	cse->uio.uio_iov = cse->iovec;
339 	bzero(&cse->iovec, sizeof(cse->iovec));
340 	cse->uio.uio_iov[0].iov_len = cop->len;
341 	cse->uio.uio_iov[0].iov_base = malloc(cop->len, M_XDATA, M_WAITOK);
342 	for (i = 0; i < cse->uio.uio_iovcnt; i++)
343 		cse->uio.uio_resid += cse->uio.uio_iov[0].iov_len;
344 
345 	crp = crypto_getreq((cse->txform != NULL) + (cse->thash != NULL));
346 	if (crp == NULL) {
347 		error = ENOMEM;
348 		goto bail;
349 	}
350 
351 	if (cse->thash) {
352 		crda = crp->crp_desc;
353 		if (cse->txform)
354 			crde = crda->crd_next;
355 	} else {
356 		if (cse->txform)
357 			crde = crp->crp_desc;
358 		else {
359 			error = EINVAL;
360 			goto bail;
361 		}
362 	}
363 
364 	if ((error = copyin(cop->src, cse->uio.uio_iov[0].iov_base, cop->len)))
365 		goto bail;
366 
367 	if (crda) {
368 		crda->crd_skip = 0;
369 		crda->crd_len = cop->len;
370 		crda->crd_inject = 0;	/* ??? */
371 
372 		crda->crd_alg = cse->mac;
373 		crda->crd_key = cse->mackey;
374 		crda->crd_klen = cse->mackeylen * 8;
375 	}
376 
377 	if (crde) {
378 		if (cop->op == COP_ENCRYPT)
379 			crde->crd_flags |= CRD_F_ENCRYPT;
380 		else
381 			crde->crd_flags &= ~CRD_F_ENCRYPT;
382 		crde->crd_len = cop->len;
383 		crde->crd_inject = 0;
384 
385 		crde->crd_alg = cse->cipher;
386 		crde->crd_key = cse->key;
387 		crde->crd_klen = cse->keylen * 8;
388 	}
389 
390 	crp->crp_ilen = cop->len;
391 	crp->crp_buf = (caddr_t)&cse->uio;
392 	crp->crp_callback = (int (*) (struct cryptop *)) cryptodev_cb;
393 	crp->crp_sid = cse->sid;
394 	crp->crp_opaque = (void *)cse;
395 
396 	if (cop->iv) {
397 		if (crde == NULL) {
398 			error = EINVAL;
399 			goto bail;
400 		}
401 		if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
402 			error = EINVAL;
403 			goto bail;
404 		}
405 		if ((error = copyin(cop->iv, cse->tmp_iv, cse->txform->blocksize)))
406 			goto bail;
407 		bcopy(cse->tmp_iv, crde->crd_iv, cse->txform->blocksize);
408 		crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
409 		crde->crd_skip = 0;
410 	} else if (cse->cipher == CRYPTO_ARC4) { /* XXX use flag? */
411 		crde->crd_skip = 0;
412 	} else if (crde) {
413 		crde->crd_flags |= CRD_F_IV_PRESENT;
414 		crde->crd_skip = cse->txform->blocksize;
415 		crde->crd_len -= cse->txform->blocksize;
416 	}
417 
418 	if (cop->mac) {
419 		if (crda == NULL) {
420 			error = EINVAL;
421 			goto bail;
422 		}
423 		crp->crp_mac=cse->tmp_mac;
424 	}
425 
426 	/* try the fast path first */
427 	crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_NOQUEUE;
428 	hid = (crp->crp_sid >> 32) & 0xffffffff;
429 	if (hid >= crypto_drivers_num)
430 		goto dispatch;
431 	if (crypto_drivers[hid].cc_flags & CRYPTOCAP_F_SOFTWARE)
432 		goto dispatch;
433 	if (crypto_drivers[hid].cc_process == NULL)
434 		goto dispatch;
435 	error = crypto_drivers[hid].cc_process(crp);
436 	if (error) {
437 		/* clear error */
438 		crp->crp_etype = 0;
439 		goto dispatch;
440 	}
441 	goto processed;
442  dispatch:
443 	crp->crp_flags = CRYPTO_F_IOV;
444 	crypto_dispatch(crp);
445  processed:
446 	s = splnet();
447 	while (!(crp->crp_flags & CRYPTO_F_DONE)) {
448 		error = tsleep(cse, PSOCK, "crydev", 0);
449 	}
450 	splx(s);
451 	if (error) {
452 		/* XXX can this happen?  if so, how do we recover? */
453 		goto bail;
454 	}
455 
456 	if (cse->error) {
457 		error = cse->error;
458 		goto bail;
459 	}
460 	if (crp->crp_etype != 0) {
461 		error = crp->crp_etype;
462 		goto bail;
463 	}
464 
465 
466 	if (cop->dst &&
467 	    (error = copyout(cse->uio.uio_iov[0].iov_base, cop->dst, cop->len)))
468 		goto bail;
469 
470 	if (cop->mac &&
471 	    (error = copyout(crp->crp_mac, cop->mac, cse->thash->authsize)))
472 		goto bail;
473 
474 bail:
475 	if (crp)
476 		crypto_freereq(crp);
477 	if (cse->uio.uio_iov[0].iov_base)
478 		free(cse->uio.uio_iov[0].iov_base, M_XDATA);
479 
480 	return (error);
481 }
482 
483 int
cryptodev_cb(void * op)484 cryptodev_cb(void *op)
485 {
486 	struct cryptop *crp = (struct cryptop *) op;
487 	struct csession *cse = (struct csession *)crp->crp_opaque;
488 
489 	cse->error = crp->crp_etype;
490 	if (crp->crp_etype == EAGAIN) {
491 		crp->crp_flags = CRYPTO_F_IOV;
492 		return crypto_dispatch(crp);
493 	}
494 	wakeup(cse);
495 	return (0);
496 }
497 
498 int
cryptodevkey_cb(void * op)499 cryptodevkey_cb(void *op)
500 {
501 	struct cryptkop *krp = (struct cryptkop *) op;
502 
503 	wakeup(krp);
504 	return (0);
505 }
506 
507 int
cryptodev_key(struct crypt_kop * kop)508 cryptodev_key(struct crypt_kop *kop)
509 {
510 	struct cryptkop *krp = NULL;
511 	int error = EINVAL;
512 	int in, out, size, i;
513 
514 	if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) {
515 		return (EFBIG);
516 	}
517 
518 	in = kop->crk_iparams;
519 	out = kop->crk_oparams;
520 	switch (kop->crk_op) {
521 	case CRK_MOD_EXP:
522 		if (in == 3 && out == 1)
523 			break;
524 		return (EINVAL);
525 	case CRK_MOD_EXP_CRT:
526 		if (in == 6 && out == 1)
527 			break;
528 		return (EINVAL);
529 	case CRK_DSA_SIGN:
530 		if (in == 5 && out == 2)
531 			break;
532 		return (EINVAL);
533 	case CRK_DSA_VERIFY:
534 		if (in == 7 && out == 0)
535 			break;
536 		return (EINVAL);
537 	case CRK_DH_COMPUTE_KEY:
538 		if (in == 3 && out == 1)
539 			break;
540 		return (EINVAL);
541 	default:
542 		return (EINVAL);
543 	}
544 
545 	krp = (struct cryptkop *)malloc(sizeof *krp, M_XDATA, M_WAITOK);
546 	if (!krp)
547 		return (ENOMEM);
548 	bzero(krp, sizeof *krp);
549 	krp->krp_op = kop->crk_op;
550 	krp->krp_status = kop->crk_status;
551 	krp->krp_iparams = kop->crk_iparams;
552 	krp->krp_oparams = kop->crk_oparams;
553 	krp->krp_status = 0;
554 	krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
555 
556 	for (i = 0; i < CRK_MAXPARAM; i++)
557 		krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
558 	for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
559 		size = (krp->krp_param[i].crp_nbits + 7) / 8;
560 		if (size == 0)
561 			continue;
562 		MALLOC(krp->krp_param[i].crp_p, caddr_t, size, M_XDATA, M_WAITOK);
563 		if (i >= krp->krp_iparams)
564 			continue;
565 		error = copyin(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p, size);
566 		if (error)
567 			goto fail;
568 	}
569 
570 	error = crypto_kdispatch(krp);
571 	if (error)
572 		goto fail;
573 	error = tsleep(krp, PSOCK, "crydev", 0);
574 	if (error) {
575 		/* XXX can this happen?  if so, how do we recover? */
576 		goto fail;
577 	}
578 
579 	if (krp->krp_status != 0) {
580 		error = krp->krp_status;
581 		goto fail;
582 	}
583 
584 	for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) {
585 		size = (krp->krp_param[i].crp_nbits + 7) / 8;
586 		if (size == 0)
587 			continue;
588 		error = copyout(krp->krp_param[i].crp_p, kop->crk_param[i].crp_p, size);
589 		if (error)
590 			goto fail;
591 	}
592 
593 fail:
594 	if (krp) {
595 		kop->crk_status = krp->krp_status;
596 		for (i = 0; i < CRK_MAXPARAM; i++) {
597 			if (krp->krp_param[i].crp_p)
598 				FREE(krp->krp_param[i].crp_p, M_XDATA);
599 		}
600 		free(krp, M_XDATA);
601 	}
602 	return (error);
603 }
604 
605 /* ARGSUSED */
606 int
cryptof_poll(struct file * fp,int events,struct proc * p)607 cryptof_poll(struct file *fp, int events, struct proc *p)
608 {
609 	return (0);
610 }
611 
612 /* ARGSUSED */
613 int
cryptof_kqfilter(struct file * fp,struct knote * kn)614 cryptof_kqfilter(struct file *fp, struct knote *kn)
615 {
616 	return (0);
617 }
618 
619 /* ARGSUSED */
620 int
cryptof_stat(struct file * fp,struct stat * sb,struct proc * p)621 cryptof_stat(struct file *fp, struct stat *sb, struct proc *p)
622 {
623 	return (EOPNOTSUPP);
624 }
625 
626 /* ARGSUSED */
627 int
cryptof_close(struct file * fp,struct proc * p)628 cryptof_close(struct file *fp, struct proc *p)
629 {
630 	struct fcrypt *fcr = (struct fcrypt *)fp->f_data;
631 	struct csession *cse;
632 
633 	while ((cse = TAILQ_FIRST(&fcr->csessions))) {
634 		TAILQ_REMOVE(&fcr->csessions, cse, next);
635 		(void)csefree(cse);
636 	}
637 	FREE(fcr, M_XDATA);
638 	fp->f_data = NULL;
639 	return 0;
640 }
641 
642 void
cryptoattach(int n)643 cryptoattach(int n)
644 {
645 }
646 
647 int
cryptoopen(dev_t dev,int flag,int mode,struct proc * p)648 cryptoopen(dev_t dev, int flag, int mode, struct proc *p)
649 {
650 	if (usercrypto == 0)
651 		return (ENXIO);
652 
653 	MINOR_DIVERT_TPM(open, dev, flag, mode, p);
654 
655 #ifdef CRYPTO
656 	return (0);
657 #else
658 	return (ENXIO);
659 #endif
660 }
661 
662 int
cryptoclose(dev_t dev,int flag,int mode,struct proc * p)663 cryptoclose(dev_t dev, int flag, int mode, struct proc *p)
664 {
665 	MINOR_DIVERT_TPM(close, dev, flag, mode, p);
666 
667 	return (0);
668 }
669 
670 int
cryptoread(dev_t dev,struct uio * uio,int ioflag)671 cryptoread(dev_t dev, struct uio *uio, int ioflag)
672 {
673 	MINOR_DIVERT_TPM(read, dev, uio, ioflag);
674 
675 	return (EIO);
676 }
677 
678 int
cryptowrite(dev_t dev,struct uio * uio,int ioflag)679 cryptowrite(dev_t dev, struct uio *uio, int ioflag)
680 {
681 	MINOR_DIVERT_TPM(write, dev, uio, ioflag);
682 
683 	return (EIO);
684 }
685 
686 int
cryptoioctl(dev_t dev,u_long cmd,caddr_t data,int flag,struct proc * p)687 cryptoioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
688 {
689 	struct file *f;
690 	struct fcrypt *fcr;
691 	int fd, error;
692 
693 	MINOR_DIVERT_TPM(ioctl, dev, cmd, data, flag, p);
694 
695 	switch (cmd) {
696 	case CRIOGET:
697 		MALLOC(fcr, struct fcrypt *,
698 		    sizeof(struct fcrypt), M_XDATA, M_WAITOK);
699 		TAILQ_INIT(&fcr->csessions);
700 		fcr->sesn = 0;
701 
702 		error = falloc(p, &f, &fd);
703 		if (error) {
704 			FREE(fcr, M_XDATA);
705 			return (error);
706 		}
707 		f->f_flag = FREAD | FWRITE;
708 		f->f_type = DTYPE_CRYPTO;
709 		f->f_ops = &cryptofops;
710 		f->f_data = (caddr_t)fcr;
711 		*(u_int32_t *)data = fd;
712 		FILE_SET_MATURE(f);
713 		break;
714 	default:
715 		error = EINVAL;
716 		break;
717 	}
718 	return (error);
719 }
720 
721 int
cryptopoll(dev_t dev,int events,struct proc * p)722 cryptopoll(dev_t dev, int events, struct proc *p)
723 {
724 	return (seltrue(dev, events, p));
725 }
726 
727 struct csession *
csefind(struct fcrypt * fcr,u_int ses)728 csefind(struct fcrypt *fcr, u_int ses)
729 {
730 	struct csession *cse;
731 
732 	TAILQ_FOREACH(cse, &fcr->csessions, next)
733 		if (cse->ses == ses)
734 			return (cse);
735 	return (NULL);
736 }
737 
738 int
csedelete(struct fcrypt * fcr,struct csession * cse_del)739 csedelete(struct fcrypt *fcr, struct csession *cse_del)
740 {
741 	struct csession *cse;
742 
743 	TAILQ_FOREACH(cse, &fcr->csessions, next) {
744 		if (cse == cse_del) {
745 			TAILQ_REMOVE(&fcr->csessions, cse, next);
746 			return (1);
747 		}
748 	}
749 	return (0);
750 }
751 
752 struct csession *
cseadd(struct fcrypt * fcr,struct csession * cse)753 cseadd(struct fcrypt *fcr, struct csession *cse)
754 {
755 	TAILQ_INSERT_TAIL(&fcr->csessions, cse, next);
756 	cse->ses = fcr->sesn++;
757 	return (cse);
758 }
759 
760 struct csession *
csecreate(struct fcrypt * fcr,u_int64_t sid,caddr_t key,u_int64_t keylen,caddr_t mackey,u_int64_t mackeylen,u_int32_t cipher,u_int32_t mac,struct enc_xform * txform,struct auth_hash * thash)761 csecreate(struct fcrypt *fcr, u_int64_t sid, caddr_t key, u_int64_t keylen,
762     caddr_t mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac,
763     struct enc_xform *txform, struct auth_hash *thash)
764 {
765 	struct csession *cse;
766 
767 	MALLOC(cse, struct csession *, sizeof(struct csession),
768 	    M_XDATA, M_NOWAIT);
769 	if (cse == NULL)
770 		return NULL;
771 	cse->key = key;
772 	cse->keylen = keylen/8;
773 	cse->mackey = mackey;
774 	cse->mackeylen = mackeylen/8;
775 	cse->sid = sid;
776 	cse->cipher = cipher;
777 	cse->mac = mac;
778 	cse->txform = txform;
779 	cse->thash = thash;
780 	cseadd(fcr, cse);
781 	return (cse);
782 }
783 
784 int
csefree(struct csession * cse)785 csefree(struct csession *cse)
786 {
787 	int error;
788 
789 	error = crypto_freesession(cse->sid);
790 	if (cse->key)
791 		FREE(cse->key, M_XDATA);
792 	if (cse->mackey)
793 		FREE(cse->mackey, M_XDATA);
794 	FREE(cse, M_XDATA);
795 	return (error);
796 }
797