dm - Add crypt target
[dragonfly.git] / sys / dev / disk / dm / dm_target_crypt.c
1 /*
2  * Copyright (c) 2010 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Alex Hornung <ahornung@gmail.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 /*
36  * This file implements initial version of device-mapper crypt target.
37  */
38 #include <sys/types.h>
39 #include <sys/param.h>
40
41 #include <sys/bio.h>
42 #include <sys/buf.h>
43 #include <sys/malloc.h>
44 #include <sys/vnode.h>
45 #include <crypto/sha1.h>
46 #include <crypto/sha2/sha2.h>
47 #include <opencrypto/cryptodev.h>
48
49 #include "dm.h"
50 MALLOC_DEFINE(M_DMCRYPT, "dm_crypt", "Device Mapper Target Crypt");
51
52 /*-
53  * HMAC-SHA-224/256/384/512 implementation
54  * Last update: 06/15/2005
55  * Issue date:  06/15/2005
56  *
57  * Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
58  * All rights reserved.
59  *
60  * Redistribution and use in source and binary forms, with or without
61  * modification, are permitted provided that the following conditions
62  * are met:
63  * 1. Redistributions of source code must retain the above copyright
64  *    notice, this list of conditions and the following disclaimer.
65  * 2. Redistributions in binary form must reproduce the above copyright
66  *    notice, this list of conditions and the following disclaimer in the
67  *    documentation and/or other materials provided with the distribution.
68  * 3. Neither the name of the project nor the names of its contributors
69  *    may be used to endorse or promote products derived from this software
70  *    without specific prior written permission.
71  *
72  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
73  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
74  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
75  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
76  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
77  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
78  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
79  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
80  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
81  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
82  * SUCH DAMAGE.
83  */
84
85 typedef struct {
86     SHA512_CTX ctx_inside;
87     SHA512_CTX ctx_outside;
88
89     /* for hmac_reinit */
90     SHA512_CTX ctx_inside_reinit;
91     SHA512_CTX ctx_outside_reinit;
92
93     unsigned char block_ipad[SHA512_BLOCK_LENGTH];
94     unsigned char block_opad[SHA512_BLOCK_LENGTH];
95 } hmac_sha512_ctx;
96
97 /* HMAC-SHA-512 functions */
98 static void
99 hmac_sha512_init(hmac_sha512_ctx *ctx, unsigned char *key,
100                       unsigned int key_size)
101 {
102     unsigned int fill;
103     unsigned int num;
104
105     unsigned char *key_used;
106     unsigned char key_temp[SHA512_DIGEST_LENGTH];
107     int i;
108
109     if (key_size == SHA512_BLOCK_LENGTH) {
110         key_used = key;
111         num = SHA512_BLOCK_LENGTH;
112     } else {
113         if (key_size > SHA512_BLOCK_LENGTH){
114             key_used = key_temp;
115             num = SHA512_DIGEST_LENGTH;
116             SHA512_Data(key, key_size, key_used);
117         } else { /* key_size > SHA512_BLOCK_LENGTH */
118             key_used = key;
119             num = key_size;
120         }
121         fill = SHA512_BLOCK_LENGTH - num;
122
123         memset(ctx->block_ipad + num, 0x36, fill);
124         memset(ctx->block_opad + num, 0x5c, fill);
125     }
126
127     for (i = 0; i < num; i++) {
128         ctx->block_ipad[i] = key_used[i] ^ 0x36;
129         ctx->block_opad[i] = key_used[i] ^ 0x5c;
130     }
131
132     SHA512_Init(&ctx->ctx_inside);
133     SHA512_Update(&ctx->ctx_inside, ctx->block_ipad, SHA512_BLOCK_LENGTH);
134
135     SHA512_Init(&ctx->ctx_outside);
136     SHA512_Update(&ctx->ctx_outside, ctx->block_opad,
137                   SHA512_BLOCK_LENGTH);
138
139     /* for hmac_reinit */
140     memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside,
141            sizeof(SHA512_CTX));
142     memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside,
143            sizeof(SHA512_CTX));
144 }
145
146 #if 0
147 static void
148 hmac_sha512_reinit(hmac_sha512_ctx *ctx)
149 {
150     memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit,
151            sizeof(SHA512_CTX));
152     memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit,
153            sizeof(SHA512_CTX));
154 }
155 #endif
156
157 static void
158 hmac_sha512_update(hmac_sha512_ctx *ctx, unsigned char *message,
159                         unsigned int message_len)
160 {
161     SHA512_Update(&ctx->ctx_inside, message, message_len);
162 }
163
164 static void
165 hmac_sha512_final(hmac_sha512_ctx *ctx, unsigned char *mac,
166                        unsigned int mac_size)
167 {
168     unsigned char digest_inside[SHA512_DIGEST_LENGTH];
169     unsigned char mac_temp[SHA512_DIGEST_LENGTH];
170
171     SHA512_Final(digest_inside, &ctx->ctx_inside);
172     SHA512_Update(&ctx->ctx_outside, digest_inside, SHA512_DIGEST_LENGTH);
173     SHA512_Final(mac_temp, &ctx->ctx_outside);
174     memcpy(mac, mac_temp, mac_size);
175 }
176
177 static void
178 hmac_sha512(unsigned char *key, unsigned int key_size,
179           unsigned char *message, unsigned int message_len,
180           unsigned char *mac, unsigned mac_size)
181 {
182     hmac_sha512_ctx ctx;
183
184     hmac_sha512_init(&ctx, key, key_size);
185     hmac_sha512_update(&ctx, message, message_len);
186     hmac_sha512_final(&ctx, mac, mac_size);
187 }
188
189 /*-
190  * pkcs5_pbkdf2 function
191  * Copyright (c) 2008 Damien Bergamini <damien.bergamini@free.fr>
192  *
193  * Permission to use, copy, modify, and distribute this software for any
194  * purpose with or without fee is hereby granted, provided that the above
195  * copyright notice and this permission notice appear in all copies.
196  *
197  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
198  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
199  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
200  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
201  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
202  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
203  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
204  */
205
206 /*
207  * Password-Based Key Derivation Function 2 (PKCS #5 v2.0).
208  * Code based on IEEE Std 802.11-2007, Annex H.4.2.
209  */
210 static int
211 pkcs5_pbkdf2(const char *pass, size_t pass_len, const char *salt, size_t salt_len,
212     u_int8_t *key, size_t key_len, u_int rounds)
213 {
214         u_int8_t *asalt, obuf[SHA512_DIGEST_LENGTH];
215         u_int8_t d1[SHA512_DIGEST_LENGTH], d2[SHA512_DIGEST_LENGTH];
216         u_int i, j;
217         u_int count;
218         size_t r;
219
220         if (rounds < 1 || key_len == 0)
221                 return -1;
222         if (salt_len == 0 || salt_len > SIZE_MAX - 1)
223                 return -1;
224         if ((asalt = kmalloc(salt_len + 4, M_TEMP, M_WAITOK)) == NULL)
225                 return -1; /* XXX: this is not possible */
226
227         memcpy(asalt, salt, salt_len);
228
229         for (count = 1; key_len > 0; count++) {
230                 asalt[salt_len + 0] = (count >> 24) & 0xff;
231                 asalt[salt_len + 1] = (count >> 16) & 0xff;
232                 asalt[salt_len + 2] = (count >> 8) & 0xff;
233                 asalt[salt_len + 3] = count & 0xff;
234                 hmac_sha512(__DECONST(char *, pass), pass_len, asalt, salt_len + 4, d1, sizeof(d1));
235                 memcpy(obuf, d1, sizeof(obuf));
236
237                 for (i = 1; i < rounds; i++) {
238                         hmac_sha512(__DECONST(char *, pass), pass_len, d1, sizeof(d1), d2, sizeof(d2));
239                         memcpy(d1, d2, sizeof(d1));
240                         for (j = 0; j < sizeof(obuf); j++)
241                                 obuf[j] ^= d1[j];
242                 }
243
244                 r = MIN(key_len, SHA512_DIGEST_LENGTH);
245                 memcpy(key, obuf, r);
246                 key += r;
247                 key_len -= r;
248         };
249         bzero(asalt, salt_len + 4);
250         kfree(asalt, M_TEMP);
251         bzero(d1, sizeof(d1));
252         bzero(d2, sizeof(d2));
253         bzero(obuf, sizeof(obuf));
254
255         return 0;
256 }
257
258
259 /* ---------------------------------------------------------------------- */
260
261 struct target_crypt_config;
262 typedef void ivgen_t(struct target_crypt_config *, u_int8_t *, size_t, off_t);
263
264 typedef struct target_crypt_config {
265         size_t  params_len;
266         dm_pdev_t *pdev;
267         int     crypto_alg;
268         int     crypto_klen;
269         u_int8_t        crypto_key[512>>3];
270         u_int8_t        crypto_keyhash[SHA512_DIGEST_LENGTH];
271         u_int64_t       crypto_sid;
272         SHA512_CTX      essivsha512_ctx;
273         struct cryptoini        crypto_session;
274         ivgen_t *crypto_ivgen;
275         /* XXX: uuid */
276 } dm_target_crypt_config_t;
277
278 static void dm_target_crypt_work(dm_target_crypt_config_t *priv, struct bio *bio);
279 static void dm_target_crypt_read_done(struct bio *bio);
280 static void dm_target_crypt_write_done(struct bio *bio);
281 static int dm_target_crypt_crypto_done_read(struct cryptop *crp);
282 static int dm_target_crypt_crypto_done_write(struct cryptop *crp);
283
284
285 static void
286 essiv_hash_mkey(dm_target_crypt_config_t *priv)
287 {
288         SHA1_CTX        ctxsha1;
289         SHA256_CTX      ctx256;
290         SHA384_CTX      ctx384;
291         SHA512_CTX      ctx512;
292
293         if (priv->crypto_klen <= 128) {
294                 SHA1Init(&ctxsha1);
295                 SHA1Update(&ctxsha1, priv->crypto_key, priv->crypto_klen>>3);
296                 SHA1Final(priv->crypto_keyhash, &ctxsha1);
297         } else if (priv->crypto_klen <= 256) {
298                 SHA256_Init(&ctx256);
299                 SHA256_Update(&ctx256, priv->crypto_key, priv->crypto_klen>>3);
300                 SHA256_Final(priv->crypto_keyhash, &ctx256);
301         } else if (priv->crypto_klen <= 384) {
302                 SHA384_Init(&ctx384);
303                 SHA384_Update(&ctx384, priv->crypto_key, priv->crypto_klen>>3);
304                 SHA384_Final(priv->crypto_keyhash, &ctx384);
305         } else if (priv->crypto_klen <= 512) {
306                 SHA512_Init(&ctx512);
307                 SHA512_Update(&ctx512, priv->crypto_key, priv->crypto_klen>>3);
308                 SHA512_Final(priv->crypto_keyhash, &ctx512);
309         } else {
310                 panic("Unexpected crypto_klen = %d", priv->crypto_klen);
311         }
312 }
313
314 static int
315 essiv_ivgen_done(struct cryptop *crp)
316 {
317
318         if (crp->crp_etype == EAGAIN)
319                 return crypto_dispatch(crp);
320
321         if (crp->crp_etype != 0) {
322                 kprintf("essiv_ivgen_done, crp->crp_etype = %d\n", crp->crp_etype);
323         }
324
325         atomic_add_int((int *)crp->crp_opaque, 1);
326         wakeup(crp->crp_opaque);
327         return 0;
328 }
329
330 static void
331 essiv_ivgen(dm_target_crypt_config_t *priv, u_int8_t *iv, size_t iv_len, off_t sector)
332 {
333         struct cryptodesc crd;
334         struct cryptop crp;
335         int error, id;
336
337         id = 0;
338         bzero(iv, iv_len);
339         *((off_t *)iv) = sector;
340         crp.crp_buf = (caddr_t)iv;
341
342         crp.crp_sid = priv->crypto_sid;
343         crp.crp_ilen = crp.crp_olen = iv_len;
344
345         crp.crp_opaque = (void *)&id;
346
347         crp.crp_callback = essiv_ivgen_done;
348
349         crp.crp_desc = &crd;
350         crp.crp_etype = 0;
351         crp.crp_flags = CRYPTO_F_CBIFSYNC | CRYPTO_F_REL;
352
353         crd.crd_alg = priv->crypto_alg;
354         crd.crd_key = (caddr_t)priv->crypto_keyhash;
355         crd.crd_klen = priv->crypto_klen;
356
357         bzero(crd.crd_iv, sizeof(crd.crd_iv));
358
359         crd.crd_skip = 0;
360         crd.crd_len = iv_len;
361         crd.crd_flags = CRD_F_KEY_EXPLICIT | CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
362         crd.crd_flags |= CRD_F_ENCRYPT;
363         crd.crd_next = NULL;
364
365         error = crypto_dispatch(&crp);
366         if (error)
367                 kprintf("essiv_ivgen, error = %d\n", error);
368
369         /*
370          * id is modified in the callback, so that if crypto_dispatch finishes
371          * synchronously we don't tsleep() forever.
372          */
373         if (id == 0)
374                 tsleep((void *)&error, 0, "essivgen", 0);
375 }
376
377
378 static void
379 alt_ivgen(dm_target_crypt_config_t *priv, u_int8_t *iv, size_t iv_len, off_t sector)
380 {
381
382         SHA512_CTX      ctx512;
383         u_int8_t        md[SHA512_DIGEST_LENGTH]; /* Max. Digest Size */
384
385         memcpy(&ctx512, &priv->essivsha512_ctx, sizeof(SHA512_CTX));
386         SHA512_Update(&ctx512, (u_int8_t*)&sector, sizeof(off_t));
387         SHA512_Final(md, &ctx512);
388
389         memcpy(iv, md, iv_len);
390 }
391
392 struct dmtc_helper {
393         caddr_t free_addr;
394         caddr_t orig_buf;
395 };
396
397 static void
398 dm_target_crypt_work(dm_target_crypt_config_t *priv, struct bio *bio)
399 {
400         struct dmtc_helper *dmtc;
401         struct cryptodesc *crd;
402         struct cryptop *crp;
403         struct cryptoini *cri;
404
405         int error, i, bytes, isector, sectors, write, sz;
406         u_char *ptr, *space, *data;
407
408         cri = &priv->crypto_session;
409
410         write = (bio->bio_buf->b_cmd == BUF_CMD_WRITE) ? 1 : 0;
411         bytes = bio->bio_buf->b_bcount; /* XXX: b_resid no good after reads... == 0 */
412         isector = bio->bio_offset/DEV_BSIZE;    /* Initial sector */
413         sectors = bytes/DEV_BSIZE;              /* Number of sectors affected by bio */
414         sz = sectors * (sizeof(*crp) + sizeof(*crd));
415
416         if (write) {
417                 space = kmalloc(sizeof(struct dmtc_helper) + sz + bytes, M_DMCRYPT, M_WAITOK);
418                 dmtc = (struct dmtc_helper *)space;
419                 dmtc->free_addr = space;
420                 dmtc->orig_buf = bio->bio_buf->b_data;
421                 space += sizeof(struct dmtc_helper);
422                 memcpy(space + sz, bio->bio_buf->b_data, bytes);
423                 bio->bio_caller_info2.ptr = dmtc;
424                 bio->bio_buf->b_data = data = space + sz;
425         } else {
426                 space = kmalloc(sz, M_DMCRYPT, M_WAITOK);
427                 data = bio->bio_buf->b_data;
428                 bio->bio_caller_info2.ptr = space;
429         }
430
431         ptr = space;
432         bio->bio_caller_info3.value = sectors;
433         kprintf("Write? %d, bytes = %d (b_bcount), sectors = %d (bio = %p, b_cmd = %d)\n", write, bytes, sectors, bio, bio->bio_buf->b_cmd);
434
435         for (i = 0; i < sectors; i++) {
436                 crp = (struct cryptop *)ptr;
437                 ptr += sizeof(*crp);
438                 crd = (struct cryptodesc *)ptr;
439                 ptr += sizeof (*crd);
440
441                 crp->crp_buf = (data + i*DEV_BSIZE);
442
443                 crp->crp_sid = priv->crypto_sid;
444                 crp->crp_ilen = crp->crp_olen = DEV_BSIZE;
445
446                 crp->crp_opaque = (void *)bio;
447
448                 if (write)
449                         crp->crp_callback = dm_target_crypt_crypto_done_write;
450                 else
451                         crp->crp_callback = dm_target_crypt_crypto_done_read;
452                 crp->crp_desc = crd;
453                 crp->crp_etype = 0;
454                 crp->crp_flags = CRYPTO_F_CBIFSYNC | CRYPTO_F_REL;
455
456                 crd->crd_alg = priv->crypto_alg;
457                 crd->crd_key = (caddr_t)priv->crypto_key;
458                 crd->crd_klen = priv->crypto_klen;
459 #if 0
460                 bzero(crd->crd_iv, EALG_MAX_BLOCK_LEN);
461                 alt_ivgen(priv, crd->crd_iv, sizeof(crd->crd_iv), isector + i);
462                 essiv_ivgen(priv, crd->crd_iv, sizeof(crd->crd_iv), isector + i);
463 #endif
464                 priv->crypto_ivgen(priv, crd->crd_iv, sizeof(crd->crd_iv), isector + i);
465
466                 crd->crd_skip = 0;
467                 crd->crd_len = DEV_BSIZE /* XXX */;
468                 crd->crd_flags = CRD_F_KEY_EXPLICIT | CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
469                 crd->crd_next = NULL;
470
471                 if (write)
472                         crd->crd_flags |= CRD_F_ENCRYPT;
473                 else
474                         crd->crd_flags &= ~CRD_F_ENCRYPT;
475
476                 error = crypto_dispatch(crp);
477         }
478 }
479
480 static void
481 dm_target_crypt_read_done(struct bio *bio)
482 {
483         dm_target_crypt_config_t *priv;
484
485         priv = bio->bio_caller_info1.ptr;
486         kprintf("dm_target_crypt_read_done %p\n", bio);
487
488         dm_target_crypt_work(priv, bio);
489 }
490
491 static void
492 dm_target_crypt_write_done(struct bio *bio)
493 {
494         struct dmtc_helper *dmtc;
495         struct bio *obio;
496
497         kprintf("dm_target_crypt_write_done %p\n", bio);
498         dmtc = bio->bio_caller_info2.ptr;
499         bio->bio_buf->b_data = dmtc->orig_buf;
500         kfree(dmtc->free_addr, M_DMCRYPT);
501         obio = pop_bio(bio);
502         biodone(obio);
503 }
504
505 static int
506 dm_target_crypt_crypto_done_read(struct cryptop *crp)
507 {
508         struct bio *bio, *obio;
509         int n;
510
511         if (crp->crp_etype == EAGAIN)
512                 return crypto_dispatch(crp);
513
514         bio = (struct bio *)crp->crp_opaque;
515         KKASSERT(bio != NULL);
516         
517         n = atomic_fetchadd_int(&bio->bio_caller_info3.value, -1);
518 #if 0
519         kprintf("dm_target_crypt_crypto_done_read %p, n = %d\n", bio, n);
520 #endif
521         if (crp->crp_etype != 0) {
522                 kprintf("dm_target_crypt_crypto_done_read crp_etype = %d\n", crp->crp_etype);
523                 /* XXX: Print something out */
524                 bio->bio_buf->b_error = crp->crp_etype; 
525         }
526         if (n == 1) {
527                 kprintf("dm_target_crypt_crypt_done_read: n == 1\n");
528                 kfree(bio->bio_caller_info2.ptr, M_DMCRYPT);
529                 /* This is the last chunk of the read */
530                 obio = pop_bio(bio);
531                 biodone(obio);
532         }
533
534         return 0;
535 }
536
537 static int
538 dm_target_crypt_crypto_done_write(struct cryptop *crp)
539 {
540         struct dmtc_helper *dmtc;
541         dm_target_crypt_config_t *priv;
542         struct bio *bio, *obio;
543         int n;
544
545         if (crp->crp_etype == EAGAIN)
546                 return crypto_dispatch(crp);
547
548         bio = (struct bio *)crp->crp_opaque;
549         KKASSERT(bio != NULL);
550         
551         n = atomic_fetchadd_int(&bio->bio_caller_info3.value, -1);
552 #if 0
553         kprintf("dm_target_crypt_crypto_done_write %p, n = %d\n", bio, n);
554 #endif
555         if (crp->crp_etype != 0) {
556                 kprintf("dm_target_crypt_crypto_done_write crp_etype = %d\n", crp->crp_etype);
557                 /* XXX: Print something out */
558                 bio->bio_buf->b_error = crp->crp_etype; 
559         }
560         if (n == 1) {
561                 kprintf("dm_target_crypt_crypt_done_write: n == 1\n");
562                 /* This is the last chunk of the write */
563                 if (bio->bio_buf->b_error != 0) {
564                         /* XXX */
565                         dmtc = bio->bio_caller_info2.ptr;
566                         bio->bio_buf->b_data = dmtc->orig_buf;
567                         kfree(dmtc->free_addr, M_DMCRYPT);
568                         obio = pop_bio(bio);
569                         biodone(obio);
570                 } else {
571                         priv = (dm_target_crypt_config_t *)bio->bio_caller_info1.ptr;
572                         vn_strategy(priv->pdev->pdev_vnode, bio);
573                 }
574         }
575
576         return 0;
577 }
578
579 /*
580 strategy -> read_done -> crypto_work -> crypto_done_read -> FINISH READ
581 strategy -> crypto_work -> crypto_done_write -> write dispatch -> write_done -> FINISH WRITE
582 */
583
584 #ifdef DM_TARGET_MODULE
585 /*
586  * Every target can be compiled directly to dm driver or as a
587  * separate module this part of target is used for loading targets
588  * to dm driver.
589  * Target can be unloaded from kernel only if there are no users of
590  * it e.g. there are no devices which uses that target.
591  */
592 #include <sys/kernel.h>
593 #include <sys/module.h>
594
595 static int
596 dm_target_crypt_modcmd(modcmd_t cmd, void *arg)
597 {
598         dm_target_t *dmt;
599         int r;
600         dmt = NULL;
601
602         switch (cmd) {
603         case MODULE_CMD_INIT:
604                 if ((dmt = dm_target_lookup("crypt")) != NULL) {
605                         dm_target_unbusy(dmt);
606                         return EEXIST;
607                 }
608                 dmt = dm_target_alloc("crypt");
609
610                 dmt->version[0] = 1;
611                 dmt->version[1] = 0;
612                 dmt->version[2] = 0;
613                 strlcpy(dmt->name, "crypt", DM_MAX_TYPE_NAME);
614                 dmt->init = &dm_target_crypt_init;
615                 dmt->status = &dm_target_crypt_status;
616                 dmt->strategy = &dm_target_crypt_strategy;
617                 dmt->deps = &dm_target_crypt_deps;
618                 dmt->destroy = &dm_target_crypt_destroy;
619                 dmt->upcall = &dm_target_crypt_upcall;
620
621                 r = dm_target_insert(dmt);
622
623                 break;
624
625         case MODULE_CMD_FINI:
626                 r = dm_target_rem("crypt");
627                 break;
628
629         case MODULE_CMD_STAT:
630                 return ENOTTY;
631
632         default:
633                 return ENOTTY;
634         }
635
636         return r;
637 }
638 #endif
639
640 /*
641  * Init function called from dm_table_load_ioctl.
642  * Accepted format:
643  * <device>     <crypto algorithm>[-<keysize>]  <iv generator>  <passphrase>
644  * /dev/foo     aes-256                         essiv           foobar
645  */
646 int
647 dm_target_crypt_init(dm_dev_t * dmv, void **target_config, char *params)
648 {
649         dm_target_crypt_config_t *priv;
650         size_t len;
651         char **ap, *args[5];
652         int argc, klen, error;
653
654         if (params == NULL)
655                 return EINVAL;
656
657         len = strlen(params) + 1;
658         argc = 0;
659
660         /*
661          * Parse a string, containing tokens delimited by white space,
662          * into an argument vector
663          */
664         for (ap = args; ap < &args[4] &&
665             (*ap = strsep(&params, " \t")) != NULL;) {
666                 if (**ap != '\0') {
667                         argc++;
668                         ap++;
669                 }
670         }
671
672         kprintf("\nCrypto target init function called, argc = %d!!\n", argc);
673         if (argc < 4) {
674                 kprintf("not enough arguments for target crypt\n");
675                 return ENOMEM; /* XXX */
676         }
677
678         kprintf("Crypto target - device name %s -- algorithm %s\n\n", args[0], args[1]);
679
680         if ((priv = kmalloc(sizeof(dm_target_crypt_config_t), M_DMCRYPT, M_NOWAIT))
681             == NULL) {
682                 kprintf("kmalloc in dm_target_crypt_init failed, M_NOWAIT to blame\n");
683                 return ENOMEM;
684         }
685
686         /* Insert dmp to global pdev list */
687         if ((priv->pdev = dm_pdev_insert(args[0])) == NULL) {
688                 kprintf("dm_pdev_insert failed\n");
689                 return ENOENT;
690         }
691
692         if (!strncmp(args[1], "aes-", 4)) {
693                 priv->crypto_alg = CRYPTO_AES_CBC;
694                 klen = atoi(args[1]+4);
695                 if (klen != 128 && klen != 192 && klen != 256)
696                         goto notsup;
697                 priv->crypto_klen = klen;
698
699         } else if (!strncmp(args[1], "blowfish-", 9)) {
700                 priv->crypto_alg = CRYPTO_BLF_CBC;
701                 klen = atoi(args[1]+9);
702                 if (klen < 128 || klen > 448 || (klen % 8) != 0)
703                         goto notsup;
704                 priv->crypto_klen = klen;
705
706         } else if (!strcmp(args[1], "3DES")) {
707                 priv->crypto_alg = CRYPTO_3DES_CBC;
708                 priv->crypto_klen = 168;
709
710         } else if (!strncmp(args[1], "camellia-", 9)) {
711                 priv->crypto_alg = CRYPTO_CAMELLIA_CBC;
712                 klen = atoi(args[1]+9);
713                 if (klen != 128 && klen != 192 && klen != 256)
714                         goto notsup;
715                 priv->crypto_klen = klen;
716
717         } else if (!strcmp(args[1], "skipjack")) {
718                 priv->crypto_alg = CRYPTO_SKIPJACK_CBC;
719                 priv->crypto_klen = 80;
720
721         } else if (!strcmp(args[1], "CAST-128")) {
722                 priv->crypto_alg = CRYPTO_CAST_CBC;
723                 priv->crypto_klen = 128;
724
725         } else if (!strcmp(args[1], "null")) {
726                 priv->crypto_alg = CRYPTO_NULL_CBC;
727                 priv->crypto_klen = 128;
728         }
729
730         /* Save length of param string */
731         priv->params_len = len;
732
733         *target_config = priv;
734
735         dmv->dev_type = DM_CRYPTO_DEV;
736
737         priv->crypto_session.cri_alg = priv->crypto_alg;
738         priv->crypto_session.cri_klen = priv->crypto_klen;
739         priv->crypto_session.cri_mlen = 0;
740         error = pkcs5_pbkdf2(args[3], strlen(args[3]),
741                              "This is the salt", 16, /* XXX !!!!!!!!!!!!! */
742                              (u_int8_t *)priv->crypto_key, priv->crypto_klen >> 3,
743                              1000);
744         if (error)
745                 panic("dm_target_crypt: pkcs5_pbkdf2 returned error!");
746
747         kprintf("priv->crypto_klen >> 3 = %d\n", priv->crypto_klen >> 3);
748
749
750         if (!strcmp(args[2], "essiv")) {
751                 essiv_hash_mkey(priv);
752                 priv->crypto_ivgen = essiv_ivgen;
753         } else {
754                 SHA512_Init(&priv->essivsha512_ctx);
755                 SHA512_Update(&priv->essivsha512_ctx, (u_int8_t*)priv->crypto_key, priv->crypto_klen >> 3);
756                 priv->crypto_ivgen = alt_ivgen;
757         }
758
759         priv->crypto_session.cri_key = (u_int8_t *)priv->crypto_key;
760         priv->crypto_session.cri_next = NULL;
761
762         error = crypto_newsession(&priv->crypto_sid,
763                                   &priv->crypto_session,
764                                   CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE);
765         if (error) {
766                 kprintf("Error during crypto_newsession, error = %d\n", error);
767                 return error;
768         }
769
770         /* XXX: eventually support some on-disk metadata */
771         return 0;
772
773 notsup:
774         kprintf("returning ENOTSUP from crypt_init thingie... notsup label\n");
775         return ENOTSUP;
776 }
777
778 /* Status routine called to get params string. */
779 char *
780 dm_target_crypt_status(void *target_config)
781 {
782         dm_target_crypt_config_t *priv;
783         char *params;
784
785         priv = target_config;
786
787         if ((params = kmalloc(DM_MAX_PARAMS_SIZE, M_DMCRYPT, M_WAITOK)) == NULL)
788                 return NULL;
789
790         ksnprintf(params, DM_MAX_PARAMS_SIZE, "%s",
791             priv->pdev->name);
792
793         return params;
794 }
795
796 /* Strategy routine called from dm_strategy. */
797 /*
798  * Do IO operation, called from dmstrategy routine.
799  */
800 int
801 dm_target_crypt_strategy(dm_table_entry_t * table_en, struct buf * bp)
802 {
803         struct bio *bio;
804
805         dm_target_crypt_config_t *priv;
806         priv = table_en->target_config;
807
808         /* Get rid of stuff we can't really handle */
809         if ((bp->b_cmd == BUF_CMD_READ) || (bp->b_cmd == BUF_CMD_WRITE)) {
810                 if (((bp->b_bcount % DEV_BSIZE) != 0) || (bp->b_bcount == 0)) {
811                         kprintf("dm_target_crypt_strategy: can't really handle bp->b_bcount = %d\n", bp->b_bcount);
812                         bp->b_error = EINVAL;
813                         bp->b_flags |= B_ERROR | B_INVAL;
814                         biodone(&bp->b_bio1);
815                         return 0;
816                 }
817         }
818
819         switch (bp->b_cmd) {
820         case BUF_CMD_READ:
821                 bio = push_bio(&bp->b_bio1);
822                 bio->bio_offset = bp->b_bio1.bio_offset;
823                 bio->bio_caller_info1.ptr = priv;
824                 bio->bio_done = dm_target_crypt_read_done;
825                 vn_strategy(priv->pdev->pdev_vnode, bio);
826                 break;
827
828         case BUF_CMD_WRITE:
829                 bio = push_bio(&bp->b_bio1);
830                 bio->bio_offset = bp->b_bio1.bio_offset;
831                 bio->bio_caller_info1.ptr = priv;
832                 bio->bio_done = dm_target_crypt_write_done;
833                 dm_target_crypt_work(priv, bio);
834                 break;
835
836         default:
837                 vn_strategy(priv->pdev->pdev_vnode, &bp->b_bio1);               
838         }
839
840         return 0;
841
842 }
843
844 int
845 dm_target_crypt_destroy(dm_table_entry_t * table_en)
846 {
847         dm_target_crypt_config_t *priv;
848
849         priv = table_en->target_config;
850
851         if (priv == NULL)
852                 return 0;
853
854         dm_pdev_decr(priv->pdev);
855
856         /* Unbusy target so we can unload it */
857         dm_target_unbusy(table_en->target);
858
859         kfree(priv, M_DMCRYPT);
860
861         table_en->target_config = NULL;
862
863         return 0;
864 }
865
866 int
867 dm_target_crypt_deps(dm_table_entry_t * table_en, prop_array_t prop_array)
868 {
869         dm_target_crypt_config_t *priv;
870         struct vattr va;
871
872         int error;
873
874         if (table_en->target_config == NULL)
875                 return ENOENT;
876
877         priv = table_en->target_config;
878
879         if ((error = VOP_GETATTR(priv->pdev->pdev_vnode, &va)) != 0)
880                 return error;
881
882         prop_array_add_uint64(prop_array, (uint64_t) makeudev(va.va_rmajor, va.va_rminor));
883
884         return 0;
885 }
886
887 /* Unsupported for this target. */
888 int
889 dm_target_crypt_upcall(dm_table_entry_t * table_en, struct buf * bp)
890 {
891         return 0;
892 }