cgd.c revision 1.91.2.8 1 1.91.2.8 skrll /* $NetBSD: cgd.c,v 1.91.2.8 2017/08/28 17:52:00 skrll Exp $ */
2 1.1 elric
3 1.1 elric /*-
4 1.1 elric * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 1.1 elric * All rights reserved.
6 1.1 elric *
7 1.1 elric * This code is derived from software contributed to The NetBSD Foundation
8 1.1 elric * by Roland C. Dowdeswell.
9 1.1 elric *
10 1.1 elric * Redistribution and use in source and binary forms, with or without
11 1.1 elric * modification, are permitted provided that the following conditions
12 1.1 elric * are met:
13 1.1 elric * 1. Redistributions of source code must retain the above copyright
14 1.1 elric * notice, this list of conditions and the following disclaimer.
15 1.1 elric * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 elric * notice, this list of conditions and the following disclaimer in the
17 1.1 elric * documentation and/or other materials provided with the distribution.
18 1.1 elric *
19 1.1 elric * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 elric * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 elric * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 elric * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 elric * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 elric * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 elric * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 elric * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 elric * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 elric * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 elric * POSSIBILITY OF SUCH DAMAGE.
30 1.1 elric */
31 1.1 elric
32 1.1 elric #include <sys/cdefs.h>
33 1.91.2.8 skrll __KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.91.2.8 2017/08/28 17:52:00 skrll Exp $");
34 1.1 elric
35 1.1 elric #include <sys/types.h>
36 1.1 elric #include <sys/param.h>
37 1.1 elric #include <sys/systm.h>
38 1.1 elric #include <sys/proc.h>
39 1.1 elric #include <sys/errno.h>
40 1.1 elric #include <sys/buf.h>
41 1.21 yamt #include <sys/bufq.h>
42 1.1 elric #include <sys/malloc.h>
43 1.74 jruoho #include <sys/module.h>
44 1.1 elric #include <sys/pool.h>
45 1.1 elric #include <sys/ioctl.h>
46 1.1 elric #include <sys/device.h>
47 1.1 elric #include <sys/disk.h>
48 1.1 elric #include <sys/disklabel.h>
49 1.1 elric #include <sys/fcntl.h>
50 1.71 dholland #include <sys/namei.h> /* for pathbuf */
51 1.1 elric #include <sys/vnode.h>
52 1.1 elric #include <sys/conf.h>
53 1.62 christos #include <sys/syslog.h>
54 1.1 elric
55 1.1 elric #include <dev/dkvar.h>
56 1.1 elric #include <dev/cgdvar.h>
57 1.1 elric
58 1.88 hannken #include <miscfs/specfs/specdev.h> /* for v_rdev */
59 1.88 hannken
60 1.91.2.3 skrll #include "ioconf.h"
61 1.1 elric
62 1.91.2.7 skrll struct selftest_params {
63 1.91.2.7 skrll const char *alg;
64 1.91.2.7 skrll int blocksize; /* number of bytes */
65 1.91.2.7 skrll int secsize;
66 1.91.2.7 skrll daddr_t blkno;
67 1.91.2.7 skrll int keylen; /* number of bits */
68 1.91.2.7 skrll int txtlen; /* number of bytes */
69 1.91.2.7 skrll const uint8_t *key;
70 1.91.2.7 skrll const uint8_t *ptxt;
71 1.91.2.7 skrll const uint8_t *ctxt;
72 1.91.2.7 skrll };
73 1.91.2.7 skrll
74 1.91.2.3 skrll /* Entry Point Functions */
75 1.1 elric
76 1.18 thorpej static dev_type_open(cgdopen);
77 1.18 thorpej static dev_type_close(cgdclose);
78 1.18 thorpej static dev_type_read(cgdread);
79 1.18 thorpej static dev_type_write(cgdwrite);
80 1.18 thorpej static dev_type_ioctl(cgdioctl);
81 1.18 thorpej static dev_type_strategy(cgdstrategy);
82 1.18 thorpej static dev_type_dump(cgddump);
83 1.18 thorpej static dev_type_size(cgdsize);
84 1.1 elric
85 1.1 elric const struct bdevsw cgd_bdevsw = {
86 1.84 dholland .d_open = cgdopen,
87 1.84 dholland .d_close = cgdclose,
88 1.84 dholland .d_strategy = cgdstrategy,
89 1.84 dholland .d_ioctl = cgdioctl,
90 1.84 dholland .d_dump = cgddump,
91 1.84 dholland .d_psize = cgdsize,
92 1.89 dholland .d_discard = nodiscard,
93 1.84 dholland .d_flag = D_DISK
94 1.1 elric };
95 1.1 elric
96 1.1 elric const struct cdevsw cgd_cdevsw = {
97 1.84 dholland .d_open = cgdopen,
98 1.84 dholland .d_close = cgdclose,
99 1.84 dholland .d_read = cgdread,
100 1.84 dholland .d_write = cgdwrite,
101 1.84 dholland .d_ioctl = cgdioctl,
102 1.84 dholland .d_stop = nostop,
103 1.84 dholland .d_tty = notty,
104 1.84 dholland .d_poll = nopoll,
105 1.84 dholland .d_mmap = nommap,
106 1.84 dholland .d_kqfilter = nokqfilter,
107 1.90 dholland .d_discard = nodiscard,
108 1.84 dholland .d_flag = D_DISK
109 1.1 elric };
110 1.1 elric
111 1.91.2.7 skrll /*
112 1.91.2.7 skrll * Vector 5 from IEEE 1619/D16 truncated to 64 bytes, blkno 1.
113 1.91.2.7 skrll */
114 1.91.2.7 skrll static const uint8_t selftest_aes_xts_256_ptxt[64] = {
115 1.91.2.7 skrll 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
116 1.91.2.7 skrll 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
117 1.91.2.7 skrll 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
118 1.91.2.7 skrll 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
119 1.91.2.7 skrll 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
120 1.91.2.7 skrll 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
121 1.91.2.7 skrll 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
122 1.91.2.7 skrll 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
123 1.91.2.7 skrll };
124 1.91.2.7 skrll
125 1.91.2.7 skrll static const uint8_t selftest_aes_xts_256_ctxt[512] = {
126 1.91.2.7 skrll 0x26, 0x4d, 0x3c, 0xa8, 0x51, 0x21, 0x94, 0xfe,
127 1.91.2.7 skrll 0xc3, 0x12, 0xc8, 0xc9, 0x89, 0x1f, 0x27, 0x9f,
128 1.91.2.7 skrll 0xef, 0xdd, 0x60, 0x8d, 0x0c, 0x02, 0x7b, 0x60,
129 1.91.2.7 skrll 0x48, 0x3a, 0x3f, 0xa8, 0x11, 0xd6, 0x5e, 0xe5,
130 1.91.2.7 skrll 0x9d, 0x52, 0xd9, 0xe4, 0x0e, 0xc5, 0x67, 0x2d,
131 1.91.2.7 skrll 0x81, 0x53, 0x2b, 0x38, 0xb6, 0xb0, 0x89, 0xce,
132 1.91.2.7 skrll 0x95, 0x1f, 0x0f, 0x9c, 0x35, 0x59, 0x0b, 0x8b,
133 1.91.2.7 skrll 0x97, 0x8d, 0x17, 0x52, 0x13, 0xf3, 0x29, 0xbb,
134 1.91.2.7 skrll };
135 1.91.2.7 skrll
136 1.91.2.7 skrll static const uint8_t selftest_aes_xts_256_key[33] = {
137 1.91.2.7 skrll 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
138 1.91.2.7 skrll 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
139 1.91.2.7 skrll 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
140 1.91.2.7 skrll 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95,
141 1.91.2.7 skrll 0
142 1.91.2.7 skrll };
143 1.91.2.7 skrll
144 1.91.2.7 skrll /*
145 1.91.2.7 skrll * Vector 11 from IEEE 1619/D16 truncated to 64 bytes, blkno 0xffff.
146 1.91.2.7 skrll */
147 1.91.2.7 skrll static const uint8_t selftest_aes_xts_512_ptxt[64] = {
148 1.91.2.7 skrll 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
149 1.91.2.7 skrll 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
150 1.91.2.7 skrll 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
151 1.91.2.7 skrll 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
152 1.91.2.7 skrll 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
153 1.91.2.7 skrll 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
154 1.91.2.7 skrll 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
155 1.91.2.7 skrll 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
156 1.91.2.7 skrll };
157 1.91.2.7 skrll
158 1.91.2.7 skrll static const uint8_t selftest_aes_xts_512_ctxt[64] = {
159 1.91.2.7 skrll 0x77, 0xa3, 0x12, 0x51, 0x61, 0x8a, 0x15, 0xe6,
160 1.91.2.7 skrll 0xb9, 0x2d, 0x1d, 0x66, 0xdf, 0xfe, 0x7b, 0x50,
161 1.91.2.7 skrll 0xb5, 0x0b, 0xad, 0x55, 0x23, 0x05, 0xba, 0x02,
162 1.91.2.7 skrll 0x17, 0xa6, 0x10, 0x68, 0x8e, 0xff, 0x7e, 0x11,
163 1.91.2.7 skrll 0xe1, 0xd0, 0x22, 0x54, 0x38, 0xe0, 0x93, 0x24,
164 1.91.2.7 skrll 0x2d, 0x6d, 0xb2, 0x74, 0xfd, 0xe8, 0x01, 0xd4,
165 1.91.2.7 skrll 0xca, 0xe0, 0x6f, 0x20, 0x92, 0xc7, 0x28, 0xb2,
166 1.91.2.7 skrll 0x47, 0x85, 0x59, 0xdf, 0x58, 0xe8, 0x37, 0xc2,
167 1.91.2.7 skrll };
168 1.91.2.7 skrll
169 1.91.2.7 skrll static const uint8_t selftest_aes_xts_512_key[65] = {
170 1.91.2.7 skrll 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
171 1.91.2.7 skrll 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
172 1.91.2.7 skrll 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69,
173 1.91.2.7 skrll 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27,
174 1.91.2.7 skrll 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
175 1.91.2.7 skrll 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95,
176 1.91.2.7 skrll 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37,
177 1.91.2.7 skrll 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92,
178 1.91.2.7 skrll 0
179 1.91.2.7 skrll };
180 1.91.2.7 skrll
181 1.91.2.7 skrll const struct selftest_params selftests[] = {
182 1.91.2.7 skrll {
183 1.91.2.7 skrll .alg = "aes-xts",
184 1.91.2.7 skrll .blocksize = 16,
185 1.91.2.7 skrll .secsize = 512,
186 1.91.2.7 skrll .blkno = 1,
187 1.91.2.7 skrll .keylen = 256,
188 1.91.2.7 skrll .txtlen = sizeof(selftest_aes_xts_256_ptxt),
189 1.91.2.7 skrll .key = selftest_aes_xts_256_key,
190 1.91.2.7 skrll .ptxt = selftest_aes_xts_256_ptxt,
191 1.91.2.7 skrll .ctxt = selftest_aes_xts_256_ctxt
192 1.91.2.7 skrll },
193 1.91.2.7 skrll {
194 1.91.2.7 skrll .alg = "aes-xts",
195 1.91.2.7 skrll .blocksize = 16,
196 1.91.2.7 skrll .secsize = 512,
197 1.91.2.7 skrll .blkno = 0xffff,
198 1.91.2.7 skrll .keylen = 512,
199 1.91.2.7 skrll .txtlen = sizeof(selftest_aes_xts_512_ptxt),
200 1.91.2.7 skrll .key = selftest_aes_xts_512_key,
201 1.91.2.7 skrll .ptxt = selftest_aes_xts_512_ptxt,
202 1.91.2.7 skrll .ctxt = selftest_aes_xts_512_ctxt
203 1.91.2.7 skrll }
204 1.91.2.7 skrll };
205 1.91.2.7 skrll
206 1.65 dyoung static int cgd_match(device_t, cfdata_t, void *);
207 1.65 dyoung static void cgd_attach(device_t, device_t, void *);
208 1.65 dyoung static int cgd_detach(device_t, int);
209 1.65 dyoung static struct cgd_softc *cgd_spawn(int);
210 1.65 dyoung static int cgd_destroy(device_t);
211 1.65 dyoung
212 1.1 elric /* Internal Functions */
213 1.1 elric
214 1.91.2.3 skrll static int cgd_diskstart(device_t, struct buf *);
215 1.1 elric static void cgdiodone(struct buf *);
216 1.91.2.6 skrll static int cgd_dumpblocks(device_t, void *, daddr_t, int);
217 1.1 elric
218 1.32 christos static int cgd_ioctl_set(struct cgd_softc *, void *, struct lwp *);
219 1.65 dyoung static int cgd_ioctl_clr(struct cgd_softc *, struct lwp *);
220 1.78 christos static int cgd_ioctl_get(dev_t, void *, struct lwp *);
221 1.27 drochner static int cgdinit(struct cgd_softc *, const char *, struct vnode *,
222 1.32 christos struct lwp *);
223 1.44 christos static void cgd_cipher(struct cgd_softc *, void *, void *,
224 1.1 elric size_t, daddr_t, size_t, int);
225 1.1 elric
226 1.29 yamt static struct dkdriver cgddkdriver = {
227 1.91.2.2 skrll .d_minphys = minphys,
228 1.91.2.2 skrll .d_open = cgdopen,
229 1.91.2.2 skrll .d_close = cgdclose,
230 1.91.2.2 skrll .d_strategy = cgdstrategy,
231 1.91.2.2 skrll .d_iosize = NULL,
232 1.91.2.3 skrll .d_diskstart = cgd_diskstart,
233 1.91.2.6 skrll .d_dumpblocks = cgd_dumpblocks,
234 1.91.2.2 skrll .d_lastclose = NULL
235 1.29 yamt };
236 1.29 yamt
237 1.65 dyoung CFATTACH_DECL3_NEW(cgd, sizeof(struct cgd_softc),
238 1.65 dyoung cgd_match, cgd_attach, cgd_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
239 1.65 dyoung extern struct cfdriver cgd_cd;
240 1.65 dyoung
241 1.1 elric /* DIAGNOSTIC and DEBUG definitions */
242 1.1 elric
243 1.1 elric #if defined(CGDDEBUG) && !defined(DEBUG)
244 1.1 elric #define DEBUG
245 1.1 elric #endif
246 1.1 elric
247 1.1 elric #ifdef DEBUG
248 1.1 elric int cgddebug = 0;
249 1.1 elric
250 1.1 elric #define CGDB_FOLLOW 0x1
251 1.1 elric #define CGDB_IO 0x2
252 1.1 elric #define CGDB_CRYPTO 0x4
253 1.1 elric
254 1.1 elric #define IFDEBUG(x,y) if (cgddebug & (x)) y
255 1.1 elric #define DPRINTF(x,y) IFDEBUG(x, printf y)
256 1.1 elric #define DPRINTF_FOLLOW(y) DPRINTF(CGDB_FOLLOW, y)
257 1.1 elric
258 1.26 drochner static void hexprint(const char *, void *, int);
259 1.1 elric
260 1.1 elric #else
261 1.1 elric #define IFDEBUG(x,y)
262 1.1 elric #define DPRINTF(x,y)
263 1.1 elric #define DPRINTF_FOLLOW(y)
264 1.1 elric #endif
265 1.1 elric
266 1.1 elric #ifdef DIAGNOSTIC
267 1.22 perry #define DIAGPANIC(x) panic x
268 1.1 elric #define DIAGCONDPANIC(x,y) if (x) panic y
269 1.1 elric #else
270 1.1 elric #define DIAGPANIC(x)
271 1.1 elric #define DIAGCONDPANIC(x,y)
272 1.1 elric #endif
273 1.1 elric
274 1.1 elric /* Global variables */
275 1.1 elric
276 1.1 elric /* Utility Functions */
277 1.1 elric
278 1.1 elric #define CGDUNIT(x) DISKUNIT(x)
279 1.1 elric #define GETCGD_SOFTC(_cs, x) if (!((_cs) = getcgd_softc(x))) return ENXIO
280 1.1 elric
281 1.65 dyoung /* The code */
282 1.65 dyoung
283 1.1 elric static struct cgd_softc *
284 1.1 elric getcgd_softc(dev_t dev)
285 1.1 elric {
286 1.1 elric int unit = CGDUNIT(dev);
287 1.65 dyoung struct cgd_softc *sc;
288 1.1 elric
289 1.56 cegger DPRINTF_FOLLOW(("getcgd_softc(0x%"PRIx64"): unit = %d\n", dev, unit));
290 1.65 dyoung
291 1.65 dyoung sc = device_lookup_private(&cgd_cd, unit);
292 1.65 dyoung if (sc == NULL)
293 1.65 dyoung sc = cgd_spawn(unit);
294 1.65 dyoung return sc;
295 1.1 elric }
296 1.1 elric
297 1.65 dyoung static int
298 1.65 dyoung cgd_match(device_t self, cfdata_t cfdata, void *aux)
299 1.65 dyoung {
300 1.65 dyoung
301 1.65 dyoung return 1;
302 1.65 dyoung }
303 1.1 elric
304 1.1 elric static void
305 1.65 dyoung cgd_attach(device_t parent, device_t self, void *aux)
306 1.1 elric {
307 1.65 dyoung struct cgd_softc *sc = device_private(self);
308 1.1 elric
309 1.85 skrll mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_BIO);
310 1.91.2.2 skrll dk_init(&sc->sc_dksc, self, DKTYPE_CGD);
311 1.65 dyoung disk_init(&sc->sc_dksc.sc_dkdev, sc->sc_dksc.sc_xname, &cgddkdriver);
312 1.70 joerg
313 1.91.2.2 skrll if (!pmf_device_register(self, NULL, NULL))
314 1.91.2.5 skrll aprint_error_dev(self,
315 1.91.2.5 skrll "unable to register power management hooks\n");
316 1.65 dyoung }
317 1.65 dyoung
318 1.65 dyoung
319 1.65 dyoung static int
320 1.65 dyoung cgd_detach(device_t self, int flags)
321 1.65 dyoung {
322 1.67 dyoung int ret;
323 1.67 dyoung const int pmask = 1 << RAW_PART;
324 1.65 dyoung struct cgd_softc *sc = device_private(self);
325 1.67 dyoung struct dk_softc *dksc = &sc->sc_dksc;
326 1.67 dyoung
327 1.67 dyoung if (DK_BUSY(dksc, pmask))
328 1.67 dyoung return EBUSY;
329 1.65 dyoung
330 1.91.2.2 skrll if (DK_ATTACHED(dksc) &&
331 1.67 dyoung (ret = cgd_ioctl_clr(sc, curlwp)) != 0)
332 1.67 dyoung return ret;
333 1.65 dyoung
334 1.67 dyoung disk_destroy(&dksc->sc_dkdev);
335 1.86 christos mutex_destroy(&sc->sc_lock);
336 1.65 dyoung
337 1.67 dyoung return 0;
338 1.1 elric }
339 1.1 elric
340 1.1 elric void
341 1.1 elric cgdattach(int num)
342 1.1 elric {
343 1.65 dyoung int error;
344 1.65 dyoung
345 1.65 dyoung error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
346 1.65 dyoung if (error != 0)
347 1.65 dyoung aprint_error("%s: unable to register cfattach\n",
348 1.65 dyoung cgd_cd.cd_name);
349 1.65 dyoung }
350 1.65 dyoung
351 1.65 dyoung static struct cgd_softc *
352 1.65 dyoung cgd_spawn(int unit)
353 1.65 dyoung {
354 1.65 dyoung cfdata_t cf;
355 1.65 dyoung
356 1.65 dyoung cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK);
357 1.65 dyoung cf->cf_name = cgd_cd.cd_name;
358 1.65 dyoung cf->cf_atname = cgd_cd.cd_name;
359 1.65 dyoung cf->cf_unit = unit;
360 1.65 dyoung cf->cf_fstate = FSTATE_STAR;
361 1.65 dyoung
362 1.65 dyoung return device_private(config_attach_pseudo(cf));
363 1.65 dyoung }
364 1.65 dyoung
365 1.65 dyoung static int
366 1.65 dyoung cgd_destroy(device_t dev)
367 1.65 dyoung {
368 1.65 dyoung int error;
369 1.65 dyoung cfdata_t cf;
370 1.1 elric
371 1.65 dyoung cf = device_cfdata(dev);
372 1.65 dyoung error = config_detach(dev, DETACH_QUIET);
373 1.65 dyoung if (error)
374 1.65 dyoung return error;
375 1.65 dyoung free(cf, M_DEVBUF);
376 1.65 dyoung return 0;
377 1.1 elric }
378 1.1 elric
379 1.18 thorpej static int
380 1.32 christos cgdopen(dev_t dev, int flags, int fmt, struct lwp *l)
381 1.1 elric {
382 1.1 elric struct cgd_softc *cs;
383 1.1 elric
384 1.56 cegger DPRINTF_FOLLOW(("cgdopen(0x%"PRIx64", %d)\n", dev, flags));
385 1.1 elric GETCGD_SOFTC(cs, dev);
386 1.91.2.2 skrll return dk_open(&cs->sc_dksc, dev, flags, fmt, l);
387 1.1 elric }
388 1.1 elric
389 1.18 thorpej static int
390 1.32 christos cgdclose(dev_t dev, int flags, int fmt, struct lwp *l)
391 1.1 elric {
392 1.65 dyoung int error;
393 1.1 elric struct cgd_softc *cs;
394 1.65 dyoung struct dk_softc *dksc;
395 1.1 elric
396 1.56 cegger DPRINTF_FOLLOW(("cgdclose(0x%"PRIx64", %d)\n", dev, flags));
397 1.1 elric GETCGD_SOFTC(cs, dev);
398 1.65 dyoung dksc = &cs->sc_dksc;
399 1.91.2.2 skrll if ((error = dk_close(dksc, dev, flags, fmt, l)) != 0)
400 1.65 dyoung return error;
401 1.65 dyoung
402 1.91.2.2 skrll if (!DK_ATTACHED(dksc)) {
403 1.77 elric if ((error = cgd_destroy(cs->sc_dksc.sc_dev)) != 0) {
404 1.77 elric aprint_error_dev(dksc->sc_dev,
405 1.65 dyoung "unable to detach instance\n");
406 1.65 dyoung return error;
407 1.65 dyoung }
408 1.65 dyoung }
409 1.65 dyoung return 0;
410 1.1 elric }
411 1.1 elric
412 1.18 thorpej static void
413 1.1 elric cgdstrategy(struct buf *bp)
414 1.1 elric {
415 1.91.2.6 skrll struct cgd_softc *cs;
416 1.1 elric
417 1.1 elric DPRINTF_FOLLOW(("cgdstrategy(%p): b_bcount = %ld\n", bp,
418 1.1 elric (long)bp->b_bcount));
419 1.72 riastrad
420 1.91.2.6 skrll cs = getcgd_softc(bp->b_dev);
421 1.91.2.6 skrll if (!cs) {
422 1.91.2.6 skrll bp->b_error = ENXIO;
423 1.91.2.6 skrll goto bail;
424 1.91.2.6 skrll }
425 1.91.2.6 skrll
426 1.72 riastrad /*
427 1.91.2.6 skrll * Reject unaligned writes.
428 1.72 riastrad */
429 1.91.2.6 skrll if (((uintptr_t)bp->b_data & 3) != 0) {
430 1.72 riastrad bp->b_error = EINVAL;
431 1.91.2.6 skrll goto bail;
432 1.72 riastrad }
433 1.72 riastrad
434 1.91.2.2 skrll dk_strategy(&cs->sc_dksc, bp);
435 1.1 elric return;
436 1.91.2.6 skrll
437 1.91.2.6 skrll bail:
438 1.91.2.6 skrll bp->b_resid = bp->b_bcount;
439 1.91.2.6 skrll biodone(bp);
440 1.91.2.6 skrll return;
441 1.1 elric }
442 1.1 elric
443 1.18 thorpej static int
444 1.1 elric cgdsize(dev_t dev)
445 1.1 elric {
446 1.1 elric struct cgd_softc *cs = getcgd_softc(dev);
447 1.1 elric
448 1.56 cegger DPRINTF_FOLLOW(("cgdsize(0x%"PRIx64")\n", dev));
449 1.1 elric if (!cs)
450 1.1 elric return -1;
451 1.91.2.2 skrll return dk_size(&cs->sc_dksc, dev);
452 1.1 elric }
453 1.1 elric
454 1.16 elric /*
455 1.16 elric * cgd_{get,put}data are functions that deal with getting a buffer
456 1.16 elric * for the new encrypted data. We have a buffer per device so that
457 1.16 elric * we can ensure that we can always have a transaction in flight.
458 1.16 elric * We use this buffer first so that we have one less piece of
459 1.16 elric * malloc'ed data at any given point.
460 1.16 elric */
461 1.16 elric
462 1.16 elric static void *
463 1.16 elric cgd_getdata(struct dk_softc *dksc, unsigned long size)
464 1.16 elric {
465 1.77 elric struct cgd_softc *cs = (struct cgd_softc *)dksc;
466 1.44 christos void * data = NULL;
467 1.16 elric
468 1.85 skrll mutex_enter(&cs->sc_lock);
469 1.16 elric if (cs->sc_data_used == 0) {
470 1.16 elric cs->sc_data_used = 1;
471 1.16 elric data = cs->sc_data;
472 1.16 elric }
473 1.85 skrll mutex_exit(&cs->sc_lock);
474 1.16 elric
475 1.16 elric if (data)
476 1.16 elric return data;
477 1.16 elric
478 1.16 elric return malloc(size, M_DEVBUF, M_NOWAIT);
479 1.16 elric }
480 1.16 elric
481 1.1 elric static void
482 1.44 christos cgd_putdata(struct dk_softc *dksc, void *data)
483 1.16 elric {
484 1.77 elric struct cgd_softc *cs = (struct cgd_softc *)dksc;
485 1.16 elric
486 1.16 elric if (data == cs->sc_data) {
487 1.85 skrll mutex_enter(&cs->sc_lock);
488 1.16 elric cs->sc_data_used = 0;
489 1.85 skrll mutex_exit(&cs->sc_lock);
490 1.16 elric } else {
491 1.16 elric free(data, M_DEVBUF);
492 1.16 elric }
493 1.16 elric }
494 1.16 elric
495 1.91.2.3 skrll static int
496 1.91.2.3 skrll cgd_diskstart(device_t dev, struct buf *bp)
497 1.1 elric {
498 1.91.2.2 skrll struct cgd_softc *cs = device_private(dev);
499 1.91.2.2 skrll struct dk_softc *dksc = &cs->sc_dksc;
500 1.91.2.4 skrll struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
501 1.91.2.3 skrll struct buf *nbp;
502 1.44 christos void * addr;
503 1.44 christos void * newaddr;
504 1.1 elric daddr_t bn;
505 1.49 ad struct vnode *vp;
506 1.1 elric
507 1.91.2.3 skrll DPRINTF_FOLLOW(("cgd_diskstart(%p, %p)\n", dksc, bp));
508 1.1 elric
509 1.91.2.3 skrll bn = bp->b_rawblkno;
510 1.22 perry
511 1.91.2.3 skrll /*
512 1.91.2.3 skrll * We attempt to allocate all of our resources up front, so that
513 1.91.2.3 skrll * we can fail quickly if they are unavailable.
514 1.91.2.3 skrll */
515 1.91.2.3 skrll nbp = getiobuf(cs->sc_tvn, false);
516 1.91.2.3 skrll if (nbp == NULL)
517 1.91.2.3 skrll return EAGAIN;
518 1.16 elric
519 1.91.2.3 skrll /*
520 1.91.2.3 skrll * If we are writing, then we need to encrypt the outgoing
521 1.91.2.3 skrll * block into a new block of memory.
522 1.91.2.3 skrll */
523 1.91.2.3 skrll newaddr = addr = bp->b_data;
524 1.91.2.3 skrll if ((bp->b_flags & B_READ) == 0) {
525 1.91.2.3 skrll newaddr = cgd_getdata(dksc, bp->b_bcount);
526 1.91.2.3 skrll if (!newaddr) {
527 1.91.2.3 skrll putiobuf(nbp);
528 1.91.2.3 skrll return EAGAIN;
529 1.16 elric }
530 1.91.2.3 skrll cgd_cipher(cs, newaddr, addr, bp->b_bcount, bn,
531 1.91.2.4 skrll dg->dg_secsize, CGD_CIPHER_ENCRYPT);
532 1.91.2.3 skrll }
533 1.1 elric
534 1.91.2.3 skrll nbp->b_data = newaddr;
535 1.91.2.3 skrll nbp->b_flags = bp->b_flags;
536 1.91.2.3 skrll nbp->b_oflags = bp->b_oflags;
537 1.91.2.3 skrll nbp->b_cflags = bp->b_cflags;
538 1.91.2.3 skrll nbp->b_iodone = cgdiodone;
539 1.91.2.3 skrll nbp->b_proc = bp->b_proc;
540 1.91.2.4 skrll nbp->b_blkno = btodb(bn * dg->dg_secsize);
541 1.91.2.3 skrll nbp->b_bcount = bp->b_bcount;
542 1.91.2.3 skrll nbp->b_private = bp;
543 1.91.2.3 skrll
544 1.91.2.3 skrll BIO_COPYPRIO(nbp, bp);
545 1.91.2.3 skrll
546 1.91.2.3 skrll if ((nbp->b_flags & B_READ) == 0) {
547 1.91.2.3 skrll vp = nbp->b_vp;
548 1.91.2.3 skrll mutex_enter(vp->v_interlock);
549 1.91.2.3 skrll vp->v_numoutput++;
550 1.91.2.3 skrll mutex_exit(vp->v_interlock);
551 1.17 dbj }
552 1.91.2.3 skrll VOP_STRATEGY(cs->sc_tvn, nbp);
553 1.91.2.3 skrll
554 1.91.2.3 skrll return 0;
555 1.1 elric }
556 1.1 elric
557 1.18 thorpej static void
558 1.17 dbj cgdiodone(struct buf *nbp)
559 1.1 elric {
560 1.17 dbj struct buf *obp = nbp->b_private;
561 1.17 dbj struct cgd_softc *cs = getcgd_softc(obp->b_dev);
562 1.1 elric struct dk_softc *dksc = &cs->sc_dksc;
563 1.91.2.4 skrll struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
564 1.91.2.4 skrll daddr_t bn;
565 1.22 perry
566 1.17 dbj KDASSERT(cs);
567 1.1 elric
568 1.17 dbj DPRINTF_FOLLOW(("cgdiodone(%p)\n", nbp));
569 1.20 yamt DPRINTF(CGDB_IO, ("cgdiodone: bp %p bcount %d resid %d\n",
570 1.1 elric obp, obp->b_bcount, obp->b_resid));
571 1.91.2.5 skrll DPRINTF(CGDB_IO, (" dev 0x%"PRIx64", nbp %p bn %" PRId64
572 1.91.2.5 skrll " addr %p bcnt %d\n", nbp->b_dev, nbp, nbp->b_blkno, nbp->b_data,
573 1.91.2.5 skrll nbp->b_bcount));
574 1.46 ad if (nbp->b_error != 0) {
575 1.46 ad obp->b_error = nbp->b_error;
576 1.62 christos DPRINTF(CGDB_IO, ("%s: error %d\n", dksc->sc_xname,
577 1.62 christos obp->b_error));
578 1.1 elric }
579 1.1 elric
580 1.16 elric /* Perform the decryption if we are reading.
581 1.1 elric *
582 1.1 elric * Note: use the blocknumber from nbp, since it is what
583 1.1 elric * we used to encrypt the blocks.
584 1.1 elric */
585 1.1 elric
586 1.91.2.4 skrll if (nbp->b_flags & B_READ) {
587 1.91.2.4 skrll bn = dbtob(nbp->b_blkno) / dg->dg_secsize;
588 1.1 elric cgd_cipher(cs, obp->b_data, obp->b_data, obp->b_bcount,
589 1.91.2.4 skrll bn, dg->dg_secsize, CGD_CIPHER_DECRYPT);
590 1.91.2.4 skrll }
591 1.1 elric
592 1.16 elric /* If we allocated memory, free it now... */
593 1.1 elric if (nbp->b_data != obp->b_data)
594 1.16 elric cgd_putdata(dksc, nbp->b_data);
595 1.1 elric
596 1.33 yamt putiobuf(nbp);
597 1.1 elric
598 1.1 elric /* Request is complete for whatever reason */
599 1.1 elric obp->b_resid = 0;
600 1.46 ad if (obp->b_error != 0)
601 1.1 elric obp->b_resid = obp->b_bcount;
602 1.91.2.3 skrll
603 1.91.2.3 skrll dk_done(dksc, obp);
604 1.91.2.3 skrll dk_start(dksc, NULL);
605 1.1 elric }
606 1.1 elric
607 1.91.2.6 skrll static int
608 1.91.2.6 skrll cgd_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk)
609 1.91.2.6 skrll {
610 1.91.2.6 skrll struct cgd_softc *sc = device_private(dev);
611 1.91.2.6 skrll struct dk_softc *dksc = &sc->sc_dksc;
612 1.91.2.6 skrll struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
613 1.91.2.6 skrll size_t nbytes, blksize;
614 1.91.2.6 skrll void *buf;
615 1.91.2.6 skrll int error;
616 1.91.2.6 skrll
617 1.91.2.6 skrll /*
618 1.91.2.6 skrll * dk_dump gives us units of disklabel sectors. Everything
619 1.91.2.6 skrll * else in cgd uses units of diskgeom sectors. These had
620 1.91.2.6 skrll * better agree; otherwise we need to figure out how to convert
621 1.91.2.6 skrll * between them.
622 1.91.2.6 skrll */
623 1.91.2.6 skrll KASSERTMSG((dg->dg_secsize == dksc->sc_dkdev.dk_label->d_secsize),
624 1.91.2.6 skrll "diskgeom secsize %"PRIu32" != disklabel secsize %"PRIu32,
625 1.91.2.6 skrll dg->dg_secsize, dksc->sc_dkdev.dk_label->d_secsize);
626 1.91.2.6 skrll blksize = dg->dg_secsize;
627 1.91.2.6 skrll
628 1.91.2.6 skrll /*
629 1.91.2.6 skrll * Compute the number of bytes in this request, which dk_dump
630 1.91.2.6 skrll * has `helpfully' converted to a number of blocks for us.
631 1.91.2.6 skrll */
632 1.91.2.6 skrll nbytes = nblk*blksize;
633 1.91.2.6 skrll
634 1.91.2.6 skrll /* Try to acquire a buffer to store the ciphertext. */
635 1.91.2.6 skrll buf = cgd_getdata(dksc, nbytes);
636 1.91.2.6 skrll if (buf == NULL)
637 1.91.2.6 skrll /* Out of memory: give up. */
638 1.91.2.6 skrll return ENOMEM;
639 1.91.2.6 skrll
640 1.91.2.6 skrll /* Encrypt the caller's data into the temporary buffer. */
641 1.91.2.6 skrll cgd_cipher(sc, buf, va, nbytes, blkno, blksize, CGD_CIPHER_ENCRYPT);
642 1.91.2.6 skrll
643 1.91.2.6 skrll /* Pass it on to the underlying disk device. */
644 1.91.2.6 skrll error = bdev_dump(sc->sc_tdev, blkno, buf, nbytes);
645 1.91.2.6 skrll
646 1.91.2.6 skrll /* Release the buffer. */
647 1.91.2.6 skrll cgd_putdata(dksc, buf);
648 1.91.2.6 skrll
649 1.91.2.6 skrll /* Return any error from the underlying disk device. */
650 1.91.2.6 skrll return error;
651 1.91.2.6 skrll }
652 1.91.2.6 skrll
653 1.1 elric /* XXX: we should probably put these into dksubr.c, mostly */
654 1.18 thorpej static int
655 1.40 christos cgdread(dev_t dev, struct uio *uio, int flags)
656 1.1 elric {
657 1.1 elric struct cgd_softc *cs;
658 1.1 elric struct dk_softc *dksc;
659 1.1 elric
660 1.56 cegger DPRINTF_FOLLOW(("cgdread(0x%llx, %p, %d)\n",
661 1.56 cegger (unsigned long long)dev, uio, flags));
662 1.1 elric GETCGD_SOFTC(cs, dev);
663 1.1 elric dksc = &cs->sc_dksc;
664 1.91.2.2 skrll if (!DK_ATTACHED(dksc))
665 1.1 elric return ENXIO;
666 1.1 elric return physio(cgdstrategy, NULL, dev, B_READ, minphys, uio);
667 1.1 elric }
668 1.1 elric
669 1.1 elric /* XXX: we should probably put these into dksubr.c, mostly */
670 1.18 thorpej static int
671 1.40 christos cgdwrite(dev_t dev, struct uio *uio, int flags)
672 1.1 elric {
673 1.1 elric struct cgd_softc *cs;
674 1.1 elric struct dk_softc *dksc;
675 1.1 elric
676 1.56 cegger DPRINTF_FOLLOW(("cgdwrite(0x%"PRIx64", %p, %d)\n", dev, uio, flags));
677 1.1 elric GETCGD_SOFTC(cs, dev);
678 1.1 elric dksc = &cs->sc_dksc;
679 1.91.2.2 skrll if (!DK_ATTACHED(dksc))
680 1.1 elric return ENXIO;
681 1.1 elric return physio(cgdstrategy, NULL, dev, B_WRITE, minphys, uio);
682 1.1 elric }
683 1.1 elric
684 1.18 thorpej static int
685 1.44 christos cgdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
686 1.1 elric {
687 1.1 elric struct cgd_softc *cs;
688 1.1 elric struct dk_softc *dksc;
689 1.1 elric int part = DISKPART(dev);
690 1.1 elric int pmask = 1 << part;
691 1.1 elric
692 1.56 cegger DPRINTF_FOLLOW(("cgdioctl(0x%"PRIx64", %ld, %p, %d, %p)\n",
693 1.32 christos dev, cmd, data, flag, l));
694 1.78 christos
695 1.1 elric switch (cmd) {
696 1.91.2.1 skrll case CGDIOCGET:
697 1.91.2.1 skrll return cgd_ioctl_get(dev, data, l);
698 1.1 elric case CGDIOCSET:
699 1.1 elric case CGDIOCCLR:
700 1.1 elric if ((flag & FWRITE) == 0)
701 1.1 elric return EBADF;
702 1.78 christos /* FALLTHROUGH */
703 1.78 christos default:
704 1.78 christos GETCGD_SOFTC(cs, dev);
705 1.78 christos dksc = &cs->sc_dksc;
706 1.78 christos break;
707 1.1 elric }
708 1.1 elric
709 1.1 elric switch (cmd) {
710 1.1 elric case CGDIOCSET:
711 1.91.2.2 skrll if (DK_ATTACHED(dksc))
712 1.68 dyoung return EBUSY;
713 1.68 dyoung return cgd_ioctl_set(cs, data, l);
714 1.1 elric case CGDIOCCLR:
715 1.65 dyoung if (DK_BUSY(&cs->sc_dksc, pmask))
716 1.68 dyoung return EBUSY;
717 1.68 dyoung return cgd_ioctl_clr(cs, l);
718 1.91.2.8 skrll case DIOCGCACHE:
719 1.57 apb case DIOCCACHESYNC:
720 1.91.2.8 skrll if (!DK_ATTACHED(dksc))
721 1.91.2.8 skrll return ENOENT;
722 1.57 apb /*
723 1.57 apb * We pass this call down to the underlying disk.
724 1.57 apb */
725 1.68 dyoung return VOP_IOCTL(cs->sc_tvn, cmd, data, flag, l->l_cred);
726 1.91.2.3 skrll case DIOCGSTRATEGY:
727 1.91.2.3 skrll case DIOCSSTRATEGY:
728 1.91.2.3 skrll if (!DK_ATTACHED(dksc))
729 1.91.2.3 skrll return ENOENT;
730 1.91.2.3 skrll /*FALLTHROUGH*/
731 1.1 elric default:
732 1.91.2.2 skrll return dk_ioctl(dksc, dev, cmd, data, flag, l);
733 1.91.2.1 skrll case CGDIOCGET:
734 1.91.2.1 skrll KASSERT(0);
735 1.91.2.1 skrll return EINVAL;
736 1.1 elric }
737 1.1 elric }
738 1.1 elric
739 1.18 thorpej static int
740 1.44 christos cgddump(dev_t dev, daddr_t blkno, void *va, size_t size)
741 1.1 elric {
742 1.1 elric struct cgd_softc *cs;
743 1.1 elric
744 1.56 cegger DPRINTF_FOLLOW(("cgddump(0x%"PRIx64", %" PRId64 ", %p, %lu)\n",
745 1.56 cegger dev, blkno, va, (unsigned long)size));
746 1.1 elric GETCGD_SOFTC(cs, dev);
747 1.91.2.2 skrll return dk_dump(&cs->sc_dksc, dev, blkno, va, size);
748 1.1 elric }
749 1.1 elric
750 1.1 elric /*
751 1.1 elric * XXXrcd:
752 1.1 elric * for now we hardcode the maximum key length.
753 1.1 elric */
754 1.1 elric #define MAX_KEYSIZE 1024
755 1.1 elric
756 1.53 christos static const struct {
757 1.53 christos const char *n;
758 1.53 christos int v;
759 1.53 christos int d;
760 1.53 christos } encblkno[] = {
761 1.53 christos { "encblkno", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
762 1.53 christos { "encblkno8", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
763 1.53 christos { "encblkno1", CGD_CIPHER_CBC_ENCBLKNO1, 8 },
764 1.53 christos };
765 1.53 christos
766 1.1 elric /* ARGSUSED */
767 1.1 elric static int
768 1.32 christos cgd_ioctl_set(struct cgd_softc *cs, void *data, struct lwp *l)
769 1.1 elric {
770 1.1 elric struct cgd_ioctl *ci = data;
771 1.1 elric struct vnode *vp;
772 1.1 elric int ret;
773 1.53 christos size_t i;
774 1.43 cbiere size_t keybytes; /* key length in bytes */
775 1.27 drochner const char *cp;
776 1.71 dholland struct pathbuf *pb;
777 1.36 christos char *inbuf;
778 1.80 christos struct dk_softc *dksc = &cs->sc_dksc;
779 1.1 elric
780 1.1 elric cp = ci->ci_disk;
781 1.71 dholland
782 1.71 dholland ret = pathbuf_copyin(ci->ci_disk, &pb);
783 1.71 dholland if (ret != 0) {
784 1.71 dholland return ret;
785 1.71 dholland }
786 1.71 dholland ret = dk_lookup(pb, l, &vp);
787 1.71 dholland pathbuf_destroy(pb);
788 1.71 dholland if (ret != 0) {
789 1.1 elric return ret;
790 1.71 dholland }
791 1.1 elric
792 1.36 christos inbuf = malloc(MAX_KEYSIZE, M_TEMP, M_WAITOK);
793 1.36 christos
794 1.32 christos if ((ret = cgdinit(cs, cp, vp, l)) != 0)
795 1.1 elric goto bail;
796 1.1 elric
797 1.36 christos (void)memset(inbuf, 0, MAX_KEYSIZE);
798 1.1 elric ret = copyinstr(ci->ci_alg, inbuf, 256, NULL);
799 1.1 elric if (ret)
800 1.1 elric goto bail;
801 1.1 elric cs->sc_cfuncs = cryptfuncs_find(inbuf);
802 1.1 elric if (!cs->sc_cfuncs) {
803 1.1 elric ret = EINVAL;
804 1.1 elric goto bail;
805 1.1 elric }
806 1.1 elric
807 1.43 cbiere (void)memset(inbuf, 0, MAX_KEYSIZE);
808 1.36 christos ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL);
809 1.1 elric if (ret)
810 1.1 elric goto bail;
811 1.53 christos
812 1.53 christos for (i = 0; i < __arraycount(encblkno); i++)
813 1.53 christos if (strcmp(encblkno[i].n, inbuf) == 0)
814 1.53 christos break;
815 1.53 christos
816 1.53 christos if (i == __arraycount(encblkno)) {
817 1.1 elric ret = EINVAL;
818 1.1 elric goto bail;
819 1.1 elric }
820 1.1 elric
821 1.15 dan keybytes = ci->ci_keylen / 8 + 1;
822 1.15 dan if (keybytes > MAX_KEYSIZE) {
823 1.1 elric ret = EINVAL;
824 1.1 elric goto bail;
825 1.1 elric }
826 1.53 christos
827 1.36 christos (void)memset(inbuf, 0, MAX_KEYSIZE);
828 1.15 dan ret = copyin(ci->ci_key, inbuf, keybytes);
829 1.1 elric if (ret)
830 1.1 elric goto bail;
831 1.1 elric
832 1.1 elric cs->sc_cdata.cf_blocksize = ci->ci_blocksize;
833 1.53 christos cs->sc_cdata.cf_mode = encblkno[i].v;
834 1.78 christos cs->sc_cdata.cf_keylen = ci->ci_keylen;
835 1.1 elric cs->sc_cdata.cf_priv = cs->sc_cfuncs->cf_init(ci->ci_keylen, inbuf,
836 1.1 elric &cs->sc_cdata.cf_blocksize);
837 1.62 christos if (cs->sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) {
838 1.62 christos log(LOG_WARNING, "cgd: Disallowed cipher with blocksize %zu > %u\n",
839 1.63 christos cs->sc_cdata.cf_blocksize, CGD_MAXBLOCKSIZE);
840 1.62 christos cs->sc_cdata.cf_priv = NULL;
841 1.62 christos }
842 1.78 christos
843 1.53 christos /*
844 1.53 christos * The blocksize is supposed to be in bytes. Unfortunately originally
845 1.53 christos * it was expressed in bits. For compatibility we maintain encblkno
846 1.53 christos * and encblkno8.
847 1.53 christos */
848 1.53 christos cs->sc_cdata.cf_blocksize /= encblkno[i].d;
849 1.91.2.2 skrll (void)explicit_memset(inbuf, 0, MAX_KEYSIZE);
850 1.1 elric if (!cs->sc_cdata.cf_priv) {
851 1.1 elric ret = EINVAL; /* XXX is this the right error? */
852 1.1 elric goto bail;
853 1.1 elric }
854 1.36 christos free(inbuf, M_TEMP);
855 1.1 elric
856 1.80 christos bufq_alloc(&dksc->sc_bufq, "fcfs", 0);
857 1.16 elric
858 1.16 elric cs->sc_data = malloc(MAXPHYS, M_DEVBUF, M_WAITOK);
859 1.16 elric cs->sc_data_used = 0;
860 1.16 elric
861 1.1 elric /* Attach the disk. */
862 1.91.2.2 skrll dk_attach(dksc);
863 1.80 christos disk_attach(&dksc->sc_dkdev);
864 1.1 elric
865 1.91.2.2 skrll disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL);
866 1.91.2.2 skrll
867 1.29 yamt /* Discover wedges on this disk. */
868 1.80 christos dkwedge_discover(&dksc->sc_dkdev);
869 1.29 yamt
870 1.1 elric return 0;
871 1.1 elric
872 1.1 elric bail:
873 1.36 christos free(inbuf, M_TEMP);
874 1.51 ad (void)vn_close(vp, FREAD|FWRITE, l->l_cred);
875 1.1 elric return ret;
876 1.1 elric }
877 1.1 elric
878 1.1 elric /* ARGSUSED */
879 1.1 elric static int
880 1.65 dyoung cgd_ioctl_clr(struct cgd_softc *cs, struct lwp *l)
881 1.1 elric {
882 1.80 christos struct dk_softc *dksc = &cs->sc_dksc;
883 1.65 dyoung
884 1.91.2.2 skrll if (!DK_ATTACHED(dksc))
885 1.65 dyoung return ENXIO;
886 1.16 elric
887 1.29 yamt /* Delete all of our wedges. */
888 1.80 christos dkwedge_delall(&dksc->sc_dkdev);
889 1.29 yamt
890 1.16 elric /* Kill off any queued buffers. */
891 1.91.2.3 skrll dk_drain(dksc);
892 1.80 christos bufq_free(dksc->sc_bufq);
893 1.1 elric
894 1.51 ad (void)vn_close(cs->sc_tvn, FREAD|FWRITE, l->l_cred);
895 1.1 elric cs->sc_cfuncs->cf_destroy(cs->sc_cdata.cf_priv);
896 1.1 elric free(cs->sc_tpath, M_DEVBUF);
897 1.16 elric free(cs->sc_data, M_DEVBUF);
898 1.16 elric cs->sc_data_used = 0;
899 1.91.2.2 skrll dk_detach(dksc);
900 1.80 christos disk_detach(&dksc->sc_dkdev);
901 1.1 elric
902 1.1 elric return 0;
903 1.1 elric }
904 1.1 elric
905 1.1 elric static int
906 1.78 christos cgd_ioctl_get(dev_t dev, void *data, struct lwp *l)
907 1.78 christos {
908 1.81 martin struct cgd_softc *cs = getcgd_softc(dev);
909 1.78 christos struct cgd_user *cgu;
910 1.78 christos int unit;
911 1.80 christos struct dk_softc *dksc = &cs->sc_dksc;
912 1.78 christos
913 1.78 christos unit = CGDUNIT(dev);
914 1.78 christos cgu = (struct cgd_user *)data;
915 1.78 christos
916 1.78 christos DPRINTF_FOLLOW(("cgd_ioctl_get(0x%"PRIx64", %d, %p, %p)\n",
917 1.78 christos dev, unit, data, l));
918 1.78 christos
919 1.78 christos if (cgu->cgu_unit == -1)
920 1.78 christos cgu->cgu_unit = unit;
921 1.78 christos
922 1.78 christos if (cgu->cgu_unit < 0)
923 1.78 christos return EINVAL; /* XXX: should this be ENXIO? */
924 1.78 christos
925 1.78 christos cs = device_lookup_private(&cgd_cd, unit);
926 1.91.2.2 skrll if (cs == NULL || !DK_ATTACHED(dksc)) {
927 1.78 christos cgu->cgu_dev = 0;
928 1.78 christos cgu->cgu_alg[0] = '\0';
929 1.78 christos cgu->cgu_blocksize = 0;
930 1.78 christos cgu->cgu_mode = 0;
931 1.78 christos cgu->cgu_keylen = 0;
932 1.78 christos }
933 1.78 christos else {
934 1.78 christos cgu->cgu_dev = cs->sc_tdev;
935 1.78 christos strlcpy(cgu->cgu_alg, cs->sc_cfuncs->cf_name,
936 1.78 christos sizeof(cgu->cgu_alg));
937 1.78 christos cgu->cgu_blocksize = cs->sc_cdata.cf_blocksize;
938 1.78 christos cgu->cgu_mode = cs->sc_cdata.cf_mode;
939 1.78 christos cgu->cgu_keylen = cs->sc_cdata.cf_keylen;
940 1.78 christos }
941 1.78 christos return 0;
942 1.78 christos }
943 1.78 christos
944 1.78 christos static int
945 1.27 drochner cgdinit(struct cgd_softc *cs, const char *cpath, struct vnode *vp,
946 1.32 christos struct lwp *l)
947 1.1 elric {
948 1.80 christos struct disk_geom *dg;
949 1.1 elric int ret;
950 1.36 christos char *tmppath;
951 1.76 christos uint64_t psize;
952 1.76 christos unsigned secsize;
953 1.80 christos struct dk_softc *dksc = &cs->sc_dksc;
954 1.1 elric
955 1.1 elric cs->sc_tvn = vp;
956 1.36 christos cs->sc_tpath = NULL;
957 1.1 elric
958 1.36 christos tmppath = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
959 1.1 elric ret = copyinstr(cpath, tmppath, MAXPATHLEN, &cs->sc_tpathlen);
960 1.1 elric if (ret)
961 1.1 elric goto bail;
962 1.1 elric cs->sc_tpath = malloc(cs->sc_tpathlen, M_DEVBUF, M_WAITOK);
963 1.1 elric memcpy(cs->sc_tpath, tmppath, cs->sc_tpathlen);
964 1.1 elric
965 1.88 hannken cs->sc_tdev = vp->v_rdev;
966 1.1 elric
967 1.76 christos if ((ret = getdisksize(vp, &psize, &secsize)) != 0)
968 1.1 elric goto bail;
969 1.1 elric
970 1.76 christos if (psize == 0) {
971 1.1 elric ret = ENODEV;
972 1.1 elric goto bail;
973 1.1 elric }
974 1.1 elric
975 1.1 elric /*
976 1.1 elric * XXX here we should probe the underlying device. If we
977 1.1 elric * are accessing a partition of type RAW_PART, then
978 1.1 elric * we should populate our initial geometry with the
979 1.1 elric * geometry that we discover from the device.
980 1.1 elric */
981 1.80 christos dg = &dksc->sc_dkdev.dk_geom;
982 1.80 christos memset(dg, 0, sizeof(*dg));
983 1.80 christos dg->dg_secperunit = psize;
984 1.91.2.4 skrll dg->dg_secsize = secsize;
985 1.80 christos dg->dg_ntracks = 1;
986 1.91.2.4 skrll dg->dg_nsectors = 1024 * 1024 / dg->dg_secsize;
987 1.80 christos dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors;
988 1.1 elric
989 1.1 elric bail:
990 1.36 christos free(tmppath, M_TEMP);
991 1.1 elric if (ret && cs->sc_tpath)
992 1.1 elric free(cs->sc_tpath, M_DEVBUF);
993 1.1 elric return ret;
994 1.1 elric }
995 1.1 elric
996 1.1 elric /*
997 1.1 elric * Our generic cipher entry point. This takes care of the
998 1.1 elric * IV mode and passes off the work to the specific cipher.
999 1.1 elric * We implement here the IV method ``encrypted block
1000 1.1 elric * number''.
1001 1.22 perry *
1002 1.1 elric * XXXrcd: for now we rely on our own crypto framework defined
1003 1.1 elric * in dev/cgd_crypto.c. This will change when we
1004 1.1 elric * get a generic kernel crypto framework.
1005 1.1 elric */
1006 1.1 elric
1007 1.1 elric static void
1008 1.25 xtraeme blkno2blkno_buf(char *sbuf, daddr_t blkno)
1009 1.1 elric {
1010 1.1 elric int i;
1011 1.1 elric
1012 1.1 elric /* Set up the blkno in blkno_buf, here we do not care much
1013 1.1 elric * about the final layout of the information as long as we
1014 1.1 elric * can guarantee that each sector will have a different IV
1015 1.1 elric * and that the endianness of the machine will not affect
1016 1.1 elric * the representation that we have chosen.
1017 1.1 elric *
1018 1.1 elric * We choose this representation, because it does not rely
1019 1.1 elric * on the size of buf (which is the blocksize of the cipher),
1020 1.1 elric * but allows daddr_t to grow without breaking existing
1021 1.1 elric * disks.
1022 1.1 elric *
1023 1.1 elric * Note that blkno2blkno_buf does not take a size as input,
1024 1.1 elric * and hence must be called on a pre-zeroed buffer of length
1025 1.1 elric * greater than or equal to sizeof(daddr_t).
1026 1.1 elric */
1027 1.1 elric for (i=0; i < sizeof(daddr_t); i++) {
1028 1.25 xtraeme *sbuf++ = blkno & 0xff;
1029 1.1 elric blkno >>= 8;
1030 1.1 elric }
1031 1.1 elric }
1032 1.1 elric
1033 1.1 elric static void
1034 1.44 christos cgd_cipher(struct cgd_softc *cs, void *dstv, void *srcv,
1035 1.44 christos size_t len, daddr_t blkno, size_t secsize, int dir)
1036 1.1 elric {
1037 1.44 christos char *dst = dstv;
1038 1.91.2.7 skrll char *src = srcv;
1039 1.91.2.7 skrll cfunc_cipher_prep *ciprep = cs->sc_cfuncs->cf_cipher_prep;
1040 1.1 elric cfunc_cipher *cipher = cs->sc_cfuncs->cf_cipher;
1041 1.1 elric struct uio dstuio;
1042 1.1 elric struct uio srcuio;
1043 1.1 elric struct iovec dstiov[2];
1044 1.1 elric struct iovec srciov[2];
1045 1.42 christos size_t blocksize = cs->sc_cdata.cf_blocksize;
1046 1.91.2.4 skrll size_t todo;
1047 1.91.2.7 skrll char blkno_buf[CGD_MAXBLOCKSIZE], *iv;
1048 1.1 elric
1049 1.1 elric DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir));
1050 1.1 elric
1051 1.22 perry DIAGCONDPANIC(len % blocksize != 0,
1052 1.1 elric ("cgd_cipher: len %% blocksize != 0"));
1053 1.1 elric
1054 1.1 elric /* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */
1055 1.1 elric DIAGCONDPANIC(sizeof(daddr_t) > blocksize,
1056 1.1 elric ("cgd_cipher: sizeof(daddr_t) > blocksize"));
1057 1.1 elric
1058 1.91.2.7 skrll DIAGCONDPANIC(blocksize > CGD_MAXBLOCKSIZE,
1059 1.91.2.7 skrll ("cgd_cipher: blocksize > CGD_MAXBLOCKSIZE"));
1060 1.1 elric
1061 1.1 elric dstuio.uio_iov = dstiov;
1062 1.91.2.7 skrll dstuio.uio_iovcnt = 1;
1063 1.1 elric
1064 1.1 elric srcuio.uio_iov = srciov;
1065 1.91.2.7 skrll srcuio.uio_iovcnt = 1;
1066 1.1 elric
1067 1.91.2.4 skrll for (; len > 0; len -= todo) {
1068 1.91.2.4 skrll todo = MIN(len, secsize);
1069 1.91.2.4 skrll
1070 1.91.2.7 skrll dstiov[0].iov_base = dst;
1071 1.91.2.7 skrll srciov[0].iov_base = src;
1072 1.91.2.7 skrll dstiov[0].iov_len = todo;
1073 1.91.2.7 skrll srciov[0].iov_len = todo;
1074 1.1 elric
1075 1.64 christos memset(blkno_buf, 0x0, blocksize);
1076 1.1 elric blkno2blkno_buf(blkno_buf, blkno);
1077 1.1 elric IFDEBUG(CGDB_CRYPTO, hexprint("step 1: blkno_buf",
1078 1.64 christos blkno_buf, blocksize));
1079 1.91.2.7 skrll
1080 1.91.2.7 skrll /*
1081 1.91.2.7 skrll * Compute an initial IV. All ciphers
1082 1.91.2.7 skrll * can convert blkno_buf in-place.
1083 1.91.2.7 skrll */
1084 1.91.2.7 skrll iv = blkno_buf;
1085 1.91.2.7 skrll ciprep(cs->sc_cdata.cf_priv, iv, blkno_buf, blocksize, dir);
1086 1.91.2.7 skrll IFDEBUG(CGDB_CRYPTO, hexprint("step 2: iv", iv, blocksize));
1087 1.91.2.7 skrll
1088 1.91.2.7 skrll cipher(cs->sc_cdata.cf_priv, &dstuio, &srcuio, iv, dir);
1089 1.1 elric
1090 1.91.2.4 skrll dst += todo;
1091 1.91.2.4 skrll src += todo;
1092 1.1 elric blkno++;
1093 1.1 elric }
1094 1.1 elric }
1095 1.1 elric
1096 1.1 elric #ifdef DEBUG
1097 1.1 elric static void
1098 1.26 drochner hexprint(const char *start, void *buf, int len)
1099 1.1 elric {
1100 1.1 elric char *c = buf;
1101 1.1 elric
1102 1.1 elric DIAGCONDPANIC(len < 0, ("hexprint: called with len < 0"));
1103 1.1 elric printf("%s: len=%06d 0x", start, len);
1104 1.1 elric while (len--)
1105 1.43 cbiere printf("%02x", (unsigned char) *c++);
1106 1.1 elric }
1107 1.1 elric #endif
1108 1.58 haad
1109 1.91.2.7 skrll static void
1110 1.91.2.7 skrll selftest(void)
1111 1.91.2.7 skrll {
1112 1.91.2.7 skrll struct cgd_softc cs;
1113 1.91.2.7 skrll void *buf;
1114 1.91.2.7 skrll
1115 1.91.2.7 skrll printf("running cgd selftest ");
1116 1.91.2.7 skrll
1117 1.91.2.7 skrll for (size_t i = 0; i < __arraycount(selftests); i++) {
1118 1.91.2.7 skrll const char *alg = selftests[i].alg;
1119 1.91.2.7 skrll const uint8_t *key = selftests[i].key;
1120 1.91.2.7 skrll int keylen = selftests[i].keylen;
1121 1.91.2.7 skrll int txtlen = selftests[i].txtlen;
1122 1.91.2.7 skrll
1123 1.91.2.7 skrll printf("%s-%d ", alg, keylen);
1124 1.91.2.7 skrll
1125 1.91.2.7 skrll memset(&cs, 0, sizeof(cs));
1126 1.91.2.7 skrll
1127 1.91.2.7 skrll cs.sc_cfuncs = cryptfuncs_find(alg);
1128 1.91.2.7 skrll if (cs.sc_cfuncs == NULL)
1129 1.91.2.7 skrll panic("%s not implemented", alg);
1130 1.91.2.7 skrll
1131 1.91.2.7 skrll cs.sc_cdata.cf_blocksize = 8 * selftests[i].blocksize;
1132 1.91.2.7 skrll cs.sc_cdata.cf_mode = CGD_CIPHER_CBC_ENCBLKNO1;
1133 1.91.2.7 skrll cs.sc_cdata.cf_keylen = keylen;
1134 1.91.2.7 skrll
1135 1.91.2.7 skrll cs.sc_cdata.cf_priv = cs.sc_cfuncs->cf_init(keylen,
1136 1.91.2.7 skrll key, &cs.sc_cdata.cf_blocksize);
1137 1.91.2.7 skrll if (cs.sc_cdata.cf_priv == NULL)
1138 1.91.2.7 skrll panic("cf_priv is NULL");
1139 1.91.2.7 skrll if (cs.sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE)
1140 1.91.2.7 skrll panic("bad block size %zu", cs.sc_cdata.cf_blocksize);
1141 1.91.2.7 skrll
1142 1.91.2.7 skrll cs.sc_cdata.cf_blocksize /= 8;
1143 1.91.2.7 skrll
1144 1.91.2.7 skrll buf = malloc(txtlen, M_DEVBUF, M_WAITOK);
1145 1.91.2.7 skrll memcpy(buf, selftests[i].ptxt, txtlen);
1146 1.91.2.7 skrll
1147 1.91.2.7 skrll cgd_cipher(&cs, buf, buf, txtlen, selftests[i].blkno,
1148 1.91.2.7 skrll selftests[i].secsize, CGD_CIPHER_ENCRYPT);
1149 1.91.2.7 skrll if (memcmp(buf, selftests[i].ctxt, txtlen) != 0)
1150 1.91.2.7 skrll panic("encryption is broken");
1151 1.91.2.7 skrll
1152 1.91.2.7 skrll cgd_cipher(&cs, buf, buf, txtlen, selftests[i].blkno,
1153 1.91.2.7 skrll selftests[i].secsize, CGD_CIPHER_DECRYPT);
1154 1.91.2.7 skrll if (memcmp(buf, selftests[i].ptxt, txtlen) != 0)
1155 1.91.2.7 skrll panic("decryption is broken");
1156 1.91.2.7 skrll
1157 1.91.2.7 skrll free(buf, M_DEVBUF);
1158 1.91.2.7 skrll cs.sc_cfuncs->cf_destroy(cs.sc_cdata.cf_priv);
1159 1.91.2.7 skrll }
1160 1.91.2.7 skrll
1161 1.91.2.7 skrll printf("done\n");
1162 1.91.2.7 skrll }
1163 1.91.2.7 skrll
1164 1.91.2.7 skrll MODULE(MODULE_CLASS_DRIVER, cgd, "blowfish,des,dk_subr");
1165 1.74 jruoho
1166 1.58 haad #ifdef _MODULE
1167 1.66 dyoung CFDRIVER_DECL(cgd, DV_DISK, NULL);
1168 1.91.2.6 skrll
1169 1.91.2.6 skrll devmajor_t cgd_bmajor = -1, cgd_cmajor = -1;
1170 1.74 jruoho #endif
1171 1.58 haad
1172 1.58 haad static int
1173 1.58 haad cgd_modcmd(modcmd_t cmd, void *arg)
1174 1.58 haad {
1175 1.82 martin int error = 0;
1176 1.74 jruoho
1177 1.58 haad switch (cmd) {
1178 1.58 haad case MODULE_CMD_INIT:
1179 1.91.2.7 skrll selftest();
1180 1.74 jruoho #ifdef _MODULE
1181 1.66 dyoung error = config_cfdriver_attach(&cgd_cd);
1182 1.66 dyoung if (error)
1183 1.66 dyoung break;
1184 1.66 dyoung
1185 1.66 dyoung error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
1186 1.66 dyoung if (error) {
1187 1.66 dyoung config_cfdriver_detach(&cgd_cd);
1188 1.91.2.6 skrll aprint_error("%s: unable to register cfattach for"
1189 1.91.2.6 skrll "%s, error %d\n", __func__, cgd_cd.cd_name, error);
1190 1.66 dyoung break;
1191 1.66 dyoung }
1192 1.91.2.6 skrll /*
1193 1.91.2.6 skrll * Attach the {b,c}devsw's
1194 1.91.2.6 skrll */
1195 1.91.2.6 skrll error = devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1196 1.91.2.6 skrll &cgd_cdevsw, &cgd_cmajor);
1197 1.74 jruoho
1198 1.91.2.6 skrll /*
1199 1.91.2.6 skrll * If devsw_attach fails, remove from autoconf database
1200 1.91.2.6 skrll */
1201 1.66 dyoung if (error) {
1202 1.66 dyoung config_cfattach_detach(cgd_cd.cd_name, &cgd_ca);
1203 1.66 dyoung config_cfdriver_detach(&cgd_cd);
1204 1.91.2.6 skrll aprint_error("%s: unable to attach %s devsw, "
1205 1.91.2.6 skrll "error %d", __func__, cgd_cd.cd_name, error);
1206 1.66 dyoung break;
1207 1.66 dyoung }
1208 1.74 jruoho #endif
1209 1.58 haad break;
1210 1.58 haad
1211 1.58 haad case MODULE_CMD_FINI:
1212 1.74 jruoho #ifdef _MODULE
1213 1.91.2.6 skrll /*
1214 1.91.2.6 skrll * Remove {b,c}devsw's
1215 1.91.2.6 skrll */
1216 1.91.2.6 skrll devsw_detach(&cgd_bdevsw, &cgd_cdevsw);
1217 1.91.2.6 skrll
1218 1.91.2.6 skrll /*
1219 1.91.2.6 skrll * Now remove device from autoconf database
1220 1.91.2.6 skrll */
1221 1.66 dyoung error = config_cfattach_detach(cgd_cd.cd_name, &cgd_ca);
1222 1.91.2.6 skrll if (error) {
1223 1.91.2.6 skrll (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1224 1.91.2.6 skrll &cgd_cdevsw, &cgd_cmajor);
1225 1.91.2.6 skrll aprint_error("%s: failed to detach %s cfattach, "
1226 1.91.2.6 skrll "error %d\n", __func__, cgd_cd.cd_name, error);
1227 1.91.2.6 skrll break;
1228 1.91.2.6 skrll }
1229 1.91.2.6 skrll error = config_cfdriver_detach(&cgd_cd);
1230 1.91.2.6 skrll if (error) {
1231 1.91.2.6 skrll (void)config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
1232 1.91.2.6 skrll (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1233 1.91.2.6 skrll &cgd_cdevsw, &cgd_cmajor);
1234 1.91.2.6 skrll aprint_error("%s: failed to detach %s cfdriver, "
1235 1.91.2.6 skrll "error %d\n", __func__, cgd_cd.cd_name, error);
1236 1.66 dyoung break;
1237 1.91.2.6 skrll }
1238 1.74 jruoho #endif
1239 1.58 haad break;
1240 1.58 haad
1241 1.58 haad case MODULE_CMD_STAT:
1242 1.91.2.6 skrll error = ENOTTY;
1243 1.91.2.6 skrll break;
1244 1.58 haad default:
1245 1.91.2.6 skrll error = ENOTTY;
1246 1.91.2.6 skrll break;
1247 1.58 haad }
1248 1.58 haad
1249 1.58 haad return error;
1250 1.58 haad }
1251