Index: sys/dev/cgd.c =================================================================== RCS file: /cvsroot/src/sys/dev/cgd.c,v retrieving revision 1.77 diff -u -p -u -r1.77 cgd.c --- sys/dev/cgd.c 25 May 2012 10:53:46 -0000 1.77 +++ sys/dev/cgd.c 4 Dec 2012 22:14:38 -0000 @@ -91,6 +91,7 @@ static void cgdiodone(struct buf *); static int cgd_ioctl_set(struct cgd_softc *, void *, struct lwp *); static int cgd_ioctl_clr(struct cgd_softc *, struct lwp *); +static int cgd_ioctl_get(dev_t, void *, struct lwp *); static int cgdinit(struct cgd_softc *, const char *, struct vnode *, struct lwp *); static void cgd_cipher(struct cgd_softc *, void *, void *, @@ -523,14 +524,23 @@ cgdioctl(dev_t dev, u_long cmd, void *da DPRINTF_FOLLOW(("cgdioctl(0x%"PRIx64", %ld, %p, %d, %p)\n", dev, cmd, data, flag, l)); - GETCGD_SOFTC(cs, dev); - dksc = &cs->sc_dksc; - dk = &dksc->sc_dkdev; + switch (cmd) { + case CGDIOCGET: /* don't call cgd_spawn() if the device isn't there */ + cs = NULL; + dksc = NULL; + dk = NULL; + break; case CGDIOCSET: case CGDIOCCLR: if ((flag & FWRITE) == 0) return EBADF; + /* FALLTHROUGH */ + default: + GETCGD_SOFTC(cs, dev); + dksc = &cs->sc_dksc; + dk = &dksc->sc_dkdev; + break; } switch (cmd) { @@ -542,6 +552,8 @@ cgdioctl(dev_t dev, u_long cmd, void *da if (DK_BUSY(&cs->sc_dksc, pmask)) return EBUSY; return cgd_ioctl_clr(cs, l); + case CGDIOCGET: + return cgd_ioctl_get(dev, data, l); case DIOCCACHESYNC: /* * XXX Do we really need to care about having a writable @@ -653,6 +665,7 @@ cgd_ioctl_set(struct cgd_softc *cs, void cs->sc_cdata.cf_blocksize = ci->ci_blocksize; cs->sc_cdata.cf_mode = encblkno[i].v; + cs->sc_cdata.cf_keylen = ci->ci_keylen; cs->sc_cdata.cf_priv = cs->sc_cfuncs->cf_init(ci->ci_keylen, inbuf, &cs->sc_cdata.cf_blocksize); if (cs->sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) { @@ -660,7 +673,7 @@ cgd_ioctl_set(struct cgd_softc *cs, void cs->sc_cdata.cf_blocksize, CGD_MAXBLOCKSIZE); cs->sc_cdata.cf_priv = NULL; } - + /* * The blocksize is supposed to be in bytes. Unfortunately originally * it was expressed in bits. For compatibility we maintain encblkno @@ -733,6 +746,44 @@ cgd_ioctl_clr(struct cgd_softc *cs, stru } static int +cgd_ioctl_get(dev_t dev, void *data, struct lwp *l) +{ + struct cgd_softc *cs; + struct cgd_user *cgu; + int unit; + + unit = CGDUNIT(dev); + cgu = (struct cgd_user *)data; + + DPRINTF_FOLLOW(("cgd_ioctl_get(0x%"PRIx64", %d, %p, %p)\n", + dev, unit, data, l)); + + if (cgu->cgu_unit == -1) + cgu->cgu_unit = unit; + + if (cgu->cgu_unit < 0) + return EINVAL; /* XXX: should this be ENXIO? */ + + cs = device_lookup_private(&cgd_cd, unit); + if (cs == NULL || (cs->sc_dksc.sc_flags & DKF_INITED) == 0) { + cgu->cgu_dev = 0; + cgu->cgu_alg[0] = '\0'; + cgu->cgu_blocksize = 0; + cgu->cgu_mode = 0; + cgu->cgu_keylen = 0; + } + else { + cgu->cgu_dev = cs->sc_tdev; + strlcpy(cgu->cgu_alg, cs->sc_cfuncs->cf_name, + sizeof(cgu->cgu_alg)); + cgu->cgu_blocksize = cs->sc_cdata.cf_blocksize; + cgu->cgu_mode = cs->sc_cdata.cf_mode; + cgu->cgu_keylen = cs->sc_cdata.cf_keylen; + } + return 0; +} + +static int cgdinit(struct cgd_softc *cs, const char *cpath, struct vnode *vp, struct lwp *l) { Index: sys/dev/cgd_crypto.c =================================================================== RCS file: /cvsroot/src/sys/dev/cgd_crypto.c,v retrieving revision 1.10 diff -u -p -u -r1.10 cgd_crypto.c --- sys/dev/cgd_crypto.c 30 Aug 2012 12:16:48 -0000 1.10 +++ sys/dev/cgd_crypto.c 4 Dec 2012 22:14:39 -0000 @@ -45,6 +45,10 @@ __KERNEL_RCSID(0, "$NetBSD: cgd_crypto.c #include +#include +#include +#include + #ifdef DIAGNOSTIC #define DIAGPANIC(x) panic x #else @@ -58,26 +62,52 @@ __KERNEL_RCSID(0, "$NetBSD: cgd_crypto.c * to check key size and block size. */ -extern struct cryptfuncs cgd_AES_funcs; -extern struct cryptfuncs cgd_3des_funcs; -extern struct cryptfuncs cgd_BF_funcs; - -struct cryptfuncs * +static cfunc_init cgd_cipher_aes_init; +static cfunc_destroy cgd_cipher_aes_destroy; +static cfunc_cipher cgd_cipher_aes_cbc; + +static cfunc_init cgd_cipher_3des_init; +static cfunc_destroy cgd_cipher_3des_destroy; +static cfunc_cipher cgd_cipher_3des_cbc; + +static cfunc_init cgd_cipher_bf_init; +static cfunc_destroy cgd_cipher_bf_destroy; +static cfunc_cipher cgd_cipher_bf_cbc; + +static const struct cryptfuncs cf[] = { + { + .cf_name = "aes-cbc", + .cf_init = cgd_cipher_aes_init, + .cf_destroy = cgd_cipher_aes_destroy, + .cf_cipher = cgd_cipher_aes_cbc, + }, + { + .cf_name = "3des-cbc", + .cf_init = cgd_cipher_3des_init, + .cf_destroy = cgd_cipher_3des_destroy, + .cf_cipher = cgd_cipher_3des_cbc, + }, + { + .cf_name = "blowfish-cbc", + .cf_init = cgd_cipher_bf_init, + .cf_destroy = cgd_cipher_bf_destroy, + .cf_cipher = cgd_cipher_bf_cbc, + }, +}; +const struct cryptfuncs * cryptfuncs_find(const char *alg) { - if (!strcmp("aes-cbc", alg)) - return &cgd_AES_funcs; - if (!strcmp("3des-cbc", alg)) - return &cgd_3des_funcs; - if (!strcmp("blowfish-cbc", alg)) - return &cgd_BF_funcs; + for (size_t i = 0; i < __arraycount(cf); i++) + if (strcmp(cf[i].cf_name, alg) == 0) + return &cf[i]; + return NULL; } typedef void (*cipher_func)(void *, void *, const void *, size_t); -void +static void cgd_cipher_uio_cbc(void *privdata, cipher_func cipher, struct uio *dstuio, struct uio *srcuio); @@ -92,7 +122,7 @@ cgd_cipher_uio_cbc(void *privdata, ciphe * of this case, either by issuing an error or copying the data. */ -void +static void cgd_cipher_uio_cbc(void *privdata, cipher_func cipher, struct uio *dstuio, struct uio *srcuio) { @@ -139,18 +169,6 @@ cgd_cipher_uio_cbc(void *privdata, ciphe * AES Framework */ -#include - -cfunc_init cgd_cipher_aes_init; -cfunc_destroy cgd_cipher_aes_destroy; -cfunc_cipher cgd_cipher_aes_cbc; - -struct cryptfuncs cgd_AES_funcs = { - cgd_cipher_aes_init, - cgd_cipher_aes_destroy, - cgd_cipher_aes_cbc, -}; - /* * NOTE: we do not store the blocksize in here, because it is not * variable [yet], we hardcode the blocksize to 16 (128 bits). @@ -166,10 +184,7 @@ struct aes_encdata { u_int8_t ae_iv[16]; /* Initialization Vector */ }; -static void aes_cbc_enc_int(void *, void *, const void *, size_t); -static void aes_cbc_dec_int(void *, void *, const void *, size_t); - -void * +static void * cgd_cipher_aes_init(size_t keylen, const void *key, size_t *blocksize) { struct aes_privdata *ap; @@ -190,7 +205,7 @@ cgd_cipher_aes_init(size_t keylen, const return ap; } -void +static void cgd_cipher_aes_destroy(void *data) { struct aes_privdata *apd = data; @@ -199,7 +214,7 @@ cgd_cipher_aes_destroy(void *data) free(apd, M_DEVBUF); } -void +static void aes_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len) { struct aes_encdata *ae = privdata; @@ -210,7 +225,7 @@ aes_cbc_enc_int(void *privdata, void *ds (void)memcpy(ae->ae_iv, (u_int8_t *)dst + (len - 16), 16); } -void +static void aes_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len) { struct aes_encdata *ae = privdata; @@ -221,7 +236,7 @@ aes_cbc_dec_int(void *privdata, void *ds (void)memcpy(ae->ae_iv, (const u_int8_t *)src + (len - 16), 16); } -void +static void cgd_cipher_aes_cbc(void *privdata, struct uio *dstuio, struct uio *srcuio, void *iv, int dir) { @@ -247,27 +262,12 @@ cgd_cipher_aes_cbc(void *privdata, struc * 3DES Framework */ -#include - -cfunc_init cgd_cipher_3des_init; -cfunc_destroy cgd_cipher_3des_destroy; -cfunc_cipher cgd_cipher_3des_cbc; - -struct cryptfuncs cgd_3des_funcs = { - cgd_cipher_3des_init, - cgd_cipher_3des_destroy, - cgd_cipher_3des_cbc, -}; - struct c3des_privdata { des_key_schedule cp_key1; des_key_schedule cp_key2; des_key_schedule cp_key3; }; -static void c3des_cbc_enc_int(void *, void *, const void *, size_t); -static void c3des_cbc_dec_int(void *, void *, const void *, size_t); - struct c3des_encdata { des_key_schedule *ce_key1; des_key_schedule *ce_key2; @@ -275,7 +275,7 @@ struct c3des_encdata { u_int8_t ce_iv[8]; }; -void * +static void * cgd_cipher_3des_init(size_t keylen, const void *key, size_t *blocksize) { struct c3des_privdata *cp; @@ -303,7 +303,7 @@ cgd_cipher_3des_init(size_t keylen, cons return cp; } -void +static void cgd_cipher_3des_destroy(void *data) { struct c3des_privdata *cp = data; @@ -332,7 +332,7 @@ c3des_cbc_dec_int(void *privdata, void * (void)memcpy(ce->ce_iv, (const u_int8_t *)src + (len - 8), 8); } -void +static void cgd_cipher_3des_cbc(void *privdata, struct uio *dstuio, struct uio *srcuio, void *iv, int dir) { @@ -359,21 +359,6 @@ cgd_cipher_3des_cbc(void *privdata, stru * Blowfish Framework */ -#include - -cfunc_init cgd_cipher_bf_init; -cfunc_destroy cgd_cipher_bf_destroy; -cfunc_cipher cgd_cipher_bf_cbc; - -struct cryptfuncs cgd_BF_funcs = { - cgd_cipher_bf_init, - cgd_cipher_bf_destroy, - cgd_cipher_bf_cbc, -}; - -static void bf_cbc_enc_int(void *, void *, const void *, size_t); -static void bf_cbc_dec_int(void *, void *, const void *, size_t); - struct bf_privdata { BF_KEY bp_key; }; @@ -383,7 +368,7 @@ struct bf_encdata { u_int8_t be_iv[8]; }; -void * +static void * cgd_cipher_bf_init(size_t keylen, const void *key, size_t *blocksize) { struct bf_privdata *bp; @@ -403,7 +388,7 @@ cgd_cipher_bf_init(size_t keylen, const return bp; } -void +static void cgd_cipher_bf_destroy(void *data) { struct bf_privdata *bp = data; @@ -412,7 +397,7 @@ cgd_cipher_bf_destroy(void *data) free(bp, M_DEVBUF); } -void +static void bf_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len) { struct bf_encdata *be = privdata; @@ -421,7 +406,7 @@ bf_cbc_enc_int(void *privdata, void *dst (void)memcpy(be->be_iv, (u_int8_t *)dst + (len - 8), 8); } -void +static void bf_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len) { struct bf_encdata *be = privdata; @@ -430,7 +415,7 @@ bf_cbc_dec_int(void *privdata, void *dst (void)memcpy(be->be_iv, (const u_int8_t *)src + (len - 8), 8); } -void +static void cgd_cipher_bf_cbc(void *privdata, struct uio *dstuio, struct uio *srcuio, void *iv, int dir) { Index: sys/dev/cgd_crypto.h =================================================================== RCS file: /cvsroot/src/sys/dev/cgd_crypto.h,v retrieving revision 1.6 diff -u -p -u -r1.6 cgd_crypto.h --- sys/dev/cgd_crypto.h 28 Apr 2008 20:23:46 -0000 1.6 +++ sys/dev/cgd_crypto.h 4 Dec 2012 22:14:39 -0000 @@ -41,12 +41,13 @@ typedef void (cfunc_destroy)(void *); typedef void (cfunc_cipher)(void *, struct uio *, struct uio *, void *, int); struct cryptfuncs { + const char *cf_name; /* cipher name */ cfunc_init *cf_init; /* Initialisation function */ cfunc_destroy *cf_destroy; /* destruction function */ cfunc_cipher *cf_cipher; /* the cipher itself */ }; -struct cryptfuncs *cryptfuncs_find(const char *); +const struct cryptfuncs *cryptfuncs_find(const char *); #endif /* _KERNEL */ #endif /* _DEV_CGD_CRYPTO_H_ */ Index: sys/dev/cgdvar.h =================================================================== RCS file: /cvsroot/src/sys/dev/cgdvar.h,v retrieving revision 1.15 diff -u -p -u -r1.15 cgdvar.h --- sys/dev/cgdvar.h 25 May 2012 10:53:46 -0000 1.15 +++ sys/dev/cgdvar.h 4 Dec 2012 22:14:39 -0000 @@ -34,7 +34,7 @@ #include -/* ioctl(2) code */ +/* ioctl(2) code: used by CGDIOCSET and CGDIOCCLR */ struct cgd_ioctl { const char *ci_disk; int ci_flags; @@ -47,6 +47,22 @@ struct cgd_ioctl { size_t ci_blocksize; }; +/* ioctl(2) code: used by CGDIOCGET */ +struct cgd_user { + int cgu_unit; /* which cgd unit */ + dev_t cgu_dev; /* target device */ + char cgu_alg[32]; /* algorithm name */ + size_t cgu_blocksize; /* block size (in bytes) */ + int cgu_mode; /* Cipher Mode and IV Gen method */ +#define CGD_CIPHER_CBC_ENCBLKNO8 1 /* CBC Mode w/ Enc Block Number + * 8 passes (compat only) + */ +#define CGD_CIPHER_CBC_ENCBLKNO1 2 /* CBC Mode w/ Enc Block Number + * 1 pass (default) + */ + int cgu_keylen; /* keylength */ +}; + #ifdef _KERNEL #include @@ -58,19 +74,14 @@ struct cgd_ioctl { struct cryptdata { size_t cf_blocksize; /* block size (in bytes) */ - int cf_mode; /* Cipher Mode and IV Gen method */ -#define CGD_CIPHER_CBC_ENCBLKNO8 1 /* CBC Mode w/ Enc Block Number - * 8 passes (compat only) - */ -#define CGD_CIPHER_CBC_ENCBLKNO1 2 /* CBC Mode w/ Enc Block Number - * 1 pass (default) - */ + int cf_keylen; /* key length */ + int cf_mode; /* Cipher Mode and IV Gen method + * (see cgu_mode above for defines) */ void *cf_priv; /* enc alg private data */ }; struct cgd_softc { struct dk_softc sc_dksc; /* generic disk interface */ - struct cryptinfo *sc_crypt; /* the alg/key/etc */ struct vnode *sc_tvn; /* target device's vnode */ dev_t sc_tdev; /* target device */ char *sc_tpath; /* target device's path */ @@ -78,7 +89,7 @@ struct cgd_softc { int sc_data_used; /* Really lame, we'll change */ size_t sc_tpathlen; /* length of prior string */ struct cryptdata sc_cdata; /* crypto data */ - struct cryptfuncs *sc_cfuncs; /* encryption functions */ + const struct cryptfuncs *sc_cfuncs; /* encryption functions */ struct simplelock sc_slock; /* our lock */ }; #endif @@ -86,6 +97,7 @@ struct cgd_softc { /* XXX XAX XXX elric: check these out properly. */ #define CGDIOCSET _IOWR('F', 18, struct cgd_ioctl) #define CGDIOCCLR _IOW('F', 19, struct cgd_ioctl) +#define CGDIOCGET _IOWR('F', 20, struct cgd_user) /* Maximum block sized to be used by the ciphers */ #define CGD_MAXBLOCKSIZE 128 Index: share/man/man4/cgd.4 =================================================================== RCS file: /cvsroot/src/share/man/man4/cgd.4,v retrieving revision 1.16 diff -u -p -u -r1.16 cgd.4 --- share/man/man4/cgd.4 15 Apr 2010 09:56:56 -0000 1.16 +++ share/man/man4/cgd.4 4 Dec 2012 22:14:39 -0000 @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd April 15, 2010 +.Dd December 3, 2012 .Dt CGD 4 .Os .Sh NAME @@ -148,6 +148,9 @@ at the underlying disk. .It Dv CGDIOCCLR Unconfigure the .Nm . +.It Dv CGDIOCGET +Get info about the +.Nm . .El .Pp These Index: sbin/cgdconfig/cgdconfig.8 =================================================================== RCS file: /cvsroot/src/sbin/cgdconfig/cgdconfig.8,v retrieving revision 1.31 diff -u -p -u -r1.31 cgdconfig.8 --- sbin/cgdconfig/cgdconfig.8 3 Jul 2011 19:05:10 -0000 1.31 +++ sbin/cgdconfig/cgdconfig.8 4 Dec 2012 22:14:39 -0000 @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd October 19, 2009 +.Dd December 3, 2012 .Dt CGDCONFIG 8 .Os .Sh NAME @@ -44,10 +44,6 @@ .Op Fl nv .Op Fl f Ar configfile .Nm -.Fl U -.Op Fl nv -.Op Fl f Ar configfile -.Nm .Fl G .Op Fl nv .Op Fl i Ar ivmeth @@ -63,6 +59,9 @@ .Ar alg .Op Ar keylen .Nm +.Fl l +.Op Fl cgd +.Nm .Fl s .Op Fl nv .Op Fl i Ar ivmeth @@ -71,6 +70,10 @@ .Ar alg .Op Ar keylen .Nm +.Fl U +.Op Fl nv +.Op Fl f Ar configfile +.Nm .Fl u .Op Fl nv .Ar cgd @@ -100,6 +103,11 @@ Generate a paramsfile (to stdout). Specify the IV method (default: encblkno1). .It Fl k Ar kgmeth Specify the key generation method (default: pkcs5_pbkdf2/sha1). +.It Fl l Op Ar cgd +List state of all devices or just the one +.Ar cgd +device. +The verbosity level affects the output. .It Fl n Do not actually configure or unconfigure a cryptographic disk device, but instead report the steps that would be taken. @@ -335,22 +343,29 @@ when we configure the first time to set Here is the sequence of commands that is recommended: .Bd -literal - # cgdconfig -g -o /etc/cgd/wd0e -V disklabel aes-cbc - # cgdconfig -V re-enter cgd0 /dev/wd0e - /dev/wd0e's passphrase: - re-enter device's passphrase: - # disklabel -e -I cgd0 - # cgdconfig -u cgd0 - # cgdconfig cgd0 /dev/wd0e - /dev/wd0e's passphrase: + # cgdconfig -g -o /etc/cgd/wd0e -V disklabel aes-cbc + # cgdconfig -V re-enter cgd0 /dev/wd0e + /dev/wd0e's passphrase: + re-enter device's passphrase: + # disklabel -e -I cgd0 + # cgdconfig -u cgd0 + # cgdconfig cgd0 /dev/wd0e + /dev/wd0e's passphrase: +.Ed +.Pp +To scrub data from a disk before setting up a cgd: +.Bd -literal + # cgdconfig -s cgd0 /dev/sd0e aes-cbc 256 < /dev/urandom + # dd if=/dev/zero of=/dev/rcgd0d bs=32k progress=512 + # cgdconfig -u cgd0 .Ed .Pp To create a new parameters file that will generate the same key as an old parameters file: .Bd -literal - # cgdconfig -G -o newparamsfile oldparamsfile - old file's passphrase: - new file's passphrase: + # cgdconfig -G -o newparamsfile oldparamsfile + old file's passphrase: + new file's passphrase: .Ed .Pp To configure a cgd that uses Blowfish with a 200 bit key that it @@ -395,9 +410,13 @@ An example cgd1 /dev/sd0h /usr/local/etc/cgd/sd0h .Ed .Pp -Note that this will store the parameters file as +Note the first entry will store the parameters file as .Pa /etc/cgd/wd0e . And use the entered passphrase to generate the key. +.Pp +Although not required, the partition type +.Ar cgd +should be used in the disklabel for the cgd partition. .Sh DIAGNOSTICS .Bl -diag .It "cgdconfig: could not calibrate pkcs5_pbkdf2" Index: sbin/cgdconfig/cgdconfig.c =================================================================== RCS file: /cvsroot/src/sbin/cgdconfig/cgdconfig.c,v retrieving revision 1.33 diff -u -p -u -r1.33 cgdconfig.c --- sbin/cgdconfig/cgdconfig.c 29 Aug 2011 14:34:59 -0000 1.33 +++ sbin/cgdconfig/cgdconfig.c 4 Dec 2012 22:14:39 -0000 @@ -51,6 +51,7 @@ __RCSID("$NetBSD: cgdconfig.c,v 1.33 201 #include #include #include +#include #include @@ -73,7 +74,8 @@ enum action { ACTION_GENERATE_CONVERT, /* generate a ``dup'' paramsfile */ ACTION_CONFIGALL, /* configure all from config file */ ACTION_UNCONFIGALL, /* unconfigure all from config file */ - ACTION_CONFIGSTDIN /* configure, key from stdin */ + ACTION_CONFIGSTDIN, /* configure, key from stdin */ + ACTION_LIST /* list configured devices */ }; /* if nflag is set, do not configure/unconfigure the cgd's */ @@ -93,6 +95,7 @@ static int generate_convert(struct param static int unconfigure(int, char **, struct params *, int); static int do_all(const char *, int, char **, int (*)(int, char **, struct params *, int)); +static int do_list(int, char **); #define CONFIG_FLAGS_FROMALL 1 /* called from configure_all() */ #define CONFIG_FLAGS_FROMMAIN 2 /* called from main() */ @@ -129,13 +132,14 @@ usage(void) (void)fprintf(stderr, "usage: %s [-nv] [-V vmeth] cgd dev [paramsfile]\n", getprogname()); (void)fprintf(stderr, " %s -C [-nv] [-f configfile]\n", getprogname()); - (void)fprintf(stderr, " %s -U [-nv] [-f configfile]\n", getprogname()); (void)fprintf(stderr, " %s -G [-nv] [-i ivmeth] [-k kgmeth] " "[-o outfile] paramsfile\n", getprogname()); (void)fprintf(stderr, " %s -g [-nv] [-i ivmeth] [-k kgmeth] " "[-o outfile] alg [keylen]\n", getprogname()); + (void)fprintf(stderr, " %s -l\n", getprogname()); (void)fprintf(stderr, " %s -s [-nv] [-i ivmeth] cgd dev alg " "[keylen]\n", getprogname()); + (void)fprintf(stderr, " %s -U [-nv] [-f configfile]\n", getprogname()); (void)fprintf(stderr, " %s -u [-nv] cgd\n", getprogname()); exit(EXIT_FAILURE); } @@ -188,7 +192,7 @@ main(int argc, char **argv) p = params_new(); kg = NULL; - while ((ch = getopt(argc, argv, "CGUV:b:f:gi:k:no:spuv")) != -1) + while ((ch = getopt(argc, argv, "CGUV:b:f:gi:k:lno:spuv")) != -1) switch (ch) { case 'C': set_action(&action, ACTION_CONFIGALL); @@ -235,6 +239,9 @@ main(int argc, char **argv) usage(); keygen_addlist(&p->keygen, kg); break; + case 'l': + set_action(&action, ACTION_LIST); + break; case 'n': nflag = 1; break; @@ -290,6 +297,8 @@ main(int argc, char **argv) return do_all(cfile, argc, argv, unconfigure); case ACTION_CONFIGSTDIN: return configure_stdin(p, argc, argv); + case ACTION_LIST: + return do_list(argc, argv); default: errx(EXIT_FAILURE, "undefined action"); /* NOTREACHED */ @@ -497,7 +506,7 @@ configure(int argc, char **argv, struct int ret; char cgdname[PATH_MAX]; - if (argc == 2) { + if (argc == 2) { char *pfile; if (asprintf(&pfile, "%s/%s", @@ -976,6 +985,85 @@ do_all(const char *cfile, int argc, char return ret; } +static const char * +iv_method(int mode) +{ + + switch (mode) { + case CGD_CIPHER_CBC_ENCBLKNO8: + return "encblkno8"; + case CGD_CIPHER_CBC_ENCBLKNO1: + return "encblkno1"; + default: + return "unknown"; + } +} + +static int +do_list(int argc, char **argv) +{ + char path[64], buf[16]; + struct cgd_user cgu; + const char *fn; + int fd, n, rv; + + if (argc != 0 && argc != 1) + usage(); + + fn = argc ? argv[0] : "cgd0"; + n = 0; + for (;;) { + fd = opendisk(fn, O_RDONLY, path, sizeof(path), 0); + if (fd == -1) { + if (argc) + err(1, "open: %s", fn); + break; + } + + cgu.cgu_unit = argc ? -1 : n; + rv = prog_ioctl(fd, CGDIOCGET, &cgu); + if (rv == -1) { + close(fd); + err(1, "CGDIOCGET"); + } + + printf("%s: ", fn); + + if (cgu.cgu_dev == 0) + printf("not in use"); + else { + char *dev; + + dev = devname(cgu.cgu_dev, S_IFBLK); + if (dev != NULL) + printf("%s ", dev); + else + printf("dev %llu,%llu ", + (unsigned long long)major(cgu.cgu_dev), + (unsigned long long)minor(cgu.cgu_dev)); + + if (verbose) + printf("%s ", cgu.cgu_alg); + if (verbose > 1) { + printf("keylen %d ", cgu.cgu_keylen); + printf("blksize %zd ", cgu.cgu_blocksize); + printf("%s ", iv_method(cgu.cgu_mode)); + } + } + putchar('\n'); + close(fd); + + if (argc) + break; + + n++; + snprintf(buf, sizeof(buf), "cgd%d", n); + fn = buf; + } + + return 0; +} + static void eliminate_cores(void) {