kernel - dm - rewrite dm_target_stripe.c to add functionality and fix bugs
[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 #include <sys/endian.h>
41
42 #include <sys/bio.h>
43 #include <sys/buf.h>
44 #include <sys/malloc.h>
45 #include <sys/md5.h>
46 #include <sys/vnode.h>
47 #include <crypto/sha1.h>
48 #include <crypto/sha2/sha2.h>
49 #include <opencrypto/cryptodev.h>
50 #include <opencrypto/rmd160.h>
51
52 #include "dm.h"
53 MALLOC_DEFINE(M_DMCRYPT, "dm_crypt", "Device Mapper Target Crypt");
54
55 struct target_crypt_config;
56 typedef void ivgen_t(struct target_crypt_config *, u_int8_t *, size_t, off_t);
57
58 typedef struct target_crypt_config {
59         size_t  params_len;
60         dm_pdev_t *pdev;
61         char    *status_str;
62         int     crypto_alg;
63         int     crypto_klen;
64         u_int8_t        crypto_key[512>>3];
65         u_int8_t        crypto_keyhash[SHA512_DIGEST_LENGTH];
66         u_int64_t       crypto_sid;
67         u_int64_t       block_offset;
68         u_int64_t       iv_offset;
69         SHA512_CTX      essivsha512_ctx;
70         struct cryptoini        crypto_session;
71         ivgen_t *crypto_ivgen;
72 } dm_target_crypt_config_t;
73
74 struct dmtc_helper {
75         caddr_t free_addr;
76         caddr_t orig_buf;
77 };
78
79 static void dmtc_crypto_start(dm_target_crypt_config_t *priv, struct bio *bio);
80 static void dmtc_bio_read_done(struct bio *bio);
81 static void dmtc_bio_write_done(struct bio *bio);
82 static int dmtc_crypto_cb_read_done(struct cryptop *crp);
83 static int dmtc_crypto_cb_write_done(struct cryptop *crp);
84
85
86
87 static int
88 essiv_hash_mkey(dm_target_crypt_config_t *priv, char *iv_hash)
89 {
90         unsigned int klen;
91
92         klen = (priv->crypto_klen >> 3);
93
94         if (iv_hash == NULL)
95                 return EINVAL;
96
97         if (!strcmp(iv_hash, "sha1")) {
98                 SHA1_CTX ctx;
99
100                 if (klen != SHA1_RESULTLEN)
101                         return EINVAL;
102
103                 SHA1Init(&ctx);
104                 SHA1Update(&ctx, priv->crypto_key, priv->crypto_klen>>3);
105                 SHA1Final(priv->crypto_keyhash, &ctx);
106         } else if (!strcmp(iv_hash, "sha256")) {
107                 SHA256_CTX ctx;
108
109                 if (klen != SHA256_DIGEST_LENGTH)
110                         return EINVAL;
111
112                 SHA256_Init(&ctx);
113                 SHA256_Update(&ctx, priv->crypto_key, priv->crypto_klen>>3);
114                 SHA256_Final(priv->crypto_keyhash, &ctx);
115         } else if (!strcmp(iv_hash, "sha384")) {
116                 SHA384_CTX ctx;
117
118                 if (klen != SHA384_DIGEST_LENGTH)
119                         return EINVAL;
120
121                 SHA384_Init(&ctx);
122                 SHA384_Update(&ctx, priv->crypto_key, priv->crypto_klen>>3);
123                 SHA384_Final(priv->crypto_keyhash, &ctx);
124         } else if (!strcmp(iv_hash, "sha512")) {
125                 SHA512_CTX ctx;
126
127                 if (klen != SHA512_DIGEST_LENGTH)
128                         return EINVAL;
129
130                 SHA512_Init(&ctx);
131                 SHA512_Update(&ctx, priv->crypto_key, priv->crypto_klen>>3);
132                 SHA512_Final(priv->crypto_keyhash, &ctx);
133         } else if (!strcmp(iv_hash, "md5")) {
134                 MD5_CTX ctx;
135
136                 if (klen != MD5_DIGEST_LENGTH)
137                         return EINVAL;
138
139                 MD5Init(&ctx);
140                 MD5Update(&ctx, priv->crypto_key, priv->crypto_klen>>3);
141                 MD5Final(priv->crypto_keyhash, &ctx);
142         } else if (!strcmp(iv_hash, "rmd160") || !strcmp(iv_hash, "ripemd160")) {
143                 RMD160_CTX ctx;
144
145                 if (klen != (160/8))
146                         return EINVAL;
147
148                 RMD160Init(&ctx);
149                 RMD160Update(&ctx, priv->crypto_key, priv->crypto_klen>>3);
150                 RMD160Final(priv->crypto_keyhash, &ctx);
151         } else {
152                 return EINVAL;
153         }
154
155         return 0;
156 }
157
158 static int
159 essiv_ivgen_done(struct cryptop *crp)
160 {
161
162         if (crp->crp_etype == EAGAIN)
163                 return crypto_dispatch(crp);
164
165         if (crp->crp_etype != 0) {
166                 kprintf("dm_target_crypt: essiv_ivgen_done, crp->crp_etype = %d\n", crp->crp_etype);
167         }
168
169         atomic_add_int((int *)crp->crp_opaque, 1);
170         wakeup(crp->crp_opaque);
171         return 0;
172 }
173
174 static void
175 plain_ivgen(dm_target_crypt_config_t *priv, u_int8_t *iv, size_t iv_len, off_t sector)
176 {
177         bzero(iv, iv_len);
178         *((off_t *)iv) = htole64(sector + priv->iv_offset);
179 }
180
181 static void
182 essiv_ivgen(dm_target_crypt_config_t *priv, u_int8_t *iv, size_t iv_len, off_t sector)
183 {
184         struct cryptodesc crd;
185         struct cryptop crp;
186         int error, id;
187
188         id = 0;
189         bzero(iv, iv_len);
190         *((off_t *)iv) = htole64(sector + priv->iv_offset);
191         crp.crp_buf = (caddr_t)iv;
192
193         crp.crp_sid = priv->crypto_sid;
194         crp.crp_ilen = crp.crp_olen = iv_len;
195
196         crp.crp_opaque = (void *)&id;
197
198         crp.crp_callback = essiv_ivgen_done;
199
200         crp.crp_desc = &crd;
201         crp.crp_etype = 0;
202         crp.crp_flags = CRYPTO_F_CBIFSYNC | CRYPTO_F_REL;
203
204         crd.crd_alg = priv->crypto_alg;
205         crd.crd_key = (caddr_t)priv->crypto_keyhash;
206         crd.crd_klen = priv->crypto_klen;
207
208         bzero(crd.crd_iv, sizeof(crd.crd_iv));
209
210         crd.crd_skip = 0;
211         crd.crd_len = iv_len;
212         crd.crd_flags = CRD_F_KEY_EXPLICIT | CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
213         crd.crd_flags |= CRD_F_ENCRYPT;
214         crd.crd_next = NULL;
215
216         error = crypto_dispatch(&crp);
217         if (error)
218                 kprintf("dm_target_crypt: essiv_ivgen, error = %d\n", error);
219
220         /*
221          * id is modified in the callback, so that if crypto_dispatch finishes
222          * synchronously we don't tsleep() forever.
223          */
224         if (id == 0)
225                 tsleep((void *)&error, 0, "essivgen", 0);
226 }
227
228 #if 0
229 static void
230 geli_ivgen(dm_target_crypt_config_t *priv, u_int8_t *iv, size_t iv_len, off_t sector)
231 {
232
233         SHA512_CTX      ctx512;
234         u_int8_t        md[SHA512_DIGEST_LENGTH]; /* Max. Digest Size */
235
236         memcpy(&ctx512, &priv->essivsha512_ctx, sizeof(SHA512_CTX));
237         SHA512_Update(&ctx512, (u_int8_t*)&sector, sizeof(off_t));
238         SHA512_Final(md, &ctx512);
239
240         memcpy(iv, md, iv_len);
241 }
242 #endif
243
244 static void
245 dmtc_crypto_start(dm_target_crypt_config_t *priv, struct bio *bio)
246 {
247         struct dmtc_helper *dmtc;
248         struct cryptodesc *crd;
249         struct cryptop *crp;
250         struct cryptoini *cri;
251
252         int error, i, bytes, isector, sectors, write, sz;
253         u_char *ptr, *space, *data;
254
255         cri = &priv->crypto_session;
256
257         write = (bio->bio_buf->b_cmd == BUF_CMD_WRITE) ? 1 : 0;
258         bytes = bio->bio_buf->b_bcount; /* XXX: b_resid no good after reads... == 0 */
259         isector = bio->bio_offset/DEV_BSIZE;    /* Initial sector */
260         sectors = bytes/DEV_BSIZE;              /* Number of sectors affected by bio */
261         sz = sectors * (sizeof(*crp) + sizeof(*crd));
262
263         if (write) {
264                 space = kmalloc(sizeof(struct dmtc_helper) + sz + bytes, M_DMCRYPT, M_WAITOK);
265                 dmtc = (struct dmtc_helper *)space;
266                 dmtc->free_addr = space;
267                 dmtc->orig_buf = bio->bio_buf->b_data;
268                 space += sizeof(struct dmtc_helper);
269                 memcpy(space + sz, bio->bio_buf->b_data, bytes);
270                 bio->bio_caller_info2.ptr = dmtc;
271                 bio->bio_buf->b_data = data = space + sz;
272         } else {
273                 space = kmalloc(sz, M_DMCRYPT, M_WAITOK);
274                 data = bio->bio_buf->b_data;
275                 bio->bio_caller_info2.ptr = space;
276         }
277
278         ptr = space;
279         bio->bio_caller_info3.value = sectors;
280 #if 0
281         kprintf("Write? %d, bytes = %d (b_bcount), sectors = %d (bio = %p, b_cmd = %d)\n", write, bytes, sectors, bio, bio->bio_buf->b_cmd);
282 #endif
283         for (i = 0; i < sectors; i++) {
284                 crp = (struct cryptop *)ptr;
285                 ptr += sizeof(*crp);
286                 crd = (struct cryptodesc *)ptr;
287                 ptr += sizeof (*crd);
288
289                 crp->crp_buf = (data + i*DEV_BSIZE);
290
291                 crp->crp_sid = priv->crypto_sid;
292                 crp->crp_ilen = crp->crp_olen = DEV_BSIZE;
293
294                 crp->crp_opaque = (void *)bio;
295
296                 if (write)
297                         crp->crp_callback = dmtc_crypto_cb_write_done;
298                 else
299                         crp->crp_callback = dmtc_crypto_cb_read_done;
300                 crp->crp_desc = crd;
301                 crp->crp_etype = 0;
302                 crp->crp_flags = CRYPTO_F_CBIFSYNC | CRYPTO_F_REL;
303
304                 crd->crd_alg = priv->crypto_alg;
305                 crd->crd_key = (caddr_t)priv->crypto_key;
306                 crd->crd_klen = priv->crypto_klen;
307
308                 priv->crypto_ivgen(priv, crd->crd_iv, sizeof(crd->crd_iv), isector + i);
309
310                 crd->crd_skip = 0;
311                 crd->crd_len = DEV_BSIZE /* XXX */;
312                 crd->crd_flags = CRD_F_KEY_EXPLICIT | CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
313                 crd->crd_next = NULL;
314
315                 if (write)
316                         crd->crd_flags |= CRD_F_ENCRYPT;
317                 else
318                         crd->crd_flags &= ~CRD_F_ENCRYPT;
319
320                 error = crypto_dispatch(crp);
321         }
322 }
323
324 static void
325 dmtc_bio_read_done(struct bio *bio)
326 {
327         dm_target_crypt_config_t *priv;
328
329         priv = bio->bio_caller_info1.ptr;
330
331         dmtc_crypto_start(priv, bio);
332 }
333
334 static void
335 dmtc_bio_write_done(struct bio *bio)
336 {
337         struct dmtc_helper *dmtc;
338         struct bio *obio;
339
340         dmtc = bio->bio_caller_info2.ptr;
341         bio->bio_buf->b_data = dmtc->orig_buf;
342         kfree(dmtc->free_addr, M_DMCRYPT);
343         obio = pop_bio(bio);
344         biodone(obio);
345 }
346
347 static int
348 dmtc_crypto_cb_read_done(struct cryptop *crp)
349 {
350         struct bio *bio, *obio;
351         int n;
352
353         if (crp->crp_etype == EAGAIN)
354                 return crypto_dispatch(crp);
355
356         bio = (struct bio *)crp->crp_opaque;
357         KKASSERT(bio != NULL);
358
359         n = atomic_fetchadd_int(&bio->bio_caller_info3.value, -1);
360 #if 0
361         kprintf("dmtc_crypto_cb_read_done %p, n = %d\n", bio, n);
362 #endif
363         if (crp->crp_etype != 0) {
364                 kprintf("dm_target_crypt: dmtc_crypto_cb_read_done crp_etype = %d\n", crp->crp_etype);
365                 bio->bio_buf->b_error = crp->crp_etype;
366         }
367         if (n == 1) {
368                 kfree(bio->bio_caller_info2.ptr, M_DMCRYPT);
369                 /* This is the last chunk of the read */
370                 obio = pop_bio(bio);
371                 biodone(obio);
372         }
373
374         return 0;
375 }
376
377 static int
378 dmtc_crypto_cb_write_done(struct cryptop *crp)
379 {
380         struct dmtc_helper *dmtc;
381         dm_target_crypt_config_t *priv;
382         struct bio *bio, *obio;
383         int n;
384
385         if (crp->crp_etype == EAGAIN)
386                 return crypto_dispatch(crp);
387
388         bio = (struct bio *)crp->crp_opaque;
389         KKASSERT(bio != NULL);
390
391         n = atomic_fetchadd_int(&bio->bio_caller_info3.value, -1);
392 #if 0
393         kprintf("dmtc_crypto_cb_write_done %p, n = %d\n", bio, n);
394 #endif
395         if (crp->crp_etype != 0) {
396                 kprintf("dm_target_crypt: dmtc_crypto_cb_write_done crp_etype = %d\n", crp->crp_etype);
397                 bio->bio_buf->b_error = crp->crp_etype;
398         }
399         if (n == 1) {
400                 /* This is the last chunk of the write */
401                 if (bio->bio_buf->b_error != 0) {
402                         /* XXX */
403                         dmtc = bio->bio_caller_info2.ptr;
404                         bio->bio_buf->b_data = dmtc->orig_buf;
405                         kfree(dmtc->free_addr, M_DMCRYPT);
406                         obio = pop_bio(bio);
407                         biodone(obio);
408                 } else {
409                         priv = (dm_target_crypt_config_t *)bio->bio_caller_info1.ptr;
410                         vn_strategy(priv->pdev->pdev_vnode, bio);
411                 }
412         }
413
414         return 0;
415 }
416
417 /*
418 strategy -> read_done -> crypto_work -> crypto_done_read -> FINISH READ
419 strategy -> crypto_work -> crypto_done_write -> write dispatch -> write_done -> FINISH WRITE
420 */
421
422 #ifdef DM_TARGET_MODULE
423 /*
424  * Every target can be compiled directly to dm driver or as a
425  * separate module this part of target is used for loading targets
426  * to dm driver.
427  * Target can be unloaded from kernel only if there are no users of
428  * it e.g. there are no devices which uses that target.
429  */
430 #include <sys/kernel.h>
431 #include <sys/module.h>
432
433 static int
434 dm_target_crypt_modcmd(modcmd_t cmd, void *arg)
435 {
436         dm_target_t *dmt;
437         int r;
438         dmt = NULL;
439
440         switch (cmd) {
441         case MODULE_CMD_INIT:
442                 if ((dmt = dm_target_lookup("crypt")) != NULL) {
443                         dm_target_unbusy(dmt);
444                         return EEXIST;
445                 }
446                 dmt = dm_target_alloc("crypt");
447
448                 dmt->version[0] = 1;
449                 dmt->version[1] = 0;
450                 dmt->version[2] = 0;
451                 strlcpy(dmt->name, "crypt", DM_MAX_TYPE_NAME);
452                 dmt->init = &dm_target_crypt_init;
453                 dmt->status = &dm_target_crypt_status;
454                 dmt->strategy = &dm_target_crypt_strategy;
455                 dmt->deps = &dm_target_crypt_deps;
456                 dmt->destroy = &dm_target_crypt_destroy;
457                 dmt->upcall = &dm_target_crypt_upcall;
458
459                 r = dm_target_insert(dmt);
460
461                 break;
462
463         case MODULE_CMD_FINI:
464                 r = dm_target_rem("crypt");
465                 break;
466
467         case MODULE_CMD_STAT:
468                 return ENOTTY;
469
470         default:
471                 return ENOTTY;
472         }
473
474         return r;
475 }
476 #endif
477
478 /*
479  * Init function called from dm_table_load_ioctl.
480  * cryptsetup actually passes us this:
481  * aes-cbc-essiv:sha256 7997f8af... 0 /dev/ad0s0a 8
482  */
483
484 static int
485 hex2key(char *hex, size_t hex_length, u_int8_t *key)
486 {
487         char hex_buf[3];
488         size_t key_idx;
489
490         key_idx = 0;
491         bzero(hex_buf, sizeof(hex_buf));
492
493         for (; hex_length > 0; hex_length -= 2) {
494                 hex_buf[0] = *hex++;
495                 hex_buf[1] = *hex++;
496                 key[key_idx++] = (u_int8_t)strtoul(hex_buf, NULL, 16);
497         }
498
499         return 0;
500 }
501
502 int
503 dm_target_crypt_init(dm_dev_t * dmv, void **target_config, char *params)
504 {
505         dm_target_crypt_config_t *priv;
506         size_t len;
507         char **ap, *args[5];
508         char *crypto_alg, *crypto_mode, *iv_mode, *iv_opt, *key, *dev;
509         char *status_str;
510         int argc, klen, error;
511         uint64_t iv_offset, block_offset;
512
513         if (params == NULL)
514                 return EINVAL;
515
516         len = strlen(params) + 1;
517         argc = 0;
518
519         status_str = kstrdup(params, M_DMCRYPT);
520         /*
521          * Parse a string, containing tokens delimited by white space,
522          * into an argument vector
523          */
524         for (ap = args; ap < &args[5] &&
525             (*ap = strsep(&params, " \t")) != NULL;) {
526                 if (**ap != '\0') {
527                         argc++;
528                         ap++;
529                 }
530         }
531
532         if (argc != 5) {
533                 kprintf("dm_target_crypt: not enough arguments, need exactly 5\n");
534                 kfree(status_str, M_DMCRYPT);
535                 return ENOMEM; /* XXX */
536         }
537
538         crypto_alg = strsep(&args[0], "-");
539         crypto_mode = strsep(&args[0], "-");
540         iv_opt = strsep(&args[0], "-");
541         iv_mode = strsep(&iv_opt, ":");
542         key = args[1];
543         iv_offset = strtouq(args[2], NULL, 0);
544         dev = args[3];
545         block_offset = strtouq(args[4], NULL, 0);
546         /* bits / 8 = bytes, 1 byte = 2 hexa chars, so << 2 */
547         klen = strlen(key) << 2;
548
549         kprintf("dm_target_crypt: dev=%s, crypto_alg=%s, crypto_mode=%s, "
550                 "iv_mode=%s, iv_opt=%s, key=%s, iv_offset=%ju, block_offset=%ju\n",
551                 dev, crypto_alg, crypto_mode, iv_mode, iv_opt, key, iv_offset,
552                 block_offset);
553
554         priv = kmalloc(sizeof(dm_target_crypt_config_t), M_DMCRYPT, M_WAITOK);
555         if (priv == NULL) {
556                 kprintf("dm_target_crypt: could not allocate memory\n");
557                 kfree(status_str, M_DMCRYPT);
558                 return ENOMEM;
559         }
560
561         /* Insert dmp to global pdev list */
562         if ((priv->pdev = dm_pdev_insert(dev)) == NULL) {
563                 kprintf("dm_target_crypt: dm_pdev_insert failed\n");
564                 kfree(status_str, M_DMCRYPT);
565                 return ENOENT;
566         }
567
568         if (strcmp(crypto_mode, "cbc") != 0) {
569                 kprintf("dm_target_crypt: only support 'cbc' chaining mode, invalid mode '%s'\n", crypto_mode);
570                 goto notsup;
571         }
572
573         if (!strcmp(crypto_alg, "aes")) {
574                 priv->crypto_alg = CRYPTO_AES_CBC;
575                 if (klen != 128 && klen != 192 && klen != 256)
576                         goto notsup;
577                 priv->crypto_klen = klen;
578
579         } else if (!strcmp(crypto_alg, "blowfish")) {
580                 priv->crypto_alg = CRYPTO_BLF_CBC;
581                 if (klen < 128 || klen > 448 || (klen % 8) != 0)
582                         goto notsup;
583                 priv->crypto_klen = klen;
584
585         } else if (!strcmp(crypto_alg, "3des") || !strncmp(crypto_alg, "des3", 4)) {
586                 priv->crypto_alg = CRYPTO_3DES_CBC;
587                 if (klen != 168)
588                         goto notsup;
589                 priv->crypto_klen = 168;
590
591         } else if (!strcmp(crypto_alg, "camellia")) {
592                 priv->crypto_alg = CRYPTO_CAMELLIA_CBC;
593                 if (klen != 128 && klen != 192 && klen != 256)
594                         goto notsup;
595                 priv->crypto_klen = klen;
596
597         } else if (!strcmp(crypto_alg, "skipjack")) {
598                 priv->crypto_alg = CRYPTO_SKIPJACK_CBC;
599                 if (klen != 80)
600                         goto notsup;
601                 priv->crypto_klen = 80;
602
603         } else if (!strcmp(crypto_alg, "cast5")) {
604                 priv->crypto_alg = CRYPTO_CAST_CBC;
605                 if (klen != 128)
606                         goto notsup;
607                 priv->crypto_klen = 128;
608
609         } else if (!strcmp(crypto_alg, "null")) {
610                 priv->crypto_alg = CRYPTO_NULL_CBC;
611                 if (klen != 128)
612                         goto notsup;
613                 priv->crypto_klen = 128;
614
615         } else {
616                 kprintf("dm_target_crypt: Unsupported crypto algorithm: %s\n", crypto_alg);
617                 goto notsup;
618         }
619
620         /* Save length of param string */
621         priv->params_len = len;
622         priv->block_offset = block_offset;
623         priv->iv_offset = iv_offset;
624
625         *target_config = priv;
626
627         dmv->dev_type = DM_CRYPTO_DEV;
628
629         priv->crypto_session.cri_alg = priv->crypto_alg;
630         priv->crypto_session.cri_klen = priv->crypto_klen;
631         priv->crypto_session.cri_mlen = 0;
632
633         error = hex2key(key, priv->crypto_klen >> 3, (u_int8_t *)priv->crypto_key);
634         if (error) {
635                 kprintf("dm_target_crypt: hex2key failed, invalid key format\n");
636                 goto notsup;
637         }
638
639
640         if (!strcmp(iv_mode, "essiv")) {
641                 error = essiv_hash_mkey(priv, iv_opt);
642                 if (error) {
643                         kprintf("dm_target_crypt: essiv_hash_mkey failed\n");
644                         goto notsup;
645                 }
646                 priv->crypto_ivgen = essiv_ivgen;
647         } else if (!strcmp(iv_mode, "plain")) {
648                 priv->crypto_ivgen = plain_ivgen;
649         } else {
650                 kprintf("dm_target_crypt: only support iv_mode='essiv' and 'plain', iv_mode='%s' unsupported\n", iv_mode);
651         }
652
653         priv->crypto_session.cri_key = (u_int8_t *)priv->crypto_key;
654         priv->crypto_session.cri_next = NULL;
655
656         error = crypto_newsession(&priv->crypto_sid,
657                                   &priv->crypto_session,
658                                   CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE);
659         if (error) {
660                 kprintf("dm_target_crypt: Error during crypto_newsession, error = %d\n", error);
661                 goto notsup;
662         }
663
664         priv->status_str = status_str;
665         return 0;
666
667 notsup:
668         kprintf("dm_target_crypt: ENOTSUP\n");
669         kfree(status_str, M_DMCRYPT);
670         return ENOTSUP;
671 }
672
673 /* Status routine called to get params string. */
674 char *
675 dm_target_crypt_status(void *target_config)
676 {
677         dm_target_crypt_config_t *priv;
678         char *params;
679
680         priv = target_config;
681
682         /* caller expects use of M_DM */
683         params = kmalloc(DM_MAX_PARAMS_SIZE, M_DM, M_WAITOK);
684
685         ksnprintf(params, DM_MAX_PARAMS_SIZE, "%s",
686             priv->status_str);
687
688         return params;
689 }
690
691 /* Strategy routine called from dm_strategy. */
692 /*
693  * Do IO operation, called from dmstrategy routine.
694  */
695 int
696 dm_target_crypt_strategy(dm_table_entry_t * table_en, struct buf * bp)
697 {
698         struct bio *bio;
699
700         dm_target_crypt_config_t *priv;
701         priv = table_en->target_config;
702
703         /* Get rid of stuff we can't really handle */
704         if ((bp->b_cmd == BUF_CMD_READ) || (bp->b_cmd == BUF_CMD_WRITE)) {
705                 if (((bp->b_bcount % DEV_BSIZE) != 0) || (bp->b_bcount == 0)) {
706                         kprintf("dm_target_crypt_strategy: can't really handle bp->b_bcount = %d\n", bp->b_bcount);
707                         bp->b_error = EINVAL;
708                         bp->b_flags |= B_ERROR | B_INVAL;
709                         biodone(&bp->b_bio1);
710                         return 0;
711                 }
712         }
713
714         switch (bp->b_cmd) {
715         case BUF_CMD_READ:
716                 bio = push_bio(&bp->b_bio1);
717                 bio->bio_offset = bp->b_bio1.bio_offset + priv->block_offset*DEV_BSIZE;
718                 bio->bio_caller_info1.ptr = priv;
719                 bio->bio_done = dmtc_bio_read_done;
720                 vn_strategy(priv->pdev->pdev_vnode, bio);
721                 break;
722
723         case BUF_CMD_WRITE:
724                 bio = push_bio(&bp->b_bio1);
725                 bio->bio_offset = bp->b_bio1.bio_offset + priv->block_offset*DEV_BSIZE;
726                 bio->bio_caller_info1.ptr = priv;
727                 bio->bio_done = dmtc_bio_write_done;
728                 dmtc_crypto_start(priv, bio);
729                 break;
730
731         default:
732                 vn_strategy(priv->pdev->pdev_vnode, &bp->b_bio1);
733         }
734
735         return 0;
736
737 }
738
739 int
740 dm_target_crypt_destroy(dm_table_entry_t * table_en)
741 {
742         dm_target_crypt_config_t *priv;
743
744         priv = table_en->target_config;
745
746         if (priv == NULL)
747                 return 0;
748
749         dm_pdev_decr(priv->pdev);
750
751         /* Unbusy target so we can unload it */
752         dm_target_unbusy(table_en->target);
753
754         /*
755          * Overwrite the private information before freeing memory to
756          * avoid leaking it.
757          */
758         memset(priv->status_str, 0xFF, strlen(priv->status_str));
759         bzero(priv->status_str, strlen(priv->status_str));
760         memset(priv, 0xFF, sizeof(dm_target_crypt_config_t));
761         bzero(priv, sizeof(dm_target_crypt_config_t));
762
763         kfree(priv->status_str, M_DMCRYPT);
764         kfree(priv, M_DMCRYPT);
765
766         table_en->target_config = NULL;
767
768         return 0;
769 }
770
771 int
772 dm_target_crypt_deps(dm_table_entry_t * table_en, prop_array_t prop_array)
773 {
774         dm_target_crypt_config_t *priv;
775         struct vattr va;
776
777         int error;
778
779         if (table_en->target_config == NULL)
780                 return ENOENT;
781
782         priv = table_en->target_config;
783
784         if ((error = VOP_GETATTR(priv->pdev->pdev_vnode, &va)) != 0)
785                 return error;
786
787         prop_array_add_uint64(prop_array, (uint64_t) makeudev(va.va_rmajor, va.va_rminor));
788
789         return 0;
790 }
791
792 /* Unsupported for this target. */
793 int
794 dm_target_crypt_upcall(dm_table_entry_t * table_en, struct buf * bp)
795 {
796         return 0;
797 }