File: | dev/softraid_crypto.c |
Warning: | line 759, 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_keydisk' |
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, |
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_keydisk' | |
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 */ |