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