Index: bioctl.c
===================================================================
RCS file: /cvs/src/sbin/bioctl/bioctl.c,v
retrieving revision 1.126
diff -u -p -r1.126 bioctl.c
--- bioctl.c    11 May 2015 12:14:22 -0000      1.126
+++ bioctl.c    24 May 2015 12:39:27 -0000
@@ -31,6 +31,7 @@
 #include <sys/ioctl.h>
 #include <sys/dkio.h>
 #include <sys/stat.h>
+#include <dev/softraid_luks.h>
 #include <dev/softraidvar.h>
 #include <dev/biovar.h>
 
@@ -60,6 +61,8 @@ int                   bio_parse_devlist(char *, dev_t *)
 void                   bio_kdf_derive(struct sr_crypto_kdfinfo *,
                            struct sr_crypto_kdf_pbkdf2 *, char *, int);
 void                   bio_kdf_generate(struct sr_crypto_kdfinfo *);
+void                   luks_kdf_derive(u_int8_t **, size_t *,
+                           struct luks_user_pbkdf2 *);
 void                   derive_key_pkcs(int, u_int8_t *, size_t, u_int8_t *,
                            size_t, char *, int);
 
@@ -765,6 +768,8 @@ bio_createraid(u_int16_t level, char *de
        struct sr_crypto_kdfinfo kdfinfo;
        struct sr_crypto_kdf_pbkdf2 kdfhint;
        struct stat             sb;
+       u_int8_t                *response = NULL;
+       size_t                  resplen;
        int                     rv, no_dev, fd;
        dev_t                   *dt;
        u_int16_t               min_disks = 0;
@@ -788,6 +793,7 @@ bio_createraid(u_int16_t level, char *de
        case 5:
                min_disks = 3;
                break;
+       case 'L':
        case 'C':
                min_disks = 1;
                break;
@@ -813,7 +819,36 @@ bio_createraid(u_int16_t level, char *de
        create.bc_flags = BIOC_SCDEVT | cflags;
        create.bc_key_disk = NODEV;
 
-       if (level == 'C' && key_disk == NULL) {
+       if (level == 'L') {
+
+               struct luks_user_pbkdf2  hint;
+
+               memset(&hint, 0, sizeof hint);
+
+               create.bc_flags |= BIOC_SCNOAUTOASSEMBLE;
+
+               create.bc_opaque = &hint;
+               create.bc_opaque_size = sizeof hint;
+               create.bc_opaque_flags = BIOC_SOOUT;
+
+               if (ioctl(devh, BIOCCREATERAID, &create))
+                       err(1, "ioctl");
+
+               bio_status(&create.bc_bio.bio_status);
+
+               if (create.bc_opaque_status == BIOC_SOINOUT_OK) {
+                       luks_kdf_derive(&response, &resplen, &hint);
+                       memset(&hint, 0, sizeof hint);
+               } else {
+                       errx(1, "creating LUKS not supported yet");
+               }
+               
+               create.bc_opaque = response;
+               create.bc_opaque_size = resplen;
+               create.bc_opaque_flags = BIOC_SOIN;
+
+       }
+       else if (level == 'C' && key_disk == NULL) {
 
                memset(&kdfinfo, 0, sizeof(kdfinfo));
                memset(&kdfhint, 0, sizeof(kdfhint));
@@ -870,6 +905,10 @@ bio_createraid(u_int16_t level, char *de
 
        rv = ioctl(devh, BIOCCREATERAID, &create);
        explicit_bzero(&kdfinfo, sizeof(kdfinfo));
+       if (response != NULL) {
+               explicit_bzero(response, resplen);
+               free(response);
+       }
        if (rv == -1)
                err(1, "BIOCCREATERAID");
 
@@ -921,6 +960,47 @@ bio_kdf_generate(struct sr_crypto_kdfinf
            kdfinfo->maskkey, sizeof(kdfinfo->maskkey),
            kdfinfo->pbkdf2.salt, sizeof(kdfinfo->pbkdf2.salt),
            "New passphrase: ", 1);
+}
+
+void
+luks_kdf_derive(u_int8_t **respp, size_t *resplenp, struct luks_user_pbkdf2 *h)
+{
+       char passphrase[1024];
+       u_int8_t *ret;
+       int i; 
+
+       if (readpassphrase("LUKS Passphrase: ", passphrase, sizeof(passphrase),
+           rpp_flag) == NULL)
+               errx(1, "unable to read passphrase");
+
+       /* This will be leaked, but this is a one-shot program anyway. */
+       ret = reallocarray(NULL, h->key_bytes, LUKS_NUM_KEYS);
+       if (ret == NULL) {
+               explicit_bzero(passphrase, sizeof(passphrase));
+               errx(1, "out of memory, need %u\n", h->key_bytes);
+       }
+
+       for (i = 0; i < LUKS_NUM_KEYS; ++i) {
+               u_int8_t *digest = ret + (i * h->key_bytes);
+
+               if ((h->have_keys & (1 << i)) == 0)
+                       continue;
+
+               /* derive key from passphrase */
+               if (pkcs5_pbkdf2(passphrase, strlen(passphrase),
+                   h->keys[i].salt, LUKS_SALT_LEN,
+                   digest, h->key_bytes, h->keys[i].iterations) != 0)
+                       goto fail;
+       }
+       explicit_bzero(passphrase, sizeof(passphrase));
+
+       *respp = ret;
+       *resplenp = h->key_bytes * LUKS_NUM_KEYS;
+       return;
+ fail:
+       explicit_bzero(passphrase, sizeof(passphrase));
+       explicit_bzero(ret, h->key_bytes * LUKS_NUM_KEYS);
+       errx(1, "pbkdf2 failed");
 }
 
 int

Reply via email to