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