cgd.c revision 1.129 1 1.129 riastrad /* $NetBSD: cgd.c,v 1.129 2020/06/13 18:38:33 riastradh 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.129 riastrad __KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.129 2020/06/13 18:38:33 riastradh 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/buf.h>
38 1.21 yamt #include <sys/bufq.h>
39 1.129 riastrad #include <sys/conf.h>
40 1.129 riastrad #include <sys/cpu.h>
41 1.1 elric #include <sys/device.h>
42 1.1 elric #include <sys/disk.h>
43 1.1 elric #include <sys/disklabel.h>
44 1.129 riastrad #include <sys/errno.h>
45 1.1 elric #include <sys/fcntl.h>
46 1.129 riastrad #include <sys/ioctl.h>
47 1.129 riastrad #include <sys/kmem.h>
48 1.129 riastrad #include <sys/module.h>
49 1.71 dholland #include <sys/namei.h> /* for pathbuf */
50 1.129 riastrad #include <sys/pool.h>
51 1.129 riastrad #include <sys/proc.h>
52 1.129 riastrad #include <sys/syslog.h>
53 1.129 riastrad #include <sys/systm.h>
54 1.1 elric #include <sys/vnode.h>
55 1.122 mlelstv #include <sys/workqueue.h>
56 1.1 elric
57 1.129 riastrad #include <dev/cgd_crypto.h>
58 1.129 riastrad #include <dev/cgdvar.h>
59 1.1 elric #include <dev/dkvar.h>
60 1.1 elric
61 1.88 hannken #include <miscfs/specfs/specdev.h> /* for v_rdev */
62 1.88 hannken
63 1.102 christos #include "ioconf.h"
64 1.102 christos
65 1.112 alnsn struct selftest_params {
66 1.112 alnsn const char *alg;
67 1.112 alnsn int blocksize; /* number of bytes */
68 1.112 alnsn int secsize;
69 1.112 alnsn daddr_t blkno;
70 1.112 alnsn int keylen; /* number of bits */
71 1.112 alnsn int txtlen; /* number of bytes */
72 1.112 alnsn const uint8_t *key;
73 1.112 alnsn const uint8_t *ptxt;
74 1.112 alnsn const uint8_t *ctxt;
75 1.112 alnsn };
76 1.112 alnsn
77 1.1 elric /* Entry Point Functions */
78 1.1 elric
79 1.18 thorpej static dev_type_open(cgdopen);
80 1.18 thorpej static dev_type_close(cgdclose);
81 1.18 thorpej static dev_type_read(cgdread);
82 1.18 thorpej static dev_type_write(cgdwrite);
83 1.18 thorpej static dev_type_ioctl(cgdioctl);
84 1.18 thorpej static dev_type_strategy(cgdstrategy);
85 1.18 thorpej static dev_type_dump(cgddump);
86 1.18 thorpej static dev_type_size(cgdsize);
87 1.1 elric
88 1.1 elric const struct bdevsw cgd_bdevsw = {
89 1.84 dholland .d_open = cgdopen,
90 1.84 dholland .d_close = cgdclose,
91 1.84 dholland .d_strategy = cgdstrategy,
92 1.84 dholland .d_ioctl = cgdioctl,
93 1.84 dholland .d_dump = cgddump,
94 1.84 dholland .d_psize = cgdsize,
95 1.89 dholland .d_discard = nodiscard,
96 1.122 mlelstv .d_flag = D_DISK | D_MPSAFE
97 1.1 elric };
98 1.1 elric
99 1.1 elric const struct cdevsw cgd_cdevsw = {
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.122 mlelstv .d_flag = D_DISK | D_MPSAFE
112 1.1 elric };
113 1.1 elric
114 1.112 alnsn /*
115 1.112 alnsn * Vector 5 from IEEE 1619/D16 truncated to 64 bytes, blkno 1.
116 1.112 alnsn */
117 1.112 alnsn static const uint8_t selftest_aes_xts_256_ptxt[64] = {
118 1.112 alnsn 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
119 1.112 alnsn 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
120 1.112 alnsn 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
121 1.112 alnsn 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
122 1.112 alnsn 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
123 1.112 alnsn 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
124 1.112 alnsn 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
125 1.112 alnsn 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
126 1.112 alnsn };
127 1.112 alnsn
128 1.112 alnsn static const uint8_t selftest_aes_xts_256_ctxt[512] = {
129 1.112 alnsn 0x26, 0x4d, 0x3c, 0xa8, 0x51, 0x21, 0x94, 0xfe,
130 1.112 alnsn 0xc3, 0x12, 0xc8, 0xc9, 0x89, 0x1f, 0x27, 0x9f,
131 1.112 alnsn 0xef, 0xdd, 0x60, 0x8d, 0x0c, 0x02, 0x7b, 0x60,
132 1.112 alnsn 0x48, 0x3a, 0x3f, 0xa8, 0x11, 0xd6, 0x5e, 0xe5,
133 1.112 alnsn 0x9d, 0x52, 0xd9, 0xe4, 0x0e, 0xc5, 0x67, 0x2d,
134 1.112 alnsn 0x81, 0x53, 0x2b, 0x38, 0xb6, 0xb0, 0x89, 0xce,
135 1.112 alnsn 0x95, 0x1f, 0x0f, 0x9c, 0x35, 0x59, 0x0b, 0x8b,
136 1.112 alnsn 0x97, 0x8d, 0x17, 0x52, 0x13, 0xf3, 0x29, 0xbb,
137 1.112 alnsn };
138 1.112 alnsn
139 1.112 alnsn static const uint8_t selftest_aes_xts_256_key[33] = {
140 1.112 alnsn 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
141 1.112 alnsn 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
142 1.112 alnsn 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
143 1.112 alnsn 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95,
144 1.112 alnsn 0
145 1.112 alnsn };
146 1.112 alnsn
147 1.112 alnsn /*
148 1.112 alnsn * Vector 11 from IEEE 1619/D16 truncated to 64 bytes, blkno 0xffff.
149 1.112 alnsn */
150 1.112 alnsn static const uint8_t selftest_aes_xts_512_ptxt[64] = {
151 1.112 alnsn 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
152 1.112 alnsn 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
153 1.112 alnsn 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
154 1.112 alnsn 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
155 1.112 alnsn 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
156 1.112 alnsn 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
157 1.112 alnsn 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
158 1.112 alnsn 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
159 1.112 alnsn };
160 1.112 alnsn
161 1.112 alnsn static const uint8_t selftest_aes_xts_512_ctxt[64] = {
162 1.112 alnsn 0x77, 0xa3, 0x12, 0x51, 0x61, 0x8a, 0x15, 0xe6,
163 1.112 alnsn 0xb9, 0x2d, 0x1d, 0x66, 0xdf, 0xfe, 0x7b, 0x50,
164 1.112 alnsn 0xb5, 0x0b, 0xad, 0x55, 0x23, 0x05, 0xba, 0x02,
165 1.112 alnsn 0x17, 0xa6, 0x10, 0x68, 0x8e, 0xff, 0x7e, 0x11,
166 1.112 alnsn 0xe1, 0xd0, 0x22, 0x54, 0x38, 0xe0, 0x93, 0x24,
167 1.112 alnsn 0x2d, 0x6d, 0xb2, 0x74, 0xfd, 0xe8, 0x01, 0xd4,
168 1.112 alnsn 0xca, 0xe0, 0x6f, 0x20, 0x92, 0xc7, 0x28, 0xb2,
169 1.112 alnsn 0x47, 0x85, 0x59, 0xdf, 0x58, 0xe8, 0x37, 0xc2,
170 1.112 alnsn };
171 1.112 alnsn
172 1.112 alnsn static const uint8_t selftest_aes_xts_512_key[65] = {
173 1.112 alnsn 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
174 1.112 alnsn 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
175 1.112 alnsn 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69,
176 1.112 alnsn 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27,
177 1.112 alnsn 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
178 1.112 alnsn 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95,
179 1.112 alnsn 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37,
180 1.112 alnsn 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92,
181 1.112 alnsn 0
182 1.112 alnsn };
183 1.112 alnsn
184 1.126 riastrad static const uint8_t selftest_aes_cbc_key[32] = {
185 1.126 riastrad 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
186 1.126 riastrad 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
187 1.126 riastrad 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69,
188 1.126 riastrad 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27,
189 1.126 riastrad };
190 1.126 riastrad
191 1.126 riastrad static const uint8_t selftest_aes_cbc_128_ptxt[64] = {
192 1.126 riastrad 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
193 1.126 riastrad 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
194 1.126 riastrad 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
195 1.126 riastrad 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
196 1.126 riastrad 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
197 1.126 riastrad 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
198 1.126 riastrad 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
199 1.126 riastrad 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
200 1.126 riastrad };
201 1.126 riastrad
202 1.126 riastrad static const uint8_t selftest_aes_cbc_128_ctxt[64] = { /* blkno=1 */
203 1.126 riastrad 0x93, 0x94, 0x56, 0x36, 0x83, 0xbc, 0xff, 0xa4,
204 1.126 riastrad 0xe0, 0x24, 0x34, 0x12, 0xbe, 0xfa, 0xb0, 0x7d,
205 1.126 riastrad 0x88, 0x1e, 0xc5, 0x57, 0x55, 0x23, 0x05, 0x0c,
206 1.126 riastrad 0x69, 0xa5, 0xc1, 0xda, 0x64, 0xee, 0x74, 0x10,
207 1.126 riastrad 0xc2, 0xc5, 0xe6, 0x66, 0xd6, 0xa7, 0x49, 0x1c,
208 1.126 riastrad 0x9d, 0x40, 0xb5, 0x0c, 0x9b, 0x6e, 0x1c, 0xe6,
209 1.126 riastrad 0xb1, 0x7a, 0x1c, 0xe7, 0x5a, 0xfe, 0xf9, 0x2a,
210 1.126 riastrad 0x78, 0xfa, 0xb7, 0x7b, 0x08, 0xdf, 0x8e, 0x51,
211 1.126 riastrad };
212 1.126 riastrad
213 1.126 riastrad static const uint8_t selftest_aes_cbc_256_ptxt[64] = {
214 1.126 riastrad 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
215 1.126 riastrad 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
216 1.126 riastrad 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
217 1.126 riastrad 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
218 1.126 riastrad 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
219 1.126 riastrad 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
220 1.126 riastrad 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
221 1.126 riastrad 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
222 1.126 riastrad };
223 1.126 riastrad
224 1.126 riastrad static const uint8_t selftest_aes_cbc_256_ctxt[64] = { /* blkno=0xffff */
225 1.126 riastrad 0x6c, 0xa3, 0x15, 0x17, 0x51, 0x90, 0xe9, 0x69,
226 1.126 riastrad 0x08, 0x36, 0x7b, 0xa6, 0xbb, 0xd1, 0x0b, 0x9e,
227 1.126 riastrad 0xcd, 0x6b, 0x1e, 0xaf, 0xb6, 0x2e, 0x62, 0x7d,
228 1.126 riastrad 0x8e, 0xde, 0xf0, 0xed, 0x0d, 0x44, 0xe7, 0x31,
229 1.126 riastrad 0x26, 0xcf, 0xd5, 0x0b, 0x3e, 0x95, 0x59, 0x89,
230 1.126 riastrad 0xdf, 0x5d, 0xd6, 0x9a, 0x00, 0x66, 0xcc, 0x7f,
231 1.126 riastrad 0x45, 0xd3, 0x06, 0x58, 0xed, 0xef, 0x49, 0x47,
232 1.126 riastrad 0x87, 0x89, 0x17, 0x7d, 0x08, 0x56, 0x50, 0xe1,
233 1.126 riastrad };
234 1.126 riastrad
235 1.126 riastrad static const uint8_t selftest_3des_cbc_key[24] = {
236 1.126 riastrad 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
237 1.126 riastrad 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
238 1.126 riastrad 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
239 1.126 riastrad };
240 1.126 riastrad
241 1.126 riastrad static const uint8_t selftest_3des_cbc_ptxt[64] = {
242 1.126 riastrad 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
243 1.126 riastrad 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
244 1.126 riastrad 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
245 1.126 riastrad 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
246 1.126 riastrad 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
247 1.126 riastrad 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
248 1.126 riastrad 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
249 1.126 riastrad 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
250 1.126 riastrad };
251 1.126 riastrad
252 1.126 riastrad static const uint8_t selftest_3des_cbc_ctxt[64] = {
253 1.126 riastrad 0xa2, 0xfe, 0x81, 0xaa, 0x10, 0x6c, 0xea, 0xb9,
254 1.126 riastrad 0x11, 0x58, 0x1f, 0x29, 0xb5, 0x86, 0x71, 0x56,
255 1.126 riastrad 0xe9, 0x25, 0x1d, 0x07, 0xb1, 0x69, 0x59, 0x6c,
256 1.126 riastrad 0x96, 0x80, 0xf7, 0x54, 0x38, 0xaa, 0xa7, 0xe4,
257 1.126 riastrad 0xe8, 0x81, 0xf5, 0x00, 0xbb, 0x1c, 0x00, 0x3c,
258 1.126 riastrad 0xba, 0x38, 0x45, 0x97, 0x4c, 0xcf, 0x84, 0x14,
259 1.126 riastrad 0x46, 0x86, 0xd9, 0xf4, 0xc5, 0xe2, 0xf0, 0x54,
260 1.126 riastrad 0xde, 0x41, 0xf6, 0xa1, 0xef, 0x1b, 0x0a, 0xea,
261 1.126 riastrad };
262 1.126 riastrad
263 1.126 riastrad static const uint8_t selftest_bf_cbc_key[56] = {
264 1.126 riastrad 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
265 1.126 riastrad 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
266 1.126 riastrad 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
267 1.126 riastrad 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
268 1.126 riastrad 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
269 1.126 riastrad 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
270 1.126 riastrad 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
271 1.126 riastrad };
272 1.126 riastrad
273 1.126 riastrad static const uint8_t selftest_bf_cbc_ptxt[64] = {
274 1.126 riastrad 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
275 1.126 riastrad 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
276 1.126 riastrad 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
277 1.126 riastrad 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
278 1.126 riastrad 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
279 1.126 riastrad 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
280 1.126 riastrad 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
281 1.126 riastrad 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
282 1.126 riastrad };
283 1.126 riastrad
284 1.126 riastrad static const uint8_t selftest_bf_cbc_ctxt[64] = {
285 1.126 riastrad 0xec, 0xa2, 0xc0, 0x0e, 0xa9, 0x7f, 0x04, 0x1e,
286 1.126 riastrad 0x2e, 0x4f, 0x64, 0x07, 0x67, 0x3e, 0xf4, 0x58,
287 1.126 riastrad 0x61, 0x5f, 0xd3, 0x50, 0x5e, 0xd3, 0x4d, 0x34,
288 1.126 riastrad 0xa0, 0x53, 0xbe, 0x47, 0x75, 0x69, 0x3b, 0x1f,
289 1.126 riastrad 0x86, 0xf2, 0xae, 0x8b, 0xb7, 0x91, 0xda, 0xd4,
290 1.126 riastrad 0x2b, 0xa5, 0x47, 0x9b, 0x7d, 0x13, 0x30, 0xdd,
291 1.126 riastrad 0x7b, 0xad, 0x86, 0x57, 0x51, 0x11, 0x74, 0x42,
292 1.126 riastrad 0xb8, 0xbf, 0x69, 0x17, 0x20, 0x0a, 0xf7, 0xda,
293 1.126 riastrad };
294 1.126 riastrad
295 1.112 alnsn const struct selftest_params selftests[] = {
296 1.112 alnsn {
297 1.112 alnsn .alg = "aes-xts",
298 1.112 alnsn .blocksize = 16,
299 1.112 alnsn .secsize = 512,
300 1.112 alnsn .blkno = 1,
301 1.112 alnsn .keylen = 256,
302 1.112 alnsn .txtlen = sizeof(selftest_aes_xts_256_ptxt),
303 1.112 alnsn .key = selftest_aes_xts_256_key,
304 1.112 alnsn .ptxt = selftest_aes_xts_256_ptxt,
305 1.112 alnsn .ctxt = selftest_aes_xts_256_ctxt
306 1.112 alnsn },
307 1.112 alnsn {
308 1.112 alnsn .alg = "aes-xts",
309 1.112 alnsn .blocksize = 16,
310 1.112 alnsn .secsize = 512,
311 1.112 alnsn .blkno = 0xffff,
312 1.112 alnsn .keylen = 512,
313 1.112 alnsn .txtlen = sizeof(selftest_aes_xts_512_ptxt),
314 1.112 alnsn .key = selftest_aes_xts_512_key,
315 1.112 alnsn .ptxt = selftest_aes_xts_512_ptxt,
316 1.112 alnsn .ctxt = selftest_aes_xts_512_ctxt
317 1.126 riastrad },
318 1.126 riastrad {
319 1.126 riastrad .alg = "aes-cbc",
320 1.126 riastrad .blocksize = 16,
321 1.126 riastrad .secsize = 512,
322 1.126 riastrad .blkno = 1,
323 1.126 riastrad .keylen = 128,
324 1.126 riastrad .txtlen = sizeof(selftest_aes_cbc_128_ptxt),
325 1.126 riastrad .key = selftest_aes_cbc_key,
326 1.126 riastrad .ptxt = selftest_aes_cbc_128_ptxt,
327 1.126 riastrad .ctxt = selftest_aes_cbc_128_ctxt,
328 1.126 riastrad },
329 1.126 riastrad {
330 1.126 riastrad .alg = "aes-cbc",
331 1.126 riastrad .blocksize = 16,
332 1.126 riastrad .secsize = 512,
333 1.126 riastrad .blkno = 0xffff,
334 1.126 riastrad .keylen = 256,
335 1.126 riastrad .txtlen = sizeof(selftest_aes_cbc_256_ptxt),
336 1.126 riastrad .key = selftest_aes_cbc_key,
337 1.126 riastrad .ptxt = selftest_aes_cbc_256_ptxt,
338 1.126 riastrad .ctxt = selftest_aes_cbc_256_ctxt,
339 1.126 riastrad },
340 1.126 riastrad {
341 1.126 riastrad .alg = "3des-cbc",
342 1.126 riastrad .blocksize = 8,
343 1.126 riastrad .secsize = 512,
344 1.126 riastrad .blkno = 1,
345 1.126 riastrad .keylen = 192, /* 168 + 3*8 parity bits */
346 1.126 riastrad .txtlen = sizeof(selftest_3des_cbc_ptxt),
347 1.126 riastrad .key = selftest_3des_cbc_key,
348 1.126 riastrad .ptxt = selftest_3des_cbc_ptxt,
349 1.126 riastrad .ctxt = selftest_3des_cbc_ctxt,
350 1.126 riastrad },
351 1.126 riastrad {
352 1.126 riastrad .alg = "blowfish-cbc",
353 1.126 riastrad .blocksize = 8,
354 1.126 riastrad .secsize = 512,
355 1.126 riastrad .blkno = 1,
356 1.126 riastrad .keylen = 448,
357 1.126 riastrad .txtlen = sizeof(selftest_bf_cbc_ptxt),
358 1.126 riastrad .key = selftest_bf_cbc_key,
359 1.126 riastrad .ptxt = selftest_bf_cbc_ptxt,
360 1.126 riastrad .ctxt = selftest_bf_cbc_ctxt,
361 1.126 riastrad },
362 1.112 alnsn };
363 1.112 alnsn
364 1.65 dyoung static int cgd_match(device_t, cfdata_t, void *);
365 1.65 dyoung static void cgd_attach(device_t, device_t, void *);
366 1.65 dyoung static int cgd_detach(device_t, int);
367 1.65 dyoung static struct cgd_softc *cgd_spawn(int);
368 1.122 mlelstv static struct cgd_worker *cgd_create_one_worker(void);
369 1.122 mlelstv static void cgd_destroy_one_worker(struct cgd_worker *);
370 1.122 mlelstv static struct cgd_worker *cgd_create_worker(void);
371 1.122 mlelstv static void cgd_destroy_worker(struct cgd_worker *);
372 1.65 dyoung static int cgd_destroy(device_t);
373 1.65 dyoung
374 1.1 elric /* Internal Functions */
375 1.1 elric
376 1.99 mlelstv static int cgd_diskstart(device_t, struct buf *);
377 1.122 mlelstv static void cgd_diskstart2(struct cgd_softc *, struct cgd_xfer *);
378 1.1 elric static void cgdiodone(struct buf *);
379 1.122 mlelstv static void cgd_iodone2(struct cgd_softc *, struct cgd_xfer *);
380 1.122 mlelstv static void cgd_enqueue(struct cgd_softc *, struct cgd_xfer *);
381 1.122 mlelstv static void cgd_process(struct work *, void *);
382 1.108 riastrad static int cgd_dumpblocks(device_t, void *, daddr_t, int);
383 1.1 elric
384 1.32 christos static int cgd_ioctl_set(struct cgd_softc *, void *, struct lwp *);
385 1.65 dyoung static int cgd_ioctl_clr(struct cgd_softc *, struct lwp *);
386 1.78 christos static int cgd_ioctl_get(dev_t, void *, struct lwp *);
387 1.27 drochner static int cgdinit(struct cgd_softc *, const char *, struct vnode *,
388 1.32 christos struct lwp *);
389 1.44 christos static void cgd_cipher(struct cgd_softc *, void *, void *,
390 1.1 elric size_t, daddr_t, size_t, int);
391 1.1 elric
392 1.125 maxv static const struct dkdriver cgddkdriver = {
393 1.98 mlelstv .d_minphys = minphys,
394 1.98 mlelstv .d_open = cgdopen,
395 1.98 mlelstv .d_close = cgdclose,
396 1.98 mlelstv .d_strategy = cgdstrategy,
397 1.98 mlelstv .d_iosize = NULL,
398 1.99 mlelstv .d_diskstart = cgd_diskstart,
399 1.108 riastrad .d_dumpblocks = cgd_dumpblocks,
400 1.98 mlelstv .d_lastclose = NULL
401 1.29 yamt };
402 1.29 yamt
403 1.65 dyoung CFATTACH_DECL3_NEW(cgd, sizeof(struct cgd_softc),
404 1.65 dyoung cgd_match, cgd_attach, cgd_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
405 1.65 dyoung
406 1.1 elric /* DIAGNOSTIC and DEBUG definitions */
407 1.1 elric
408 1.1 elric #if defined(CGDDEBUG) && !defined(DEBUG)
409 1.1 elric #define DEBUG
410 1.1 elric #endif
411 1.1 elric
412 1.1 elric #ifdef DEBUG
413 1.1 elric int cgddebug = 0;
414 1.1 elric
415 1.1 elric #define CGDB_FOLLOW 0x1
416 1.1 elric #define CGDB_IO 0x2
417 1.1 elric #define CGDB_CRYPTO 0x4
418 1.1 elric
419 1.1 elric #define IFDEBUG(x,y) if (cgddebug & (x)) y
420 1.1 elric #define DPRINTF(x,y) IFDEBUG(x, printf y)
421 1.1 elric #define DPRINTF_FOLLOW(y) DPRINTF(CGDB_FOLLOW, y)
422 1.1 elric
423 1.26 drochner static void hexprint(const char *, void *, int);
424 1.1 elric
425 1.1 elric #else
426 1.1 elric #define IFDEBUG(x,y)
427 1.1 elric #define DPRINTF(x,y)
428 1.1 elric #define DPRINTF_FOLLOW(y)
429 1.1 elric #endif
430 1.1 elric
431 1.1 elric /* Global variables */
432 1.1 elric
433 1.122 mlelstv static kmutex_t cgd_spawning_mtx;
434 1.122 mlelstv static kcondvar_t cgd_spawning_cv;
435 1.122 mlelstv static bool cgd_spawning;
436 1.122 mlelstv static struct cgd_worker *cgd_worker;
437 1.122 mlelstv static u_int cgd_refcnt; /* number of users of cgd_worker */
438 1.122 mlelstv
439 1.1 elric /* Utility Functions */
440 1.1 elric
441 1.1 elric #define CGDUNIT(x) DISKUNIT(x)
442 1.1 elric
443 1.65 dyoung /* The code */
444 1.65 dyoung
445 1.122 mlelstv static int
446 1.122 mlelstv cgd_lock(bool intr)
447 1.122 mlelstv {
448 1.122 mlelstv int error = 0;
449 1.122 mlelstv
450 1.122 mlelstv mutex_enter(&cgd_spawning_mtx);
451 1.122 mlelstv while (cgd_spawning) {
452 1.122 mlelstv if (intr)
453 1.122 mlelstv error = cv_wait_sig(&cgd_spawning_cv, &cgd_spawning_mtx);
454 1.122 mlelstv else
455 1.122 mlelstv cv_wait(&cgd_spawning_cv, &cgd_spawning_mtx);
456 1.122 mlelstv }
457 1.122 mlelstv if (error == 0)
458 1.122 mlelstv cgd_spawning = true;
459 1.122 mlelstv mutex_exit(&cgd_spawning_mtx);
460 1.122 mlelstv return error;
461 1.122 mlelstv }
462 1.122 mlelstv
463 1.122 mlelstv static void
464 1.122 mlelstv cgd_unlock(void)
465 1.122 mlelstv {
466 1.122 mlelstv mutex_enter(&cgd_spawning_mtx);
467 1.122 mlelstv cgd_spawning = false;
468 1.122 mlelstv cv_broadcast(&cgd_spawning_cv);
469 1.122 mlelstv mutex_exit(&cgd_spawning_mtx);
470 1.122 mlelstv }
471 1.122 mlelstv
472 1.1 elric static struct cgd_softc *
473 1.1 elric getcgd_softc(dev_t dev)
474 1.1 elric {
475 1.122 mlelstv return device_lookup_private(&cgd_cd, CGDUNIT(dev));
476 1.1 elric }
477 1.1 elric
478 1.65 dyoung static int
479 1.65 dyoung cgd_match(device_t self, cfdata_t cfdata, void *aux)
480 1.65 dyoung {
481 1.65 dyoung
482 1.65 dyoung return 1;
483 1.65 dyoung }
484 1.1 elric
485 1.1 elric static void
486 1.65 dyoung cgd_attach(device_t parent, device_t self, void *aux)
487 1.1 elric {
488 1.65 dyoung struct cgd_softc *sc = device_private(self);
489 1.1 elric
490 1.85 skrll mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_BIO);
491 1.122 mlelstv cv_init(&sc->sc_cv, "cgdcv");
492 1.98 mlelstv dk_init(&sc->sc_dksc, self, DKTYPE_CGD);
493 1.65 dyoung disk_init(&sc->sc_dksc.sc_dkdev, sc->sc_dksc.sc_xname, &cgddkdriver);
494 1.70 joerg
495 1.98 mlelstv if (!pmf_device_register(self, NULL, NULL))
496 1.107 msaitoh aprint_error_dev(self,
497 1.107 msaitoh "unable to register power management hooks\n");
498 1.65 dyoung }
499 1.65 dyoung
500 1.65 dyoung
501 1.65 dyoung static int
502 1.65 dyoung cgd_detach(device_t self, int flags)
503 1.65 dyoung {
504 1.67 dyoung int ret;
505 1.67 dyoung const int pmask = 1 << RAW_PART;
506 1.65 dyoung struct cgd_softc *sc = device_private(self);
507 1.67 dyoung struct dk_softc *dksc = &sc->sc_dksc;
508 1.67 dyoung
509 1.67 dyoung if (DK_BUSY(dksc, pmask))
510 1.67 dyoung return EBUSY;
511 1.65 dyoung
512 1.98 mlelstv if (DK_ATTACHED(dksc) &&
513 1.67 dyoung (ret = cgd_ioctl_clr(sc, curlwp)) != 0)
514 1.67 dyoung return ret;
515 1.65 dyoung
516 1.67 dyoung disk_destroy(&dksc->sc_dkdev);
517 1.122 mlelstv cv_destroy(&sc->sc_cv);
518 1.86 christos mutex_destroy(&sc->sc_lock);
519 1.65 dyoung
520 1.67 dyoung return 0;
521 1.1 elric }
522 1.1 elric
523 1.1 elric void
524 1.1 elric cgdattach(int num)
525 1.1 elric {
526 1.122 mlelstv #ifndef _MODULE
527 1.65 dyoung int error;
528 1.65 dyoung
529 1.122 mlelstv mutex_init(&cgd_spawning_mtx, MUTEX_DEFAULT, IPL_NONE);
530 1.122 mlelstv cv_init(&cgd_spawning_cv, "cgspwn");
531 1.122 mlelstv
532 1.65 dyoung error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
533 1.65 dyoung if (error != 0)
534 1.65 dyoung aprint_error("%s: unable to register cfattach\n",
535 1.65 dyoung cgd_cd.cd_name);
536 1.122 mlelstv #endif
537 1.65 dyoung }
538 1.65 dyoung
539 1.65 dyoung static struct cgd_softc *
540 1.65 dyoung cgd_spawn(int unit)
541 1.65 dyoung {
542 1.65 dyoung cfdata_t cf;
543 1.122 mlelstv struct cgd_worker *cw;
544 1.122 mlelstv struct cgd_softc *sc;
545 1.65 dyoung
546 1.122 mlelstv cf = kmem_alloc(sizeof(*cf), KM_SLEEP);
547 1.65 dyoung cf->cf_name = cgd_cd.cd_name;
548 1.65 dyoung cf->cf_atname = cgd_cd.cd_name;
549 1.65 dyoung cf->cf_unit = unit;
550 1.65 dyoung cf->cf_fstate = FSTATE_STAR;
551 1.65 dyoung
552 1.122 mlelstv cw = cgd_create_one_worker();
553 1.122 mlelstv if (cw == NULL) {
554 1.122 mlelstv kmem_free(cf, sizeof(*cf));
555 1.122 mlelstv return NULL;
556 1.122 mlelstv }
557 1.122 mlelstv
558 1.122 mlelstv sc = device_private(config_attach_pseudo(cf));
559 1.122 mlelstv if (sc == NULL) {
560 1.122 mlelstv cgd_destroy_one_worker(cw);
561 1.122 mlelstv return NULL;
562 1.122 mlelstv }
563 1.122 mlelstv
564 1.122 mlelstv sc->sc_worker = cw;
565 1.122 mlelstv
566 1.122 mlelstv return sc;
567 1.65 dyoung }
568 1.65 dyoung
569 1.65 dyoung static int
570 1.65 dyoung cgd_destroy(device_t dev)
571 1.65 dyoung {
572 1.122 mlelstv struct cgd_softc *sc = device_private(dev);
573 1.122 mlelstv struct cgd_worker *cw = sc->sc_worker;
574 1.122 mlelstv cfdata_t cf;
575 1.65 dyoung int error;
576 1.1 elric
577 1.65 dyoung cf = device_cfdata(dev);
578 1.65 dyoung error = config_detach(dev, DETACH_QUIET);
579 1.65 dyoung if (error)
580 1.65 dyoung return error;
581 1.122 mlelstv
582 1.122 mlelstv cgd_destroy_one_worker(cw);
583 1.122 mlelstv
584 1.122 mlelstv kmem_free(cf, sizeof(*cf));
585 1.65 dyoung return 0;
586 1.1 elric }
587 1.1 elric
588 1.122 mlelstv static void
589 1.122 mlelstv cgd_busy(struct cgd_softc *sc)
590 1.122 mlelstv {
591 1.122 mlelstv
592 1.122 mlelstv mutex_enter(&sc->sc_lock);
593 1.122 mlelstv while (sc->sc_busy)
594 1.122 mlelstv cv_wait(&sc->sc_cv, &sc->sc_lock);
595 1.122 mlelstv sc->sc_busy = true;
596 1.122 mlelstv mutex_exit(&sc->sc_lock);
597 1.122 mlelstv }
598 1.122 mlelstv
599 1.122 mlelstv static void
600 1.122 mlelstv cgd_unbusy(struct cgd_softc *sc)
601 1.122 mlelstv {
602 1.122 mlelstv
603 1.122 mlelstv mutex_enter(&sc->sc_lock);
604 1.122 mlelstv sc->sc_busy = false;
605 1.122 mlelstv cv_broadcast(&sc->sc_cv);
606 1.122 mlelstv mutex_exit(&sc->sc_lock);
607 1.122 mlelstv }
608 1.122 mlelstv
609 1.122 mlelstv static struct cgd_worker *
610 1.122 mlelstv cgd_create_one_worker(void)
611 1.122 mlelstv {
612 1.122 mlelstv KASSERT(cgd_spawning);
613 1.122 mlelstv
614 1.122 mlelstv if (cgd_refcnt++ == 0) {
615 1.122 mlelstv KASSERT(cgd_worker == NULL);
616 1.122 mlelstv cgd_worker = cgd_create_worker();
617 1.122 mlelstv }
618 1.122 mlelstv
619 1.122 mlelstv KASSERT(cgd_worker != NULL);
620 1.122 mlelstv return cgd_worker;
621 1.122 mlelstv }
622 1.122 mlelstv
623 1.122 mlelstv static void
624 1.122 mlelstv cgd_destroy_one_worker(struct cgd_worker *cw)
625 1.122 mlelstv {
626 1.122 mlelstv KASSERT(cgd_spawning);
627 1.122 mlelstv KASSERT(cw == cgd_worker);
628 1.122 mlelstv
629 1.122 mlelstv if (--cgd_refcnt == 0) {
630 1.122 mlelstv cgd_destroy_worker(cgd_worker);
631 1.122 mlelstv cgd_worker = NULL;
632 1.122 mlelstv }
633 1.122 mlelstv }
634 1.122 mlelstv
635 1.122 mlelstv static struct cgd_worker *
636 1.122 mlelstv cgd_create_worker(void)
637 1.122 mlelstv {
638 1.122 mlelstv struct cgd_worker *cw;
639 1.122 mlelstv struct workqueue *wq;
640 1.122 mlelstv struct pool *cp;
641 1.122 mlelstv int error;
642 1.122 mlelstv
643 1.122 mlelstv cw = kmem_alloc(sizeof(struct cgd_worker), KM_SLEEP);
644 1.122 mlelstv cp = kmem_alloc(sizeof(struct pool), KM_SLEEP);
645 1.122 mlelstv
646 1.122 mlelstv error = workqueue_create(&wq, "cgd", cgd_process, NULL,
647 1.122 mlelstv PRI_BIO, IPL_BIO, WQ_MPSAFE | WQ_PERCPU);
648 1.122 mlelstv if (error) {
649 1.122 mlelstv kmem_free(cp, sizeof(struct pool));
650 1.122 mlelstv kmem_free(cw, sizeof(struct cgd_worker));
651 1.122 mlelstv return NULL;
652 1.122 mlelstv }
653 1.122 mlelstv
654 1.122 mlelstv cw->cw_cpool = cp;
655 1.122 mlelstv cw->cw_wq = wq;
656 1.122 mlelstv pool_init(cw->cw_cpool, sizeof(struct cgd_xfer), 0,
657 1.122 mlelstv 0, 0, "cgdcpl", NULL, IPL_BIO);
658 1.122 mlelstv
659 1.122 mlelstv mutex_init(&cw->cw_lock, MUTEX_DEFAULT, IPL_BIO);
660 1.122 mlelstv
661 1.122 mlelstv return cw;
662 1.122 mlelstv }
663 1.122 mlelstv
664 1.122 mlelstv static void
665 1.122 mlelstv cgd_destroy_worker(struct cgd_worker *cw)
666 1.122 mlelstv {
667 1.122 mlelstv mutex_destroy(&cw->cw_lock);
668 1.122 mlelstv
669 1.122 mlelstv if (cw->cw_cpool) {
670 1.122 mlelstv pool_destroy(cw->cw_cpool);
671 1.122 mlelstv kmem_free(cw->cw_cpool, sizeof(struct pool));
672 1.122 mlelstv }
673 1.122 mlelstv if (cw->cw_wq)
674 1.122 mlelstv workqueue_destroy(cw->cw_wq);
675 1.122 mlelstv
676 1.122 mlelstv kmem_free(cw, sizeof(struct cgd_worker));
677 1.122 mlelstv }
678 1.122 mlelstv
679 1.18 thorpej static int
680 1.32 christos cgdopen(dev_t dev, int flags, int fmt, struct lwp *l)
681 1.1 elric {
682 1.122 mlelstv struct cgd_softc *sc;
683 1.122 mlelstv int error;
684 1.1 elric
685 1.56 cegger DPRINTF_FOLLOW(("cgdopen(0x%"PRIx64", %d)\n", dev, flags));
686 1.122 mlelstv
687 1.122 mlelstv error = cgd_lock(true);
688 1.122 mlelstv if (error)
689 1.122 mlelstv return error;
690 1.122 mlelstv sc = getcgd_softc(dev);
691 1.122 mlelstv if (sc == NULL)
692 1.122 mlelstv sc = cgd_spawn(CGDUNIT(dev));
693 1.122 mlelstv cgd_unlock();
694 1.122 mlelstv if (sc == NULL)
695 1.122 mlelstv return ENXIO;
696 1.122 mlelstv
697 1.122 mlelstv return dk_open(&sc->sc_dksc, dev, flags, fmt, l);
698 1.1 elric }
699 1.1 elric
700 1.18 thorpej static int
701 1.32 christos cgdclose(dev_t dev, int flags, int fmt, struct lwp *l)
702 1.1 elric {
703 1.122 mlelstv struct cgd_softc *sc;
704 1.122 mlelstv struct dk_softc *dksc;
705 1.65 dyoung int error;
706 1.1 elric
707 1.56 cegger DPRINTF_FOLLOW(("cgdclose(0x%"PRIx64", %d)\n", dev, flags));
708 1.122 mlelstv
709 1.122 mlelstv error = cgd_lock(false);
710 1.122 mlelstv if (error)
711 1.122 mlelstv return error;
712 1.122 mlelstv sc = getcgd_softc(dev);
713 1.122 mlelstv if (sc == NULL) {
714 1.122 mlelstv error = ENXIO;
715 1.122 mlelstv goto done;
716 1.122 mlelstv }
717 1.122 mlelstv
718 1.122 mlelstv dksc = &sc->sc_dksc;
719 1.98 mlelstv if ((error = dk_close(dksc, dev, flags, fmt, l)) != 0)
720 1.122 mlelstv goto done;
721 1.65 dyoung
722 1.98 mlelstv if (!DK_ATTACHED(dksc)) {
723 1.122 mlelstv if ((error = cgd_destroy(sc->sc_dksc.sc_dev)) != 0) {
724 1.122 mlelstv device_printf(dksc->sc_dev,
725 1.65 dyoung "unable to detach instance\n");
726 1.122 mlelstv goto done;
727 1.65 dyoung }
728 1.65 dyoung }
729 1.122 mlelstv
730 1.122 mlelstv done:
731 1.122 mlelstv cgd_unlock();
732 1.122 mlelstv
733 1.122 mlelstv return error;
734 1.1 elric }
735 1.1 elric
736 1.18 thorpej static void
737 1.1 elric cgdstrategy(struct buf *bp)
738 1.1 elric {
739 1.122 mlelstv struct cgd_softc *sc = getcgd_softc(bp->b_dev);
740 1.1 elric
741 1.1 elric DPRINTF_FOLLOW(("cgdstrategy(%p): b_bcount = %ld\n", bp,
742 1.1 elric (long)bp->b_bcount));
743 1.72 riastrad
744 1.72 riastrad /*
745 1.111 mlelstv * Reject unaligned writes.
746 1.72 riastrad */
747 1.111 mlelstv if (((uintptr_t)bp->b_data & 3) != 0) {
748 1.72 riastrad bp->b_error = EINVAL;
749 1.111 mlelstv goto bail;
750 1.72 riastrad }
751 1.72 riastrad
752 1.122 mlelstv dk_strategy(&sc->sc_dksc, bp);
753 1.1 elric return;
754 1.111 mlelstv
755 1.111 mlelstv bail:
756 1.111 mlelstv bp->b_resid = bp->b_bcount;
757 1.111 mlelstv biodone(bp);
758 1.111 mlelstv return;
759 1.1 elric }
760 1.1 elric
761 1.18 thorpej static int
762 1.1 elric cgdsize(dev_t dev)
763 1.1 elric {
764 1.122 mlelstv struct cgd_softc *sc = getcgd_softc(dev);
765 1.1 elric
766 1.56 cegger DPRINTF_FOLLOW(("cgdsize(0x%"PRIx64")\n", dev));
767 1.122 mlelstv if (!sc)
768 1.1 elric return -1;
769 1.122 mlelstv return dk_size(&sc->sc_dksc, dev);
770 1.1 elric }
771 1.1 elric
772 1.16 elric /*
773 1.16 elric * cgd_{get,put}data are functions that deal with getting a buffer
774 1.122 mlelstv * for the new encrypted data.
775 1.122 mlelstv * We can no longer have a buffer per device, we need a buffer per
776 1.122 mlelstv * work queue...
777 1.16 elric */
778 1.16 elric
779 1.16 elric static void *
780 1.122 mlelstv cgd_getdata(struct cgd_softc *sc, unsigned long size)
781 1.16 elric {
782 1.122 mlelstv void *data = NULL;
783 1.16 elric
784 1.122 mlelstv mutex_enter(&sc->sc_lock);
785 1.122 mlelstv if (!sc->sc_data_used) {
786 1.122 mlelstv sc->sc_data_used = true;
787 1.122 mlelstv data = sc->sc_data;
788 1.16 elric }
789 1.122 mlelstv mutex_exit(&sc->sc_lock);
790 1.16 elric
791 1.16 elric if (data)
792 1.16 elric return data;
793 1.16 elric
794 1.124 tnn return kmem_intr_alloc(size, KM_NOSLEEP);
795 1.16 elric }
796 1.16 elric
797 1.1 elric static void
798 1.124 tnn cgd_putdata(struct cgd_softc *sc, void *data, unsigned long size)
799 1.16 elric {
800 1.16 elric
801 1.122 mlelstv if (data == sc->sc_data) {
802 1.122 mlelstv mutex_enter(&sc->sc_lock);
803 1.122 mlelstv sc->sc_data_used = false;
804 1.122 mlelstv mutex_exit(&sc->sc_lock);
805 1.122 mlelstv } else
806 1.124 tnn kmem_intr_free(data, size);
807 1.16 elric }
808 1.16 elric
809 1.99 mlelstv static int
810 1.99 mlelstv cgd_diskstart(device_t dev, struct buf *bp)
811 1.1 elric {
812 1.122 mlelstv struct cgd_softc *sc = device_private(dev);
813 1.122 mlelstv struct cgd_worker *cw = sc->sc_worker;
814 1.122 mlelstv struct dk_softc *dksc = &sc->sc_dksc;
815 1.105 mlelstv struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
816 1.122 mlelstv struct cgd_xfer *cx;
817 1.99 mlelstv struct buf *nbp;
818 1.44 christos void * newaddr;
819 1.1 elric daddr_t bn;
820 1.1 elric
821 1.99 mlelstv DPRINTF_FOLLOW(("cgd_diskstart(%p, %p)\n", dksc, bp));
822 1.1 elric
823 1.99 mlelstv bn = bp->b_rawblkno;
824 1.22 perry
825 1.99 mlelstv /*
826 1.99 mlelstv * We attempt to allocate all of our resources up front, so that
827 1.99 mlelstv * we can fail quickly if they are unavailable.
828 1.99 mlelstv */
829 1.122 mlelstv nbp = getiobuf(sc->sc_tvn, false);
830 1.99 mlelstv if (nbp == NULL)
831 1.99 mlelstv return EAGAIN;
832 1.16 elric
833 1.122 mlelstv cx = pool_get(cw->cw_cpool, PR_NOWAIT);
834 1.122 mlelstv if (cx == NULL) {
835 1.122 mlelstv putiobuf(nbp);
836 1.122 mlelstv return EAGAIN;
837 1.122 mlelstv }
838 1.122 mlelstv
839 1.122 mlelstv cx->cx_sc = sc;
840 1.122 mlelstv cx->cx_obp = bp;
841 1.122 mlelstv cx->cx_nbp = nbp;
842 1.122 mlelstv cx->cx_srcv = cx->cx_dstv = bp->b_data;
843 1.122 mlelstv cx->cx_blkno = bn;
844 1.122 mlelstv cx->cx_secsize = dg->dg_secsize;
845 1.122 mlelstv
846 1.99 mlelstv /*
847 1.99 mlelstv * If we are writing, then we need to encrypt the outgoing
848 1.99 mlelstv * block into a new block of memory.
849 1.99 mlelstv */
850 1.99 mlelstv if ((bp->b_flags & B_READ) == 0) {
851 1.122 mlelstv newaddr = cgd_getdata(sc, bp->b_bcount);
852 1.99 mlelstv if (!newaddr) {
853 1.122 mlelstv pool_put(cw->cw_cpool, cx);
854 1.99 mlelstv putiobuf(nbp);
855 1.99 mlelstv return EAGAIN;
856 1.16 elric }
857 1.122 mlelstv
858 1.122 mlelstv cx->cx_dstv = newaddr;
859 1.122 mlelstv cx->cx_len = bp->b_bcount;
860 1.122 mlelstv cx->cx_dir = CGD_CIPHER_ENCRYPT;
861 1.122 mlelstv
862 1.122 mlelstv cgd_enqueue(sc, cx);
863 1.122 mlelstv return 0;
864 1.99 mlelstv }
865 1.1 elric
866 1.122 mlelstv cgd_diskstart2(sc, cx);
867 1.122 mlelstv return 0;
868 1.122 mlelstv }
869 1.122 mlelstv
870 1.122 mlelstv static void
871 1.122 mlelstv cgd_diskstart2(struct cgd_softc *sc, struct cgd_xfer *cx)
872 1.122 mlelstv {
873 1.122 mlelstv struct vnode *vp;
874 1.122 mlelstv struct buf *bp;
875 1.122 mlelstv struct buf *nbp;
876 1.122 mlelstv
877 1.122 mlelstv bp = cx->cx_obp;
878 1.122 mlelstv nbp = cx->cx_nbp;
879 1.122 mlelstv
880 1.122 mlelstv nbp->b_data = cx->cx_dstv;
881 1.99 mlelstv nbp->b_flags = bp->b_flags;
882 1.99 mlelstv nbp->b_oflags = bp->b_oflags;
883 1.99 mlelstv nbp->b_cflags = bp->b_cflags;
884 1.99 mlelstv nbp->b_iodone = cgdiodone;
885 1.99 mlelstv nbp->b_proc = bp->b_proc;
886 1.122 mlelstv nbp->b_blkno = btodb(cx->cx_blkno * cx->cx_secsize);
887 1.99 mlelstv nbp->b_bcount = bp->b_bcount;
888 1.122 mlelstv nbp->b_private = cx;
889 1.99 mlelstv
890 1.99 mlelstv BIO_COPYPRIO(nbp, bp);
891 1.99 mlelstv
892 1.99 mlelstv if ((nbp->b_flags & B_READ) == 0) {
893 1.99 mlelstv vp = nbp->b_vp;
894 1.99 mlelstv mutex_enter(vp->v_interlock);
895 1.99 mlelstv vp->v_numoutput++;
896 1.99 mlelstv mutex_exit(vp->v_interlock);
897 1.17 dbj }
898 1.122 mlelstv VOP_STRATEGY(sc->sc_tvn, nbp);
899 1.1 elric }
900 1.1 elric
901 1.18 thorpej static void
902 1.17 dbj cgdiodone(struct buf *nbp)
903 1.1 elric {
904 1.122 mlelstv struct cgd_xfer *cx = nbp->b_private;
905 1.122 mlelstv struct buf *obp = cx->cx_obp;
906 1.122 mlelstv struct cgd_softc *sc = getcgd_softc(obp->b_dev);
907 1.122 mlelstv struct dk_softc *dksc = &sc->sc_dksc;
908 1.105 mlelstv struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
909 1.105 mlelstv daddr_t bn;
910 1.22 perry
911 1.122 mlelstv KDASSERT(sc);
912 1.1 elric
913 1.17 dbj DPRINTF_FOLLOW(("cgdiodone(%p)\n", nbp));
914 1.20 yamt DPRINTF(CGDB_IO, ("cgdiodone: bp %p bcount %d resid %d\n",
915 1.1 elric obp, obp->b_bcount, obp->b_resid));
916 1.107 msaitoh DPRINTF(CGDB_IO, (" dev 0x%"PRIx64", nbp %p bn %" PRId64
917 1.107 msaitoh " addr %p bcnt %d\n", nbp->b_dev, nbp, nbp->b_blkno, nbp->b_data,
918 1.107 msaitoh nbp->b_bcount));
919 1.46 ad if (nbp->b_error != 0) {
920 1.46 ad obp->b_error = nbp->b_error;
921 1.62 christos DPRINTF(CGDB_IO, ("%s: error %d\n", dksc->sc_xname,
922 1.62 christos obp->b_error));
923 1.1 elric }
924 1.1 elric
925 1.16 elric /* Perform the decryption if we are reading.
926 1.1 elric *
927 1.1 elric * Note: use the blocknumber from nbp, since it is what
928 1.1 elric * we used to encrypt the blocks.
929 1.1 elric */
930 1.1 elric
931 1.105 mlelstv if (nbp->b_flags & B_READ) {
932 1.105 mlelstv bn = dbtob(nbp->b_blkno) / dg->dg_secsize;
933 1.122 mlelstv
934 1.122 mlelstv cx->cx_obp = obp;
935 1.122 mlelstv cx->cx_nbp = nbp;
936 1.122 mlelstv cx->cx_dstv = obp->b_data;
937 1.122 mlelstv cx->cx_srcv = obp->b_data;
938 1.122 mlelstv cx->cx_len = obp->b_bcount;
939 1.122 mlelstv cx->cx_blkno = bn;
940 1.122 mlelstv cx->cx_secsize = dg->dg_secsize;
941 1.122 mlelstv cx->cx_dir = CGD_CIPHER_DECRYPT;
942 1.122 mlelstv
943 1.122 mlelstv cgd_enqueue(sc, cx);
944 1.122 mlelstv return;
945 1.105 mlelstv }
946 1.1 elric
947 1.122 mlelstv cgd_iodone2(sc, cx);
948 1.122 mlelstv }
949 1.122 mlelstv
950 1.122 mlelstv static void
951 1.122 mlelstv cgd_iodone2(struct cgd_softc *sc, struct cgd_xfer *cx)
952 1.122 mlelstv {
953 1.122 mlelstv struct cgd_worker *cw = sc->sc_worker;
954 1.122 mlelstv struct buf *obp = cx->cx_obp;
955 1.122 mlelstv struct buf *nbp = cx->cx_nbp;
956 1.122 mlelstv struct dk_softc *dksc = &sc->sc_dksc;
957 1.122 mlelstv
958 1.122 mlelstv pool_put(cw->cw_cpool, cx);
959 1.122 mlelstv
960 1.16 elric /* If we allocated memory, free it now... */
961 1.1 elric if (nbp->b_data != obp->b_data)
962 1.124 tnn cgd_putdata(sc, nbp->b_data, nbp->b_bcount);
963 1.1 elric
964 1.33 yamt putiobuf(nbp);
965 1.1 elric
966 1.100 mlelstv /* Request is complete for whatever reason */
967 1.100 mlelstv obp->b_resid = 0;
968 1.100 mlelstv if (obp->b_error != 0)
969 1.100 mlelstv obp->b_resid = obp->b_bcount;
970 1.100 mlelstv
971 1.99 mlelstv dk_done(dksc, obp);
972 1.101 mlelstv dk_start(dksc, NULL);
973 1.1 elric }
974 1.1 elric
975 1.108 riastrad static int
976 1.108 riastrad cgd_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk)
977 1.108 riastrad {
978 1.108 riastrad struct cgd_softc *sc = device_private(dev);
979 1.108 riastrad struct dk_softc *dksc = &sc->sc_dksc;
980 1.108 riastrad struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
981 1.108 riastrad size_t nbytes, blksize;
982 1.108 riastrad void *buf;
983 1.108 riastrad int error;
984 1.108 riastrad
985 1.108 riastrad /*
986 1.108 riastrad * dk_dump gives us units of disklabel sectors. Everything
987 1.108 riastrad * else in cgd uses units of diskgeom sectors. These had
988 1.108 riastrad * better agree; otherwise we need to figure out how to convert
989 1.108 riastrad * between them.
990 1.108 riastrad */
991 1.108 riastrad KASSERTMSG((dg->dg_secsize == dksc->sc_dkdev.dk_label->d_secsize),
992 1.108 riastrad "diskgeom secsize %"PRIu32" != disklabel secsize %"PRIu32,
993 1.108 riastrad dg->dg_secsize, dksc->sc_dkdev.dk_label->d_secsize);
994 1.108 riastrad blksize = dg->dg_secsize;
995 1.108 riastrad
996 1.108 riastrad /*
997 1.108 riastrad * Compute the number of bytes in this request, which dk_dump
998 1.108 riastrad * has `helpfully' converted to a number of blocks for us.
999 1.108 riastrad */
1000 1.108 riastrad nbytes = nblk*blksize;
1001 1.108 riastrad
1002 1.108 riastrad /* Try to acquire a buffer to store the ciphertext. */
1003 1.122 mlelstv buf = cgd_getdata(sc, nbytes);
1004 1.108 riastrad if (buf == NULL)
1005 1.108 riastrad /* Out of memory: give up. */
1006 1.108 riastrad return ENOMEM;
1007 1.108 riastrad
1008 1.108 riastrad /* Encrypt the caller's data into the temporary buffer. */
1009 1.108 riastrad cgd_cipher(sc, buf, va, nbytes, blkno, blksize, CGD_CIPHER_ENCRYPT);
1010 1.108 riastrad
1011 1.108 riastrad /* Pass it on to the underlying disk device. */
1012 1.108 riastrad error = bdev_dump(sc->sc_tdev, blkno, buf, nbytes);
1013 1.108 riastrad
1014 1.108 riastrad /* Release the buffer. */
1015 1.124 tnn cgd_putdata(sc, buf, nbytes);
1016 1.108 riastrad
1017 1.108 riastrad /* Return any error from the underlying disk device. */
1018 1.108 riastrad return error;
1019 1.108 riastrad }
1020 1.108 riastrad
1021 1.1 elric /* XXX: we should probably put these into dksubr.c, mostly */
1022 1.18 thorpej static int
1023 1.40 christos cgdread(dev_t dev, struct uio *uio, int flags)
1024 1.1 elric {
1025 1.122 mlelstv struct cgd_softc *sc;
1026 1.1 elric struct dk_softc *dksc;
1027 1.1 elric
1028 1.56 cegger DPRINTF_FOLLOW(("cgdread(0x%llx, %p, %d)\n",
1029 1.56 cegger (unsigned long long)dev, uio, flags));
1030 1.122 mlelstv sc = getcgd_softc(dev);
1031 1.122 mlelstv if (sc == NULL)
1032 1.122 mlelstv return ENXIO;
1033 1.122 mlelstv dksc = &sc->sc_dksc;
1034 1.98 mlelstv if (!DK_ATTACHED(dksc))
1035 1.1 elric return ENXIO;
1036 1.1 elric return physio(cgdstrategy, NULL, dev, B_READ, minphys, uio);
1037 1.1 elric }
1038 1.1 elric
1039 1.1 elric /* XXX: we should probably put these into dksubr.c, mostly */
1040 1.18 thorpej static int
1041 1.40 christos cgdwrite(dev_t dev, struct uio *uio, int flags)
1042 1.1 elric {
1043 1.122 mlelstv struct cgd_softc *sc;
1044 1.1 elric struct dk_softc *dksc;
1045 1.1 elric
1046 1.56 cegger DPRINTF_FOLLOW(("cgdwrite(0x%"PRIx64", %p, %d)\n", dev, uio, flags));
1047 1.122 mlelstv sc = getcgd_softc(dev);
1048 1.122 mlelstv if (sc == NULL)
1049 1.122 mlelstv return ENXIO;
1050 1.122 mlelstv dksc = &sc->sc_dksc;
1051 1.98 mlelstv if (!DK_ATTACHED(dksc))
1052 1.1 elric return ENXIO;
1053 1.1 elric return physio(cgdstrategy, NULL, dev, B_WRITE, minphys, uio);
1054 1.1 elric }
1055 1.1 elric
1056 1.18 thorpej static int
1057 1.44 christos cgdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
1058 1.1 elric {
1059 1.122 mlelstv struct cgd_softc *sc;
1060 1.1 elric struct dk_softc *dksc;
1061 1.1 elric int part = DISKPART(dev);
1062 1.1 elric int pmask = 1 << part;
1063 1.122 mlelstv int error;
1064 1.1 elric
1065 1.56 cegger DPRINTF_FOLLOW(("cgdioctl(0x%"PRIx64", %ld, %p, %d, %p)\n",
1066 1.32 christos dev, cmd, data, flag, l));
1067 1.78 christos
1068 1.1 elric switch (cmd) {
1069 1.93 christos case CGDIOCGET:
1070 1.93 christos return cgd_ioctl_get(dev, data, l);
1071 1.1 elric case CGDIOCSET:
1072 1.1 elric case CGDIOCCLR:
1073 1.1 elric if ((flag & FWRITE) == 0)
1074 1.1 elric return EBADF;
1075 1.78 christos /* FALLTHROUGH */
1076 1.78 christos default:
1077 1.122 mlelstv sc = getcgd_softc(dev);
1078 1.122 mlelstv if (sc == NULL)
1079 1.122 mlelstv return ENXIO;
1080 1.122 mlelstv dksc = &sc->sc_dksc;
1081 1.78 christos break;
1082 1.1 elric }
1083 1.1 elric
1084 1.1 elric switch (cmd) {
1085 1.1 elric case CGDIOCSET:
1086 1.122 mlelstv cgd_busy(sc);
1087 1.98 mlelstv if (DK_ATTACHED(dksc))
1088 1.122 mlelstv error = EBUSY;
1089 1.122 mlelstv else
1090 1.122 mlelstv error = cgd_ioctl_set(sc, data, l);
1091 1.122 mlelstv cgd_unbusy(sc);
1092 1.122 mlelstv break;
1093 1.1 elric case CGDIOCCLR:
1094 1.122 mlelstv cgd_busy(sc);
1095 1.122 mlelstv if (DK_BUSY(&sc->sc_dksc, pmask))
1096 1.122 mlelstv error = EBUSY;
1097 1.122 mlelstv else
1098 1.122 mlelstv error = cgd_ioctl_clr(sc, l);
1099 1.122 mlelstv cgd_unbusy(sc);
1100 1.122 mlelstv break;
1101 1.114 jdolecek case DIOCGCACHE:
1102 1.57 apb case DIOCCACHESYNC:
1103 1.122 mlelstv cgd_busy(sc);
1104 1.122 mlelstv if (!DK_ATTACHED(dksc)) {
1105 1.122 mlelstv cgd_unbusy(sc);
1106 1.122 mlelstv error = ENOENT;
1107 1.122 mlelstv break;
1108 1.122 mlelstv }
1109 1.57 apb /*
1110 1.57 apb * We pass this call down to the underlying disk.
1111 1.57 apb */
1112 1.122 mlelstv error = VOP_IOCTL(sc->sc_tvn, cmd, data, flag, l->l_cred);
1113 1.122 mlelstv cgd_unbusy(sc);
1114 1.122 mlelstv break;
1115 1.121 riastrad case DIOCGSECTORALIGN: {
1116 1.121 riastrad struct disk_sectoralign *dsa = data;
1117 1.121 riastrad
1118 1.122 mlelstv cgd_busy(sc);
1119 1.122 mlelstv if (!DK_ATTACHED(dksc)) {
1120 1.122 mlelstv cgd_unbusy(sc);
1121 1.122 mlelstv error = ENOENT;
1122 1.122 mlelstv break;
1123 1.122 mlelstv }
1124 1.121 riastrad
1125 1.121 riastrad /* Get the underlying disk's sector alignment. */
1126 1.122 mlelstv error = VOP_IOCTL(sc->sc_tvn, cmd, data, flag, l->l_cred);
1127 1.122 mlelstv if (error) {
1128 1.122 mlelstv cgd_unbusy(sc);
1129 1.122 mlelstv break;
1130 1.122 mlelstv }
1131 1.121 riastrad
1132 1.121 riastrad /* Adjust for the disklabel partition if necessary. */
1133 1.121 riastrad if (part != RAW_PART) {
1134 1.121 riastrad struct disklabel *lp = dksc->sc_dkdev.dk_label;
1135 1.121 riastrad daddr_t offset = lp->d_partitions[part].p_offset;
1136 1.121 riastrad uint32_t r = offset % dsa->dsa_alignment;
1137 1.121 riastrad
1138 1.121 riastrad if (r < dsa->dsa_firstaligned)
1139 1.121 riastrad dsa->dsa_firstaligned = dsa->dsa_firstaligned
1140 1.121 riastrad - r;
1141 1.121 riastrad else
1142 1.121 riastrad dsa->dsa_firstaligned = (dsa->dsa_firstaligned
1143 1.121 riastrad + dsa->dsa_alignment) - r;
1144 1.121 riastrad }
1145 1.122 mlelstv cgd_unbusy(sc);
1146 1.122 mlelstv break;
1147 1.121 riastrad }
1148 1.103 christos case DIOCGSTRATEGY:
1149 1.103 christos case DIOCSSTRATEGY:
1150 1.122 mlelstv if (!DK_ATTACHED(dksc)) {
1151 1.122 mlelstv error = ENOENT;
1152 1.122 mlelstv break;
1153 1.122 mlelstv }
1154 1.103 christos /*FALLTHROUGH*/
1155 1.1 elric default:
1156 1.122 mlelstv error = dk_ioctl(dksc, dev, cmd, data, flag, l);
1157 1.122 mlelstv break;
1158 1.93 christos case CGDIOCGET:
1159 1.93 christos KASSERT(0);
1160 1.122 mlelstv error = EINVAL;
1161 1.1 elric }
1162 1.122 mlelstv
1163 1.122 mlelstv return error;
1164 1.1 elric }
1165 1.1 elric
1166 1.18 thorpej static int
1167 1.44 christos cgddump(dev_t dev, daddr_t blkno, void *va, size_t size)
1168 1.1 elric {
1169 1.122 mlelstv struct cgd_softc *sc;
1170 1.1 elric
1171 1.56 cegger DPRINTF_FOLLOW(("cgddump(0x%"PRIx64", %" PRId64 ", %p, %lu)\n",
1172 1.56 cegger dev, blkno, va, (unsigned long)size));
1173 1.122 mlelstv sc = getcgd_softc(dev);
1174 1.122 mlelstv if (sc == NULL)
1175 1.122 mlelstv return ENXIO;
1176 1.122 mlelstv return dk_dump(&sc->sc_dksc, dev, blkno, va, size, DK_DUMP_RECURSIVE);
1177 1.1 elric }
1178 1.1 elric
1179 1.1 elric /*
1180 1.1 elric * XXXrcd:
1181 1.1 elric * for now we hardcode the maximum key length.
1182 1.1 elric */
1183 1.1 elric #define MAX_KEYSIZE 1024
1184 1.1 elric
1185 1.53 christos static const struct {
1186 1.53 christos const char *n;
1187 1.53 christos int v;
1188 1.53 christos int d;
1189 1.53 christos } encblkno[] = {
1190 1.53 christos { "encblkno", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
1191 1.53 christos { "encblkno8", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
1192 1.53 christos { "encblkno1", CGD_CIPHER_CBC_ENCBLKNO1, 8 },
1193 1.53 christos };
1194 1.53 christos
1195 1.1 elric /* ARGSUSED */
1196 1.1 elric static int
1197 1.122 mlelstv cgd_ioctl_set(struct cgd_softc *sc, void *data, struct lwp *l)
1198 1.1 elric {
1199 1.1 elric struct cgd_ioctl *ci = data;
1200 1.1 elric struct vnode *vp;
1201 1.1 elric int ret;
1202 1.53 christos size_t i;
1203 1.43 cbiere size_t keybytes; /* key length in bytes */
1204 1.27 drochner const char *cp;
1205 1.71 dholland struct pathbuf *pb;
1206 1.36 christos char *inbuf;
1207 1.122 mlelstv struct dk_softc *dksc = &sc->sc_dksc;
1208 1.1 elric
1209 1.1 elric cp = ci->ci_disk;
1210 1.71 dholland
1211 1.71 dholland ret = pathbuf_copyin(ci->ci_disk, &pb);
1212 1.71 dholland if (ret != 0) {
1213 1.71 dholland return ret;
1214 1.71 dholland }
1215 1.117 mlelstv ret = vn_bdev_openpath(pb, &vp, l);
1216 1.71 dholland pathbuf_destroy(pb);
1217 1.71 dholland if (ret != 0) {
1218 1.1 elric return ret;
1219 1.71 dholland }
1220 1.1 elric
1221 1.122 mlelstv inbuf = kmem_alloc(MAX_KEYSIZE, KM_SLEEP);
1222 1.36 christos
1223 1.122 mlelstv if ((ret = cgdinit(sc, cp, vp, l)) != 0)
1224 1.1 elric goto bail;
1225 1.1 elric
1226 1.36 christos (void)memset(inbuf, 0, MAX_KEYSIZE);
1227 1.1 elric ret = copyinstr(ci->ci_alg, inbuf, 256, NULL);
1228 1.1 elric if (ret)
1229 1.1 elric goto bail;
1230 1.122 mlelstv sc->sc_cfuncs = cryptfuncs_find(inbuf);
1231 1.122 mlelstv if (!sc->sc_cfuncs) {
1232 1.1 elric ret = EINVAL;
1233 1.1 elric goto bail;
1234 1.1 elric }
1235 1.1 elric
1236 1.43 cbiere (void)memset(inbuf, 0, MAX_KEYSIZE);
1237 1.36 christos ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL);
1238 1.1 elric if (ret)
1239 1.1 elric goto bail;
1240 1.53 christos
1241 1.53 christos for (i = 0; i < __arraycount(encblkno); i++)
1242 1.53 christos if (strcmp(encblkno[i].n, inbuf) == 0)
1243 1.53 christos break;
1244 1.53 christos
1245 1.53 christos if (i == __arraycount(encblkno)) {
1246 1.1 elric ret = EINVAL;
1247 1.1 elric goto bail;
1248 1.1 elric }
1249 1.1 elric
1250 1.15 dan keybytes = ci->ci_keylen / 8 + 1;
1251 1.15 dan if (keybytes > MAX_KEYSIZE) {
1252 1.1 elric ret = EINVAL;
1253 1.1 elric goto bail;
1254 1.1 elric }
1255 1.53 christos
1256 1.36 christos (void)memset(inbuf, 0, MAX_KEYSIZE);
1257 1.15 dan ret = copyin(ci->ci_key, inbuf, keybytes);
1258 1.1 elric if (ret)
1259 1.1 elric goto bail;
1260 1.1 elric
1261 1.122 mlelstv sc->sc_cdata.cf_blocksize = ci->ci_blocksize;
1262 1.122 mlelstv sc->sc_cdata.cf_mode = encblkno[i].v;
1263 1.122 mlelstv sc->sc_cdata.cf_keylen = ci->ci_keylen;
1264 1.122 mlelstv sc->sc_cdata.cf_priv = sc->sc_cfuncs->cf_init(ci->ci_keylen, inbuf,
1265 1.122 mlelstv &sc->sc_cdata.cf_blocksize);
1266 1.122 mlelstv if (sc->sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) {
1267 1.62 christos log(LOG_WARNING, "cgd: Disallowed cipher with blocksize %zu > %u\n",
1268 1.122 mlelstv sc->sc_cdata.cf_blocksize, CGD_MAXBLOCKSIZE);
1269 1.122 mlelstv sc->sc_cdata.cf_priv = NULL;
1270 1.62 christos }
1271 1.78 christos
1272 1.53 christos /*
1273 1.53 christos * The blocksize is supposed to be in bytes. Unfortunately originally
1274 1.53 christos * it was expressed in bits. For compatibility we maintain encblkno
1275 1.53 christos * and encblkno8.
1276 1.53 christos */
1277 1.122 mlelstv sc->sc_cdata.cf_blocksize /= encblkno[i].d;
1278 1.97 riastrad (void)explicit_memset(inbuf, 0, MAX_KEYSIZE);
1279 1.122 mlelstv if (!sc->sc_cdata.cf_priv) {
1280 1.1 elric ret = EINVAL; /* XXX is this the right error? */
1281 1.1 elric goto bail;
1282 1.1 elric }
1283 1.122 mlelstv kmem_free(inbuf, MAX_KEYSIZE);
1284 1.1 elric
1285 1.80 christos bufq_alloc(&dksc->sc_bufq, "fcfs", 0);
1286 1.16 elric
1287 1.124 tnn sc->sc_data = kmem_alloc(MAXPHYS, KM_SLEEP);
1288 1.122 mlelstv sc->sc_data_used = false;
1289 1.16 elric
1290 1.98 mlelstv /* Attach the disk. */
1291 1.98 mlelstv dk_attach(dksc);
1292 1.98 mlelstv disk_attach(&dksc->sc_dkdev);
1293 1.1 elric
1294 1.80 christos disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL);
1295 1.77 elric
1296 1.29 yamt /* Discover wedges on this disk. */
1297 1.80 christos dkwedge_discover(&dksc->sc_dkdev);
1298 1.29 yamt
1299 1.1 elric return 0;
1300 1.1 elric
1301 1.1 elric bail:
1302 1.122 mlelstv kmem_free(inbuf, MAX_KEYSIZE);
1303 1.51 ad (void)vn_close(vp, FREAD|FWRITE, l->l_cred);
1304 1.1 elric return ret;
1305 1.1 elric }
1306 1.1 elric
1307 1.1 elric /* ARGSUSED */
1308 1.1 elric static int
1309 1.122 mlelstv cgd_ioctl_clr(struct cgd_softc *sc, struct lwp *l)
1310 1.1 elric {
1311 1.122 mlelstv struct dk_softc *dksc = &sc->sc_dksc;
1312 1.65 dyoung
1313 1.98 mlelstv if (!DK_ATTACHED(dksc))
1314 1.65 dyoung return ENXIO;
1315 1.16 elric
1316 1.29 yamt /* Delete all of our wedges. */
1317 1.80 christos dkwedge_delall(&dksc->sc_dkdev);
1318 1.29 yamt
1319 1.16 elric /* Kill off any queued buffers. */
1320 1.104 mlelstv dk_drain(dksc);
1321 1.80 christos bufq_free(dksc->sc_bufq);
1322 1.1 elric
1323 1.122 mlelstv (void)vn_close(sc->sc_tvn, FREAD|FWRITE, l->l_cred);
1324 1.122 mlelstv sc->sc_cfuncs->cf_destroy(sc->sc_cdata.cf_priv);
1325 1.122 mlelstv kmem_free(sc->sc_tpath, sc->sc_tpathlen);
1326 1.124 tnn kmem_free(sc->sc_data, MAXPHYS);
1327 1.122 mlelstv sc->sc_data_used = false;
1328 1.98 mlelstv dk_detach(dksc);
1329 1.80 christos disk_detach(&dksc->sc_dkdev);
1330 1.1 elric
1331 1.1 elric return 0;
1332 1.1 elric }
1333 1.1 elric
1334 1.1 elric static int
1335 1.78 christos cgd_ioctl_get(dev_t dev, void *data, struct lwp *l)
1336 1.78 christos {
1337 1.122 mlelstv struct cgd_softc *sc;
1338 1.78 christos struct cgd_user *cgu;
1339 1.122 mlelstv int unit, error;
1340 1.78 christos
1341 1.78 christos unit = CGDUNIT(dev);
1342 1.78 christos cgu = (struct cgd_user *)data;
1343 1.78 christos
1344 1.78 christos DPRINTF_FOLLOW(("cgd_ioctl_get(0x%"PRIx64", %d, %p, %p)\n",
1345 1.78 christos dev, unit, data, l));
1346 1.78 christos
1347 1.122 mlelstv /* XXX, we always return this units data, so if cgu_unit is
1348 1.122 mlelstv * not -1, that field doesn't match the rest
1349 1.122 mlelstv */
1350 1.78 christos if (cgu->cgu_unit == -1)
1351 1.78 christos cgu->cgu_unit = unit;
1352 1.78 christos
1353 1.78 christos if (cgu->cgu_unit < 0)
1354 1.78 christos return EINVAL; /* XXX: should this be ENXIO? */
1355 1.78 christos
1356 1.122 mlelstv error = cgd_lock(false);
1357 1.122 mlelstv if (error)
1358 1.122 mlelstv return error;
1359 1.122 mlelstv
1360 1.122 mlelstv sc = device_lookup_private(&cgd_cd, unit);
1361 1.122 mlelstv if (sc == NULL || !DK_ATTACHED(&sc->sc_dksc)) {
1362 1.78 christos cgu->cgu_dev = 0;
1363 1.78 christos cgu->cgu_alg[0] = '\0';
1364 1.78 christos cgu->cgu_blocksize = 0;
1365 1.78 christos cgu->cgu_mode = 0;
1366 1.78 christos cgu->cgu_keylen = 0;
1367 1.78 christos }
1368 1.78 christos else {
1369 1.122 mlelstv mutex_enter(&sc->sc_lock);
1370 1.122 mlelstv cgu->cgu_dev = sc->sc_tdev;
1371 1.122 mlelstv strncpy(cgu->cgu_alg, sc->sc_cfuncs->cf_name,
1372 1.78 christos sizeof(cgu->cgu_alg));
1373 1.122 mlelstv cgu->cgu_blocksize = sc->sc_cdata.cf_blocksize;
1374 1.122 mlelstv cgu->cgu_mode = sc->sc_cdata.cf_mode;
1375 1.122 mlelstv cgu->cgu_keylen = sc->sc_cdata.cf_keylen;
1376 1.122 mlelstv mutex_exit(&sc->sc_lock);
1377 1.78 christos }
1378 1.122 mlelstv
1379 1.122 mlelstv cgd_unlock();
1380 1.78 christos return 0;
1381 1.78 christos }
1382 1.78 christos
1383 1.78 christos static int
1384 1.122 mlelstv cgdinit(struct cgd_softc *sc, const char *cpath, struct vnode *vp,
1385 1.32 christos struct lwp *l)
1386 1.1 elric {
1387 1.80 christos struct disk_geom *dg;
1388 1.1 elric int ret;
1389 1.36 christos char *tmppath;
1390 1.76 christos uint64_t psize;
1391 1.76 christos unsigned secsize;
1392 1.122 mlelstv struct dk_softc *dksc = &sc->sc_dksc;
1393 1.1 elric
1394 1.122 mlelstv sc->sc_tvn = vp;
1395 1.122 mlelstv sc->sc_tpath = NULL;
1396 1.1 elric
1397 1.122 mlelstv tmppath = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1398 1.122 mlelstv ret = copyinstr(cpath, tmppath, MAXPATHLEN, &sc->sc_tpathlen);
1399 1.1 elric if (ret)
1400 1.1 elric goto bail;
1401 1.122 mlelstv sc->sc_tpath = kmem_alloc(sc->sc_tpathlen, KM_SLEEP);
1402 1.122 mlelstv memcpy(sc->sc_tpath, tmppath, sc->sc_tpathlen);
1403 1.1 elric
1404 1.122 mlelstv sc->sc_tdev = vp->v_rdev;
1405 1.1 elric
1406 1.76 christos if ((ret = getdisksize(vp, &psize, &secsize)) != 0)
1407 1.1 elric goto bail;
1408 1.1 elric
1409 1.76 christos if (psize == 0) {
1410 1.1 elric ret = ENODEV;
1411 1.1 elric goto bail;
1412 1.1 elric }
1413 1.1 elric
1414 1.1 elric /*
1415 1.1 elric * XXX here we should probe the underlying device. If we
1416 1.1 elric * are accessing a partition of type RAW_PART, then
1417 1.1 elric * we should populate our initial geometry with the
1418 1.1 elric * geometry that we discover from the device.
1419 1.1 elric */
1420 1.80 christos dg = &dksc->sc_dkdev.dk_geom;
1421 1.80 christos memset(dg, 0, sizeof(*dg));
1422 1.80 christos dg->dg_secperunit = psize;
1423 1.105 mlelstv dg->dg_secsize = secsize;
1424 1.80 christos dg->dg_ntracks = 1;
1425 1.105 mlelstv dg->dg_nsectors = 1024 * 1024 / dg->dg_secsize;
1426 1.80 christos dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors;
1427 1.1 elric
1428 1.1 elric bail:
1429 1.122 mlelstv kmem_free(tmppath, MAXPATHLEN);
1430 1.122 mlelstv if (ret && sc->sc_tpath)
1431 1.122 mlelstv kmem_free(sc->sc_tpath, sc->sc_tpathlen);
1432 1.1 elric return ret;
1433 1.1 elric }
1434 1.1 elric
1435 1.1 elric /*
1436 1.1 elric * Our generic cipher entry point. This takes care of the
1437 1.1 elric * IV mode and passes off the work to the specific cipher.
1438 1.1 elric * We implement here the IV method ``encrypted block
1439 1.1 elric * number''.
1440 1.22 perry *
1441 1.1 elric * XXXrcd: for now we rely on our own crypto framework defined
1442 1.1 elric * in dev/cgd_crypto.c. This will change when we
1443 1.1 elric * get a generic kernel crypto framework.
1444 1.1 elric */
1445 1.1 elric
1446 1.1 elric static void
1447 1.25 xtraeme blkno2blkno_buf(char *sbuf, daddr_t blkno)
1448 1.1 elric {
1449 1.1 elric int i;
1450 1.1 elric
1451 1.1 elric /* Set up the blkno in blkno_buf, here we do not care much
1452 1.1 elric * about the final layout of the information as long as we
1453 1.1 elric * can guarantee that each sector will have a different IV
1454 1.1 elric * and that the endianness of the machine will not affect
1455 1.1 elric * the representation that we have chosen.
1456 1.1 elric *
1457 1.1 elric * We choose this representation, because it does not rely
1458 1.1 elric * on the size of buf (which is the blocksize of the cipher),
1459 1.1 elric * but allows daddr_t to grow without breaking existing
1460 1.1 elric * disks.
1461 1.1 elric *
1462 1.1 elric * Note that blkno2blkno_buf does not take a size as input,
1463 1.1 elric * and hence must be called on a pre-zeroed buffer of length
1464 1.1 elric * greater than or equal to sizeof(daddr_t).
1465 1.1 elric */
1466 1.1 elric for (i=0; i < sizeof(daddr_t); i++) {
1467 1.25 xtraeme *sbuf++ = blkno & 0xff;
1468 1.1 elric blkno >>= 8;
1469 1.1 elric }
1470 1.1 elric }
1471 1.1 elric
1472 1.122 mlelstv static struct cpu_info *
1473 1.122 mlelstv cgd_cpu(struct cgd_softc *sc)
1474 1.122 mlelstv {
1475 1.122 mlelstv struct cgd_worker *cw = sc->sc_worker;
1476 1.122 mlelstv struct cpu_info *ci = NULL;
1477 1.122 mlelstv u_int cidx, i;
1478 1.122 mlelstv
1479 1.122 mlelstv if (cw->cw_busy == 0) {
1480 1.122 mlelstv cw->cw_last = cpu_index(curcpu());
1481 1.122 mlelstv return NULL;
1482 1.122 mlelstv }
1483 1.122 mlelstv
1484 1.122 mlelstv for (i=0, cidx = cw->cw_last+1; i<maxcpus; ++i, ++cidx) {
1485 1.122 mlelstv if (cidx >= maxcpus)
1486 1.122 mlelstv cidx = 0;
1487 1.122 mlelstv ci = cpu_lookup(cidx);
1488 1.122 mlelstv if (ci) {
1489 1.122 mlelstv cw->cw_last = cidx;
1490 1.122 mlelstv break;
1491 1.122 mlelstv }
1492 1.122 mlelstv }
1493 1.122 mlelstv
1494 1.122 mlelstv return ci;
1495 1.122 mlelstv }
1496 1.122 mlelstv
1497 1.122 mlelstv static void
1498 1.122 mlelstv cgd_enqueue(struct cgd_softc *sc, struct cgd_xfer *cx)
1499 1.122 mlelstv {
1500 1.122 mlelstv struct cgd_worker *cw = sc->sc_worker;
1501 1.122 mlelstv struct cpu_info *ci;
1502 1.122 mlelstv
1503 1.122 mlelstv mutex_enter(&cw->cw_lock);
1504 1.122 mlelstv ci = cgd_cpu(sc);
1505 1.122 mlelstv cw->cw_busy++;
1506 1.122 mlelstv mutex_exit(&cw->cw_lock);
1507 1.122 mlelstv
1508 1.122 mlelstv workqueue_enqueue(cw->cw_wq, &cx->cx_work, ci);
1509 1.122 mlelstv }
1510 1.122 mlelstv
1511 1.122 mlelstv static void
1512 1.122 mlelstv cgd_process(struct work *wk, void *arg)
1513 1.122 mlelstv {
1514 1.122 mlelstv struct cgd_xfer *cx = (struct cgd_xfer *)wk;
1515 1.122 mlelstv struct cgd_softc *sc = cx->cx_sc;
1516 1.122 mlelstv struct cgd_worker *cw = sc->sc_worker;
1517 1.122 mlelstv
1518 1.122 mlelstv cgd_cipher(sc, cx->cx_dstv, cx->cx_srcv, cx->cx_len,
1519 1.122 mlelstv cx->cx_blkno, cx->cx_secsize, cx->cx_dir);
1520 1.122 mlelstv
1521 1.122 mlelstv if (cx->cx_dir == CGD_CIPHER_ENCRYPT) {
1522 1.122 mlelstv cgd_diskstart2(sc, cx);
1523 1.122 mlelstv } else {
1524 1.122 mlelstv cgd_iodone2(sc, cx);
1525 1.122 mlelstv }
1526 1.122 mlelstv
1527 1.122 mlelstv mutex_enter(&cw->cw_lock);
1528 1.122 mlelstv if (cw->cw_busy > 0)
1529 1.122 mlelstv cw->cw_busy--;
1530 1.122 mlelstv mutex_exit(&cw->cw_lock);
1531 1.122 mlelstv }
1532 1.122 mlelstv
1533 1.1 elric static void
1534 1.122 mlelstv cgd_cipher(struct cgd_softc *sc, void *dstv, void *srcv,
1535 1.44 christos size_t len, daddr_t blkno, size_t secsize, int dir)
1536 1.1 elric {
1537 1.44 christos char *dst = dstv;
1538 1.112 alnsn char *src = srcv;
1539 1.122 mlelstv cfunc_cipher *cipher = sc->sc_cfuncs->cf_cipher;
1540 1.1 elric struct uio dstuio;
1541 1.1 elric struct uio srcuio;
1542 1.1 elric struct iovec dstiov[2];
1543 1.1 elric struct iovec srciov[2];
1544 1.122 mlelstv size_t blocksize = sc->sc_cdata.cf_blocksize;
1545 1.105 mlelstv size_t todo;
1546 1.127 riastrad char blkno_buf[CGD_MAXBLOCKSIZE];
1547 1.1 elric
1548 1.1 elric DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir));
1549 1.1 elric
1550 1.118 riastrad KASSERTMSG(len % blocksize == 0,
1551 1.118 riastrad "cgd_cipher: len %% blocksize != 0");
1552 1.1 elric
1553 1.1 elric /* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */
1554 1.118 riastrad KASSERTMSG(sizeof(daddr_t) <= blocksize,
1555 1.118 riastrad "cgd_cipher: sizeof(daddr_t) > blocksize");
1556 1.1 elric
1557 1.118 riastrad KASSERTMSG(blocksize <= CGD_MAXBLOCKSIZE,
1558 1.118 riastrad "cgd_cipher: blocksize > CGD_MAXBLOCKSIZE");
1559 1.1 elric
1560 1.1 elric dstuio.uio_iov = dstiov;
1561 1.112 alnsn dstuio.uio_iovcnt = 1;
1562 1.1 elric
1563 1.1 elric srcuio.uio_iov = srciov;
1564 1.112 alnsn srcuio.uio_iovcnt = 1;
1565 1.1 elric
1566 1.105 mlelstv for (; len > 0; len -= todo) {
1567 1.105 mlelstv todo = MIN(len, secsize);
1568 1.105 mlelstv
1569 1.112 alnsn dstiov[0].iov_base = dst;
1570 1.112 alnsn srciov[0].iov_base = src;
1571 1.112 alnsn dstiov[0].iov_len = todo;
1572 1.112 alnsn srciov[0].iov_len = todo;
1573 1.1 elric
1574 1.64 christos memset(blkno_buf, 0x0, blocksize);
1575 1.1 elric blkno2blkno_buf(blkno_buf, blkno);
1576 1.1 elric IFDEBUG(CGDB_CRYPTO, hexprint("step 1: blkno_buf",
1577 1.64 christos blkno_buf, blocksize));
1578 1.112 alnsn
1579 1.127 riastrad cipher(sc->sc_cdata.cf_priv, &dstuio, &srcuio, blkno_buf, dir);
1580 1.1 elric
1581 1.105 mlelstv dst += todo;
1582 1.105 mlelstv src += todo;
1583 1.1 elric blkno++;
1584 1.1 elric }
1585 1.1 elric }
1586 1.1 elric
1587 1.1 elric #ifdef DEBUG
1588 1.1 elric static void
1589 1.26 drochner hexprint(const char *start, void *buf, int len)
1590 1.1 elric {
1591 1.1 elric char *c = buf;
1592 1.1 elric
1593 1.118 riastrad KASSERTMSG(len >= 0, "hexprint: called with len < 0");
1594 1.1 elric printf("%s: len=%06d 0x", start, len);
1595 1.1 elric while (len--)
1596 1.43 cbiere printf("%02x", (unsigned char) *c++);
1597 1.1 elric }
1598 1.1 elric #endif
1599 1.58 haad
1600 1.112 alnsn static void
1601 1.112 alnsn selftest(void)
1602 1.112 alnsn {
1603 1.122 mlelstv struct cgd_softc sc;
1604 1.112 alnsn void *buf;
1605 1.112 alnsn
1606 1.112 alnsn for (size_t i = 0; i < __arraycount(selftests); i++) {
1607 1.112 alnsn const char *alg = selftests[i].alg;
1608 1.112 alnsn const uint8_t *key = selftests[i].key;
1609 1.112 alnsn int keylen = selftests[i].keylen;
1610 1.112 alnsn int txtlen = selftests[i].txtlen;
1611 1.112 alnsn
1612 1.128 riastrad aprint_verbose("cgd: self-test %s-%d\n", alg, keylen);
1613 1.112 alnsn
1614 1.122 mlelstv memset(&sc, 0, sizeof(sc));
1615 1.112 alnsn
1616 1.122 mlelstv sc.sc_cfuncs = cryptfuncs_find(alg);
1617 1.122 mlelstv if (sc.sc_cfuncs == NULL)
1618 1.112 alnsn panic("%s not implemented", alg);
1619 1.112 alnsn
1620 1.122 mlelstv sc.sc_cdata.cf_blocksize = 8 * selftests[i].blocksize;
1621 1.122 mlelstv sc.sc_cdata.cf_mode = CGD_CIPHER_CBC_ENCBLKNO1;
1622 1.122 mlelstv sc.sc_cdata.cf_keylen = keylen;
1623 1.122 mlelstv
1624 1.122 mlelstv sc.sc_cdata.cf_priv = sc.sc_cfuncs->cf_init(keylen,
1625 1.122 mlelstv key, &sc.sc_cdata.cf_blocksize);
1626 1.122 mlelstv if (sc.sc_cdata.cf_priv == NULL)
1627 1.112 alnsn panic("cf_priv is NULL");
1628 1.122 mlelstv if (sc.sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE)
1629 1.122 mlelstv panic("bad block size %zu", sc.sc_cdata.cf_blocksize);
1630 1.112 alnsn
1631 1.122 mlelstv sc.sc_cdata.cf_blocksize /= 8;
1632 1.112 alnsn
1633 1.124 tnn buf = kmem_alloc(txtlen, KM_SLEEP);
1634 1.112 alnsn memcpy(buf, selftests[i].ptxt, txtlen);
1635 1.112 alnsn
1636 1.122 mlelstv cgd_cipher(&sc, buf, buf, txtlen, selftests[i].blkno,
1637 1.112 alnsn selftests[i].secsize, CGD_CIPHER_ENCRYPT);
1638 1.112 alnsn if (memcmp(buf, selftests[i].ctxt, txtlen) != 0)
1639 1.112 alnsn panic("encryption is broken");
1640 1.112 alnsn
1641 1.122 mlelstv cgd_cipher(&sc, buf, buf, txtlen, selftests[i].blkno,
1642 1.112 alnsn selftests[i].secsize, CGD_CIPHER_DECRYPT);
1643 1.112 alnsn if (memcmp(buf, selftests[i].ptxt, txtlen) != 0)
1644 1.112 alnsn panic("decryption is broken");
1645 1.112 alnsn
1646 1.124 tnn kmem_free(buf, txtlen);
1647 1.122 mlelstv sc.sc_cfuncs->cf_destroy(sc.sc_cdata.cf_priv);
1648 1.112 alnsn }
1649 1.112 alnsn
1650 1.128 riastrad aprint_verbose("cgd: self-tests passed\n");
1651 1.112 alnsn }
1652 1.112 alnsn
1653 1.116 pgoyette MODULE(MODULE_CLASS_DRIVER, cgd, "blowfish,des,dk_subr,bufq_fcfs");
1654 1.74 jruoho
1655 1.58 haad #ifdef _MODULE
1656 1.66 dyoung CFDRIVER_DECL(cgd, DV_DISK, NULL);
1657 1.109 pgoyette
1658 1.109 pgoyette devmajor_t cgd_bmajor = -1, cgd_cmajor = -1;
1659 1.74 jruoho #endif
1660 1.58 haad
1661 1.58 haad static int
1662 1.58 haad cgd_modcmd(modcmd_t cmd, void *arg)
1663 1.58 haad {
1664 1.82 martin int error = 0;
1665 1.74 jruoho
1666 1.58 haad switch (cmd) {
1667 1.58 haad case MODULE_CMD_INIT:
1668 1.112 alnsn selftest();
1669 1.74 jruoho #ifdef _MODULE
1670 1.122 mlelstv mutex_init(&cgd_spawning_mtx, MUTEX_DEFAULT, IPL_NONE);
1671 1.122 mlelstv cv_init(&cgd_spawning_cv, "cgspwn");
1672 1.122 mlelstv
1673 1.66 dyoung error = config_cfdriver_attach(&cgd_cd);
1674 1.66 dyoung if (error)
1675 1.66 dyoung break;
1676 1.66 dyoung
1677 1.66 dyoung error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
1678 1.66 dyoung if (error) {
1679 1.66 dyoung config_cfdriver_detach(&cgd_cd);
1680 1.109 pgoyette aprint_error("%s: unable to register cfattach for"
1681 1.109 pgoyette "%s, error %d\n", __func__, cgd_cd.cd_name, error);
1682 1.66 dyoung break;
1683 1.66 dyoung }
1684 1.109 pgoyette /*
1685 1.109 pgoyette * Attach the {b,c}devsw's
1686 1.109 pgoyette */
1687 1.109 pgoyette error = devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1688 1.109 pgoyette &cgd_cdevsw, &cgd_cmajor);
1689 1.74 jruoho
1690 1.109 pgoyette /*
1691 1.109 pgoyette * If devsw_attach fails, remove from autoconf database
1692 1.109 pgoyette */
1693 1.66 dyoung if (error) {
1694 1.66 dyoung config_cfattach_detach(cgd_cd.cd_name, &cgd_ca);
1695 1.66 dyoung config_cfdriver_detach(&cgd_cd);
1696 1.109 pgoyette aprint_error("%s: unable to attach %s devsw, "
1697 1.109 pgoyette "error %d", __func__, cgd_cd.cd_name, error);
1698 1.66 dyoung break;
1699 1.66 dyoung }
1700 1.74 jruoho #endif
1701 1.58 haad break;
1702 1.58 haad
1703 1.58 haad case MODULE_CMD_FINI:
1704 1.74 jruoho #ifdef _MODULE
1705 1.109 pgoyette /*
1706 1.109 pgoyette * Remove {b,c}devsw's
1707 1.109 pgoyette */
1708 1.109 pgoyette devsw_detach(&cgd_bdevsw, &cgd_cdevsw);
1709 1.109 pgoyette
1710 1.109 pgoyette /*
1711 1.109 pgoyette * Now remove device from autoconf database
1712 1.109 pgoyette */
1713 1.66 dyoung error = config_cfattach_detach(cgd_cd.cd_name, &cgd_ca);
1714 1.109 pgoyette if (error) {
1715 1.110 pgoyette (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1716 1.109 pgoyette &cgd_cdevsw, &cgd_cmajor);
1717 1.109 pgoyette aprint_error("%s: failed to detach %s cfattach, "
1718 1.109 pgoyette "error %d\n", __func__, cgd_cd.cd_name, error);
1719 1.109 pgoyette break;
1720 1.109 pgoyette }
1721 1.109 pgoyette error = config_cfdriver_detach(&cgd_cd);
1722 1.109 pgoyette if (error) {
1723 1.110 pgoyette (void)config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
1724 1.110 pgoyette (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1725 1.109 pgoyette &cgd_cdevsw, &cgd_cmajor);
1726 1.109 pgoyette aprint_error("%s: failed to detach %s cfdriver, "
1727 1.109 pgoyette "error %d\n", __func__, cgd_cd.cd_name, error);
1728 1.66 dyoung break;
1729 1.109 pgoyette }
1730 1.122 mlelstv
1731 1.122 mlelstv cv_destroy(&cgd_spawning_cv);
1732 1.122 mlelstv mutex_destroy(&cgd_spawning_mtx);
1733 1.74 jruoho #endif
1734 1.58 haad break;
1735 1.58 haad
1736 1.58 haad case MODULE_CMD_STAT:
1737 1.109 pgoyette error = ENOTTY;
1738 1.109 pgoyette break;
1739 1.58 haad default:
1740 1.109 pgoyette error = ENOTTY;
1741 1.109 pgoyette break;
1742 1.58 haad }
1743 1.58 haad
1744 1.58 haad return error;
1745 1.58 haad }
1746