The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/geom/bde/g_bde.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2002 Poul-Henning Kamp
    3  * Copyright (c) 2002 Networks Associates Technology, Inc.
    4  * All rights reserved.
    5  *
    6  * This software was developed for the FreeBSD Project by Poul-Henning Kamp
    7  * and NAI Labs, the Security Research Division of Network Associates, Inc.
    8  * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
    9  * DARPA CHATS research program.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  * $FreeBSD: releng/11.1/sys/geom/bde/g_bde.c 306764 2016-10-06 15:35:36Z mav $
   33  *
   34  */
   35 
   36 #include <sys/param.h>
   37 #include <sys/bio.h>
   38 #include <sys/lock.h>
   39 #include <sys/mutex.h>
   40 #include <sys/malloc.h>
   41 #include <sys/systm.h>
   42 #include <sys/kernel.h>
   43 #include <sys/kthread.h>
   44 #include <sys/sysctl.h>
   45 
   46 #include <crypto/rijndael/rijndael-api-fst.h>
   47 #include <crypto/sha2/sha512.h>
   48 #include <geom/geom.h>
   49 #include <geom/bde/g_bde.h>
   50 #define BDE_CLASS_NAME "BDE"
   51 
   52 FEATURE(geom_bde, "GEOM-based Disk Encryption");
   53 
   54 static void
   55 g_bde_start(struct bio *bp)
   56 {
   57 
   58         switch (bp->bio_cmd) {
   59         case BIO_DELETE:
   60         case BIO_READ:
   61         case BIO_WRITE:
   62                 g_bde_start1(bp);
   63                 break;
   64         case BIO_GETATTR:
   65                 g_io_deliver(bp, EOPNOTSUPP);
   66                 break;
   67         default:
   68                 g_io_deliver(bp, EOPNOTSUPP);
   69                 return;
   70         }
   71         return;
   72 }
   73 
   74 static void
   75 g_bde_orphan(struct g_consumer *cp)
   76 {
   77         struct g_geom *gp;
   78         struct g_provider *pp;
   79         struct g_bde_softc *sc;
   80 
   81         g_trace(G_T_TOPOLOGY, "g_bde_orphan(%p/%s)", cp, cp->provider->name);
   82         g_topology_assert();
   83 
   84         gp = cp->geom;
   85         sc = gp->softc;
   86         gp->flags |= G_GEOM_WITHER;
   87         LIST_FOREACH(pp, &gp->provider, provider)
   88                 g_wither_provider(pp, ENXIO);
   89         bzero(sc, sizeof(struct g_bde_softc));  /* destroy evidence */
   90         return;
   91 }
   92 
   93 static int
   94 g_bde_access(struct g_provider *pp, int dr, int dw, int de)
   95 {
   96         struct g_geom *gp;
   97         struct g_consumer *cp;
   98 
   99         gp = pp->geom;
  100         cp = LIST_FIRST(&gp->consumer);
  101         if (cp->acr == 0 && cp->acw == 0 && cp->ace == 0) {
  102                 de++;
  103                 dr++;
  104         }
  105         /* ... and let go of it on last close */
  106         if ((cp->acr + dr) == 0 && (cp->acw + dw) == 0 && (cp->ace + de) == 1) {
  107                 de--;
  108                 dr--;
  109         }
  110         return (g_access(cp, dr, dw, de));
  111 }
  112 
  113 static void
  114 g_bde_create_geom(struct gctl_req *req, struct g_class *mp, struct g_provider *pp)
  115 {
  116         struct g_geom *gp;
  117         struct g_consumer *cp;
  118         struct g_bde_key *kp;
  119         int error, i;
  120         u_int sectorsize;
  121         off_t mediasize;
  122         struct g_bde_softc *sc;
  123         void *pass;
  124         void *key;
  125 
  126         g_trace(G_T_TOPOLOGY, "g_bde_create_geom(%s, %s)", mp->name, pp->name);
  127         g_topology_assert();
  128         gp = NULL;
  129 
  130 
  131         gp = g_new_geomf(mp, "%s.bde", pp->name);
  132         cp = g_new_consumer(gp);
  133         g_attach(cp, pp);
  134         error = g_access(cp, 1, 1, 1);
  135         if (error) {
  136                 g_detach(cp);
  137                 g_destroy_consumer(cp);
  138                 g_destroy_geom(gp);
  139                 gctl_error(req, "could not access consumer");
  140                 return;
  141         }
  142         pass = NULL;
  143         key = NULL;
  144         do {
  145                 pass = gctl_get_param(req, "pass", &i);
  146                 if (pass == NULL || i != SHA512_DIGEST_LENGTH) {
  147                         gctl_error(req, "No usable key presented");
  148                         break;
  149                 }
  150                 key = gctl_get_param(req, "key", &i);
  151                 if (key != NULL && i != 16) {
  152                         gctl_error(req, "Invalid key presented");
  153                         break;
  154                 }
  155                 sectorsize = cp->provider->sectorsize;
  156                 mediasize = cp->provider->mediasize;
  157                 sc = g_malloc(sizeof(struct g_bde_softc), M_WAITOK | M_ZERO);
  158                 gp->softc = sc;
  159                 sc->geom = gp;
  160                 sc->consumer = cp;
  161 
  162                 error = g_bde_decrypt_lock(sc, pass, key,
  163                     mediasize, sectorsize, NULL);
  164                 bzero(sc->sha2, sizeof sc->sha2);
  165                 if (error)
  166                         break;
  167                 kp = &sc->key;
  168 
  169                 /* Initialize helper-fields */
  170                 kp->keys_per_sector = kp->sectorsize / G_BDE_SKEYLEN;
  171                 kp->zone_cont = kp->keys_per_sector * kp->sectorsize;
  172                 kp->zone_width = kp->zone_cont + kp->sectorsize;
  173                 kp->media_width = kp->sectorN - kp->sector0 -
  174                     G_BDE_MAXKEYS * kp->sectorsize;
  175 
  176                 /* Our external parameters */
  177                 sc->zone_cont = kp->zone_cont;
  178                 sc->mediasize = g_bde_max_sector(kp);
  179                 sc->sectorsize = kp->sectorsize;
  180 
  181                 TAILQ_INIT(&sc->freelist);
  182                 TAILQ_INIT(&sc->worklist);
  183                 mtx_init(&sc->worklist_mutex, "g_bde_worklist", NULL, MTX_DEF);
  184                 /* XXX: error check */
  185                 kproc_create(g_bde_worker, gp, &sc->thread, 0, 0,
  186                         "g_bde %s", gp->name);
  187                 pp = g_new_providerf(gp, "%s", gp->name);
  188                 pp->stripesize = kp->zone_cont;
  189                 pp->stripeoffset = 0;
  190                 pp->mediasize = sc->mediasize;
  191                 pp->sectorsize = sc->sectorsize;
  192                 g_error_provider(pp, 0);
  193                 break;
  194         } while (0);
  195         if (pass != NULL)
  196                 bzero(pass, SHA512_DIGEST_LENGTH);
  197         if (key != NULL)
  198                 bzero(key, 16);
  199         if (error == 0)
  200                 return;
  201         g_access(cp, -1, -1, -1);
  202         g_detach(cp);
  203         g_destroy_consumer(cp);
  204         if (gp->softc != NULL)
  205                 g_free(gp->softc);
  206         g_destroy_geom(gp);
  207         switch (error) {
  208         case ENOENT:
  209                 gctl_error(req, "Lock was destroyed");
  210                 break;
  211         case ESRCH:
  212                 gctl_error(req, "Lock was nuked");
  213                 break;
  214         case EINVAL:
  215                 gctl_error(req, "Could not open lock");
  216                 break;
  217         case ENOTDIR:
  218                 gctl_error(req, "Lock not found");
  219                 break;
  220         default:
  221                 gctl_error(req, "Could not open lock (%d)", error);
  222                 break;
  223         }
  224         return;
  225 }
  226 
  227 
  228 static int
  229 g_bde_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp)
  230 {
  231         struct g_consumer *cp;
  232         struct g_provider *pp;
  233         struct g_bde_softc *sc;
  234 
  235         g_trace(G_T_TOPOLOGY, "g_bde_destroy_geom(%s, %s)", mp->name, gp->name);
  236         g_topology_assert();
  237         /*
  238          * Orderly detachment.
  239          */
  240         KASSERT(gp != NULL, ("NULL geom"));
  241         pp = LIST_FIRST(&gp->provider);
  242         KASSERT(pp != NULL, ("NULL provider"));
  243         if (pp->acr > 0 || pp->acw > 0 || pp->ace > 0)
  244                 return (EBUSY);
  245         sc = gp->softc;
  246         cp = LIST_FIRST(&gp->consumer);
  247         KASSERT(cp != NULL, ("NULL consumer"));
  248         sc->dead = 1;
  249         wakeup(sc);
  250         g_access(cp, -1, -1, -1);
  251         g_detach(cp);
  252         g_destroy_consumer(cp);
  253         while (sc->dead != 2 && !LIST_EMPTY(&pp->consumers))
  254                 tsleep(sc, PRIBIO, "g_bdedie", hz);
  255         mtx_destroy(&sc->worklist_mutex);
  256         bzero(&sc->key, sizeof sc->key);
  257         g_free(sc);
  258         g_wither_geom(gp, ENXIO);
  259         return (0);
  260 }
  261 
  262 static void
  263 g_bde_ctlreq(struct gctl_req *req, struct g_class *mp, char const *verb)
  264 {
  265         struct g_geom *gp;
  266         struct g_provider *pp;
  267 
  268         if (!strcmp(verb, "create geom")) {
  269                 pp = gctl_get_provider(req, "provider");
  270                 if (pp != NULL)
  271                         g_bde_create_geom(req, mp, pp);
  272         } else if (!strcmp(verb, "destroy geom")) {
  273                 gp = gctl_get_geom(req, mp, "geom");
  274                 if (gp != NULL)
  275                         g_bde_destroy_geom(req, mp, gp);
  276         } else {
  277                 gctl_error(req, "unknown verb");
  278         }
  279 }
  280 
  281 static struct g_class g_bde_class       = {
  282         .name = BDE_CLASS_NAME,
  283         .version = G_VERSION,
  284         .destroy_geom = g_bde_destroy_geom,
  285         .ctlreq = g_bde_ctlreq,
  286         .start = g_bde_start,
  287         .orphan = g_bde_orphan,
  288         .access = g_bde_access,
  289         .spoiled = g_std_spoiled,
  290 };
  291 
  292 DECLARE_GEOM_CLASS(g_bde_class, g_bde);

Cache object: 30612bc75af558f9dd8a83ab621bafff


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.