Index: g_bde.c =================================================================== RCS file: /private/FreeBSD/src/sys/geom/bde/g_bde.c,v retrieving revision 1.28 diff -u -p -r1.28 g_bde.c --- g_bde.c 8 Aug 2004 07:57:51 -0000 1.28 +++ g_bde.c 11 Sep 2004 16:23:11 -0000 @@ -35,9 +35,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -46,8 +48,19 @@ #include #include #include + #define BDE_CLASS_NAME "BDE" +SYSCTL_DECL(_kern_geom); +SYSCTL_NODE(_kern_geom, OID_AUTO, bde, CTLFLAG_RW, 0, "GEOM_BDE stuff"); +static char g_bde_providers[1024] = ""; +TUNABLE_STR("kern.geom.bde.providers", g_bde_providers, + sizeof(g_bde_providers)); +static int g_bde_tries = 3; +TUNABLE_INT("kern.geom.bde.tries", &g_bde_tries); +static int g_bde_do_taste = 1; + + static void g_bde_start(struct bio *bp) { @@ -104,55 +117,44 @@ g_bde_access(struct g_provider *pp, int dr++; } /* ... and let go of it on last close */ - if ((cp->acr + dr) == 0 && (cp->acw + dw) == 0 && (cp->ace + de) == 1) { + if ((cp->acr + dr) == 1 && (cp->acw + dw) == 0 && (cp->ace + de) == 1) { de--; dr--; } return (g_access(cp, dr, dw, de)); } -static void -g_bde_create_geom(struct gctl_req *req, struct g_class *mp, struct g_provider *pp) +static struct g_geom * +g_bde_create_geom(struct gctl_req *req, struct g_class *mp, + struct g_provider *pp, void *pass, void *key) { struct g_geom *gp; struct g_consumer *cp; struct g_bde_key *kp; - int error, i; + int error; u_int sectorsize; off_t mediasize; struct g_bde_softc *sc; - void *pass; - void *key; g_trace(G_T_TOPOLOGY, "g_bde_create_geom(%s, %s)", mp->name, pp->name); g_topology_assert(); gp = NULL; - gp = g_new_geomf(mp, "%s.bde", pp->name); cp = g_new_consumer(gp); g_attach(cp, pp); - error = g_access(cp, 1, 1, 1); + error = g_access(cp, 1, 0, 0); if (error) { g_detach(cp); g_destroy_consumer(cp); g_destroy_geom(gp); - gctl_error(req, "could not access consumer"); - return; + if (req != NULL) + gctl_error(req, "Could not access consumer"); + else + printf("Could not access consumer (%s).", pp->name); + return (NULL); } - pass = NULL; - key = NULL; do { - pass = gctl_get_param(req, "pass", &i); - if (pass == NULL || i != SHA512_DIGEST_LENGTH) { - gctl_error(req, "No usable key presented"); - break; - } - key = gctl_get_param(req, "key", &i); - if (key != NULL && i != 16) { - gctl_error(req, "Invalid key presented"); - break; - } sectorsize = cp->provider->sectorsize; mediasize = cp->provider->mediasize; sc = g_malloc(sizeof(struct g_bde_softc), M_WAITOK | M_ZERO); @@ -201,19 +203,15 @@ g_bde_create_geom(struct gctl_req *req, g_error_provider(pp, 0); break; } while (0); - if (pass != NULL) - bzero(pass, SHA512_DIGEST_LENGTH); - if (key != NULL) - bzero(key, 16); + g_access(cp, -1, 0, 0); if (error == 0) - return; - g_access(cp, -1, -1, -1); + return (gp); g_detach(cp); g_destroy_consumer(cp); if (gp->softc != NULL) g_free(gp->softc); g_destroy_geom(gp); - return; + return (NULL); } @@ -237,9 +235,9 @@ g_bde_destroy_geom(struct gctl_req *req, sc = gp->softc; cp = LIST_FIRST(&gp->consumer); KASSERT(cp != NULL, ("NULL consumer")); + KASSERT(cp->acr + cp->acw + cp->ace == 0, ("consumer opened")); sc->dead = 1; wakeup(sc); - g_access(cp, -1, -1, -1); g_detach(cp); g_destroy_consumer(cp); while (sc->dead != 2 && !LIST_EMPTY(&pp->consumers)) @@ -259,8 +257,28 @@ g_bde_ctlreq(struct gctl_req *req, struc if (!strcmp(verb, "create geom")) { pp = gctl_get_provider(req, "provider"); - if (pp != NULL) - g_bde_create_geom(req, mp, pp); + if (pp != NULL) { + void *pass, *key; + int i; + + pass = gctl_get_param(req, "pass", &i); + if (pass == NULL || i != SHA512_DIGEST_LENGTH) { + gctl_error(req, "No usable key presented"); + return; + } + key = gctl_get_param(req, "key", &i); + if (key != NULL && i != 16) { + gctl_error(req, "Invalid key presented"); + if (pass != NULL) + bzero(pass, SHA512_DIGEST_LENGTH); + return; + } + g_bde_create_geom(req, mp, pp, pass, key); + if (pass != NULL) + bzero(pass, SHA512_DIGEST_LENGTH); + if (key != NULL) + bzero(key, 16); + } } else if (!strcmp(verb, "destroy geom")) { gp = gctl_get_geom(req, mp, "geom"); if (gp != NULL) @@ -270,11 +288,99 @@ g_bde_ctlreq(struct gctl_req *req, struc } } +static void +gets(char *cp) +{ + char *lp; + int c; + + lp = cp; + for (;;) { + c = cngetc() & 0177; + switch (c) { + case -1: + case '\n': + case '\r': + *lp++ = '\0'; + return; + case '\b': + case '\177': + if (lp > cp) { + printf(" \b"); + lp--; + } + continue; + case '#': + lp--; + if (lp < cp) + lp = cp; + continue; + case '@': + case 'u' & 037: + lp = cp; + printf("%c", '\n'); + continue; + default: + *lp++ = c; + } + } +} + +static int +g_bde_encrypted(const char *name) +{ + u_int i, lenl, lenp; + + lenl = strlen(g_bde_providers); + lenp = strlen(name); + if (lenl < lenp) + return (0); + lenl -= lenp; + for (i = 0; i <= lenl; i++) { + if (strncmp(g_bde_providers + i, name, lenp) == 0 && + (g_bde_providers[i + lenp] == ';' || + g_bde_providers[i + lenp] == '\0')) { + return (1); + } + } + return (0); +} + +static struct g_geom * +g_bde_taste(struct g_class *mp, struct g_provider *pp, int flags __unused) +{ + u_char sha2[SHA512_DIGEST_LENGTH]; + struct g_geom *gp; + char pass[128]; + int i; + + if (!g_bde_do_taste) + return (NULL); + g_topology_assert(); + g_trace(G_T_TOPOLOGY, "%s(%s, %s)", __func__, mp->name, pp->name); + if (!g_bde_encrypted(pp->name)) + return (NULL); + printf("Attaching %s...\n", pp->name); + gp = NULL; + for (i = 0; i < g_bde_tries; i++) { + printf("Enter passphrase (%d/%d): ", i + 1, g_bde_tries); + gets(pass); + printf("\n"); + g_bde_hash_pass(sha2, pass, strlen(pass)); + bzero(pass, sizeof(pass)); + gp = g_bde_create_geom(NULL, mp, pp, sha2, NULL); + bzero(sha2, sizeof(sha2)); + if (gp != NULL) + break; + } + return (gp); +} + static struct g_class g_bde_class = { .name = BDE_CLASS_NAME, .version = G_VERSION, - .destroy_geom = g_bde_destroy_geom, .ctlreq = g_bde_ctlreq, + .taste = g_bde_taste, .start = g_bde_start, .orphan = g_bde_orphan, .access = g_bde_access, @@ -282,3 +388,11 @@ static struct g_class g_bde_class = { }; DECLARE_GEOM_CLASS(g_bde_class, g_bde); + +static void +g_bde_on_boot(void *dummy __unused) +{ + + g_bde_do_taste = 0; +} +SYSINIT(bde, SI_SUB_MOUNT_ROOT, SI_ORDER_ANY, g_bde_on_boot, NULL) Index: g_bde.h =================================================================== RCS file: /private/FreeBSD/src/sys/geom/bde/g_bde.h,v retrieving revision 1.6 diff -u -p -r1.6 g_bde.h --- g_bde.h 7 Oct 2003 09:28:07 -0000 1.6 +++ g_bde.h 11 Sep 2004 09:51:18 -0000 @@ -157,7 +157,7 @@ int g_bde_decode_lock(struct g_bde_softc int g_bde_keyloc_encrypt(u_char *sha2, uint64_t v0, uint64_t v1, void *output); int g_bde_keyloc_decrypt(u_char *sha2, void *input, uint64_t *output); int g_bde_decrypt_lock(struct g_bde_softc *sc, u_char *keymat, u_char *meta, off_t mediasize, u_int sectorsize, u_int *nkey); -void g_bde_hash_pass(struct g_bde_softc *sc, const void *input, u_int len); +void g_bde_hash_pass(u_char *sha2, const void *input, u_int len); /* g_bde_math .c */ uint64_t g_bde_max_sector(struct g_bde_key *lp); Index: g_bde_lock.c =================================================================== RCS file: /private/FreeBSD/src/sys/geom/bde/g_bde_lock.c,v retrieving revision 1.12 diff -u -p -r1.12 g_bde_lock.c --- g_bde_lock.c 7 Oct 2003 09:28:07 -0000 1.12 +++ g_bde_lock.c 11 Sep 2004 09:50:29 -0000 @@ -74,13 +74,13 @@ */ void -g_bde_hash_pass(struct g_bde_softc *sc, const void *input, u_int len) +g_bde_hash_pass(u_char *sha2, const void *input, u_int len) { SHA512_CTX cx; SHA512_Init(&cx); SHA512_Update(&cx, input, len); - SHA512_Final(sc->sha2, &cx); + SHA512_Final(sha2, &cx); } /* Index: ../../../sbin/gbde/gbde.c =================================================================== RCS file: /private/FreeBSD/src/sbin/gbde/gbde.c,v retrieving revision 1.24 diff -u -p -r1.24 gbde.c --- ../../../sbin/gbde/gbde.c 6 Sep 2004 13:42:09 -0000 1.24 +++ ../../../sbin/gbde/gbde.c 11 Sep 2004 09:52:55 -0000 @@ -200,7 +200,7 @@ setup_passphrase(struct g_bde_softc *sc, char buf1[BUFSIZ], buf2[BUFSIZ], *p; if (input != NULL) { - g_bde_hash_pass(sc, input, strlen(input)); + g_bde_hash_pass(sc->sha2, input, strlen(input)); memcpy(sha2, sc->sha2, SHA512_DIGEST_LENGTH); return; }