kernel - dm - Reorganize the crypt code and implement B_HASBOGUS
[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         caddr_t data_buf;
78 };
79
80 static void dmtc_crypto_read_start(dm_target_crypt_config_t *priv,
81                                 struct bio *bio);
82 static void dmtc_crypto_write_start(dm_target_crypt_config_t *priv,
83                                 struct bio *bio);
84 static void dmtc_bio_read_done(struct bio *bio);
85 static void dmtc_bio_write_done(struct bio *bio);
86 static int dmtc_crypto_cb_read_done(struct cryptop *crp);
87 static int dmtc_crypto_cb_write_done(struct cryptop *crp);
88
89 /*
90  * Support routines for dm_target_crypt_init
91  */
92 static int
93 essiv_hash_mkey(dm_target_crypt_config_t *priv, char *iv_hash)
94 {
95         unsigned int klen;
96
97         klen = (priv->crypto_klen >> 3);
98
99         if (iv_hash == NULL)
100                 return EINVAL;
101
102         if (!strcmp(iv_hash, "sha1")) {
103                 SHA1_CTX ctx;
104
105                 if (klen != SHA1_RESULTLEN)
106                         return EINVAL;
107
108                 SHA1Init(&ctx);
109                 SHA1Update(&ctx, priv->crypto_key, priv->crypto_klen>>3);
110                 SHA1Final(priv->crypto_keyhash, &ctx);
111         } else if (!strcmp(iv_hash, "sha256")) {
112                 SHA256_CTX ctx;
113
114                 if (klen != SHA256_DIGEST_LENGTH)
115                         return EINVAL;
116
117                 SHA256_Init(&ctx);
118                 SHA256_Update(&ctx, priv->crypto_key, priv->crypto_klen>>3);
119                 SHA256_Final(priv->crypto_keyhash, &ctx);
120         } else if (!strcmp(iv_hash, "sha384")) {
121                 SHA384_CTX ctx;
122
123                 if (klen != SHA384_DIGEST_LENGTH)
124                         return EINVAL;
125
126                 SHA384_Init(&ctx);
127                 SHA384_Update(&ctx, priv->crypto_key, priv->crypto_klen>>3);
128                 SHA384_Final(priv->crypto_keyhash, &ctx);
129         } else if (!strcmp(iv_hash, "sha512")) {
130                 SHA512_CTX ctx;
131
132                 if (klen != SHA512_DIGEST_LENGTH)
133                         return EINVAL;
134
135                 SHA512_Init(&ctx);
136                 SHA512_Update(&ctx, priv->crypto_key, priv->crypto_klen>>3);
137                 SHA512_Final(priv->crypto_keyhash, &ctx);
138         } else if (!strcmp(iv_hash, "md5")) {
139                 MD5_CTX ctx;
140
141                 if (klen != MD5_DIGEST_LENGTH)
142                         return EINVAL;
143
144                 MD5Init(&ctx);
145                 MD5Update(&ctx, priv->crypto_key, priv->crypto_klen>>3);
146                 MD5Final(priv->crypto_keyhash, &ctx);
147         } else if (!strcmp(iv_hash, "rmd160") ||
148                    !strcmp(iv_hash, "ripemd160")) {
149                 RMD160_CTX ctx;
150
151                 if (klen != (160/8))
152                         return EINVAL;
153
154                 RMD160Init(&ctx);
155                 RMD160Update(&ctx, priv->crypto_key, priv->crypto_klen>>3);
156                 RMD160Final(priv->crypto_keyhash, &ctx);
157         } else {
158                 return EINVAL;
159         }
160
161         return 0;
162 }
163
164 static int
165 essiv_ivgen_done(struct cryptop *crp)
166 {
167
168         if (crp->crp_etype == EAGAIN)
169                 return crypto_dispatch(crp);
170
171         if (crp->crp_etype != 0) {
172                 kprintf("dm_target_crypt: essiv_ivgen_done, "
173                         "crp->crp_etype = %d\n", crp->crp_etype);
174         }
175
176         atomic_add_int((int *)crp->crp_opaque, 1);
177         wakeup(crp->crp_opaque);
178         return 0;
179 }
180
181 static void
182 plain_ivgen(dm_target_crypt_config_t *priv, u_int8_t *iv,
183             size_t iv_len, off_t sector)
184 {
185         bzero(iv, iv_len);
186         *((off_t *)iv) = htole64(sector + priv->iv_offset);
187 }
188
189 static void
190 essiv_ivgen(dm_target_crypt_config_t *priv, u_int8_t *iv,
191             size_t iv_len, off_t sector)
192 {
193         struct cryptodesc crd;
194         struct cryptop crp;
195         int error, id;
196
197         id = 0;
198         bzero(iv, iv_len);
199         *((off_t *)iv) = htole64(sector + priv->iv_offset);
200         crp.crp_buf = (caddr_t)iv;
201
202         crp.crp_sid = priv->crypto_sid;
203         crp.crp_ilen = crp.crp_olen = iv_len;
204
205         crp.crp_opaque = (void *)&id;
206
207         crp.crp_callback = essiv_ivgen_done;
208
209         crp.crp_desc = &crd;
210         crp.crp_etype = 0;
211         crp.crp_flags = CRYPTO_F_CBIFSYNC | CRYPTO_F_REL;
212
213         crd.crd_alg = priv->crypto_alg;
214         crd.crd_key = (caddr_t)priv->crypto_keyhash;
215         crd.crd_klen = priv->crypto_klen;
216
217         bzero(crd.crd_iv, sizeof(crd.crd_iv));
218
219         crd.crd_skip = 0;
220         crd.crd_len = iv_len;
221         crd.crd_flags = CRD_F_KEY_EXPLICIT | CRD_F_IV_EXPLICIT |
222                         CRD_F_IV_PRESENT;
223         crd.crd_flags |= CRD_F_ENCRYPT;
224         crd.crd_next = NULL;
225
226         error = crypto_dispatch(&crp);
227         if (error)
228                 kprintf("dm_target_crypt: essiv_ivgen, error = %d\n", error);
229
230         /*
231          * id is modified in the callback, so that if crypto_dispatch finishes
232          * synchronously we don't tsleep() forever.
233          */
234         if (id == 0)
235                 tsleep((void *)&error, 0, "essivgen", 0);
236 }
237
238 #if 0
239
240 static void
241 geli_ivgen(dm_target_crypt_config_t *priv, u_int8_t *iv,
242            size_t iv_len, off_t sector)
243 {
244
245         SHA512_CTX      ctx512;
246         u_int8_t        md[SHA512_DIGEST_LENGTH]; /* Max. Digest Size */
247
248         memcpy(&ctx512, &priv->essivsha512_ctx, sizeof(SHA512_CTX));
249         SHA512_Update(&ctx512, (u_int8_t*)&sector, sizeof(off_t));
250         SHA512_Final(md, &ctx512);
251
252         memcpy(iv, md, iv_len);
253 }
254
255 #endif
256
257 #ifdef DM_TARGET_MODULE
258 /*
259  * Every target can be compiled directly to dm driver or as a
260  * separate module this part of target is used for loading targets
261  * to dm driver.
262  * Target can be unloaded from kernel only if there are no users of
263  * it e.g. there are no devices which uses that target.
264  */
265 #include <sys/kernel.h>
266 #include <sys/module.h>
267
268 static int
269 dm_target_crypt_modcmd(modcmd_t cmd, void *arg)
270 {
271         dm_target_t *dmt;
272         int r;
273         dmt = NULL;
274
275         switch (cmd) {
276         case MODULE_CMD_INIT:
277                 if ((dmt = dm_target_lookup("crypt")) != NULL) {
278                         dm_target_unbusy(dmt);
279                         return EEXIST;
280                 }
281                 dmt = dm_target_alloc("crypt");
282
283                 dmt->version[0] = 1;
284                 dmt->version[1] = 0;
285                 dmt->version[2] = 0;
286                 strlcpy(dmt->name, "crypt", DM_MAX_TYPE_NAME);
287                 dmt->init = &dm_target_crypt_init;
288                 dmt->status = &dm_target_crypt_status;
289                 dmt->strategy = &dm_target_crypt_strategy;
290                 dmt->deps = &dm_target_crypt_deps;
291                 dmt->destroy = &dm_target_crypt_destroy;
292                 dmt->upcall = &dm_target_crypt_upcall;
293
294                 r = dm_target_insert(dmt);
295
296                 break;
297
298         case MODULE_CMD_FINI:
299                 r = dm_target_rem("crypt");
300                 break;
301
302         case MODULE_CMD_STAT:
303                 return ENOTTY;
304
305         default:
306                 return ENOTTY;
307         }
308
309         return r;
310 }
311
312 #endif
313
314 /*
315  * Init function called from dm_table_load_ioctl.
316  * cryptsetup actually passes us this:
317  * aes-cbc-essiv:sha256 7997f8af... 0 /dev/ad0s0a 8
318  */
319 static int
320 hex2key(char *hex, size_t hex_length, u_int8_t *key)
321 {
322         char hex_buf[3];
323         size_t key_idx;
324
325         key_idx = 0;
326         bzero(hex_buf, sizeof(hex_buf));
327
328         for (; hex_length > 0; hex_length -= 2) {
329                 hex_buf[0] = *hex++;
330                 hex_buf[1] = *hex++;
331                 key[key_idx++] = (u_int8_t)strtoul(hex_buf, NULL, 16);
332         }
333
334         return 0;
335 }
336
337 int
338 dm_target_crypt_init(dm_dev_t * dmv, void **target_config, char *params)
339 {
340         dm_target_crypt_config_t *priv;
341         size_t len;
342         char **ap, *args[5];
343         char *crypto_alg, *crypto_mode, *iv_mode, *iv_opt, *key, *dev;
344         char *status_str;
345         int argc, klen, error;
346         uint64_t iv_offset, block_offset;
347
348         if (params == NULL)
349                 return EINVAL;
350
351         len = strlen(params) + 1;
352         argc = 0;
353
354         status_str = kstrdup(params, M_DMCRYPT);
355         /*
356          * Parse a string, containing tokens delimited by white space,
357          * into an argument vector
358          */
359         for (ap = args; ap < &args[5] &&
360             (*ap = strsep(&params, " \t")) != NULL;) {
361                 if (**ap != '\0') {
362                         argc++;
363                         ap++;
364                 }
365         }
366
367         if (argc != 5) {
368                 kprintf("dm_target_crypt: not enough arguments, "
369                         "need exactly 5\n");
370                 kfree(status_str, M_DMCRYPT);
371                 return ENOMEM; /* XXX */
372         }
373
374         crypto_alg = strsep(&args[0], "-");
375         crypto_mode = strsep(&args[0], "-");
376         iv_opt = strsep(&args[0], "-");
377         iv_mode = strsep(&iv_opt, ":");
378         key = args[1];
379         iv_offset = strtouq(args[2], NULL, 0);
380         dev = args[3];
381         block_offset = strtouq(args[4], NULL, 0);
382         /* bits / 8 = bytes, 1 byte = 2 hexa chars, so << 2 */
383         klen = strlen(key) << 2;
384
385         kprintf("dm_target_crypt: dev=%s, crypto_alg=%s, crypto_mode=%s, "
386                 "iv_mode=%s, iv_opt=%s, key=%s, iv_offset=%ju, "
387                 "block_offset=%ju\n",
388                 dev, crypto_alg, crypto_mode, iv_mode, iv_opt, key, iv_offset,
389                 block_offset);
390
391         priv = kmalloc(sizeof(dm_target_crypt_config_t), M_DMCRYPT, M_WAITOK);
392         if (priv == NULL) {
393                 kprintf("dm_target_crypt: could not allocate memory\n");
394                 kfree(status_str, M_DMCRYPT);
395                 return ENOMEM;
396         }
397
398         /* Insert dmp to global pdev list */
399         if ((priv->pdev = dm_pdev_insert(dev)) == NULL) {
400                 kprintf("dm_target_crypt: dm_pdev_insert failed\n");
401                 kfree(status_str, M_DMCRYPT);
402                 return ENOENT;
403         }
404
405         if (strcmp(crypto_mode, "cbc") != 0) {
406                 kprintf("dm_target_crypt: only support 'cbc' chaining mode, "
407                         "invalid mode '%s'\n", crypto_mode);
408                 goto notsup;
409         }
410
411         if (!strcmp(crypto_alg, "aes")) {
412                 priv->crypto_alg = CRYPTO_AES_CBC;
413                 if (klen != 128 && klen != 192 && klen != 256)
414                         goto notsup;
415                 priv->crypto_klen = klen;
416         } else if (!strcmp(crypto_alg, "blowfish")) {
417                 priv->crypto_alg = CRYPTO_BLF_CBC;
418                 if (klen < 128 || klen > 448 || (klen % 8) != 0)
419                         goto notsup;
420                 priv->crypto_klen = klen;
421
422         } else if (!strcmp(crypto_alg, "3des") ||
423                    !strncmp(crypto_alg, "des3", 4)) {
424                 priv->crypto_alg = CRYPTO_3DES_CBC;
425                 if (klen != 168)
426                         goto notsup;
427                 priv->crypto_klen = 168;
428         } else if (!strcmp(crypto_alg, "camellia")) {
429                 priv->crypto_alg = CRYPTO_CAMELLIA_CBC;
430                 if (klen != 128 && klen != 192 && klen != 256)
431                         goto notsup;
432                 priv->crypto_klen = klen;
433         } else if (!strcmp(crypto_alg, "skipjack")) {
434                 priv->crypto_alg = CRYPTO_SKIPJACK_CBC;
435                 if (klen != 80)
436                         goto notsup;
437                 priv->crypto_klen = 80;
438         } else if (!strcmp(crypto_alg, "cast5")) {
439                 priv->crypto_alg = CRYPTO_CAST_CBC;
440                 if (klen != 128)
441                         goto notsup;
442                 priv->crypto_klen = 128;
443         } else if (!strcmp(crypto_alg, "null")) {
444                 priv->crypto_alg = CRYPTO_NULL_CBC;
445                 if (klen != 128)
446                         goto notsup;
447                 priv->crypto_klen = 128;
448         } else {
449                 kprintf("dm_target_crypt: Unsupported crypto algorithm: %s\n",
450                         crypto_alg);
451                 goto notsup;
452         }
453
454         /* Save length of param string */
455         priv->params_len = len;
456         priv->block_offset = block_offset;
457         priv->iv_offset = iv_offset;
458
459         *target_config = priv;
460
461         dmv->dev_type = DM_CRYPTO_DEV;
462
463         priv->crypto_session.cri_alg = priv->crypto_alg;
464         priv->crypto_session.cri_klen = priv->crypto_klen;
465         priv->crypto_session.cri_mlen = 0;
466
467         error = hex2key(key, priv->crypto_klen >> 3,
468                         (u_int8_t *)priv->crypto_key);
469
470         if (error) {
471                 kprintf("dm_target_crypt: hex2key failed, "
472                         "invalid key format\n");
473                 goto notsup;
474         }
475
476         if (!strcmp(iv_mode, "essiv")) {
477                 error = essiv_hash_mkey(priv, iv_opt);
478                 if (error) {
479                         kprintf("dm_target_crypt: essiv_hash_mkey failed\n");
480                         goto notsup;
481                 }
482                 priv->crypto_ivgen = essiv_ivgen;
483         } else if (!strcmp(iv_mode, "plain")) {
484                 priv->crypto_ivgen = plain_ivgen;
485         } else {
486                 kprintf("dm_target_crypt: only support iv_mode='essiv' and "
487                         "'plain', iv_mode='%s' unsupported\n",
488                         iv_mode);
489         }
490
491         priv->crypto_session.cri_key = (u_int8_t *)priv->crypto_key;
492         priv->crypto_session.cri_next = NULL;
493
494         error = crypto_newsession(&priv->crypto_sid,
495                                   &priv->crypto_session,
496                                   CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_HARDWARE);
497         if (error) {
498                 kprintf("dm_target_crypt: Error during crypto_newsession, "
499                         "error = %d\n",
500                         error);
501                 goto notsup;
502         }
503
504         priv->status_str = status_str;
505         return 0;
506
507 notsup:
508         kprintf("dm_target_crypt: ENOTSUP\n");
509         kfree(status_str, M_DMCRYPT);
510         return ENOTSUP;
511 }
512
513 /* Status routine called to get params string. */
514 char *
515 dm_target_crypt_status(void *target_config)
516 {
517         dm_target_crypt_config_t *priv;
518         char *params;
519
520         priv = target_config;
521
522         /* caller expects use of M_DM */
523         params = kmalloc(DM_MAX_PARAMS_SIZE, M_DM, M_WAITOK);
524
525         ksnprintf(params, DM_MAX_PARAMS_SIZE, "%s",
526             priv->status_str);
527
528         return params;
529 }
530
531 int
532 dm_target_crypt_destroy(dm_table_entry_t * table_en)
533 {
534         dm_target_crypt_config_t *priv;
535
536         /*
537          * Disconnect the crypt config before unbusying the target.
538          */
539         priv = table_en->target_config;
540         if (priv == NULL)
541                 return 0;
542         table_en->target_config = NULL;
543         dm_pdev_decr(priv->pdev);
544
545         dm_target_unbusy(table_en->target);
546
547         /*
548          * Clean up the crypt config
549          *
550          * Overwrite the private information before freeing memory to
551          * avoid leaking it.
552          */
553         memset(priv->status_str, 0xFF, strlen(priv->status_str));
554         bzero(priv->status_str, strlen(priv->status_str));
555         kfree(priv->status_str, M_DMCRYPT);
556
557         memset(priv, 0xFF, sizeof(dm_target_crypt_config_t));
558         bzero(priv, sizeof(dm_target_crypt_config_t));
559         kfree(priv, M_DMCRYPT);
560
561         return 0;
562 }
563
564 int
565 dm_target_crypt_deps(dm_table_entry_t * table_en, prop_array_t prop_array)
566 {
567         dm_target_crypt_config_t *priv;
568         struct vattr va;
569
570         int error;
571
572         if (table_en->target_config == NULL)
573                 return ENOENT;
574
575         priv = table_en->target_config;
576
577         if ((error = VOP_GETATTR(priv->pdev->pdev_vnode, &va)) != 0)
578                 return error;
579
580         prop_array_add_uint64(prop_array,
581                               (uint64_t)makeudev(va.va_rmajor, va.va_rminor));
582
583         return 0;
584 }
585
586 /* Unsupported for this target. */
587 int
588 dm_target_crypt_upcall(dm_table_entry_t * table_en, struct buf * bp)
589 {
590         return 0;
591 }
592
593 /************************************************************************
594  *                      STRATEGY SUPPORT FUNCTIONS                      *
595  ************************************************************************
596  *
597  * READ PATH:   doio -> bio_read_done -> crypto_work -> crypto_cb_read_done
598  * WRITE PATH:  crypto_work -> crypto_cb_write_done -> doio -> bio_write_done
599  */
600
601 /*
602  * Start IO operation, called from dmstrategy routine.
603  */
604 int
605 dm_target_crypt_strategy(dm_table_entry_t *table_en, struct buf *bp)
606 {
607         struct bio *bio;
608
609         dm_target_crypt_config_t *priv;
610         priv = table_en->target_config;
611
612         /* Get rid of stuff we can't really handle */
613         if ((bp->b_cmd == BUF_CMD_READ) || (bp->b_cmd == BUF_CMD_WRITE)) {
614                 if (((bp->b_bcount % DEV_BSIZE) != 0) || (bp->b_bcount == 0)) {
615                         kprintf("dm_target_crypt_strategy: can't really "
616                                 "handle bp->b_bcount = %d\n",
617                                 bp->b_bcount);
618                         bp->b_error = EINVAL;
619                         bp->b_flags |= B_ERROR | B_INVAL;
620                         biodone(&bp->b_bio1);
621                         return 0;
622                 }
623         }
624
625         switch (bp->b_cmd) {
626         case BUF_CMD_READ:
627                 bio = push_bio(&bp->b_bio1);
628                 bio->bio_offset = bp->b_bio1.bio_offset +
629                                   priv->block_offset * DEV_BSIZE;
630                 bio->bio_caller_info1.ptr = priv;
631                 bio->bio_done = dmtc_bio_read_done;
632                 vn_strategy(priv->pdev->pdev_vnode, bio);
633                 break;
634         case BUF_CMD_WRITE:
635                 bio = push_bio(&bp->b_bio1);
636                 bio->bio_offset = bp->b_bio1.bio_offset +
637                                   priv->block_offset * DEV_BSIZE;
638                 bio->bio_caller_info1.ptr = priv;
639                 dmtc_crypto_write_start(priv, bio);
640                 break;
641         default:
642                 vn_strategy(priv->pdev->pdev_vnode, &bp->b_bio1);
643                 break;
644         }
645         return 0;
646 }
647
648 /*
649  * STRATEGY READ PATH PART 1/3 (after read BIO completes)
650  */
651 static void
652 dmtc_bio_read_done(struct bio *bio)
653 {
654         struct bio *obio;
655
656         dm_target_crypt_config_t *priv;
657
658         /*
659          * If a read error occurs we shortcut the operation, otherwise
660          * go on to stage 2.
661          */
662         if (bio->bio_buf->b_flags & B_ERROR) {
663                 obio = pop_bio(bio);
664                 biodone(obio);
665         } else {
666                 priv = bio->bio_caller_info1.ptr;
667                 dmtc_crypto_read_start(priv, bio);
668         }
669 }
670
671 /*
672  * STRATEGY READ PATH PART 2/3
673  */
674 static void
675 dmtc_crypto_read_start(dm_target_crypt_config_t *priv, struct bio *bio)
676 {
677         struct dmtc_helper *dmtc;
678         struct cryptodesc *crd;
679         struct cryptop *crp;
680         struct cryptoini *cri;
681         int error, i, bytes, isector, sectors, sz;
682         u_char *ptr, *space;
683
684         cri = &priv->crypto_session;
685
686         /*
687          * Note: b_resid no good after read I/O, it will be 0, use
688          *       b_bcount.
689          */
690         bytes = bio->bio_buf->b_bcount;
691         isector = bio->bio_offset / DEV_BSIZE;  /* Initial sector */
692         sectors = bytes / DEV_BSIZE;            /* Number of sectors */
693         sz = sectors * (sizeof(*crp) + sizeof(*crd));
694
695         /*
696          * For reads with bogus page we can't decrypt in place as stuff
697          * can get ripped out from under us.
698          */
699         if (bio->bio_buf->b_flags & B_HASBOGUS) {
700                 space = kmalloc(sizeof(struct dmtc_helper) + sz + bytes,
701                                 M_DMCRYPT, M_WAITOK);
702                 dmtc = (struct dmtc_helper *)space;
703                 dmtc->free_addr = space;
704                 space += sizeof(struct dmtc_helper);
705                 memcpy(space + sz, bio->bio_buf->b_data, bytes);
706                 dmtc->data_buf = space + sz;
707         } else {
708                 space = kmalloc(sizeof(struct dmtc_helper) + sz,
709                                 M_DMCRYPT, M_WAITOK);
710                 dmtc = (struct dmtc_helper *)space;
711                 dmtc->free_addr = space;
712                 space += sizeof(struct dmtc_helper);
713                 dmtc->data_buf = bio->bio_buf->b_data;
714         }
715         bio->bio_caller_info2.ptr = dmtc;
716         bio->bio_buf->b_error = 0;
717
718         /*
719          * Load crypto descriptors (crp/crd loop)
720          */
721         ptr = space;
722         bio->bio_caller_info3.value = sectors;
723 #if 0
724         kprintf("Read, bytes = %d (b_bcount), "
725                 "sectors = %d (bio = %p, b_cmd = %d)\n",
726                 bytes, sectors, bio, bio->bio_buf->b_cmd);
727 #endif
728         for (i = 0; i < sectors; i++) {
729                 crp = (struct cryptop *)ptr;
730                 ptr += sizeof(*crp);
731                 crd = (struct cryptodesc *)ptr;
732                 ptr += sizeof (*crd);
733
734                 crp->crp_buf = dmtc->data_buf + i * DEV_BSIZE;
735
736                 crp->crp_sid = priv->crypto_sid;
737                 crp->crp_ilen = crp->crp_olen = DEV_BSIZE;
738
739                 crp->crp_opaque = (void *)bio;
740
741                 crp->crp_callback = dmtc_crypto_cb_read_done;
742                 crp->crp_desc = crd;
743                 crp->crp_etype = 0;
744                 crp->crp_flags = CRYPTO_F_CBIFSYNC | CRYPTO_F_REL;
745
746                 crd->crd_alg = priv->crypto_alg;
747                 crd->crd_key = (caddr_t)priv->crypto_key;
748                 crd->crd_klen = priv->crypto_klen;
749
750                 priv->crypto_ivgen(priv, crd->crd_iv, sizeof(crd->crd_iv),
751                                    isector + i);
752
753                 crd->crd_skip = 0;
754                 crd->crd_len = DEV_BSIZE /* XXX */;
755                 crd->crd_flags = CRD_F_KEY_EXPLICIT | CRD_F_IV_EXPLICIT |
756                                  CRD_F_IV_PRESENT;
757                 crd->crd_next = NULL;
758
759                 crd->crd_flags &= ~CRD_F_ENCRYPT;
760
761                 error = crypto_dispatch(crp);
762         }
763 }
764
765 /*
766  * STRATEGY READ PATH PART 3/3
767  */
768 static int
769 dmtc_crypto_cb_read_done(struct cryptop *crp)
770 {
771         struct dmtc_helper *dmtc;
772         struct bio *bio, *obio;
773         int n;
774
775         if (crp->crp_etype == EAGAIN)
776                 return crypto_dispatch(crp);
777
778         bio = (struct bio *)crp->crp_opaque;
779         KKASSERT(bio != NULL);
780
781         n = atomic_fetchadd_int(&bio->bio_caller_info3.value, -1);
782 #if 0
783         kprintf("dmtc_crypto_cb_read_done %p, n = %d\n", bio, n);
784 #endif
785
786         /*
787          * Cumulative error
788          */
789         if (crp->crp_etype) {
790                 kprintf("dm_target_crypt: dmtc_crypto_cb_read_done "
791                         "crp_etype = %d\n",
792                         crp->crp_etype);
793                 bio->bio_buf->b_error = crp->crp_etype;
794         }
795
796         /*
797          * On the last chunk of the decryption we do any required copybacks
798          * and complete the I/O.
799          */
800         if (n == 1) {
801                 /*
802                  * For the B_HASBOGUS case we didn't decrypt in place,
803                  * so we need to copy stuff back into the buf.
804                  */
805                 dmtc = bio->bio_caller_info2.ptr;
806                 if (bio->bio_buf->b_error) {
807                         bio->bio_buf->b_flags |= B_ERROR;
808                 } else if (bio->bio_buf->b_flags & B_HASBOGUS) {
809                         memcpy(bio->bio_buf->b_data, dmtc->data_buf,
810                                bio->bio_buf->b_bcount);
811                 }
812                 kfree(dmtc->free_addr, M_DMCRYPT);
813                 obio = pop_bio(bio);
814                 biodone(obio);
815         }
816         return 0;
817 }
818 /* END OF STRATEGY READ SECTION */
819
820 /*
821  * STRATEGY WRITE PATH PART 1/3
822  */
823 static void
824 dmtc_crypto_write_start(dm_target_crypt_config_t *priv, struct bio *bio)
825 {
826         struct dmtc_helper *dmtc;
827         struct cryptodesc *crd;
828         struct cryptop *crp;
829         struct cryptoini *cri;
830         int error, i, bytes, isector, sectors, sz;
831         u_char *ptr, *space;
832
833         cri = &priv->crypto_session;
834
835         /*
836          * Use b_bcount for consistency
837          */
838         bytes = bio->bio_buf->b_bcount;
839
840         isector = bio->bio_offset / DEV_BSIZE;  /* Initial sector */
841         sectors = bytes / DEV_BSIZE;            /* Number of sectors */
842         sz = sectors * (sizeof(*crp) + sizeof(*crd));
843
844         /*
845          * For writes and reads with bogus page don't decrypt in place.
846          */
847         space = kmalloc(sizeof(struct dmtc_helper) + sz + bytes,
848                         M_DMCRYPT, M_WAITOK);
849         dmtc = (struct dmtc_helper *)space;
850         dmtc->free_addr = space;
851         space += sizeof(struct dmtc_helper);
852         memcpy(space + sz, bio->bio_buf->b_data, bytes);
853
854         bio->bio_caller_info2.ptr = dmtc;
855         bio->bio_buf->b_error = 0;
856
857         dmtc->orig_buf = bio->bio_buf->b_data;
858         dmtc->data_buf = space + sz;
859
860         /*
861          * Load crypto descriptors (crp/crd loop)
862          */
863         ptr = space;
864         bio->bio_caller_info3.value = sectors;
865 #if 0
866         kprintf("Write, bytes = %d (b_bcount), "
867                 "sectors = %d (bio = %p, b_cmd = %d)\n",
868                 bytes, sectors, bio, bio->bio_buf->b_cmd);
869 #endif
870         for (i = 0; i < sectors; i++) {
871                 crp = (struct cryptop *)ptr;
872                 ptr += sizeof(*crp);
873                 crd = (struct cryptodesc *)ptr;
874                 ptr += sizeof (*crd);
875
876                 crp->crp_buf = dmtc->data_buf + i * DEV_BSIZE;
877
878                 crp->crp_sid = priv->crypto_sid;
879                 crp->crp_ilen = crp->crp_olen = DEV_BSIZE;
880
881                 crp->crp_opaque = (void *)bio;
882
883                 crp->crp_callback = dmtc_crypto_cb_write_done;
884                 crp->crp_desc = crd;
885                 crp->crp_etype = 0;
886                 crp->crp_flags = CRYPTO_F_CBIFSYNC | CRYPTO_F_REL;
887
888                 crd->crd_alg = priv->crypto_alg;
889                 crd->crd_key = (caddr_t)priv->crypto_key;
890                 crd->crd_klen = priv->crypto_klen;
891
892                 priv->crypto_ivgen(priv, crd->crd_iv, sizeof(crd->crd_iv),
893                                    isector + i);
894
895                 crd->crd_skip = 0;
896                 crd->crd_len = DEV_BSIZE /* XXX */;
897                 crd->crd_flags = CRD_F_KEY_EXPLICIT | CRD_F_IV_EXPLICIT |
898                                  CRD_F_IV_PRESENT;
899                 crd->crd_next = NULL;
900
901                 crd->crd_flags |= CRD_F_ENCRYPT;
902                 error = crypto_dispatch(crp);
903         }
904 }
905
906 /*
907  * STRATEGY WRITE PATH PART 2/3
908  */
909 static int
910 dmtc_crypto_cb_write_done(struct cryptop *crp)
911 {
912         struct dmtc_helper *dmtc;
913         dm_target_crypt_config_t *priv;
914         struct bio *bio, *obio;
915         int n;
916
917         if (crp->crp_etype == EAGAIN)
918                 return crypto_dispatch(crp);
919
920         bio = (struct bio *)crp->crp_opaque;
921         KKASSERT(bio != NULL);
922
923         n = atomic_fetchadd_int(&bio->bio_caller_info3.value, -1);
924 #if 0
925         kprintf("dmtc_crypto_cb_write_done %p, n = %d\n", bio, n);
926 #endif
927
928         /*
929          * Cumulative error
930          */
931         if (crp->crp_etype != 0) {
932                 kprintf("dm_target_crypt: dmtc_crypto_cb_write_done "
933                         "crp_etype = %d\n",
934                 crp->crp_etype);
935                 bio->bio_buf->b_error = crp->crp_etype;
936         }
937
938         /*
939          * On the last chunk of the encryption we issue the write
940          */
941         if (n == 1) {
942                 dmtc = bio->bio_caller_info2.ptr;
943                 priv = (dm_target_crypt_config_t *)bio->bio_caller_info1.ptr;
944
945                 if (bio->bio_buf->b_error) {
946                         bio->bio_buf->b_flags |= B_ERROR;
947                         kfree(dmtc->free_addr, M_DMCRYPT);
948                         obio = pop_bio(bio);
949                         biodone(obio);
950                 } else {
951                         dmtc->orig_buf = bio->bio_buf->b_data;
952                         bio->bio_buf->b_data = dmtc->data_buf;
953                         bio->bio_done = dmtc_bio_write_done;
954                         vn_strategy(priv->pdev->pdev_vnode, bio);
955                 }
956         }
957         return 0;
958 }
959
960 /*
961  * STRATEGY WRITE PATH PART 3/3
962  */
963 static void
964 dmtc_bio_write_done(struct bio *bio)
965 {
966         struct dmtc_helper *dmtc;
967         struct bio *obio;
968
969         dmtc = bio->bio_caller_info2.ptr;
970         bio->bio_buf->b_data = dmtc->orig_buf;
971         kfree(dmtc->free_addr, M_DMCRYPT);
972         obio = pop_bio(bio);
973         biodone(obio);
974 }
975 /* END OF STRATEGY WRITE SECTION */