]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - stand/libsa/geli/geliboot.c
loader: implement GELI writes
[FreeBSD/FreeBSD.git] / stand / libsa / geli / geliboot.c
1 /*-
2  * Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org>
3  * Copyright (c) 2005-2011 Pawel Jakub Dawidek <pawel@dawidek.net>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD$
28  */
29
30 #include <stand.h>
31 #include <stdarg.h>
32 #include "geliboot.h"
33 #include "geliboot_internal.h"
34
35 struct known_dev {
36         char                    name[GELIDEV_NAMELEN];
37         struct geli_dev         *gdev;
38         SLIST_ENTRY(known_dev)  entries;
39 };
40
41 SLIST_HEAD(known_dev_list, known_dev) known_devs_head = 
42     SLIST_HEAD_INITIALIZER(known_devs_head);
43
44 static geli_ukey saved_keys[GELI_MAX_KEYS];
45 static unsigned int nsaved_keys = 0;
46
47 /*
48  * Copy keys from local storage to the keybuf struct.
49  * Destroy the local storage when finished.
50  */
51 void
52 geli_export_key_buffer(struct keybuf *fkeybuf)
53 {
54         unsigned int i;
55
56         for (i = 0; i < nsaved_keys; i++) {
57                 fkeybuf->kb_ents[i].ke_type = KEYBUF_TYPE_GELI;
58                 memcpy(fkeybuf->kb_ents[i].ke_data, saved_keys[i],
59                     G_ELI_USERKEYLEN);
60         }
61         fkeybuf->kb_nents = nsaved_keys;
62         explicit_bzero(saved_keys, sizeof(saved_keys));
63 }
64
65 /*
66  * Copy keys from a keybuf struct into local storage.
67  * Zero out the keybuf.
68  */
69 void
70 geli_import_key_buffer(struct keybuf *skeybuf)
71 {
72         unsigned int i;
73
74         for (i = 0; i < skeybuf->kb_nents && i < GELI_MAX_KEYS; i++) {
75                 memcpy(saved_keys[i], skeybuf->kb_ents[i].ke_data,
76                     G_ELI_USERKEYLEN);
77                 explicit_bzero(skeybuf->kb_ents[i].ke_data,
78                     G_ELI_USERKEYLEN);
79                 skeybuf->kb_ents[i].ke_type = KEYBUF_TYPE_NONE;
80         }
81         nsaved_keys = skeybuf->kb_nents;
82         skeybuf->kb_nents = 0;
83 }
84
85 void
86 geli_add_key(geli_ukey key)
87 {
88
89         /*
90          * If we run out of key space, the worst that will happen is
91          * it will ask the user for the password again.
92          */
93         if (nsaved_keys < GELI_MAX_KEYS) {
94                 memcpy(saved_keys[nsaved_keys], key, G_ELI_USERKEYLEN);
95                 nsaved_keys++;
96         }
97 }
98
99 static int
100 geli_findkey(struct geli_dev *gdev, u_char *mkey)
101 {
102         u_int keynum;
103         int i;
104
105         if (gdev->keybuf_slot >= 0) {
106                 if (g_eli_mkey_decrypt_any(&gdev->md, saved_keys[gdev->keybuf_slot],
107                     mkey, &keynum) == 0) {
108                         return (0);
109                 }
110         }
111
112         for (i = 0; i < nsaved_keys; i++) {
113                 if (g_eli_mkey_decrypt_any(&gdev->md, saved_keys[i], mkey,
114                     &keynum) == 0) {
115                         gdev->keybuf_slot = i;
116                         return (0);
117                 }
118         }
119
120         return (1);
121 }
122
123 /*
124  * Read the last sector of a drive or partition and see if it is GELI encrypted.
125  */
126 struct geli_dev *
127 geli_taste(geli_readfunc readfunc, void *readpriv, daddr_t lastsector,
128     const char *namefmt, ...)
129 {
130         va_list args;
131         struct g_eli_metadata md;
132         struct known_dev *kdev;
133         struct geli_dev *gdev;
134         u_char *buf;
135         char devname[GELIDEV_NAMELEN];
136         int error;
137         off_t alignsector;
138
139         /*
140          * Format the name into a temp buffer and use that to search for an
141          * existing known_dev instance.  If not found, this has the side effect
142          * of initializing kdev to NULL.
143          */
144         va_start(args, namefmt);
145         vsnprintf(devname, sizeof(devname), namefmt, args);
146         va_end(args);
147         SLIST_FOREACH(kdev, &known_devs_head, entries) {
148                 if (strcmp(kdev->name, devname) == 0)
149                         return (kdev->gdev);
150         }
151
152         /* Determine whether the new device is geli-encrypted... */
153         if ((buf = malloc(DEV_GELIBOOT_BSIZE)) == NULL)
154                 goto out;
155         alignsector = rounddown2(lastsector * DEV_BSIZE, DEV_GELIBOOT_BSIZE);
156         if (alignsector + DEV_GELIBOOT_BSIZE > ((lastsector + 1) * DEV_BSIZE)) {
157                 /* Don't read past the end of the disk */
158                 alignsector = (lastsector * DEV_BSIZE) + DEV_BSIZE -
159                     DEV_GELIBOOT_BSIZE;
160         }
161         error = readfunc(NULL, readpriv, alignsector, buf, DEV_GELIBOOT_BSIZE);
162         if (error != 0) {
163                 goto out;
164         }
165
166         /*
167          * We have a new known_device.  Whether it's geli-encrypted or not,
168          * record its existance so we can avoid doing IO to probe it next time.
169          */
170         if ((kdev = malloc(sizeof(*kdev))) == NULL)
171                 goto out;
172         strlcpy(kdev->name, devname, sizeof(kdev->name));
173         kdev->gdev = NULL;
174         SLIST_INSERT_HEAD(&known_devs_head, kdev, entries);
175
176         /* Extract the last 4k sector of the disk. */
177         error = eli_metadata_decode(buf, &md);
178         if (error != 0) {
179                 /* Try the last 512 byte sector instead. */
180                 error = eli_metadata_decode(buf +
181                     (DEV_GELIBOOT_BSIZE - DEV_BSIZE), &md);
182                 if (error != 0) {
183                         goto out;
184                 }
185         }
186
187         if (!(md.md_flags & G_ELI_FLAG_GELIBOOT)) {
188                 /* The GELIBOOT feature is not activated */
189                 goto out;
190         }
191         if ((md.md_flags & G_ELI_FLAG_ONETIME)) {
192                 /* Swap device, skip it. */
193                 goto out;
194         }
195
196         /*
197          * It's geli-encrypted, create a geli_dev for it and link it into the
198          * known_dev instance.
199          */
200         gdev = malloc(sizeof(struct geli_dev));
201         if (gdev == NULL)
202                 goto out;
203         gdev->part_end = lastsector;
204         gdev->keybuf_slot = -1;
205         gdev->md = md;
206         gdev->name = kdev->name;
207         eli_metadata_softc(&gdev->sc, &md, DEV_BSIZE,
208             (lastsector + DEV_BSIZE) * DEV_BSIZE);
209         kdev->gdev = gdev;
210 out:
211         free(buf);
212         if (kdev == NULL)
213                 return (NULL);
214         return (kdev->gdev);
215 }
216
217 /*
218  * Attempt to decrypt the device.  This will try existing keys first, then will
219  * prompt for a passphrase if there are no existing keys that work.
220  */
221 static int
222 geli_probe(struct geli_dev *gdev, const char *passphrase, u_char *mkeyp)
223 {
224         u_char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN], *mkp;
225         u_int keynum;
226         struct hmac_ctx ctx;
227         int error;
228
229         if (mkeyp != NULL) {
230                 memcpy(&mkey, mkeyp, G_ELI_DATAIVKEYLEN);
231                 explicit_bzero(mkeyp, G_ELI_DATAIVKEYLEN);
232                 goto found_key;
233         }
234
235         if (geli_findkey(gdev, mkey) == 0) {
236                 goto found_key;
237         }
238
239         g_eli_crypto_hmac_init(&ctx, NULL, 0);
240         /*
241          * Prepare Derived-Key from the user passphrase.
242          */
243         if (gdev->md.md_iterations < 0) {
244                 /* XXX TODO: Support loading key files. */
245                 return (1);
246         } else if (gdev->md.md_iterations == 0) {
247                 g_eli_crypto_hmac_update(&ctx, gdev->md.md_salt,
248                     sizeof(gdev->md.md_salt));
249                 g_eli_crypto_hmac_update(&ctx, (const uint8_t *)passphrase,
250                     strlen(passphrase));
251         } else if (gdev->md.md_iterations > 0) {
252                 printf("Calculating GELI Decryption Key for %s %d"
253                     " iterations...\n", gdev->name, gdev->md.md_iterations);
254                 u_char dkey[G_ELI_USERKEYLEN];
255
256                 pkcs5v2_genkey(dkey, sizeof(dkey), gdev->md.md_salt,
257                     sizeof(gdev->md.md_salt), passphrase,
258                     gdev->md.md_iterations);
259                 g_eli_crypto_hmac_update(&ctx, dkey, sizeof(dkey));
260                 explicit_bzero(dkey, sizeof(dkey));
261         }
262
263         g_eli_crypto_hmac_final(&ctx, key, 0);
264
265         error = g_eli_mkey_decrypt_any(&gdev->md, key, mkey, &keynum);
266         if (error == -1) {
267                 explicit_bzero(mkey, sizeof(mkey));
268                 explicit_bzero(key, sizeof(key));
269                 printf("Bad GELI key: bad password?\n");
270                 return (error);
271         } else if (error != 0) {
272                 explicit_bzero(mkey, sizeof(mkey));
273                 explicit_bzero(key, sizeof(key));
274                 printf("Failed to decrypt GELI master key: %d\n", error);
275                 return (error);
276         } else {
277                 /* Add key to keychain */
278                 geli_add_key(key);
279                 explicit_bzero(&key, sizeof(key));
280         }
281
282 found_key:
283         /* Store the keys */
284         bcopy(mkey, gdev->sc.sc_mkey, sizeof(gdev->sc.sc_mkey));
285         bcopy(mkey, gdev->sc.sc_ivkey, sizeof(gdev->sc.sc_ivkey));
286         mkp = mkey + sizeof(gdev->sc.sc_ivkey);
287         if ((gdev->sc.sc_flags & G_ELI_FLAG_AUTH) == 0) {
288                 bcopy(mkp, gdev->sc.sc_ekey, G_ELI_DATAKEYLEN);
289         } else {
290                 /*
291                  * The encryption key is: ekey = HMAC_SHA512(Data-Key, 0x10)
292                  */
293                 g_eli_crypto_hmac(mkp, G_ELI_MAXKEYLEN, (const uint8_t *)"\x10", 1,
294                     gdev->sc.sc_ekey, 0);
295         }
296         explicit_bzero(mkey, sizeof(mkey));
297
298         /* Initialize the per-sector IV. */
299         switch (gdev->sc.sc_ealgo) {
300         case CRYPTO_AES_XTS:
301                 break;
302         default:
303                 SHA256_Init(&gdev->sc.sc_ivctx);
304                 SHA256_Update(&gdev->sc.sc_ivctx, gdev->sc.sc_ivkey,
305                     sizeof(gdev->sc.sc_ivkey));
306                 break;
307         }
308
309         return (0);
310 }
311
312 int
313 geli_io(struct geli_dev *gdev, geli_op_t enc, off_t offset, u_char *buf,
314     size_t bytes)
315 {
316         u_char iv[G_ELI_IVKEYLEN];
317         u_char *pbuf;
318         int error;
319         off_t dstoff;
320         uint64_t keyno;
321         size_t n, nsec, secsize;
322         struct g_eli_key gkey;
323
324         pbuf = buf;
325
326         secsize = gdev->sc.sc_sectorsize;
327         nsec = bytes / secsize;
328         if (nsec == 0) {
329                 /*
330                  * A read of less than the GELI sector size has been
331                  * requested. The caller provided destination buffer may
332                  * not be big enough to boost the read to a full sector,
333                  * so just attempt to decrypt the truncated sector.
334                  */
335                 secsize = bytes;
336                 nsec = 1;
337         }
338
339         for (n = 0, dstoff = offset; n < nsec; n++, dstoff += secsize) {
340
341                 g_eli_crypto_ivgen(&gdev->sc, dstoff, iv, G_ELI_IVKEYLEN);
342
343                 /* Get the key that corresponds to this offset. */
344                 keyno = (dstoff >> G_ELI_KEY_SHIFT) / secsize;
345                 g_eli_key_fill(&gdev->sc, &gkey, keyno);
346
347                 error = geliboot_crypt(gdev->sc.sc_ealgo, enc, pbuf, secsize,
348                     gkey.gek_key, gdev->sc.sc_ekeylen, iv);
349
350                 if (error != 0) {
351                         explicit_bzero(&gkey, sizeof(gkey));
352                         printf("%s: Failed to %s!", __func__,
353                             enc ? "encrypt" : "decrypt");
354                         return (error);
355                 }
356                 pbuf += secsize;
357         }
358         explicit_bzero(&gkey, sizeof(gkey));
359         return (0);
360 }
361
362 int
363 geli_havekey(struct geli_dev *gdev)
364 {
365         u_char mkey[G_ELI_DATAIVKEYLEN];
366         int err;
367
368         err = ENOENT;
369         if (geli_findkey(gdev, mkey) == 0) {
370                 if (geli_probe(gdev, NULL, mkey) == 0)
371                         err = 0;
372                 explicit_bzero(mkey, sizeof(mkey));
373         }
374         return (err);
375 }
376
377 int
378 geli_passphrase(struct geli_dev *gdev, char *pw)
379 {
380         int i;
381
382         /* TODO: Implement GELI keyfile(s) support */
383         for (i = 0; i < 3; i++) {
384                 /* Try cached passphrase */
385                 if (i == 0 && pw[0] != '\0') {
386                         if (geli_probe(gdev, pw, NULL) == 0) {
387                                 return (0);
388                         }
389                 }
390                 printf("GELI Passphrase for %s ", gdev->name);
391                 pwgets(pw, GELI_PW_MAXLEN,
392                     (gdev->md.md_flags & G_ELI_FLAG_GELIDISPLAYPASS) == 0);
393                 printf("\n");
394                 if (geli_probe(gdev, pw, NULL) == 0) {
395                         return (0);
396                 }
397         }
398
399         return (1);
400 }