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