geom_aes.c revision 98066
122347Spst/*- 222347Spst * Copyright (c) 2002 Poul-Henning Kamp 329964Sache * Copyright (c) 2002 Networks Associates Technology, Inc. 492906Smarkm * All rights reserved. 522347Spst * 622347Spst * This software was developed for the FreeBSD Project by Poul-Henning Kamp 722347Spst * and NAI Labs, the Security Research Division of Network Associates, Inc. 822347Spst * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 922347Spst * DARPA CHATS research program. 1022347Spst * 1122347Spst * Redistribution and use in source and binary forms, with or without 1222347Spst * modification, are permitted provided that the following conditions 1322347Spst * are met: 1422347Spst * 1. Redistributions of source code must retain the above copyright 1522347Spst * notice, this list of conditions and the following disclaimer. 1622347Spst * 2. Redistributions in binary form must reproduce the above copyright 1729964Sache * notice, this list of conditions and the following disclaimer in the 1822347Spst * documentation and/or other materials provided with the distribution. 1922347Spst * 3. The names of the authors may not be used to endorse or promote 2022347Spst * products derived from this software without specific prior written 2122347Spst * permission. 2222347Spst * 2322347Spst * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2422347Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2522347Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26117501Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2722347Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2822347Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2929964Sache * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3029964Sache * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3122347Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3222347Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3322347Spst * SUCH DAMAGE. 3422347Spst * 3522347Spst * $FreeBSD: head/sys/geom/geom_aes.c 98066 2002-06-09 10:57:34Z phk $ 3622347Spst * 3722347Spst * This method provides AES encryption with a compiled in key (default 3822347Spst * all zeroes). 3922347Spst * 4022347Spst * XXX: This could probably save a lot of code by pretending to be a slicer. 4122347Spst */ 4222347Spst 4322347Spst#include <sys/param.h> 4422347Spst#ifndef _KERNEL 4522347Spst#include <stdio.h> 4622347Spst#include <string.h> 4722347Spst#include <stdlib.h> 4822347Spst#include <signal.h> 4922347Spst#include <err.h> 5022347Spst#else 5122347Spst#include <sys/systm.h> 5222347Spst#include <sys/kernel.h> 5322347Spst#include <sys/conf.h> 5422347Spst#include <sys/bio.h> 5522347Spst#include <sys/malloc.h> 5622347Spst#include <sys/lock.h> 5722347Spst#include <sys/mutex.h> 5822347Spst#endif 5922347Spst#include <sys/errno.h> 6022347Spst#include <geom/geom.h> 6122347Spst 6222347Spst#include <crypto/rijndael/rijndael.h> 6322347Spst 6422347Spst#include <crypto/rijndael/rijndael.h> 6522347Spst 6622347Spst#define AES_CLASS_NAME "AES" 6722347Spst 6822347Spststatic u_char *aes_magic = "<<FreeBSD-GEOM-AES>>"; 6922347Spst 7022347Spststatic u_char aes_key[128 / 8] = { 7122347Spst 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 7222347Spst}; 7322347Spst 7422347Spststruct g_aes_softc { 7522347Spst u_int sectorsize; 7622347Spst off_t mediasize; 7722347Spst keyInstance ekey; 7822347Spst keyInstance dkey; 7922347Spst cipherInstance ci; 8022347Spst}; 8122347Spst 8222347Spststatic void 8322347Spstg_aes_read_done(struct bio *bp) 8422347Spst{ 8522347Spst struct g_geom *gp; 8622347Spst struct g_aes_softc *sc; 8722347Spst u_char *p, *b, *e, *sb; 88117501Skris 89117501Skris gp = bp->bio_from->geom; 90117501Skris sc = gp->softc; 9122347Spst sb = g_malloc(sc->sectorsize, M_WAITOK); 9222347Spst b = bp->bio_data; 9322347Spst e = bp->bio_data; 9422347Spst e += bp->bio_length; 9522347Spst for (p = b; p < e; p += sc->sectorsize) { 9629964Sache rijndael_blockDecrypt(&sc->ci, &sc->dkey, p, sc->sectorsize * 8, sb); 9722347Spst bcopy(sb, p, sc->sectorsize); 9822347Spst } 9922347Spst g_std_done(bp); 10022347Spst} 10122347Spst 10222347Spststatic void 10329964Sacheg_aes_write_done(struct bio *bp) 10429964Sache{ 10522347Spst 10622347Spst g_free(bp->bio_data); 10729964Sache g_std_done(bp); 10822347Spst} 10922347Spst 110117501Skrisstatic void 11122347Spstg_aes_start(struct bio *bp) 11222347Spst{ 11322347Spst struct g_geom *gp; 11422347Spst struct g_consumer *cp; 11522347Spst struct g_aes_softc *sc; 11622347Spst struct bio *bp2; 11722347Spst u_char *p1, *p2, *b, *e; 11822347Spst 119117501Skris gp = bp->bio_to->geom; 12022347Spst cp = LIST_FIRST(&gp->consumer); 12122347Spst sc = gp->softc; 122117501Skris switch (bp->bio_cmd) { 123117501Skris case BIO_READ: 12422347Spst bp2 = g_clone_bio(bp); 12522347Spst bp2->bio_done = g_aes_read_done; 12622347Spst bp2->bio_offset += sc->sectorsize; 127117501Skris g_io_request(bp2, cp); 12822347Spst break; 12922347Spst case BIO_WRITE: 13022347Spst bp2 = g_clone_bio(bp); 13122347Spst bp2->bio_done = g_aes_write_done; 13222347Spst bp2->bio_offset += sc->sectorsize; 13322347Spst bp2->bio_data = g_malloc(bp->bio_length, M_WAITOK); 13422347Spst b = bp->bio_data; 135117501Skris e = bp->bio_data; 13622347Spst e += bp->bio_length; 13722347Spst p2 = bp2->bio_data; 13822347Spst for (p1 = b; p1 < e; p1 += sc->sectorsize) { 13922347Spst rijndael_blockEncrypt(&sc->ci, &sc->ekey, 14022347Spst p1, sc->sectorsize * 8, p2); 14122347Spst p2 += sc->sectorsize; 14222347Spst } 14322347Spst g_io_request(bp2, cp); 14422347Spst break; 14522347Spst case BIO_GETATTR: 14622347Spst case BIO_SETATTR: 14722347Spst if (g_handleattr_off_t(bp, "GEOM::mediasize", sc->mediasize)) 14822347Spst return; 14922347Spst if (g_handleattr_int(bp, "GEOM::sectorsize", sc->sectorsize)) 15022347Spst return; 15122347Spst bp2 = g_clone_bio(bp); 15222347Spst bp2->bio_done = g_std_done; 15322347Spst bp2->bio_offset += sc->sectorsize; 15422347Spst g_io_request(bp2, cp); 15522347Spst break; 15622347Spst default: 15722347Spst bp->bio_error = EOPNOTSUPP; 15822347Spst g_io_deliver(bp); 15922347Spst return; 16022347Spst } 16122347Spst return; 16229964Sache} 16322347Spst 16422347Spststatic void 16522347Spstg_aes_orphan(struct g_consumer *cp) 16622347Spst{ 16722347Spst struct g_geom *gp; 16822347Spst struct g_provider *pp; 16922347Spst int error; 17022347Spst 17122347Spst g_trace(G_T_TOPOLOGY, "g_aes_orphan(%p/%s)", cp, cp->provider->name); 17222347Spst g_topology_assert(); 17322347Spst KASSERT(cp->provider->error != 0, 17422347Spst ("g_aes_orphan with error == 0")); 17522347Spst 17622347Spst gp = cp->geom; 17722347Spst gp->flags |= G_GEOM_WITHER; 17822347Spst error = cp->provider->error; 17922347Spst LIST_FOREACH(pp, &gp->provider, provider) 18022347Spst g_orphan_provider(pp, error); 18122347Spst return; 18222347Spst} 18322347Spst 18422347Spststatic int 18522347Spstg_aes_access(struct g_provider *pp, int dr, int dw, int de) 18622347Spst{ 18722347Spst struct g_geom *gp; 18822347Spst struct g_consumer *cp; 18922347Spst 19022347Spst gp = pp->geom; 19122347Spst cp = LIST_FIRST(&gp->consumer); 19222347Spst /* On first open, grab an extra "exclusive" bit */ 19322347Spst if (cp->acr == 0 && cp->acw == 0 && cp->ace == 0) 19422347Spst de++; 19522347Spst /* ... and let go of it on last close */ 19622347Spst if ((cp->acr + dr) == 0 && (cp->acw + dw) == 0 && (cp->ace + de) == 1) 19722347Spst de--; 19822347Spst return (g_access_rel(cp, dr, dw, de)); 19922347Spst} 20022347Spst 20122347Spststatic struct g_geom * 20222347Spstg_aes_taste(struct g_class *mp, struct g_provider *pp, int flags __unused) 20322347Spst{ 20422347Spst struct g_geom *gp; 20522347Spst struct g_consumer *cp; 20622347Spst struct g_aes_softc *sc; 20722347Spst int error; 20829964Sache u_int sectorsize; 20929964Sache off_t mediasize; 21029964Sache u_char *buf; 21129964Sache 21229964Sache g_trace(G_T_TOPOLOGY, "aes_taste(%s,%s)", mp->name, pp->name); 21329964Sache g_topology_assert(); 21422347Spst gp = g_new_geomf(mp, "%s.aes", pp->name); 21529964Sache gp->start = g_aes_start; 21622347Spst gp->orphan = g_aes_orphan; 217 gp->spoiled = g_std_spoiled; 218 cp = g_new_consumer(gp); 219 g_attach(cp, pp); 220 error = g_access_rel(cp, 1, 0, 0); 221 if (error) { 222 g_detach(cp); 223 g_destroy_consumer(cp); 224 g_destroy_geom(gp); 225 return (NULL); 226 } 227 buf = NULL; 228 while (1) { 229 if (gp->rank != 2) 230 break; 231 error = g_getattr("GEOM::sectorsize", cp, §orsize); 232 if (error) 233 break; 234 error = g_getattr("GEOM::mediasize", cp, &mediasize); 235 if (error) 236 break; 237 buf = g_read_data(cp, 0, sectorsize, &error); 238 if (buf == NULL || error != 0) { 239 break; 240 } 241 if (memcmp(buf, aes_magic, strlen(aes_magic))) 242 break; 243 sc = g_malloc(sizeof(struct g_aes_softc), M_WAITOK | M_ZERO); 244 gp->softc = sc; 245 gp->access = g_aes_access; 246 sc->sectorsize = sectorsize; 247 sc->mediasize = mediasize - sectorsize; 248 rijndael_cipherInit(&sc->ci, MODE_CBC, NULL); 249 rijndael_makeKey(&sc->ekey, DIR_ENCRYPT, 128, aes_key); 250 rijndael_makeKey(&sc->dkey, DIR_DECRYPT, 128, aes_key); 251 pp = g_new_providerf(gp, gp->name); 252 pp->mediasize = mediasize - sectorsize; 253 g_error_provider(pp, 0); 254 break; 255 } 256 if (buf) 257 g_free(buf); 258 g_access_rel(cp, -1, 0, 0); 259 if (gp->softc != NULL) 260 return (gp); 261 g_detach(cp); 262 g_destroy_consumer(cp); 263 g_destroy_geom(gp); 264 return (NULL); 265} 266 267static struct g_class g_aes_class = { 268 AES_CLASS_NAME, 269 g_aes_taste, 270 NULL, 271 G_CLASS_INITIALIZER 272}; 273 274DECLARE_GEOM_CLASS(g_aes_class, g_aes); 275