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