g_bde_lock.c revision 105464
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 * 3. The names of the authors may not be used to endorse or promote 20 * products derived from this software without specific prior written 21 * permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * $FreeBSD: head/sys/geom/bde/g_bde_lock.c 105464 2002-10-19 17:02:17Z phk $ 36 * 37 * This souce file contains routines which operates on the lock sectors, both 38 * for the kernel and the userland program gbde(1). 39 * 40 */ 41 42#include <sys/param.h> 43#include <sys/queue.h> 44#include <sys/stdint.h> 45#include <sys/lock.h> 46#include <sys/mutex.h> 47#include <sys/md5.h> 48 49#ifdef _KERNEL 50#include <sys/malloc.h> 51#include <sys/systm.h> 52#else 53#include <errno.h> 54#include <string.h> 55#include <stdlib.h> 56#include <stdio.h> 57#define g_free(foo) free(foo) 58#endif 59 60#include <geom/geom.h> 61#include <geom/bde/g_bde.h> 62 63#include <crypto/rijndael/rijndael.h> 64 65/* 66 * Encode/Decode the lock structure in byte-sequence format. 67 * 68 * Security objectives: none. 69 * 70 * C-structure packing and byte-endianess depends on architecture, compiler 71 * and compiler options. We therefore explicitly encode and decode struct 72 * g_bde_key using an invariant byte-sequence format. 73 * 74 */ 75 76void 77g_bde_encode_lock(struct g_bde_key *gl, u_char *ptr) 78{ 79 80 bcopy(gl->hash, ptr + 0, sizeof gl->hash); 81 g_enc_le8(ptr + 16, gl->sector0); 82 g_enc_le8(ptr + 24, gl->sectorN); 83 g_enc_le8(ptr + 32, gl->keyoffset); 84 g_enc_le4(ptr + 40, gl->sectorsize); 85 g_enc_le4(ptr + 44, gl->flags); 86 g_enc_le8(ptr + 48, gl->lsector[0]); 87 g_enc_le8(ptr + 56, gl->lsector[1]); 88 g_enc_le8(ptr + 64, gl->lsector[2]); 89 g_enc_le8(ptr + 72, gl->lsector[3]); 90 bcopy(gl->spare, ptr + 80, sizeof gl->spare); 91 bcopy(gl->key, ptr + 128, sizeof gl->key); 92} 93 94void 95g_bde_decode_lock(struct g_bde_key *gl, u_char *ptr) 96{ 97 bcopy(ptr + 0, gl->hash, sizeof gl->hash); 98 gl->sector0 = g_dec_le8(ptr + 16); 99 gl->sectorN = g_dec_le8(ptr + 24); 100 gl->keyoffset = g_dec_le8(ptr + 32); 101 gl->sectorsize = g_dec_le4(ptr + 40); 102 gl->flags = g_dec_le4(ptr + 44); 103 gl->lsector[0] = g_dec_le8(ptr + 48); 104 gl->lsector[1] = g_dec_le8(ptr + 56); 105 gl->lsector[2] = g_dec_le8(ptr + 64); 106 gl->lsector[3] = g_dec_le8(ptr + 72); 107 bcopy(ptr + 80, gl->spare, sizeof gl->spare); 108 bcopy(ptr + 128, gl->key, sizeof gl->key); 109} 110 111/* 112 * Generate key-material used for protecting lock sectors. 113 * 114 * Security objectives: from the pass-phrase provide by the user, produce a 115 * reproducible stream of bits/bytes which resemeble pseudo-random bits. 116 * 117 * This is the stream-cipher algorithm called ARC4. See for instance the 118 * description in "Applied Cryptography" by Bruce Scneier. 119 */ 120 121u_char 122g_bde_arc4(struct g_bde_softc *sc) 123{ 124 u_char c; 125 126 sc->arc4_j += sc->arc4_sbox[++sc->arc4_i]; 127 c = sc->arc4_sbox[sc->arc4_i]; 128 sc->arc4_sbox[sc->arc4_i] = sc->arc4_sbox[sc->arc4_j]; 129 sc->arc4_sbox[sc->arc4_j] = c; 130 c = sc->arc4_sbox[sc->arc4_i] + sc->arc4_sbox[sc->arc4_j]; 131 c = sc->arc4_sbox[c]; 132 return (c); 133} 134 135void 136g_bde_arc4_seq(struct g_bde_softc *sc, void *ptr, u_int len) 137{ 138 u_char *p; 139 140 p = ptr; 141 while (len--) 142 *p++ = g_bde_arc4(sc); 143} 144 145void 146g_bde_arc4_seed(struct g_bde_softc *sc, void *ptr, u_int len) 147{ 148 u_char k[256], *p, c; 149 u_int i; 150 151 p = ptr; 152 sc->arc4_i = 0; 153 bzero(k, sizeof k); 154 while(len--) 155 k[sc->arc4_i++] ^= *p++; 156 157 sc->arc4_j = 0; 158 for (i = 0; i < 256; i++) 159 sc->arc4_sbox[i] = i; 160 for (i = 0; i < 256; i++) { 161 sc->arc4_j += sc->arc4_sbox[i] + k[i]; 162 c = sc->arc4_sbox[i]; 163 sc->arc4_sbox[i] = sc->arc4_sbox[sc->arc4_j]; 164 sc->arc4_sbox[sc->arc4_j] = c; 165 } 166 sc->arc4_i = 0; 167 sc->arc4_j = 0; 168} 169 170/* 171 * Encrypt/Decrypt the metadata address with key-material. 172 */ 173 174int 175g_bde_keyloc_encrypt(struct g_bde_softc *sc, void *input, void *output) 176{ 177 u_char *p; 178 u_char buf[16], buf1[16]; 179 u_int i; 180 keyInstance ki; 181 cipherInstance ci; 182 183 rijndael_cipherInit(&ci, MODE_CBC, NULL); 184 p = input; 185 g_bde_arc4_seq(sc, buf, sizeof buf); 186 for (i = 0; i < sizeof buf; i++) 187 buf1[i] = p[i] ^ buf[i]; 188 g_bde_arc4_seq(sc, buf, sizeof buf); 189 rijndael_makeKey(&ki, DIR_ENCRYPT, G_BDE_KKEYBITS, buf); 190 rijndael_blockEncrypt(&ci, &ki, buf1, 16 * 8, output); 191 bzero(&ci, sizeof ci); 192 return (0); 193} 194 195int 196g_bde_keyloc_decrypt(struct g_bde_softc *sc, void *input, void *output) 197{ 198 u_char *p; 199 u_char buf1[16], buf2[16]; 200 u_int i; 201 keyInstance ki; 202 cipherInstance ci; 203 204 rijndael_cipherInit(&ci, MODE_CBC, NULL); 205 g_bde_arc4_seq(sc, buf1, sizeof buf1); 206 g_bde_arc4_seq(sc, buf2, sizeof buf2); 207 rijndael_makeKey(&ki, DIR_DECRYPT, G_BDE_KKEYBITS, buf2); 208 rijndael_blockDecrypt(&ci, &ki, input, 16 * 8, output); 209 p = output; 210 for (i = 0; i < sizeof buf1; i++) 211 p[i] ^= buf1[i]; 212 bzero(&ci, sizeof ci); 213 return (0); 214} 215 216/* 217 * Encode/Decode lock sectors. 218 */ 219 220int 221g_bde_decrypt_lock(struct g_bde_softc *sc, u_char *sbox, u_char *meta, off_t mediasize, u_int sectorsize, u_int *nkey) 222{ 223 u_char *buf, k1buf[16], k2buf[G_BDE_LOCKSIZE], k3buf[16], *q; 224 struct g_bde_key *gl; 225 uint64_t off[2]; 226 int error, m, i; 227 MD5_CTX c; 228 keyInstance ki; 229 cipherInstance ci; 230 231 rijndael_cipherInit(&ci, MODE_CBC, NULL); 232 bcopy(sbox, sc->arc4_sbox, 256); 233 sc->arc4_i = 0; 234 sc->arc4_j = 0; 235 gl = &sc->key; 236 error = g_bde_keyloc_decrypt(sc, meta, off); 237 if (error) 238 return(error); 239 240 if (off[0] + G_BDE_LOCKSIZE > (uint64_t)mediasize) { 241 bzero(off, sizeof off); 242 return (ESRCH); 243 } 244 off[1] = 0; 245 m = 1; 246 if (off[0] % sectorsize > sectorsize - G_BDE_LOCKSIZE) 247 m++; 248 buf = g_read_data(sc->consumer, 249 off[0] - (off[0] % sectorsize), 250 m * sectorsize, &error); 251 if (buf == NULL) { 252 off[0] = 0; 253 return(error); 254 } 255 256 q = buf + off[0] % sectorsize; 257 258 off[1] = 0; 259 for (i = 0; i < (int)sizeof(*gl); i++) 260 off[1] += q[i]; 261 262 if (off[1] == 0) { 263 off[0] = 0; 264 g_free(buf); 265 return (ESRCH); 266 } 267 268 g_bde_arc4_seq(sc, k1buf, sizeof k1buf); 269 g_bde_arc4_seq(sc, k2buf, sizeof k2buf); 270 g_bde_arc4_seq(sc, k3buf, sizeof k3buf); 271 272 MD5Init(&c); 273 MD5Update(&c, "0000", 4); /* XXX: for future versioning */ 274 MD5Update(&c, k1buf, 16); 275 MD5Final(k1buf, &c); 276 277 rijndael_makeKey(&ki, DIR_DECRYPT, 128, k3buf); 278 bzero(k3buf, sizeof k3buf); 279 rijndael_blockDecrypt(&ci, &ki, q, G_BDE_LOCKSIZE * 8, q); 280 281 for (i = 0; i < G_BDE_LOCKSIZE; i++) 282 q[i] ^= k2buf[i]; 283 bzero(k2buf, sizeof k2buf); 284 285 if (bcmp(q, k1buf, sizeof k1buf)) { 286 bzero(k1buf, sizeof k1buf); 287 bzero(buf, sectorsize * m); 288 g_free(buf); 289 off[0] = 0; 290 return (ESRCH); 291 } 292 bzero(k1buf, sizeof k1buf); 293 294 g_bde_decode_lock(gl, q); 295 bzero(buf, sectorsize * m); 296 g_free(buf); 297 298 off[1] = 0; 299 for (i = 0; i < (int)sizeof(gl->key); i++) 300 off[1] += gl->key[i]; 301 302 if (off[1] == 0) { 303 off[0] = 0; 304 return (ENOENT); 305 } 306 for (i = 0; i < G_BDE_MAXKEYS; i++) 307 if (nkey != NULL && off[0] == gl->lsector[i]) 308 *nkey = i; 309 310 return (0); 311} 312