| File: | dev/softraid_crypto.c |
| Warning: | line 1209, column 9 Access to field 'cr_crp' results in a dereference of a null pointer (loaded from variable 'crwu') |
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, | |||
| 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 */ |