| File: | dev/softraid_crypto.c |
| Warning: | line 169, column 17 Result of 'malloc' is converted to a pointer of type 'struct sr_meta_opt_hdr', which is incompatible with sizeof operand type 'struct sr_meta_crypto' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: softraid_crypto.c,v 1.145 2021/10/24 14:50:42 tobhe Exp $ */ |
| 2 | /* |
| 3 | * Copyright (c) 2007 Marco Peereboom <marco@peereboom.us> |
| 4 | * Copyright (c) 2008 Hans-Joerg Hoexer <hshoexer@openbsd.org> |
| 5 | * Copyright (c) 2008 Damien Miller <djm@mindrot.org> |
| 6 | * Copyright (c) 2009 Joel Sing <jsing@openbsd.org> |
| 7 | * |
| 8 | * Permission to use, copy, modify, and distribute this software for any |
| 9 | * purpose with or without fee is hereby granted, provided that the above |
| 10 | * copyright notice and this permission notice appear in all copies. |
| 11 | * |
| 12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 13 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| 14 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| 15 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| 16 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| 17 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| 18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 19 | */ |
| 20 | |
| 21 | #include "bio.h" |
| 22 | |
| 23 | #include <sys/param.h> |
| 24 | #include <sys/systm.h> |
| 25 | #include <sys/buf.h> |
| 26 | #include <sys/device.h> |
| 27 | #include <sys/ioctl.h> |
| 28 | #include <sys/malloc.h> |
| 29 | #include <sys/pool.h> |
| 30 | #include <sys/kernel.h> |
| 31 | #include <sys/disk.h> |
| 32 | #include <sys/rwlock.h> |
| 33 | #include <sys/queue.h> |
| 34 | #include <sys/fcntl.h> |
| 35 | #include <sys/disklabel.h> |
| 36 | #include <sys/vnode.h> |
| 37 | #include <sys/mount.h> |
| 38 | #include <sys/sensors.h> |
| 39 | #include <sys/stat.h> |
| 40 | #include <sys/conf.h> |
| 41 | #include <sys/uio.h> |
| 42 | #include <sys/dkio.h> |
| 43 | |
| 44 | #include <crypto/cryptodev.h> |
| 45 | #include <crypto/rijndael.h> |
| 46 | #include <crypto/md5.h> |
| 47 | #include <crypto/sha1.h> |
| 48 | #include <crypto/sha2.h> |
| 49 | #include <crypto/hmac.h> |
| 50 | |
| 51 | #include <scsi/scsi_all.h> |
| 52 | #include <scsi/scsiconf.h> |
| 53 | #include <scsi/scsi_disk.h> |
| 54 | |
| 55 | #include <dev/softraidvar.h> |
| 56 | |
| 57 | struct sr_crypto_wu *sr_crypto_prepare(struct sr_workunit *, |
| 58 | struct sr_crypto *, int); |
| 59 | int sr_crypto_decrypt(u_char *, u_char *, u_char *, size_t, int); |
| 60 | int sr_crypto_encrypt(u_char *, u_char *, u_char *, size_t, int); |
| 61 | int sr_crypto_decrypt_key(struct sr_discipline *, |
| 62 | struct sr_crypto *); |
| 63 | int sr_crypto_change_maskkey(struct sr_discipline *, |
| 64 | struct sr_crypto *, struct sr_crypto_kdfinfo *, |
| 65 | struct sr_crypto_kdfinfo *); |
| 66 | int sr_crypto_create(struct sr_discipline *, |
| 67 | struct bioc_createraid *, int, int64_t); |
| 68 | int sr_crypto_meta_create(struct sr_discipline *, |
| 69 | struct sr_crypto *, struct bioc_createraid *); |
| 70 | int sr_crypto_set_key(struct sr_discipline *, struct sr_crypto *, |
| 71 | struct bioc_createraid *, int, void *); |
| 72 | int sr_crypto_assemble(struct sr_discipline *, |
| 73 | struct bioc_createraid *, int, void *); |
| 74 | void sr_crypto_free_sessions(struct sr_discipline *, |
| 75 | struct sr_crypto *); |
| 76 | int sr_crypto_alloc_resources_internal(struct sr_discipline *, |
| 77 | struct sr_crypto *); |
| 78 | int sr_crypto_alloc_resources(struct sr_discipline *); |
| 79 | void sr_crypto_free_resources_internal(struct sr_discipline *, |
| 80 | struct sr_crypto *); |
| 81 | void sr_crypto_free_resources(struct sr_discipline *); |
| 82 | int sr_crypto_ioctl_internal(struct sr_discipline *, |
| 83 | struct sr_crypto *, struct bioc_discipline *); |
| 84 | int sr_crypto_ioctl(struct sr_discipline *, |
| 85 | struct bioc_discipline *); |
| 86 | int sr_crypto_meta_opt_handler_internal(struct sr_discipline *, |
| 87 | struct sr_crypto *, struct sr_meta_opt_hdr *); |
| 88 | int sr_crypto_meta_opt_handler(struct sr_discipline *, |
| 89 | struct sr_meta_opt_hdr *); |
| 90 | int sr_crypto_rw(struct sr_workunit *); |
| 91 | int sr_crypto_dev_rw(struct sr_workunit *, struct sr_crypto_wu *); |
| 92 | void sr_crypto_done_internal(struct sr_workunit *, |
| 93 | struct sr_crypto *); |
| 94 | void sr_crypto_done(struct sr_workunit *); |
| 95 | void sr_crypto_calculate_check_hmac_sha1(u_int8_t *, int, |
| 96 | u_int8_t *, int, u_char *); |
| 97 | void sr_crypto_hotplug(struct sr_discipline *, struct disk *, int); |
| 98 | |
| 99 | #ifdef SR_DEBUG0 |
| 100 | void sr_crypto_dumpkeys(struct sr_crypto *); |
| 101 | #endif |
| 102 | |
| 103 | /* Discipline initialisation. */ |
| 104 | void |
| 105 | sr_crypto_discipline_init(struct sr_discipline *sd) |
| 106 | { |
| 107 | int i; |
| 108 | |
| 109 | /* Fill out discipline members. */ |
| 110 | sd->sd_wu_size = sizeof(struct sr_crypto_wu); |
| 111 | sd->sd_type = SR_MD_CRYPTO4; |
| 112 | strlcpy(sd->sd_name, "CRYPTO", sizeof(sd->sd_name)); |
| 113 | sd->sd_capabilities = SR_CAP_SYSTEM_DISK0x00000001 | SR_CAP_AUTO_ASSEMBLE0x00000002; |
| 114 | sd->sd_max_wu = SR_CRYPTO_NOWU16; |
| 115 | |
| 116 | for (i = 0; i < SR_CRYPTO_MAXKEYS32; i++) |
| 117 | sd->mdssd_dis_specific.mdd_crypto.scr_sid[i] = (u_int64_t)-1; |
| 118 | |
| 119 | /* Setup discipline specific function pointers. */ |
| 120 | sd->sd_alloc_resources = sr_crypto_alloc_resources; |
| 121 | sd->sd_assemble = sr_crypto_assemble; |
| 122 | sd->sd_create = sr_crypto_create; |
| 123 | sd->sd_free_resources = sr_crypto_free_resources; |
| 124 | sd->sd_ioctl_handler = sr_crypto_ioctl; |
| 125 | sd->sd_meta_opt_handler = sr_crypto_meta_opt_handler; |
| 126 | sd->sd_scsi_rw = sr_crypto_rw; |
| 127 | sd->sd_scsi_done = sr_crypto_done; |
| 128 | } |
| 129 | |
| 130 | int |
| 131 | sr_crypto_create(struct sr_discipline *sd, struct bioc_createraid *bc, |
| 132 | int no_chunk, int64_t coerced_size) |
| 133 | { |
| 134 | int rv = EINVAL22; |
| 135 | |
| 136 | if (no_chunk != 1) { |
| 137 | sr_error(sd->sd_sc, "%s requires exactly one chunk", |
| 138 | sd->sd_name); |
| 139 | return (rv); |
| 140 | } |
| 141 | |
| 142 | sd->sd_meta->ssdi_sdd_invariant.ssd_size = coerced_size; |
| 143 | |
| 144 | rv = sr_crypto_meta_create(sd, &sd->mdssd_dis_specific.mdd_crypto, bc); |
| 145 | if (rv) |
| 146 | return (rv); |
| 147 | |
| 148 | sd->sd_max_ccb_per_wu = no_chunk; |
| 149 | return (0); |
| 150 | } |
| 151 | |
| 152 | int |
| 153 | sr_crypto_meta_create(struct sr_discipline *sd, struct sr_crypto *mdd_crypto, |
| 154 | struct bioc_createraid *bc) |
| 155 | { |
| 156 | struct sr_meta_opt_item *omi; |
| 157 | int rv = EINVAL22; |
| 158 | |
| 159 | if (sd->sd_meta->ssdi_sdd_invariant.ssd_size > SR_CRYPTO_MAXSIZE((1ULL << 30) * 32)) { |
| 160 | sr_error(sd->sd_sc, "%s exceeds maximum size (%lli > %llu)", |
| 161 | sd->sd_name, sd->sd_meta->ssdi_sdd_invariant.ssd_size, |
| 162 | SR_CRYPTO_MAXSIZE((1ULL << 30) * 32)); |
| 163 | goto done; |
| 164 | } |
| 165 | |
| 166 | /* Create crypto optional metadata. */ |
| 167 | omi = malloc(sizeof(struct sr_meta_opt_item), M_DEVBUF2, |
| 168 | M_WAITOK0x0001 | M_ZERO0x0008); |
| 169 | omi->omi_som = malloc(sizeof(struct sr_meta_crypto), M_DEVBUF2, |
Result of 'malloc' is converted to a pointer of type 'struct sr_meta_opt_hdr', which is incompatible with sizeof operand type 'struct sr_meta_crypto' | |
| 170 | M_WAITOK0x0001 | M_ZERO0x0008); |
| 171 | omi->omi_som->som_type = SR_OPT_CRYPTO0x01; |
| 172 | omi->omi_som->som_length = sizeof(struct sr_meta_crypto); |
| 173 | SLIST_INSERT_HEAD(&sd->sd_meta_opt, omi, omi_link)do { (omi)->omi_link.sle_next = (&sd->sd_meta_opt)-> slh_first; (&sd->sd_meta_opt)->slh_first = (omi); } while (0); |
| 174 | mdd_crypto->scr_meta = (struct sr_meta_crypto *)omi->omi_som; |
| 175 | sd->sd_meta->ssdi_sdd_invariant.ssd_opt_no++; |
| 176 | |
| 177 | mdd_crypto->key_disk = NULL((void *)0); |
| 178 | |
| 179 | if (bc->bc_key_disk != NODEV(dev_t)(-1)) { |
| 180 | |
| 181 | /* Create a key disk. */ |
| 182 | if (sr_crypto_get_kdf(bc, sd, mdd_crypto)) |
| 183 | goto done; |
| 184 | mdd_crypto->key_disk = |
| 185 | sr_crypto_create_key_disk(sd, mdd_crypto, bc->bc_key_disk); |
| 186 | if (mdd_crypto->key_disk == NULL((void *)0)) |
| 187 | goto done; |
| 188 | sd->sd_capabilities |= SR_CAP_AUTO_ASSEMBLE0x00000002; |
| 189 | |
| 190 | } else if (bc->bc_opaque_flags & BIOC_SOOUT0x02) { |
| 191 | |
| 192 | /* No hint available yet. */ |
| 193 | bc->bc_opaque_status = BIOC_SOINOUT_FAILED0x00; |
| 194 | rv = EAGAIN35; |
| 195 | goto done; |
| 196 | |
| 197 | } else if (sr_crypto_get_kdf(bc, sd, mdd_crypto)) |
| 198 | goto done; |
| 199 | |
| 200 | /* Passphrase volumes cannot be automatically assembled. */ |
| 201 | if (!(bc->bc_flags & BIOC_SCNOAUTOASSEMBLE0x04) && bc->bc_key_disk == NODEV(dev_t)(-1)) |
| 202 | goto done; |
| 203 | |
| 204 | sr_crypto_create_keys(sd, mdd_crypto); |
| 205 | |
| 206 | rv = 0; |
| 207 | done: |
| 208 | return (rv); |
| 209 | } |
| 210 | |
| 211 | int |
| 212 | sr_crypto_set_key(struct sr_discipline *sd, struct sr_crypto *mdd_crypto, |
| 213 | struct bioc_createraid *bc, int no_chunk, void *data) |
| 214 | { |
| 215 | int rv = EINVAL22; |
| 216 | |
| 217 | mdd_crypto->key_disk = NULL((void *)0); |
| 218 | |
| 219 | /* Crypto optional metadata must already exist... */ |
| 220 | if (mdd_crypto->scr_meta == NULL((void *)0)) |
| 221 | goto done; |
| 222 | |
| 223 | if (data != NULL((void *)0)) { |
| 224 | /* Kernel already has mask key. */ |
| 225 | memcpy(mdd_crypto->scr_maskkey, data,__builtin_memcpy((mdd_crypto->scr_maskkey), (data), (sizeof (mdd_crypto->scr_maskkey))) |
| 226 | sizeof(mdd_crypto->scr_maskkey))__builtin_memcpy((mdd_crypto->scr_maskkey), (data), (sizeof (mdd_crypto->scr_maskkey))); |
| 227 | } else if (bc->bc_key_disk != NODEV(dev_t)(-1)) { |
| 228 | /* Read the mask key from the key disk. */ |
| 229 | mdd_crypto->key_disk = |
| 230 | sr_crypto_read_key_disk(sd, mdd_crypto, bc->bc_key_disk); |
| 231 | if (mdd_crypto->key_disk == NULL((void *)0)) |
| 232 | goto done; |
| 233 | } else if (bc->bc_opaque_flags & BIOC_SOOUT0x02) { |
| 234 | /* provide userland with kdf hint */ |
| 235 | if (bc->bc_opaque == NULL((void *)0)) |
| 236 | goto done; |
| 237 | |
| 238 | if (sizeof(mdd_crypto->scr_meta->scm_kdfhint) < |
| 239 | bc->bc_opaque_size) |
| 240 | goto done; |
| 241 | |
| 242 | if (copyout(mdd_crypto->scr_meta->scm_kdfhint, |
| 243 | bc->bc_opaque, bc->bc_opaque_size)) |
| 244 | goto done; |
| 245 | |
| 246 | /* we're done */ |
| 247 | bc->bc_opaque_status = BIOC_SOINOUT_OK0x01; |
| 248 | rv = EAGAIN35; |
| 249 | goto done; |
| 250 | } else if (bc->bc_opaque_flags & BIOC_SOIN0x01) { |
| 251 | /* get kdf with maskkey from userland */ |
| 252 | if (sr_crypto_get_kdf(bc, sd, mdd_crypto)) |
| 253 | goto done; |
| 254 | } else |
| 255 | goto done; |
| 256 | |
| 257 | |
| 258 | rv = 0; |
| 259 | done: |
| 260 | return (rv); |
| 261 | } |
| 262 | |
| 263 | int |
| 264 | sr_crypto_assemble(struct sr_discipline *sd, |
| 265 | struct bioc_createraid *bc, int no_chunk, void *data) |
| 266 | { |
| 267 | int rv; |
| 268 | |
| 269 | rv = sr_crypto_set_key(sd, &sd->mdssd_dis_specific.mdd_crypto, bc, no_chunk, data); |
| 270 | if (rv) |
| 271 | return (rv); |
| 272 | |
| 273 | sd->sd_max_ccb_per_wu = sd->sd_meta->ssdi_sdd_invariant.ssd_chunk_no; |
| 274 | return (0); |
| 275 | } |
| 276 | |
| 277 | struct sr_crypto_wu * |
| 278 | sr_crypto_prepare(struct sr_workunit *wu, struct sr_crypto *mdd_crypto, |
| 279 | int encrypt) |
| 280 | { |
| 281 | struct scsi_xfer *xs = wu->swu_xs; |
| 282 | struct sr_crypto_wu *crwu; |
| 283 | struct cryptodesc *crd; |
| 284 | int flags, i, n; |
| 285 | daddr_t blkno; |
| 286 | u_int keyndx; |
| 287 | |
| 288 | DNPRINTF(SR_D_DIS, "%s: sr_crypto_prepare wu %p encrypt %d\n", |
| 289 | DEVNAME(wu->swu_dis->sd_sc), wu, encrypt); |
| 290 | |
| 291 | crwu = (struct sr_crypto_wu *)wu; |
| 292 | crwu->cr_uio.uio_iovcnt = 1; |
| 293 | crwu->cr_uio.uio_iov->iov_len = xs->datalen; |
| 294 | if (xs->flags & SCSI_DATA_OUT0x01000) { |
| 295 | crwu->cr_uio.uio_iov->iov_base = crwu->cr_dmabuf; |
| 296 | memcpy(crwu->cr_uio.uio_iov->iov_base, xs->data, xs->datalen)__builtin_memcpy((crwu->cr_uio.uio_iov->iov_base), (xs-> data), (xs->datalen)); |
| 297 | } else |
| 298 | crwu->cr_uio.uio_iov->iov_base = xs->data; |
| 299 | |
| 300 | blkno = wu->swu_blk_start; |
| 301 | n = xs->datalen >> DEV_BSHIFT9; |
| 302 | |
| 303 | /* |
| 304 | * We preallocated enough crypto descs for up to MAXPHYS of I/O. |
| 305 | * Since there may be less than that we need to tweak the amount |
| 306 | * of crypto desc structures to be just long enough for our needs. |
| 307 | */ |
| 308 | KASSERT(crwu->cr_crp->crp_ndescalloc >= n)((crwu->cr_crp->crp_ndescalloc >= n) ? (void)0 : __assert ("diagnostic ", "/usr/src/sys/dev/softraid_crypto.c", 308, "crwu->cr_crp->crp_ndescalloc >= n" )); |
| 309 | crwu->cr_crp->crp_ndesc = n; |
| 310 | flags = (encrypt ? CRD_F_ENCRYPT0x01 : 0) | |
| 311 | CRD_F_IV_PRESENT0x02 | CRD_F_IV_EXPLICIT0x04; |
| 312 | |
| 313 | /* |
| 314 | * Select crypto session based on block number. |
| 315 | * |
| 316 | * XXX - this does not handle the case where the read/write spans |
| 317 | * across a different key blocks (e.g. 0.5TB boundary). Currently |
| 318 | * this is already broken by the use of scr_key[0] below. |
| 319 | */ |
| 320 | keyndx = blkno >> SR_CRYPTO_KEY_BLKSHIFT30; |
| 321 | crwu->cr_crp->crp_sid = mdd_crypto->scr_sid[keyndx]; |
| 322 | |
| 323 | crwu->cr_crp->crp_ilen = xs->datalen; |
| 324 | crwu->cr_crp->crp_alloctype = M_DEVBUF2; |
| 325 | crwu->cr_crp->crp_flags = CRYPTO_F_IOV0x0002; |
| 326 | crwu->cr_crp->crp_buf = &crwu->cr_uio; |
| 327 | for (i = 0; i < crwu->cr_crp->crp_ndesc; i++, blkno++) { |
| 328 | crd = &crwu->cr_crp->crp_desc[i]; |
| 329 | crd->crd_skip = i << DEV_BSHIFT9; |
| 330 | crd->crd_len = DEV_BSIZE(1 << 9); |
| 331 | crd->crd_inject = 0; |
| 332 | crd->crd_flags = flags; |
| 333 | crd->crd_algCRD_INI.cri_alg = mdd_crypto->scr_alg; |
| 334 | crd->crd_klenCRD_INI.cri_klen = mdd_crypto->scr_klen; |
| 335 | crd->crd_keyCRD_INI.cri_key = mdd_crypto->scr_key[0]; |
| 336 | memcpy(crd->crd_iv, &blkno, sizeof(blkno))__builtin_memcpy((crd->CRD_INI.u.iv), (&blkno), (sizeof (blkno))); |
| 337 | } |
| 338 | |
| 339 | return (crwu); |
| 340 | } |
| 341 | |
| 342 | int |
| 343 | sr_crypto_get_kdf(struct bioc_createraid *bc, struct sr_discipline *sd, |
| 344 | struct sr_crypto *mdd_crypto) |
| 345 | { |
| 346 | int rv = EINVAL22; |
| 347 | struct sr_crypto_kdfinfo *kdfinfo; |
| 348 | |
| 349 | if (!(bc->bc_opaque_flags & BIOC_SOIN0x01)) |
| 350 | return (rv); |
| 351 | if (bc->bc_opaque == NULL((void *)0)) |
| 352 | return (rv); |
| 353 | if (bc->bc_opaque_size != sizeof(*kdfinfo)) |
| 354 | return (rv); |
| 355 | |
| 356 | kdfinfo = malloc(bc->bc_opaque_size, M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008); |
| 357 | if (copyin(bc->bc_opaque, kdfinfo, bc->bc_opaque_size)) |
| 358 | goto out; |
| 359 | |
| 360 | if (kdfinfo->len != bc->bc_opaque_size) |
| 361 | goto out; |
| 362 | |
| 363 | /* copy KDF hint to disk meta data */ |
| 364 | if (kdfinfo->flags & SR_CRYPTOKDF_HINT(1<<1)) { |
| 365 | if (sizeof(mdd_crypto->scr_meta->scm_kdfhint) < |
| 366 | kdfinfo->genkdf_kdfhint.generic.len) |
| 367 | goto out; |
| 368 | memcpy(mdd_crypto->scr_meta->scm_kdfhint,__builtin_memcpy((mdd_crypto->scr_meta->scm_kdfhint), ( &kdfinfo->_kdfhint.generic), (kdfinfo->_kdfhint.generic .len)) |
| 369 | &kdfinfo->genkdf, kdfinfo->genkdf.len)__builtin_memcpy((mdd_crypto->scr_meta->scm_kdfhint), ( &kdfinfo->_kdfhint.generic), (kdfinfo->_kdfhint.generic .len)); |
| 370 | } |
| 371 | |
| 372 | /* copy mask key to run-time meta data */ |
| 373 | if ((kdfinfo->flags & SR_CRYPTOKDF_KEY(1<<0))) { |
| 374 | if (sizeof(mdd_crypto->scr_maskkey) < sizeof(kdfinfo->maskkey)) |
| 375 | goto out; |
| 376 | memcpy(mdd_crypto->scr_maskkey, &kdfinfo->maskkey,__builtin_memcpy((mdd_crypto->scr_maskkey), (&kdfinfo-> maskkey), (sizeof(kdfinfo->maskkey))) |
| 377 | sizeof(kdfinfo->maskkey))__builtin_memcpy((mdd_crypto->scr_maskkey), (&kdfinfo-> maskkey), (sizeof(kdfinfo->maskkey))); |
| 378 | } |
| 379 | |
| 380 | bc->bc_opaque_status = BIOC_SOINOUT_OK0x01; |
| 381 | rv = 0; |
| 382 | out: |
| 383 | explicit_bzero(kdfinfo, bc->bc_opaque_size); |
| 384 | free(kdfinfo, M_DEVBUF2, bc->bc_opaque_size); |
| 385 | |
| 386 | return (rv); |
| 387 | } |
| 388 | |
| 389 | int |
| 390 | sr_crypto_encrypt(u_char *p, u_char *c, u_char *key, size_t size, int alg) |
| 391 | { |
| 392 | rijndael_ctx ctx; |
| 393 | int i, rv = 1; |
| 394 | |
| 395 | switch (alg) { |
| 396 | case SR_CRYPTOM_AES_ECB_2561: |
| 397 | if (rijndael_set_key_enc_only(&ctx, key, 256) != 0) |
| 398 | goto out; |
| 399 | for (i = 0; i < size; i += RIJNDAEL128_BLOCK_LEN16) |
| 400 | rijndael_encrypt(&ctx, &p[i], &c[i]); |
| 401 | rv = 0; |
| 402 | break; |
| 403 | default: |
| 404 | DNPRINTF(SR_D_DIS, "%s: unsupported encryption algorithm %d\n", |
| 405 | "softraid", alg); |
| 406 | rv = -1; |
| 407 | goto out; |
| 408 | } |
| 409 | |
| 410 | out: |
| 411 | explicit_bzero(&ctx, sizeof(ctx)); |
| 412 | return (rv); |
| 413 | } |
| 414 | |
| 415 | int |
| 416 | sr_crypto_decrypt(u_char *c, u_char *p, u_char *key, size_t size, int alg) |
| 417 | { |
| 418 | rijndael_ctx ctx; |
| 419 | int i, rv = 1; |
| 420 | |
| 421 | switch (alg) { |
| 422 | case SR_CRYPTOM_AES_ECB_2561: |
| 423 | if (rijndael_set_key(&ctx, key, 256) != 0) |
| 424 | goto out; |
| 425 | for (i = 0; i < size; i += RIJNDAEL128_BLOCK_LEN16) |
| 426 | rijndael_decrypt(&ctx, &c[i], &p[i]); |
| 427 | rv = 0; |
| 428 | break; |
| 429 | default: |
| 430 | DNPRINTF(SR_D_DIS, "%s: unsupported encryption algorithm %d\n", |
| 431 | "softraid", alg); |
| 432 | rv = -1; |
| 433 | goto out; |
| 434 | } |
| 435 | |
| 436 | out: |
| 437 | explicit_bzero(&ctx, sizeof(ctx)); |
| 438 | return (rv); |
| 439 | } |
| 440 | |
| 441 | void |
| 442 | sr_crypto_calculate_check_hmac_sha1(u_int8_t *maskkey, int maskkey_size, |
| 443 | u_int8_t *key, int key_size, u_char *check_digest) |
| 444 | { |
| 445 | u_char check_key[SHA1_DIGEST_LENGTH20]; |
| 446 | HMAC_SHA1_CTX hmacctx; |
| 447 | SHA1_CTX shactx; |
| 448 | |
| 449 | bzero(check_key, sizeof(check_key))__builtin_bzero((check_key), (sizeof(check_key))); |
| 450 | bzero(&hmacctx, sizeof(hmacctx))__builtin_bzero((&hmacctx), (sizeof(hmacctx))); |
| 451 | bzero(&shactx, sizeof(shactx))__builtin_bzero((&shactx), (sizeof(shactx))); |
| 452 | |
| 453 | /* k = SHA1(mask_key) */ |
| 454 | SHA1Init(&shactx); |
| 455 | SHA1Update(&shactx, maskkey, maskkey_size); |
| 456 | SHA1Final(check_key, &shactx); |
| 457 | |
| 458 | /* mac = HMAC_SHA1_k(unencrypted key) */ |
| 459 | HMAC_SHA1_Init(&hmacctx, check_key, sizeof(check_key)); |
| 460 | HMAC_SHA1_Update(&hmacctx, key, key_size); |
| 461 | HMAC_SHA1_Final(check_digest, &hmacctx); |
| 462 | |
| 463 | explicit_bzero(check_key, sizeof(check_key)); |
| 464 | explicit_bzero(&hmacctx, sizeof(hmacctx)); |
| 465 | explicit_bzero(&shactx, sizeof(shactx)); |
| 466 | } |
| 467 | |
| 468 | int |
| 469 | sr_crypto_decrypt_key(struct sr_discipline *sd, struct sr_crypto *mdd_crypto) |
| 470 | { |
| 471 | u_char check_digest[SHA1_DIGEST_LENGTH20]; |
| 472 | int rv = 1; |
| 473 | |
| 474 | DNPRINTF(SR_D_DIS, "%s: sr_crypto_decrypt_key\n", DEVNAME(sd->sd_sc)); |
| 475 | |
| 476 | if (mdd_crypto->scr_meta->scm_check_alg != SR_CRYPTOC_HMAC_SHA11) |
| 477 | goto out; |
| 478 | |
| 479 | if (sr_crypto_decrypt((u_char *)mdd_crypto->scr_meta->scm_key, |
| 480 | (u_char *)mdd_crypto->scr_key, |
| 481 | mdd_crypto->scr_maskkey, sizeof(mdd_crypto->scr_key), |
| 482 | mdd_crypto->scr_meta->scm_mask_alg) == -1) |
| 483 | goto out; |
| 484 | |
| 485 | #ifdef SR_DEBUG0 |
| 486 | sr_crypto_dumpkeys(mdd_crypto); |
| 487 | #endif |
| 488 | |
| 489 | /* Check that the key decrypted properly. */ |
| 490 | sr_crypto_calculate_check_hmac_sha1(mdd_crypto->scr_maskkey, |
| 491 | sizeof(mdd_crypto->scr_maskkey), (u_int8_t *)mdd_crypto->scr_key, |
| 492 | sizeof(mdd_crypto->scr_key), check_digest); |
| 493 | if (memcmp(mdd_crypto->scr_meta->chk_hmac_sha1.sch_mac,__builtin_memcmp((mdd_crypto->scr_meta->_scm_chk.chk_hmac_sha1 .sch_mac), (check_digest), (sizeof(check_digest))) |
| 494 | check_digest, sizeof(check_digest))__builtin_memcmp((mdd_crypto->scr_meta->_scm_chk.chk_hmac_sha1 .sch_mac), (check_digest), (sizeof(check_digest))) != 0) { |
| 495 | explicit_bzero(mdd_crypto->scr_key, |
| 496 | sizeof(mdd_crypto->scr_key)); |
| 497 | goto out; |
| 498 | } |
| 499 | |
| 500 | rv = 0; /* Success */ |
| 501 | out: |
| 502 | /* we don't need the mask key anymore */ |
| 503 | explicit_bzero(&mdd_crypto->scr_maskkey, |
| 504 | sizeof(mdd_crypto->scr_maskkey)); |
| 505 | |
| 506 | explicit_bzero(check_digest, sizeof(check_digest)); |
| 507 | |
| 508 | return rv; |
| 509 | } |
| 510 | |
| 511 | int |
| 512 | sr_crypto_create_keys(struct sr_discipline *sd, struct sr_crypto *mdd_crypto) |
| 513 | { |
| 514 | |
| 515 | DNPRINTF(SR_D_DIS, "%s: sr_crypto_create_keys\n", |
| 516 | DEVNAME(sd->sd_sc)); |
| 517 | |
| 518 | if (AES_MAXKEYBYTES((256)/8) < sizeof(mdd_crypto->scr_maskkey)) |
| 519 | return (1); |
| 520 | |
| 521 | /* XXX allow user to specify */ |
| 522 | mdd_crypto->scr_meta->scm_alg = SR_CRYPTOA_AES_XTS_2562; |
| 523 | |
| 524 | /* generate crypto keys */ |
| 525 | arc4random_buf(mdd_crypto->scr_key, sizeof(mdd_crypto->scr_key)); |
| 526 | |
| 527 | /* Mask the disk keys. */ |
| 528 | mdd_crypto->scr_meta->scm_mask_alg = SR_CRYPTOM_AES_ECB_2561; |
| 529 | sr_crypto_encrypt((u_char *)mdd_crypto->scr_key, |
| 530 | (u_char *)mdd_crypto->scr_meta->scm_key, |
| 531 | mdd_crypto->scr_maskkey, sizeof(mdd_crypto->scr_key), |
| 532 | mdd_crypto->scr_meta->scm_mask_alg); |
| 533 | |
| 534 | /* Prepare key decryption check code. */ |
| 535 | mdd_crypto->scr_meta->scm_check_alg = SR_CRYPTOC_HMAC_SHA11; |
| 536 | sr_crypto_calculate_check_hmac_sha1(mdd_crypto->scr_maskkey, |
| 537 | sizeof(mdd_crypto->scr_maskkey), |
| 538 | (u_int8_t *)mdd_crypto->scr_key, sizeof(mdd_crypto->scr_key), |
| 539 | mdd_crypto->scr_meta->chk_hmac_sha1_scm_chk.chk_hmac_sha1.sch_mac); |
| 540 | |
| 541 | /* Erase the plaintext disk keys */ |
| 542 | explicit_bzero(mdd_crypto->scr_key, sizeof(mdd_crypto->scr_key)); |
| 543 | |
| 544 | #ifdef SR_DEBUG0 |
| 545 | sr_crypto_dumpkeys(mdd_crypto); |
| 546 | #endif |
| 547 | |
| 548 | mdd_crypto->scr_meta->scm_flags = SR_CRYPTOF_KEY(1<<0) | SR_CRYPTOF_KDFHINT(1<<1); |
| 549 | |
| 550 | return (0); |
| 551 | } |
| 552 | |
| 553 | int |
| 554 | sr_crypto_change_maskkey(struct sr_discipline *sd, struct sr_crypto *mdd_crypto, |
| 555 | struct sr_crypto_kdfinfo *kdfinfo1, struct sr_crypto_kdfinfo *kdfinfo2) |
| 556 | { |
| 557 | u_char check_digest[SHA1_DIGEST_LENGTH20]; |
| 558 | u_char *c, *p = NULL((void *)0); |
| 559 | size_t ksz; |
| 560 | int rv = 1; |
| 561 | |
| 562 | DNPRINTF(SR_D_DIS, "%s: sr_crypto_change_maskkey\n", |
| 563 | DEVNAME(sd->sd_sc)); |
| 564 | |
| 565 | if (mdd_crypto->scr_meta->scm_check_alg != SR_CRYPTOC_HMAC_SHA11) |
| 566 | goto out; |
| 567 | |
| 568 | c = (u_char *)mdd_crypto->scr_meta->scm_key; |
| 569 | ksz = sizeof(mdd_crypto->scr_key); |
| 570 | p = malloc(ksz, M_DEVBUF2, M_WAITOK0x0001 | M_CANFAIL0x0004 | M_ZERO0x0008); |
| 571 | if (p == NULL((void *)0)) |
| 572 | goto out; |
| 573 | |
| 574 | if (sr_crypto_decrypt(c, p, kdfinfo1->maskkey, ksz, |
| 575 | mdd_crypto->scr_meta->scm_mask_alg) == -1) |
| 576 | goto out; |
| 577 | |
| 578 | #ifdef SR_DEBUG0 |
| 579 | sr_crypto_dumpkeys(mdd_crypto); |
| 580 | #endif |
| 581 | |
| 582 | sr_crypto_calculate_check_hmac_sha1(kdfinfo1->maskkey, |
| 583 | sizeof(kdfinfo1->maskkey), p, ksz, check_digest); |
| 584 | if (memcmp(mdd_crypto->scr_meta->chk_hmac_sha1.sch_mac,__builtin_memcmp((mdd_crypto->scr_meta->_scm_chk.chk_hmac_sha1 .sch_mac), (check_digest), (sizeof(check_digest))) |
| 585 | check_digest, sizeof(check_digest))__builtin_memcmp((mdd_crypto->scr_meta->_scm_chk.chk_hmac_sha1 .sch_mac), (check_digest), (sizeof(check_digest))) != 0) { |
| 586 | sr_error(sd->sd_sc, "incorrect key or passphrase"); |
| 587 | rv = EPERM1; |
| 588 | goto out; |
| 589 | } |
| 590 | |
| 591 | /* Copy new KDF hint to metadata, if supplied. */ |
| 592 | if (kdfinfo2->flags & SR_CRYPTOKDF_HINT(1<<1)) { |
| 593 | if (kdfinfo2->genkdf_kdfhint.generic.len > |
| 594 | sizeof(mdd_crypto->scr_meta->scm_kdfhint)) |
| 595 | goto out; |
| 596 | explicit_bzero(mdd_crypto->scr_meta->scm_kdfhint, |
| 597 | sizeof(mdd_crypto->scr_meta->scm_kdfhint)); |
| 598 | memcpy(mdd_crypto->scr_meta->scm_kdfhint,__builtin_memcpy((mdd_crypto->scr_meta->scm_kdfhint), ( &kdfinfo2->_kdfhint.generic), (kdfinfo2->_kdfhint.generic .len)) |
| 599 | &kdfinfo2->genkdf, kdfinfo2->genkdf.len)__builtin_memcpy((mdd_crypto->scr_meta->scm_kdfhint), ( &kdfinfo2->_kdfhint.generic), (kdfinfo2->_kdfhint.generic .len)); |
| 600 | } |
| 601 | |
| 602 | /* Mask the disk keys. */ |
| 603 | c = (u_char *)mdd_crypto->scr_meta->scm_key; |
| 604 | if (sr_crypto_encrypt(p, c, kdfinfo2->maskkey, ksz, |
| 605 | mdd_crypto->scr_meta->scm_mask_alg) == -1) |
| 606 | goto out; |
| 607 | |
| 608 | /* Prepare key decryption check code. */ |
| 609 | mdd_crypto->scr_meta->scm_check_alg = SR_CRYPTOC_HMAC_SHA11; |
| 610 | sr_crypto_calculate_check_hmac_sha1(kdfinfo2->maskkey, |
| 611 | sizeof(kdfinfo2->maskkey), (u_int8_t *)mdd_crypto->scr_key, |
| 612 | sizeof(mdd_crypto->scr_key), check_digest); |
| 613 | |
| 614 | /* Copy new encrypted key and HMAC to metadata. */ |
| 615 | memcpy(mdd_crypto->scr_meta->chk_hmac_sha1.sch_mac, check_digest,__builtin_memcpy((mdd_crypto->scr_meta->_scm_chk.chk_hmac_sha1 .sch_mac), (check_digest), (sizeof(mdd_crypto->scr_meta-> _scm_chk.chk_hmac_sha1.sch_mac))) |
| 616 | sizeof(mdd_crypto->scr_meta->chk_hmac_sha1.sch_mac))__builtin_memcpy((mdd_crypto->scr_meta->_scm_chk.chk_hmac_sha1 .sch_mac), (check_digest), (sizeof(mdd_crypto->scr_meta-> _scm_chk.chk_hmac_sha1.sch_mac))); |
| 617 | |
| 618 | rv = 0; /* Success */ |
| 619 | |
| 620 | out: |
| 621 | if (p) { |
| 622 | explicit_bzero(p, ksz); |
| 623 | free(p, M_DEVBUF2, ksz); |
| 624 | } |
| 625 | |
| 626 | explicit_bzero(check_digest, sizeof(check_digest)); |
| 627 | explicit_bzero(&kdfinfo1->maskkey, sizeof(kdfinfo1->maskkey)); |
| 628 | explicit_bzero(&kdfinfo2->maskkey, sizeof(kdfinfo2->maskkey)); |
| 629 | |
| 630 | return (rv); |
| 631 | } |
| 632 | |
| 633 | struct sr_chunk * |
| 634 | sr_crypto_create_key_disk(struct sr_discipline *sd, |
| 635 | struct sr_crypto *mdd_crypto, dev_t dev) |
| 636 | { |
| 637 | struct sr_softc *sc = sd->sd_sc; |
| 638 | struct sr_discipline *fakesd = NULL((void *)0); |
| 639 | struct sr_metadata *sm = NULL((void *)0); |
| 640 | struct sr_meta_chunk *km; |
| 641 | struct sr_meta_opt_item *omi = NULL((void *)0); |
| 642 | struct sr_meta_keydisk *skm; |
| 643 | struct sr_chunk *key_disk = NULL((void *)0); |
| 644 | struct disklabel label; |
| 645 | struct vnode *vn; |
| 646 | char devname[32]; |
| 647 | int c, part, open = 0; |
| 648 | |
| 649 | /* |
| 650 | * Create a metadata structure on the key disk and store |
| 651 | * keying material in the optional metadata. |
| 652 | */ |
| 653 | |
| 654 | sr_meta_getdevname(sc, dev, devname, sizeof(devname)); |
| 655 | |
| 656 | /* Make sure chunk is not already in use. */ |
| 657 | c = sr_chunk_in_use(sc, dev); |
| 658 | if (c != BIOC_SDINVALID0xff && c != BIOC_SDOFFLINE0x01) { |
| 659 | sr_error(sc, "%s is already in use", devname); |
| 660 | goto done; |
| 661 | } |
| 662 | |
| 663 | /* Open device. */ |
| 664 | if (bdevvp(dev, &vn)) { |
| 665 | sr_error(sc, "cannot open key disk %s", devname); |
| 666 | goto done; |
| 667 | } |
| 668 | if (VOP_OPEN(vn, FREAD0x0001 | FWRITE0x0002, NOCRED((struct ucred *)-1), curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc)) { |
| 669 | DNPRINTF(SR_D_META,"%s: sr_crypto_create_key_disk cannot " |
| 670 | "open %s\n", DEVNAME(sc), devname); |
| 671 | vput(vn); |
| 672 | goto done; |
| 673 | } |
| 674 | open = 1; /* close dev on error */ |
| 675 | |
| 676 | /* Get partition details. */ |
| 677 | part = DISKPART(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >> 8)) % 16); |
| 678 | if (VOP_IOCTL(vn, DIOCGDINFO((unsigned long)0x40000000 | ((sizeof(struct disklabel) & 0x1fff) << 16) | ((('d')) << 8) | ((101))), (caddr_t)&label, |
| 679 | FREAD0x0001, NOCRED((struct ucred *)-1), curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc)) { |
| 680 | DNPRINTF(SR_D_META, "%s: sr_crypto_create_key_disk ioctl " |
| 681 | "failed\n", DEVNAME(sc)); |
| 682 | goto done; |
| 683 | } |
| 684 | if (label.d_partitions[part].p_fstype != FS_RAID19) { |
| 685 | sr_error(sc, "%s partition not of type RAID (%d)", |
| 686 | devname, label.d_partitions[part].p_fstype); |
| 687 | goto done; |
| 688 | } |
| 689 | |
| 690 | /* |
| 691 | * Create and populate chunk metadata. |
| 692 | */ |
| 693 | |
| 694 | key_disk = malloc(sizeof(struct sr_chunk), M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008); |
| 695 | km = &key_disk->src_meta; |
| 696 | |
| 697 | key_disk->src_dev_mm = dev; |
| 698 | key_disk->src_vn = vn; |
| 699 | strlcpy(key_disk->src_devname, devname, sizeof(km->scmi_scm_invariant.scm_devname)); |
| 700 | key_disk->src_size = 0; |
| 701 | |
| 702 | km->scmi_scm_invariant.scm_volid = sd->sd_meta->ssdi_sdd_invariant.ssd_level; |
| 703 | km->scmi_scm_invariant.scm_chunk_id = 0; |
| 704 | km->scmi_scm_invariant.scm_size = 0; |
| 705 | km->scmi_scm_invariant.scm_coerced_size = 0; |
| 706 | strlcpy(km->scmi_scm_invariant.scm_devname, devname, sizeof(km->scmi_scm_invariant.scm_devname)); |
| 707 | memcpy(&km->scmi.scm_uuid, &sd->sd_meta->ssdi.ssd_uuid,__builtin_memcpy((&km->_scm_invariant.scm_uuid), (& sd->sd_meta->_sdd_invariant.ssd_uuid), (sizeof(struct sr_uuid ))) |
| 708 | sizeof(struct sr_uuid))__builtin_memcpy((&km->_scm_invariant.scm_uuid), (& sd->sd_meta->_sdd_invariant.ssd_uuid), (sizeof(struct sr_uuid ))); |
| 709 | |
| 710 | sr_checksum(sc, km, &km->scm_checksum, |
| 711 | sizeof(struct sr_meta_chunk_invariant)); |
| 712 | |
| 713 | km->scm_status = BIOC_SDONLINE0x00; |
| 714 | |
| 715 | /* |
| 716 | * Create and populate our own discipline and metadata. |
| 717 | */ |
| 718 | |
| 719 | sm = malloc(sizeof(struct sr_metadata), M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008); |
| 720 | sm->ssdi_sdd_invariant.ssd_magic = SR_MAGIC0x4d4152436372616dLLU; |
| 721 | sm->ssdi_sdd_invariant.ssd_version = SR_META_VERSION6; |
| 722 | sm->ssd_ondisk = 0; |
| 723 | sm->ssdi_sdd_invariant.ssd_vol_flags = 0; |
| 724 | memcpy(&sm->ssdi.ssd_uuid, &sd->sd_meta->ssdi.ssd_uuid,__builtin_memcpy((&sm->_sdd_invariant.ssd_uuid), (& sd->sd_meta->_sdd_invariant.ssd_uuid), (sizeof(struct sr_uuid ))) |
| 725 | sizeof(struct sr_uuid))__builtin_memcpy((&sm->_sdd_invariant.ssd_uuid), (& sd->sd_meta->_sdd_invariant.ssd_uuid), (sizeof(struct sr_uuid ))); |
| 726 | sm->ssdi_sdd_invariant.ssd_chunk_no = 1; |
| 727 | sm->ssdi_sdd_invariant.ssd_volid = SR_KEYDISK_VOLID0xfffffffe; |
| 728 | sm->ssdi_sdd_invariant.ssd_level = SR_KEYDISK_LEVEL0xfffffffe; |
| 729 | sm->ssdi_sdd_invariant.ssd_size = 0; |
| 730 | strlcpy(sm->ssdi_sdd_invariant.ssd_vendor, "OPENBSD", sizeof(sm->ssdi_sdd_invariant.ssd_vendor)); |
| 731 | snprintf(sm->ssdi_sdd_invariant.ssd_product, sizeof(sm->ssdi_sdd_invariant.ssd_product), |
| 732 | "SR %s", "KEYDISK"); |
| 733 | snprintf(sm->ssdi_sdd_invariant.ssd_revision, sizeof(sm->ssdi_sdd_invariant.ssd_revision), |
| 734 | "%03d", SR_META_VERSION6); |
| 735 | |
| 736 | fakesd = malloc(sizeof(struct sr_discipline), M_DEVBUF2, |
| 737 | M_WAITOK0x0001 | M_ZERO0x0008); |
| 738 | fakesd->sd_sc = sd->sd_sc; |
| 739 | fakesd->sd_meta = sm; |
| 740 | fakesd->sd_meta_type = SR_META_F_NATIVE0; |
| 741 | fakesd->sd_vol_status = BIOC_SVONLINE0x00; |
| 742 | strlcpy(fakesd->sd_name, "KEYDISK", sizeof(fakesd->sd_name)); |
| 743 | SLIST_INIT(&fakesd->sd_meta_opt){ ((&fakesd->sd_meta_opt)->slh_first) = ((void *)0) ; }; |
| 744 | |
| 745 | /* Add chunk to volume. */ |
| 746 | fakesd->sd_vol.sv_chunks = malloc(sizeof(struct sr_chunk *), M_DEVBUF2, |
| 747 | M_WAITOK0x0001 | M_ZERO0x0008); |
| 748 | fakesd->sd_vol.sv_chunks[0] = key_disk; |
| 749 | SLIST_INIT(&fakesd->sd_vol.sv_chunk_list){ ((&fakesd->sd_vol.sv_chunk_list)->slh_first) = (( void *)0); }; |
| 750 | SLIST_INSERT_HEAD(&fakesd->sd_vol.sv_chunk_list, key_disk, src_link)do { (key_disk)->src_link.sle_next = (&fakesd->sd_vol .sv_chunk_list)->slh_first; (&fakesd->sd_vol.sv_chunk_list )->slh_first = (key_disk); } while (0); |
| 751 | |
| 752 | /* Generate mask key. */ |
| 753 | arc4random_buf(mdd_crypto->scr_maskkey, |
| 754 | sizeof(mdd_crypto->scr_maskkey)); |
| 755 | |
| 756 | /* Copy mask key to optional metadata area. */ |
| 757 | omi = malloc(sizeof(struct sr_meta_opt_item), M_DEVBUF2, |
| 758 | M_WAITOK0x0001 | M_ZERO0x0008); |
| 759 | omi->omi_som = malloc(sizeof(struct sr_meta_keydisk), M_DEVBUF2, |
| 760 | M_WAITOK0x0001 | M_ZERO0x0008); |
| 761 | omi->omi_som->som_type = SR_OPT_KEYDISK0x03; |
| 762 | omi->omi_som->som_length = sizeof(struct sr_meta_keydisk); |
| 763 | skm = (struct sr_meta_keydisk *)omi->omi_som; |
| 764 | memcpy(&skm->skm_maskkey, mdd_crypto->scr_maskkey,__builtin_memcpy((&skm->skm_maskkey), (mdd_crypto-> scr_maskkey), (sizeof(skm->skm_maskkey))) |
| 765 | sizeof(skm->skm_maskkey))__builtin_memcpy((&skm->skm_maskkey), (mdd_crypto-> scr_maskkey), (sizeof(skm->skm_maskkey))); |
| 766 | SLIST_INSERT_HEAD(&fakesd->sd_meta_opt, omi, omi_link)do { (omi)->omi_link.sle_next = (&fakesd->sd_meta_opt )->slh_first; (&fakesd->sd_meta_opt)->slh_first = (omi); } while (0); |
| 767 | fakesd->sd_meta->ssdi_sdd_invariant.ssd_opt_no++; |
| 768 | |
| 769 | /* Save metadata. */ |
| 770 | if (sr_meta_save(fakesd, SR_META_DIRTY0x1)) { |
| 771 | sr_error(sc, "could not save metadata to %s", devname); |
| 772 | goto fail; |
| 773 | } |
| 774 | |
| 775 | goto done; |
| 776 | |
| 777 | fail: |
| 778 | free(key_disk, M_DEVBUF2, sizeof(struct sr_chunk)); |
| 779 | key_disk = NULL((void *)0); |
| 780 | |
| 781 | done: |
| 782 | free(omi, M_DEVBUF2, sizeof(struct sr_meta_opt_item)); |
| 783 | if (fakesd && fakesd->sd_vol.sv_chunks) |
| 784 | free(fakesd->sd_vol.sv_chunks, M_DEVBUF2, |
| 785 | sizeof(struct sr_chunk *)); |
| 786 | free(fakesd, M_DEVBUF2, sizeof(struct sr_discipline)); |
| 787 | free(sm, M_DEVBUF2, sizeof(struct sr_metadata)); |
| 788 | if (open) { |
| 789 | VOP_CLOSE(vn, FREAD0x0001 | FWRITE0x0002, NOCRED((struct ucred *)-1), curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc); |
| 790 | vput(vn); |
| 791 | } |
| 792 | |
| 793 | return key_disk; |
| 794 | } |
| 795 | |
| 796 | struct sr_chunk * |
| 797 | sr_crypto_read_key_disk(struct sr_discipline *sd, struct sr_crypto *mdd_crypto, |
| 798 | dev_t dev) |
| 799 | { |
| 800 | struct sr_softc *sc = sd->sd_sc; |
| 801 | struct sr_metadata *sm = NULL((void *)0); |
| 802 | struct sr_meta_opt_item *omi, *omi_next; |
| 803 | struct sr_meta_opt_hdr *omh; |
| 804 | struct sr_meta_keydisk *skm; |
| 805 | struct sr_meta_opt_head som; |
| 806 | struct sr_chunk *key_disk = NULL((void *)0); |
| 807 | struct disklabel label; |
| 808 | struct vnode *vn = NULL((void *)0); |
| 809 | char devname[32]; |
| 810 | int c, part, open = 0; |
| 811 | |
| 812 | /* |
| 813 | * Load a key disk and load keying material into memory. |
| 814 | */ |
| 815 | |
| 816 | SLIST_INIT(&som){ ((&som)->slh_first) = ((void *)0); }; |
| 817 | |
| 818 | sr_meta_getdevname(sc, dev, devname, sizeof(devname)); |
| 819 | |
| 820 | /* Make sure chunk is not already in use. */ |
| 821 | c = sr_chunk_in_use(sc, dev); |
| 822 | if (c != BIOC_SDINVALID0xff && c != BIOC_SDOFFLINE0x01) { |
| 823 | sr_error(sc, "%s is already in use", devname); |
| 824 | goto done; |
| 825 | } |
| 826 | |
| 827 | /* Open device. */ |
| 828 | if (bdevvp(dev, &vn)) { |
| 829 | sr_error(sc, "cannot open key disk %s", devname); |
| 830 | goto done; |
| 831 | } |
| 832 | if (VOP_OPEN(vn, FREAD0x0001, NOCRED((struct ucred *)-1), curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc)) { |
| 833 | DNPRINTF(SR_D_META,"%s: sr_crypto_read_key_disk cannot " |
| 834 | "open %s\n", DEVNAME(sc), devname); |
| 835 | vput(vn); |
| 836 | goto done; |
| 837 | } |
| 838 | open = 1; /* close dev on error */ |
| 839 | |
| 840 | /* Get partition details. */ |
| 841 | part = DISKPART(dev)(((unsigned)((dev) & 0xff) | (((dev) & 0xffff0000) >> 8)) % 16); |
| 842 | if (VOP_IOCTL(vn, DIOCGDINFO((unsigned long)0x40000000 | ((sizeof(struct disklabel) & 0x1fff) << 16) | ((('d')) << 8) | ((101))), (caddr_t)&label, FREAD0x0001, |
| 843 | NOCRED((struct ucred *)-1), curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc)) { |
| 844 | DNPRINTF(SR_D_META, "%s: sr_crypto_read_key_disk ioctl " |
| 845 | "failed\n", DEVNAME(sc)); |
| 846 | goto done; |
| 847 | } |
| 848 | if (label.d_partitions[part].p_fstype != FS_RAID19) { |
| 849 | sr_error(sc, "%s partition not of type RAID (%d)", |
| 850 | devname, label.d_partitions[part].p_fstype); |
| 851 | goto done; |
| 852 | } |
| 853 | |
| 854 | /* |
| 855 | * Read and validate key disk metadata. |
| 856 | */ |
| 857 | sm = malloc(SR_META_SIZE64 * DEV_BSIZE(1 << 9), M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008); |
| 858 | if (sr_meta_native_read(sd, dev, sm, NULL((void *)0))) { |
| 859 | sr_error(sc, "native bootprobe could not read native metadata"); |
| 860 | goto done; |
| 861 | } |
| 862 | |
| 863 | if (sr_meta_validate(sd, dev, sm, NULL((void *)0))) { |
| 864 | DNPRINTF(SR_D_META, "%s: invalid metadata\n", |
| 865 | DEVNAME(sc)); |
| 866 | goto done; |
| 867 | } |
| 868 | |
| 869 | /* Make sure this is a key disk. */ |
| 870 | if (sm->ssdi_sdd_invariant.ssd_level != SR_KEYDISK_LEVEL0xfffffffe) { |
| 871 | sr_error(sc, "%s is not a key disk", devname); |
| 872 | goto done; |
| 873 | } |
| 874 | |
| 875 | /* Construct key disk chunk. */ |
| 876 | key_disk = malloc(sizeof(struct sr_chunk), M_DEVBUF2, M_WAITOK0x0001 | M_ZERO0x0008); |
| 877 | key_disk->src_dev_mm = dev; |
| 878 | key_disk->src_vn = vn; |
| 879 | key_disk->src_size = 0; |
| 880 | |
| 881 | memcpy(&key_disk->src_meta, (struct sr_meta_chunk *)(sm + 1),__builtin_memcpy((&key_disk->src_meta), ((struct sr_meta_chunk *)(sm + 1)), (sizeof(key_disk->src_meta))) |
| 882 | sizeof(key_disk->src_meta))__builtin_memcpy((&key_disk->src_meta), ((struct sr_meta_chunk *)(sm + 1)), (sizeof(key_disk->src_meta))); |
| 883 | |
| 884 | /* Read mask key from optional metadata. */ |
| 885 | sr_meta_opt_load(sc, sm, &som); |
| 886 | SLIST_FOREACH(omi, &som, omi_link)for((omi) = ((&som)->slh_first); (omi) != ((void *)0); (omi) = ((omi)->omi_link.sle_next)) { |
| 887 | omh = omi->omi_som; |
| 888 | if (omh->som_type == SR_OPT_KEYDISK0x03) { |
| 889 | skm = (struct sr_meta_keydisk *)omh; |
| 890 | memcpy(mdd_crypto->scr_maskkey, &skm->skm_maskkey,__builtin_memcpy((mdd_crypto->scr_maskkey), (&skm-> skm_maskkey), (sizeof(mdd_crypto->scr_maskkey))) |
| 891 | sizeof(mdd_crypto->scr_maskkey))__builtin_memcpy((mdd_crypto->scr_maskkey), (&skm-> skm_maskkey), (sizeof(mdd_crypto->scr_maskkey))); |
| 892 | } else if (omh->som_type == SR_OPT_CRYPTO0x01) { |
| 893 | /* Original keydisk format with key in crypto area. */ |
| 894 | memcpy(mdd_crypto->scr_maskkey,__builtin_memcpy((mdd_crypto->scr_maskkey), (omh + sizeof( struct sr_meta_opt_hdr)), (sizeof(mdd_crypto->scr_maskkey) )) |
| 895 | omh + sizeof(struct sr_meta_opt_hdr),__builtin_memcpy((mdd_crypto->scr_maskkey), (omh + sizeof( struct sr_meta_opt_hdr)), (sizeof(mdd_crypto->scr_maskkey) )) |
| 896 | sizeof(mdd_crypto->scr_maskkey))__builtin_memcpy((mdd_crypto->scr_maskkey), (omh + sizeof( struct sr_meta_opt_hdr)), (sizeof(mdd_crypto->scr_maskkey) )); |
| 897 | } |
| 898 | } |
| 899 | |
| 900 | open = 0; |
| 901 | |
| 902 | done: |
| 903 | for (omi = SLIST_FIRST(&som)((&som)->slh_first); omi != NULL((void *)0); omi = omi_next) { |
| 904 | omi_next = SLIST_NEXT(omi, omi_link)((omi)->omi_link.sle_next); |
| 905 | free(omi->omi_som, M_DEVBUF2, 0); |
| 906 | free(omi, M_DEVBUF2, sizeof(struct sr_meta_opt_item)); |
| 907 | } |
| 908 | |
| 909 | free(sm, M_DEVBUF2, SR_META_SIZE64 * DEV_BSIZE(1 << 9)); |
| 910 | |
| 911 | if (vn && open) { |
| 912 | VOP_CLOSE(vn, FREAD0x0001, NOCRED((struct ucred *)-1), curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self))); __ci;})->ci_curproc); |
| 913 | vput(vn); |
| 914 | } |
| 915 | |
| 916 | return key_disk; |
| 917 | } |
| 918 | |
| 919 | void |
| 920 | sr_crypto_free_sessions(struct sr_discipline *sd, struct sr_crypto *mdd_crypto) |
| 921 | { |
| 922 | u_int i; |
| 923 | |
| 924 | for (i = 0; i < SR_CRYPTO_MAXKEYS32; i++) { |
| 925 | if (mdd_crypto->scr_sid[i] != (u_int64_t)-1) { |
| 926 | crypto_freesession(mdd_crypto->scr_sid[i]); |
| 927 | mdd_crypto->scr_sid[i] = (u_int64_t)-1; |
| 928 | } |
| 929 | } |
| 930 | } |
| 931 | |
| 932 | int |
| 933 | sr_crypto_alloc_resources_internal(struct sr_discipline *sd, |
| 934 | struct sr_crypto *mdd_crypto) |
| 935 | { |
| 936 | struct sr_workunit *wu; |
| 937 | struct sr_crypto_wu *crwu; |
| 938 | struct cryptoini cri; |
| 939 | u_int num_keys, i; |
| 940 | |
| 941 | DNPRINTF(SR_D_DIS, "%s: sr_crypto_alloc_resources\n", |
| 942 | DEVNAME(sd->sd_sc)); |
| 943 | |
| 944 | mdd_crypto->scr_alg = CRYPTO_AES_XTS15; |
| 945 | switch (mdd_crypto->scr_meta->scm_alg) { |
| 946 | case SR_CRYPTOA_AES_XTS_1281: |
| 947 | mdd_crypto->scr_klen = 256; |
| 948 | break; |
| 949 | case SR_CRYPTOA_AES_XTS_2562: |
| 950 | mdd_crypto->scr_klen = 512; |
| 951 | break; |
| 952 | default: |
| 953 | sr_error(sd->sd_sc, "unknown crypto algorithm"); |
| 954 | return (EINVAL22); |
| 955 | } |
| 956 | |
| 957 | for (i = 0; i < SR_CRYPTO_MAXKEYS32; i++) |
| 958 | mdd_crypto->scr_sid[i] = (u_int64_t)-1; |
| 959 | |
| 960 | if (sr_wu_alloc(sd)) { |
| 961 | sr_error(sd->sd_sc, "unable to allocate work units"); |
| 962 | return (ENOMEM12); |
| 963 | } |
| 964 | if (sr_ccb_alloc(sd)) { |
| 965 | sr_error(sd->sd_sc, "unable to allocate CCBs"); |
| 966 | return (ENOMEM12); |
| 967 | } |
| 968 | if (sr_crypto_decrypt_key(sd, mdd_crypto)) { |
| 969 | sr_error(sd->sd_sc, "incorrect key or passphrase"); |
| 970 | return (EPERM1); |
| 971 | } |
| 972 | |
| 973 | /* |
| 974 | * For each work unit allocate the uio, iovec and crypto structures. |
| 975 | * These have to be allocated now because during runtime we cannot |
| 976 | * fail an allocation without failing the I/O (which can cause real |
| 977 | * problems). |
| 978 | */ |
| 979 | TAILQ_FOREACH(wu, &sd->sd_wu, swu_next)for((wu) = ((&sd->sd_wu)->tqh_first); (wu) != ((void *)0); (wu) = ((wu)->swu_next.tqe_next)) { |
| 980 | crwu = (struct sr_crypto_wu *)wu; |
| 981 | crwu->cr_uio.uio_iov = &crwu->cr_iov; |
| 982 | crwu->cr_dmabuf = dma_alloc(MAXPHYS(64 * 1024), PR_WAITOK0x0001); |
| 983 | crwu->cr_crp = crypto_getreq(MAXPHYS(64 * 1024) >> DEV_BSHIFT9); |
| 984 | if (crwu->cr_crp == NULL((void *)0)) |
| 985 | return (ENOMEM12); |
| 986 | } |
| 987 | |
| 988 | memset(&cri, 0, sizeof(cri))__builtin_memset((&cri), (0), (sizeof(cri))); |
| 989 | cri.cri_alg = mdd_crypto->scr_alg; |
| 990 | cri.cri_klen = mdd_crypto->scr_klen; |
| 991 | |
| 992 | /* Allocate a session for every 2^SR_CRYPTO_KEY_BLKSHIFT blocks. */ |
| 993 | num_keys = ((sd->sd_meta->ssdi_sdd_invariant.ssd_size - 1) >> |
| 994 | SR_CRYPTO_KEY_BLKSHIFT30) + 1; |
| 995 | if (num_keys > SR_CRYPTO_MAXKEYS32) |
| 996 | return (EFBIG27); |
| 997 | for (i = 0; i < num_keys; i++) { |
| 998 | cri.cri_key = mdd_crypto->scr_key[i]; |
| 999 | if (crypto_newsession(&mdd_crypto->scr_sid[i], |
| 1000 | &cri, 0) != 0) { |
| 1001 | sr_crypto_free_sessions(sd, mdd_crypto); |
| 1002 | return (EINVAL22); |
| 1003 | } |
| 1004 | } |
| 1005 | |
| 1006 | sr_hotplug_register(sd, sr_crypto_hotplug); |
| 1007 | |
| 1008 | return (0); |
| 1009 | } |
| 1010 | |
| 1011 | int |
| 1012 | sr_crypto_alloc_resources(struct sr_discipline *sd) |
| 1013 | { |
| 1014 | return sr_crypto_alloc_resources_internal(sd, &sd->mdssd_dis_specific.mdd_crypto); |
| 1015 | } |
| 1016 | |
| 1017 | void |
| 1018 | sr_crypto_free_resources_internal(struct sr_discipline *sd, |
| 1019 | struct sr_crypto *mdd_crypto) |
| 1020 | { |
| 1021 | struct sr_workunit *wu; |
| 1022 | struct sr_crypto_wu *crwu; |
| 1023 | |
| 1024 | DNPRINTF(SR_D_DIS, "%s: sr_crypto_free_resources\n", |
| 1025 | DEVNAME(sd->sd_sc)); |
| 1026 | |
| 1027 | if (mdd_crypto->key_disk != NULL((void *)0)) { |
| 1028 | explicit_bzero(mdd_crypto->key_disk, |
| 1029 | sizeof(*mdd_crypto->key_disk)); |
| 1030 | free(mdd_crypto->key_disk, M_DEVBUF2, |
| 1031 | sizeof(*mdd_crypto->key_disk)); |
| 1032 | } |
| 1033 | |
| 1034 | sr_hotplug_unregister(sd, sr_crypto_hotplug); |
| 1035 | |
| 1036 | sr_crypto_free_sessions(sd, mdd_crypto); |
| 1037 | |
| 1038 | TAILQ_FOREACH(wu, &sd->sd_wu, swu_next)for((wu) = ((&sd->sd_wu)->tqh_first); (wu) != ((void *)0); (wu) = ((wu)->swu_next.tqe_next)) { |
| 1039 | crwu = (struct sr_crypto_wu *)wu; |
| 1040 | if (crwu->cr_dmabuf) |
| 1041 | dma_free(crwu->cr_dmabuf, MAXPHYS(64 * 1024)); |
| 1042 | if (crwu->cr_crp) |
| 1043 | crypto_freereq(crwu->cr_crp); |
| 1044 | } |
| 1045 | |
| 1046 | sr_wu_free(sd); |
| 1047 | sr_ccb_free(sd); |
| 1048 | } |
| 1049 | |
| 1050 | void |
| 1051 | sr_crypto_free_resources(struct sr_discipline *sd) |
| 1052 | { |
| 1053 | struct sr_crypto *mdd_crypto = &sd->mdssd_dis_specific.mdd_crypto; |
| 1054 | sr_crypto_free_resources_internal(sd, mdd_crypto); |
| 1055 | } |
| 1056 | |
| 1057 | int |
| 1058 | sr_crypto_ioctl_internal(struct sr_discipline *sd, |
| 1059 | struct sr_crypto *mdd_crypto, struct bioc_discipline *bd) |
| 1060 | { |
| 1061 | struct sr_crypto_kdfpair kdfpair; |
| 1062 | struct sr_crypto_kdfinfo kdfinfo1, kdfinfo2; |
| 1063 | int size, rv = 1; |
| 1064 | |
| 1065 | DNPRINTF(SR_D_IOCTL, "%s: sr_crypto_ioctl %u\n", |
| 1066 | DEVNAME(sd->sd_sc), bd->bd_cmd); |
| 1067 | |
| 1068 | switch (bd->bd_cmd) { |
| 1069 | case SR_IOCTL_GET_KDFHINT0x01: |
| 1070 | |
| 1071 | /* Get KDF hint for userland. */ |
| 1072 | size = sizeof(mdd_crypto->scr_meta->scm_kdfhint); |
| 1073 | if (bd->bd_data == NULL((void *)0) || bd->bd_size > size) |
| 1074 | goto bad; |
| 1075 | if (copyout(mdd_crypto->scr_meta->scm_kdfhint, |
| 1076 | bd->bd_data, bd->bd_size)) |
| 1077 | goto bad; |
| 1078 | |
| 1079 | rv = 0; |
| 1080 | |
| 1081 | break; |
| 1082 | |
| 1083 | case SR_IOCTL_CHANGE_PASSPHRASE0x02: |
| 1084 | |
| 1085 | /* Attempt to change passphrase. */ |
| 1086 | |
| 1087 | size = sizeof(kdfpair); |
| 1088 | if (bd->bd_data == NULL((void *)0) || bd->bd_size > size) |
| 1089 | goto bad; |
| 1090 | if (copyin(bd->bd_data, &kdfpair, size)) |
| 1091 | goto bad; |
| 1092 | |
| 1093 | size = sizeof(kdfinfo1); |
| 1094 | if (kdfpair.kdfinfo1 == NULL((void *)0) || kdfpair.kdfsize1 > size) |
| 1095 | goto bad; |
| 1096 | if (copyin(kdfpair.kdfinfo1, &kdfinfo1, size)) |
| 1097 | goto bad; |
| 1098 | |
| 1099 | size = sizeof(kdfinfo2); |
| 1100 | if (kdfpair.kdfinfo2 == NULL((void *)0) || kdfpair.kdfsize2 > size) |
| 1101 | goto bad; |
| 1102 | if (copyin(kdfpair.kdfinfo2, &kdfinfo2, size)) |
| 1103 | goto bad; |
| 1104 | |
| 1105 | if (sr_crypto_change_maskkey(sd, mdd_crypto, &kdfinfo1, |
| 1106 | &kdfinfo2)) |
| 1107 | goto bad; |
| 1108 | |
| 1109 | /* Save metadata to disk. */ |
| 1110 | rv = sr_meta_save(sd, SR_META_DIRTY0x1); |
| 1111 | |
| 1112 | break; |
| 1113 | } |
| 1114 | |
| 1115 | bad: |
| 1116 | explicit_bzero(&kdfpair, sizeof(kdfpair)); |
| 1117 | explicit_bzero(&kdfinfo1, sizeof(kdfinfo1)); |
| 1118 | explicit_bzero(&kdfinfo2, sizeof(kdfinfo2)); |
| 1119 | |
| 1120 | return (rv); |
| 1121 | } |
| 1122 | |
| 1123 | int |
| 1124 | sr_crypto_ioctl(struct sr_discipline *sd, struct bioc_discipline *bd) |
| 1125 | { |
| 1126 | struct sr_crypto *mdd_crypto = &sd->mdssd_dis_specific.mdd_crypto; |
| 1127 | return sr_crypto_ioctl_internal(sd, mdd_crypto, bd); |
| 1128 | } |
| 1129 | |
| 1130 | int |
| 1131 | sr_crypto_meta_opt_handler_internal(struct sr_discipline *sd, |
| 1132 | struct sr_crypto *mdd_crypto, struct sr_meta_opt_hdr *om) |
| 1133 | { |
| 1134 | int rv = EINVAL22; |
| 1135 | |
| 1136 | if (om->som_type == SR_OPT_CRYPTO0x01) { |
| 1137 | mdd_crypto->scr_meta = (struct sr_meta_crypto *)om; |
| 1138 | rv = 0; |
| 1139 | } |
| 1140 | |
| 1141 | return (rv); |
| 1142 | } |
| 1143 | |
| 1144 | int |
| 1145 | sr_crypto_meta_opt_handler(struct sr_discipline *sd, struct sr_meta_opt_hdr *om) |
| 1146 | { |
| 1147 | struct sr_crypto *mdd_crypto = &sd->mdssd_dis_specific.mdd_crypto; |
| 1148 | return sr_crypto_meta_opt_handler_internal(sd, mdd_crypto, om); |
| 1149 | } |
| 1150 | |
| 1151 | int |
| 1152 | sr_crypto_rw(struct sr_workunit *wu) |
| 1153 | { |
| 1154 | struct sr_crypto_wu *crwu; |
| 1155 | struct sr_crypto *mdd_crypto; |
| 1156 | daddr_t blkno; |
| 1157 | int rv, err; |
| 1158 | int s; |
| 1159 | |
| 1160 | DNPRINTF(SR_D_DIS, "%s: sr_crypto_rw wu %p\n", |
| 1161 | DEVNAME(wu->swu_dis->sd_sc), wu); |
| 1162 | |
| 1163 | if (sr_validate_io(wu, &blkno, "sr_crypto_rw")) |
| 1164 | return (1); |
| 1165 | |
| 1166 | if (wu->swu_xs->flags & SCSI_DATA_OUT0x01000) { |
| 1167 | mdd_crypto = &wu->swu_dis->mdssd_dis_specific.mdd_crypto; |
| 1168 | crwu = sr_crypto_prepare(wu, mdd_crypto, 1); |
| 1169 | rv = crypto_invoke(crwu->cr_crp); |
| 1170 | |
| 1171 | DNPRINTF(SR_D_INTR, "%s: sr_crypto_rw: wu %p xs: %p\n", |
| 1172 | DEVNAME(wu->swu_dis->sd_sc), wu, wu->swu_xs); |
| 1173 | |
| 1174 | if (rv) { |
| 1175 | /* fail io */ |
| 1176 | wu->swu_xs->error = XS_DRIVER_STUFFUP2; |
| 1177 | s = splbio()splraise(0x3); |
| 1178 | sr_scsi_done(wu->swu_dis, wu->swu_xs); |
| 1179 | splx(s)spllower(s); |
| 1180 | } |
| 1181 | |
| 1182 | if ((err = sr_crypto_dev_rw(wu, crwu)) != 0) |
| 1183 | return err; |
| 1184 | } else |
| 1185 | rv = sr_crypto_dev_rw(wu, NULL((void *)0)); |
| 1186 | |
| 1187 | return (rv); |
| 1188 | } |
| 1189 | |
| 1190 | int |
| 1191 | sr_crypto_dev_rw(struct sr_workunit *wu, struct sr_crypto_wu *crwu) |
| 1192 | { |
| 1193 | struct sr_discipline *sd = wu->swu_dis; |
| 1194 | struct scsi_xfer *xs = wu->swu_xs; |
| 1195 | struct sr_ccb *ccb; |
| 1196 | struct uio *uio; |
| 1197 | daddr_t blkno; |
| 1198 | |
| 1199 | blkno = wu->swu_blk_start; |
| 1200 | |
| 1201 | ccb = sr_ccb_rw(sd, 0, blkno, xs->datalen, xs->data, xs->flags, 0); |
| 1202 | if (!ccb) { |
| 1203 | /* should never happen but handle more gracefully */ |
| 1204 | printf("%s: %s: too many ccbs queued\n", |
| 1205 | DEVNAME(sd->sd_sc)((sd->sd_sc)->sc_dev.dv_xname), sd->sd_meta->ssd_devname); |
| 1206 | goto bad; |
| 1207 | } |
| 1208 | if (!ISSET(xs->flags, SCSI_DATA_IN)((xs->flags) & (0x00800))) { |
| 1209 | uio = crwu->cr_crp->crp_buf; |
| 1210 | ccb->ccb_buf.b_data = uio->uio_iov->iov_base; |
| 1211 | ccb->ccb_opaque = crwu; |
| 1212 | } |
| 1213 | sr_wu_enqueue_ccb(wu, ccb); |
| 1214 | sr_schedule_wu(wu); |
| 1215 | |
| 1216 | return (0); |
| 1217 | |
| 1218 | bad: |
| 1219 | return (EINVAL22); |
| 1220 | } |
| 1221 | |
| 1222 | void |
| 1223 | sr_crypto_done_internal(struct sr_workunit *wu, struct sr_crypto *mdd_crypto) |
| 1224 | { |
| 1225 | struct scsi_xfer *xs = wu->swu_xs; |
| 1226 | struct sr_crypto_wu *crwu; |
| 1227 | int rv; |
| 1228 | int s; |
| 1229 | |
| 1230 | if (ISSET(wu->swu_flags, SR_WUF_REBUILD)((wu->swu_flags) & ((1<<0)))) /* RAID 1C */ |
| 1231 | return; |
| 1232 | |
| 1233 | /* If this was a successful read, initiate decryption of the data. */ |
| 1234 | if (ISSET(xs->flags, SCSI_DATA_IN)((xs->flags) & (0x00800)) && xs->error == XS_NOERROR0) { |
| 1235 | crwu = sr_crypto_prepare(wu, mdd_crypto, 0); |
| 1236 | DNPRINTF(SR_D_INTR, "%s: sr_crypto_done: crypto_invoke %p\n", |
| 1237 | DEVNAME(wu->swu_dis->sd_sc), crwu->cr_crp); |
| 1238 | rv = crypto_invoke(crwu->cr_crp); |
| 1239 | |
| 1240 | DNPRINTF(SR_D_INTR, "%s: sr_crypto_done: wu %p xs: %p\n", |
| 1241 | DEVNAME(wu->swu_dis->sd_sc), wu, wu->swu_xs); |
| 1242 | |
| 1243 | if (rv) |
| 1244 | wu->swu_xs->error = XS_DRIVER_STUFFUP2; |
| 1245 | |
| 1246 | s = splbio()splraise(0x3); |
| 1247 | sr_scsi_done(wu->swu_dis, wu->swu_xs); |
| 1248 | splx(s)spllower(s); |
| 1249 | return; |
| 1250 | } |
| 1251 | |
| 1252 | s = splbio()splraise(0x3); |
| 1253 | sr_scsi_done(wu->swu_dis, wu->swu_xs); |
| 1254 | splx(s)spllower(s); |
| 1255 | } |
| 1256 | |
| 1257 | void |
| 1258 | sr_crypto_done(struct sr_workunit *wu) |
| 1259 | { |
| 1260 | struct sr_crypto *mdd_crypto = &wu->swu_dis->mdssd_dis_specific.mdd_crypto; |
| 1261 | sr_crypto_done_internal(wu, mdd_crypto); |
| 1262 | } |
| 1263 | |
| 1264 | void |
| 1265 | sr_crypto_hotplug(struct sr_discipline *sd, struct disk *diskp, int action) |
| 1266 | { |
| 1267 | DNPRINTF(SR_D_MISC, "%s: sr_crypto_hotplug: %s %d\n", |
| 1268 | DEVNAME(sd->sd_sc), diskp->dk_name, action); |
| 1269 | } |
| 1270 | |
| 1271 | #ifdef SR_DEBUG0 |
| 1272 | void |
| 1273 | sr_crypto_dumpkeys(struct sr_crypto *mdd_crypto) |
| 1274 | { |
| 1275 | int i, j; |
| 1276 | |
| 1277 | printf("sr_crypto_dumpkeys:\n"); |
| 1278 | for (i = 0; i < SR_CRYPTO_MAXKEYS32; i++) { |
| 1279 | printf("\tscm_key[%d]: 0x", i); |
| 1280 | for (j = 0; j < SR_CRYPTO_KEYBYTES(512 >> 3); j++) { |
| 1281 | printf("%02x", mdd_crypto->scr_meta->scm_key[i][j]); |
| 1282 | } |
| 1283 | printf("\n"); |
| 1284 | } |
| 1285 | printf("sr_crypto_dumpkeys: runtime data keys:\n"); |
| 1286 | for (i = 0; i < SR_CRYPTO_MAXKEYS32; i++) { |
| 1287 | printf("\tscr_key[%d]: 0x", i); |
| 1288 | for (j = 0; j < SR_CRYPTO_KEYBYTES(512 >> 3); j++) { |
| 1289 | printf("%02x", mdd_crypto->scr_key[i][j]); |
| 1290 | } |
| 1291 | printf("\n"); |
| 1292 | } |
| 1293 | } |
| 1294 | #endif /* SR_DEBUG */ |