| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: cgd.c,v 1.61 2009/11/10 16:49:53 tron Exp $ */ | | 1 | /* $NetBSD: cgd.c,v 1.62 2009/11/10 20:05:50 christos Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2002 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2002 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Roland C. Dowdeswell. | | 8 | * by Roland C. Dowdeswell. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -20,44 +20,45 @@ | | | @@ -20,44 +20,45 @@ |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.61 2009/11/10 16:49:53 tron Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.62 2009/11/10 20:05:50 christos Exp $"); |
34 | | | 34 | |
35 | #include <sys/types.h> | | 35 | #include <sys/types.h> |
36 | #include <sys/param.h> | | 36 | #include <sys/param.h> |
37 | #include <sys/systm.h> | | 37 | #include <sys/systm.h> |
38 | #include <sys/proc.h> | | 38 | #include <sys/proc.h> |
39 | #include <sys/errno.h> | | 39 | #include <sys/errno.h> |
40 | #include <sys/buf.h> | | 40 | #include <sys/buf.h> |
41 | #include <sys/bufq.h> | | 41 | #include <sys/bufq.h> |
42 | #include <sys/malloc.h> | | 42 | #include <sys/malloc.h> |
43 | #include <sys/pool.h> | | 43 | #include <sys/pool.h> |
44 | #include <sys/ioctl.h> | | 44 | #include <sys/ioctl.h> |
45 | #include <sys/device.h> | | 45 | #include <sys/device.h> |
46 | #include <sys/disk.h> | | 46 | #include <sys/disk.h> |
47 | #include <sys/disklabel.h> | | 47 | #include <sys/disklabel.h> |
48 | #include <sys/fcntl.h> | | 48 | #include <sys/fcntl.h> |
49 | #include <sys/vnode.h> | | 49 | #include <sys/vnode.h> |
50 | #include <sys/conf.h> | | 50 | #include <sys/conf.h> |
| | | 51 | #include <sys/syslog.h> |
51 | | | 52 | |
52 | #include <dev/dkvar.h> | | 53 | #include <dev/dkvar.h> |
53 | #include <dev/cgdvar.h> | | 54 | #include <dev/cgdvar.h> |
54 | | | 55 | |
55 | /* Entry Point Functions */ | | 56 | /* Entry Point Functions */ |
56 | | | 57 | |
57 | void cgdattach(int); | | 58 | void cgdattach(int); |
58 | | | 59 | |
59 | static dev_type_open(cgdopen); | | 60 | static dev_type_open(cgdopen); |
60 | static dev_type_close(cgdclose); | | 61 | static dev_type_close(cgdclose); |
61 | static dev_type_read(cgdread); | | 62 | static dev_type_read(cgdread); |
62 | static dev_type_write(cgdwrite); | | 63 | static dev_type_write(cgdwrite); |
63 | static dev_type_ioctl(cgdioctl); | | 64 | static dev_type_ioctl(cgdioctl); |
| @@ -173,35 +174,36 @@ cgdsoftc_init(struct cgd_softc *cs, int | | | @@ -173,35 +174,36 @@ cgdsoftc_init(struct cgd_softc *cs, int |
173 | } | | 174 | } |
174 | | | 175 | |
175 | void | | 176 | void |
176 | cgdattach(int num) | | 177 | cgdattach(int num) |
177 | { | | 178 | { |
178 | int i; | | 179 | int i; |
179 | | | 180 | |
180 | DPRINTF_FOLLOW(("cgdattach(%d)\n", num)); | | 181 | DPRINTF_FOLLOW(("cgdattach(%d)\n", num)); |
181 | if (num <= 0) { | | 182 | if (num <= 0) { |
182 | DIAGPANIC(("cgdattach: count <= 0")); | | 183 | DIAGPANIC(("cgdattach: count <= 0")); |
183 | return; | | 184 | return; |
184 | } | | 185 | } |
185 | | | 186 | |
186 | cgd_softc = (void *)malloc(num * sizeof(*cgd_softc), M_DEVBUF, M_NOWAIT); | | 187 | cgd_softc = malloc(num * sizeof(*cgd_softc), M_DEVBUF, M_NOWAIT); |
187 | if (!cgd_softc) { | | 188 | if (!cgd_softc) { |
188 | printf("WARNING: unable to malloc(9) memory for crypt disks\n"); | | 189 | DPRINTF_FOLLOW(("WARNING: unable to malloc(9) memory for %d " |
| | | 190 | "crypt disks\n", num)); |
189 | DIAGPANIC(("cgdattach: cannot malloc(9) enough memory")); | | 191 | DIAGPANIC(("cgdattach: cannot malloc(9) enough memory")); |
190 | return; | | 192 | return; |
191 | } | | 193 | } |
192 | | | 194 | |
193 | numcgd = num; | | 195 | numcgd = num; |
194 | for (i=0; i<num; i++) | | 196 | for (i = 0; i < num; i++) |
195 | cgdsoftc_init(&cgd_softc[i], i); | | 197 | cgdsoftc_init(&cgd_softc[i], i); |
196 | } | | 198 | } |
197 | | | 199 | |
198 | static int | | 200 | static int |
199 | cgdopen(dev_t dev, int flags, int fmt, struct lwp *l) | | 201 | cgdopen(dev_t dev, int flags, int fmt, struct lwp *l) |
200 | { | | 202 | { |
201 | struct cgd_softc *cs; | | 203 | struct cgd_softc *cs; |
202 | | | 204 | |
203 | DPRINTF_FOLLOW(("cgdopen(0x%"PRIx64", %d)\n", dev, flags)); | | 205 | DPRINTF_FOLLOW(("cgdopen(0x%"PRIx64", %d)\n", dev, flags)); |
204 | GETCGD_SOFTC(cs, dev); | | 206 | GETCGD_SOFTC(cs, dev); |
205 | return dk_open(di, &cs->sc_dksc, dev, flags, fmt, l); | | 207 | return dk_open(di, &cs->sc_dksc, dev, flags, fmt, l); |
206 | } | | 208 | } |
207 | | | 209 | |
| @@ -352,27 +354,28 @@ cgdiodone(struct buf *nbp) | | | @@ -352,27 +354,28 @@ cgdiodone(struct buf *nbp) |
352 | struct cgd_softc *cs = getcgd_softc(obp->b_dev); | | 354 | struct cgd_softc *cs = getcgd_softc(obp->b_dev); |
353 | struct dk_softc *dksc = &cs->sc_dksc; | | 355 | struct dk_softc *dksc = &cs->sc_dksc; |
354 | | | 356 | |
355 | KDASSERT(cs); | | 357 | KDASSERT(cs); |
356 | | | 358 | |
357 | DPRINTF_FOLLOW(("cgdiodone(%p)\n", nbp)); | | 359 | DPRINTF_FOLLOW(("cgdiodone(%p)\n", nbp)); |
358 | DPRINTF(CGDB_IO, ("cgdiodone: bp %p bcount %d resid %d\n", | | 360 | DPRINTF(CGDB_IO, ("cgdiodone: bp %p bcount %d resid %d\n", |
359 | obp, obp->b_bcount, obp->b_resid)); | | 361 | obp, obp->b_bcount, obp->b_resid)); |
360 | DPRINTF(CGDB_IO, (" dev 0x%"PRIx64", nbp %p bn %" PRId64 " addr %p bcnt %d\n", | | 362 | DPRINTF(CGDB_IO, (" dev 0x%"PRIx64", nbp %p bn %" PRId64 " addr %p bcnt %d\n", |
361 | nbp->b_dev, nbp, nbp->b_blkno, nbp->b_data, | | 363 | nbp->b_dev, nbp, nbp->b_blkno, nbp->b_data, |
362 | nbp->b_bcount)); | | 364 | nbp->b_bcount)); |
363 | if (nbp->b_error != 0) { | | 365 | if (nbp->b_error != 0) { |
364 | obp->b_error = nbp->b_error; | | 366 | obp->b_error = nbp->b_error; |
365 | printf("%s: error %d\n", dksc->sc_xname, obp->b_error); | | 367 | DPRINTF(CGDB_IO, ("%s: error %d\n", dksc->sc_xname, |
| | | 368 | obp->b_error)); |
366 | } | | 369 | } |
367 | | | 370 | |
368 | /* Perform the decryption if we are reading. | | 371 | /* Perform the decryption if we are reading. |
369 | * | | 372 | * |
370 | * Note: use the blocknumber from nbp, since it is what | | 373 | * Note: use the blocknumber from nbp, since it is what |
371 | * we used to encrypt the blocks. | | 374 | * we used to encrypt the blocks. |
372 | */ | | 375 | */ |
373 | | | 376 | |
374 | if (nbp->b_flags & B_READ) | | 377 | if (nbp->b_flags & B_READ) |
375 | cgd_cipher(cs, obp->b_data, obp->b_data, obp->b_bcount, | | 378 | cgd_cipher(cs, obp->b_data, obp->b_data, obp->b_bcount, |
376 | nbp->b_blkno, DEV_BSIZE, CGD_CIPHER_DECRYPT); | | 379 | nbp->b_blkno, DEV_BSIZE, CGD_CIPHER_DECRYPT); |
377 | | | 380 | |
378 | /* If we allocated memory, free it now... */ | | 381 | /* If we allocated memory, free it now... */ |
| @@ -562,35 +565,40 @@ cgd_ioctl_set(struct cgd_softc *cs, void | | | @@ -562,35 +565,40 @@ cgd_ioctl_set(struct cgd_softc *cs, void |
562 | ret = EINVAL; | | 565 | ret = EINVAL; |
563 | goto bail; | | 566 | goto bail; |
564 | } | | 567 | } |
565 | | | 568 | |
566 | (void)memset(inbuf, 0, MAX_KEYSIZE); | | 569 | (void)memset(inbuf, 0, MAX_KEYSIZE); |
567 | ret = copyin(ci->ci_key, inbuf, keybytes); | | 570 | ret = copyin(ci->ci_key, inbuf, keybytes); |
568 | if (ret) | | 571 | if (ret) |
569 | goto bail; | | 572 | goto bail; |
570 | | | 573 | |
571 | cs->sc_cdata.cf_blocksize = ci->ci_blocksize; | | 574 | cs->sc_cdata.cf_blocksize = ci->ci_blocksize; |
572 | cs->sc_cdata.cf_mode = encblkno[i].v; | | 575 | cs->sc_cdata.cf_mode = encblkno[i].v; |
573 | cs->sc_cdata.cf_priv = cs->sc_cfuncs->cf_init(ci->ci_keylen, inbuf, | | 576 | cs->sc_cdata.cf_priv = cs->sc_cfuncs->cf_init(ci->ci_keylen, inbuf, |
574 | &cs->sc_cdata.cf_blocksize); | | 577 | &cs->sc_cdata.cf_blocksize); |
| | | 578 | if (cs->sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) { |
| | | 579 | log(LOG_WARNING, "cgd: Disallowed cipher with blocksize %zu > %u\n", |
| | | 580 | cs->sc_data.cf_blocksize, CGD_MAXBLOCKSIZE); |
| | | 581 | cs->sc_cdata.cf_priv = NULL; |
| | | 582 | } |
| | | 583 | |
575 | /* | | 584 | /* |
576 | * The blocksize is supposed to be in bytes. Unfortunately originally | | 585 | * The blocksize is supposed to be in bytes. Unfortunately originally |
577 | * it was expressed in bits. For compatibility we maintain encblkno | | 586 | * it was expressed in bits. For compatibility we maintain encblkno |
578 | * and encblkno8. | | 587 | * and encblkno8. |
579 | */ | | 588 | */ |
580 | cs->sc_cdata.cf_blocksize /= encblkno[i].d; | | 589 | cs->sc_cdata.cf_blocksize /= encblkno[i].d; |
581 | (void)memset(inbuf, 0, MAX_KEYSIZE); | | 590 | (void)memset(inbuf, 0, MAX_KEYSIZE); |
582 | if (!cs->sc_cdata.cf_priv) { | | 591 | if (!cs->sc_cdata.cf_priv) { |
583 | printf("cgd: unable to initialize cipher\n"); | | | |
584 | ret = EINVAL; /* XXX is this the right error? */ | | 592 | ret = EINVAL; /* XXX is this the right error? */ |
585 | goto bail; | | 593 | goto bail; |
586 | } | | 594 | } |
587 | free(inbuf, M_TEMP); | | 595 | free(inbuf, M_TEMP); |
588 | | | 596 | |
589 | bufq_alloc(&cs->sc_dksc.sc_bufq, "fcfs", 0); | | 597 | bufq_alloc(&cs->sc_dksc.sc_bufq, "fcfs", 0); |
590 | | | 598 | |
591 | cs->sc_data = malloc(MAXPHYS, M_DEVBUF, M_WAITOK); | | 599 | cs->sc_data = malloc(MAXPHYS, M_DEVBUF, M_WAITOK); |
592 | cs->sc_data_used = 0; | | 600 | cs->sc_data_used = 0; |
593 | | | 601 | |
594 | cs->sc_dksc.sc_flags |= DKF_INITED; | | 602 | cs->sc_dksc.sc_flags |= DKF_INITED; |
595 | | | 603 | |
596 | /* Attach the disk. */ | | 604 | /* Attach the disk. */ |
| @@ -765,29 +773,29 @@ blkno2blkno_buf(char *sbuf, daddr_t blkn | | | @@ -765,29 +773,29 @@ blkno2blkno_buf(char *sbuf, daddr_t blkn |
765 | | | 773 | |
766 | static void | | 774 | static void |
767 | cgd_cipher(struct cgd_softc *cs, void *dstv, void *srcv, | | 775 | cgd_cipher(struct cgd_softc *cs, void *dstv, void *srcv, |
768 | size_t len, daddr_t blkno, size_t secsize, int dir) | | 776 | size_t len, daddr_t blkno, size_t secsize, int dir) |
769 | { | | 777 | { |
770 | char *dst = dstv; | | 778 | char *dst = dstv; |
771 | char *src = srcv; | | 779 | char *src = srcv; |
772 | cfunc_cipher *cipher = cs->sc_cfuncs->cf_cipher; | | 780 | cfunc_cipher *cipher = cs->sc_cfuncs->cf_cipher; |
773 | struct uio dstuio; | | 781 | struct uio dstuio; |
774 | struct uio srcuio; | | 782 | struct uio srcuio; |
775 | struct iovec dstiov[2]; | | 783 | struct iovec dstiov[2]; |
776 | struct iovec srciov[2]; | | 784 | struct iovec srciov[2]; |
777 | size_t blocksize = cs->sc_cdata.cf_blocksize; | | 785 | size_t blocksize = cs->sc_cdata.cf_blocksize; |
778 | char sink[blocksize]; | | 786 | char sink[CGD_MAXBLOCKSIZE]; |
779 | char zero_iv[blocksize]; | | 787 | char zero_iv[CGD_MAXBLOCKSIZE]; |
780 | char blkno_buf[blocksize]; | | 788 | char blkno_buf[CGD_MAXBLOCKSIZE]; |
781 | | | 789 | |
782 | DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir)); | | 790 | DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir)); |
783 | | | 791 | |
784 | DIAGCONDPANIC(len % blocksize != 0, | | 792 | DIAGCONDPANIC(len % blocksize != 0, |
785 | ("cgd_cipher: len %% blocksize != 0")); | | 793 | ("cgd_cipher: len %% blocksize != 0")); |
786 | | | 794 | |
787 | /* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */ | | 795 | /* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */ |
788 | DIAGCONDPANIC(sizeof(daddr_t) > blocksize, | | 796 | DIAGCONDPANIC(sizeof(daddr_t) > blocksize, |
789 | ("cgd_cipher: sizeof(daddr_t) > blocksize")); | | 797 | ("cgd_cipher: sizeof(daddr_t) > blocksize")); |
790 | | | 798 | |
791 | memset(zero_iv, 0x0, sizeof(zero_iv)); | | 799 | memset(zero_iv, 0x0, sizeof(zero_iv)); |
792 | | | 800 | |
793 | dstuio.uio_iov = dstiov; | | 801 | dstuio.uio_iov = dstiov; |