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