1#![deny(warnings)]
2#[warn(unused_must_use)]
3extern crate byteorder;
5extern crate either;
6extern crate uuid;
7
8use either::Either::{Left, Right};
9use std::convert;
10use std::error;
11use std::fmt::{Display, Error as FmtError, Formatter};
12use std::io;
13use std::io::Read;
14use std::str;
15use uuid::Uuid;
16
17#[derive(Debug)]
20pub enum Error {
21 InvalidMagic,
22 InvalidStringEncoding(str::Utf8Error),
23 InvalidVersion,
24 InvalidUuid(uuid::Error),
25 ReadError(io::Error),
26 ReadIncorrectHeaderSize,
27 HeaderProcessingError,
28 EmptyString,
29}
30
31impl Display for Error {
32 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
33 write!(f, "{:?}", &self)
34 }
35}
36
37impl error::Error for Error {
38 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
39 match &self {
40 &Error::InvalidStringEncoding(e) => Some(e),
41 &Error::InvalidUuid(e) => Some(e),
42 &Error::ReadError(e) => Some(e),
43 _ => None,
44 }
45 }
46}
47
48pub enum LuksHeader {
49 Luks1(LuksHeaderV1),
50 Luks2(LuksHeaderV2),
51}
52
53impl LuksHeader {
54 pub fn read<R: Read>(mut reader: R) -> Result<LuksHeader, Error> {
55 let res = match raw::read_luks_header(&mut reader)? {
56 Left(raw) => LuksHeader::Luks1(LuksHeaderV1 { raw }),
57 Right(raw) => LuksHeader::Luks2(LuksHeaderV2 { raw }),
58 };
59 Ok(res)
60 }
61}
62
63pub struct LuksHeaderV1 {
64 raw: raw::luks_phdr,
65}
66
67pub struct LuksHeaderV2 {
68 raw: raw::luks2_phdr,
69}
70
71pub trait LuksVersionedHeader {
72 fn version(&self) -> u16;
73 fn uuid(&self) -> Result<uuid::Uuid, Error>;
74}
75
76impl LuksVersionedHeader for LuksHeader {
77 fn version(&self) -> u16 {
78 match &self {
79 &LuksHeader::Luks1(h) => h.version(),
80 &LuksHeader::Luks2(h) => h.version(),
81 }
82 }
83
84 fn uuid(&self) -> Result<Uuid, Error> {
85 match &self {
86 &LuksHeader::Luks1(h) => h.uuid(),
87 &LuksHeader::Luks2(h) => h.uuid(),
88 }
89 }
90}
91
92pub trait Luks1Header: LuksVersionedHeader {
93 fn cipher_name(&self) -> Result<&str, Error>;
94 fn cipher_mode(&self) -> Result<&str, Error>;
95 fn hash_spec(&self) -> Result<&str, Error>;
96 fn payload_offset(&self) -> u32;
97 fn key_bytes(&self) -> u32;
98 fn mk_digest(&self) -> &[u8];
99 fn mk_digest_salt(&self) -> &[u8];
100 fn mk_digest_iterations(&self) -> u32;
101}
102
103impl LuksVersionedHeader for LuksHeaderV1 {
104 fn version(&self) -> u16 {
105 self.raw.version
106 }
107
108 fn uuid(&self) -> Result<Uuid, Error> {
109 raw::uuid_buf_to_uuid(&self.raw.uuid)
110 }
111}
112
113impl LuksVersionedHeader for LuksHeaderV2 {
114 fn version(&self) -> u16 {
115 self.raw.version
116 }
117
118 fn uuid(&self) -> Result<Uuid, Error> {
119 raw::uuid_buf_to_uuid(&self.raw.uuid)
120 }
121}
122
123impl Luks1Header for LuksHeaderV1 {
124 fn cipher_name(&self) -> Result<&str, Error> {
125 raw::u8_buf_to_str(&self.raw.cipherName)?.ok_or(Error::EmptyString)
126 }
127
128 fn cipher_mode(&self) -> Result<&str, Error> {
129 raw::u8_buf_to_str(&self.raw.cipherMode)?.ok_or(Error::EmptyString)
130 }
131
132 fn hash_spec(&self) -> Result<&str, Error> {
133 raw::u8_buf_to_str(&self.raw.hashSpec)?.ok_or(Error::EmptyString)
134 }
135
136 fn payload_offset(&self) -> u32 {
137 self.raw.payloadOffset
138 }
139
140 fn key_bytes(&self) -> u32 {
141 self.raw.keyBytes
142 }
143
144 fn mk_digest(&self) -> &[u8] {
145 &self.raw.mkDigest
146 }
147
148 fn mk_digest_salt(&self) -> &[u8] {
149 &self.raw.mkDigestSalt
150 }
151
152 fn mk_digest_iterations(&self) -> u32 {
153 self.raw.mkDigestIterations
154 }
155}
156
157pub trait Luks2Header: LuksVersionedHeader {
158 fn label(&self) -> Result<Option<&str>, Error>;
159 fn subsystem(&self) -> Result<Option<&str>, Error>;
160 fn seqid(&self) -> u64;
161 fn header_size(&self) -> u64;
162 fn header_offset(&self) -> u64;
163
164 }
166
167impl Luks2Header for LuksHeaderV2 {
168 fn label(&self) -> Result<Option<&str>, Error> {
169 let label_opt = raw::u8_buf_to_str(&self.raw.label)?;
170 Ok(label_opt)
171 }
172
173 fn subsystem(&self) -> Result<Option<&str>, Error> {
174 let subsystem_opt = raw::u8_buf_to_str(&self.raw.subsystem)?;
175 Ok(subsystem_opt)
176 }
177
178 fn seqid(&self) -> u64 {
179 self.raw.seqid
180 }
181
182 fn header_size(&self) -> u64 {
183 self.raw.hdr_size
184 }
185
186 fn header_offset(&self) -> u64 {
187 self.raw.hdr_offset
188 }
189}
190
191impl convert::From<str::Utf8Error> for Error {
192 fn from(error: str::Utf8Error) -> Error {
193 Error::InvalidStringEncoding(error)
194 }
195}
196
197impl convert::From<uuid::Error> for Error {
198 fn from(error: uuid::Error) -> Error {
199 Error::InvalidUuid(error)
200 }
201}
202
203impl convert::From<io::Error> for Error {
204 fn from(error: io::Error) -> Error {
205 Error::ReadError(error)
206 }
207}
208
209mod raw {
210 #![allow(non_snake_case)]
211
212 use std::convert::From;
213 use std::io::{Cursor, Read};
214 use std::mem;
215 use std::str;
216
217 use byteorder::{BigEndian, ReadBytesExt};
218 use either::Either;
219 use either::Either::{Left, Right};
220 use uuid;
221
222 const V1: u16 = 1;
223 const V2: u16 = 2;
224
225 const LUKS_MAGIC_L: usize = 6;
226 const LUKS_CIPHERNAME_L: usize = 32;
227 const LUKS_CIPHERMODE_L: usize = 32;
228 const LUKS_HASHSPEC_L: usize = 32;
229 const LUKS_DIGESTSIZE: usize = 20;
230 const LUKS_SALTSIZE: usize = 32;
231 const UUID_STRING_L: usize = 40;
232 const LUKS2_LABEL_L: usize = 48;
233 const LUKS2_SALT_L: usize = 64;
234 const LUKS2_CHECKSUM_ALG_L: usize = 32;
235 const LUKS2_CHECKSUM_L: usize = 64;
236
237 const LUKS_MAGIC: &'static [u8; LUKS_MAGIC_L] = b"LUKS\xba\xbe";
238
239 const _LUKS2_MAGIC_2: &'static [u8; LUKS_MAGIC_L] = b"SKUL\xba\xbe";
241
242 const LUKS2_PHDR_PADDING_L: usize = 184;
243
244 #[repr(C)]
246 pub struct luks_phdr {
247 pub magic: [u8; LUKS_MAGIC_L],
248 pub version: u16,
249 pub cipherName: [u8; LUKS_CIPHERNAME_L],
250 pub cipherMode: [u8; LUKS_CIPHERMODE_L],
251 pub hashSpec: [u8; LUKS_HASHSPEC_L],
252 pub payloadOffset: u32,
253 pub keyBytes: u32,
254 pub mkDigest: [u8; LUKS_DIGESTSIZE],
255 pub mkDigestSalt: [u8; LUKS_SALTSIZE],
256 pub mkDigestIterations: u32,
257 pub uuid: [u8; UUID_STRING_L],
258 }
259
260 #[repr(C)]
261 pub struct luks2_phdr {
262 pub magic: [u8; LUKS_MAGIC_L],
263 pub version: u16,
264 pub hdr_size: u64,
265 pub seqid: u64,
266 pub label: [u8; LUKS2_LABEL_L],
267 pub checksum_alg: [u8; LUKS2_CHECKSUM_ALG_L],
268 pub salt: [u8; LUKS2_SALT_L],
269 pub uuid: [u8; UUID_STRING_L],
270 pub subsystem: [u8; LUKS2_LABEL_L],
271 pub hdr_offset: u64,
272 pub _padding: [u8; LUKS2_PHDR_PADDING_L],
273 pub csum: [u8; LUKS2_CHECKSUM_L],
274 }
275
276 pub fn read_luks_header<R: Read>(reader: &mut R) -> Result<Either<luks_phdr, luks2_phdr>, super::Error> {
277 let mut start_buf = [0u8; 8];
278 reader.read_exact(&mut start_buf)?;
279
280 let mut cursor = Cursor::new(start_buf);
281
282 let mut magic_buf = [0u8; LUKS_MAGIC_L];
283 let _magic_len = cursor.read(&mut magic_buf)?;
284
285 let version = cursor.read_u16::<BigEndian>()?;
286
287 if magic_buf == &LUKS_MAGIC[..] && version == V1 {
288 let mut buf = [0u8; mem::size_of::<luks_phdr>()];
289 buf[..8].copy_from_slice(&start_buf);
290 reader.read_exact(&mut buf[8..])?;
291 luks_phdr::from_buf(&mut buf).map(|h| Left(h))
292 } else if magic_buf == &LUKS_MAGIC[..] && version == V2 {
293 let mut buf = [0u8; mem::size_of::<luks2_phdr>()];
294 buf[..8].copy_from_slice(&start_buf);
295 reader.read_exact(&mut buf[8..])?;
296 luks2_phdr::from_buf(&mut buf).map(|h| Right(h))
297 } else if magic_buf != &LUKS_MAGIC[..] {
298 Err(super::Error::InvalidMagic)
299 } else {
300 Err(super::Error::InvalidVersion)
301 }
302 }
303
304 impl luks_phdr {
305 pub fn from_buf(buf: &[u8]) -> Result<luks_phdr, super::Error> {
306 if buf.len() < mem::size_of::<luks_phdr>() {
309 return Err(super::Error::ReadIncorrectHeaderSize);
310 }
311 let mut cursor = Cursor::new(buf);
312 let mut magic_buf = [0u8; LUKS_MAGIC_L];
313 let magic_len = cursor.read(&mut magic_buf)?;
314
315 if magic_len != LUKS_MAGIC_L || magic_buf != &LUKS_MAGIC[..] {
316 return Err(super::Error::InvalidMagic);
317 }
318
319 let version = cursor.read_u16::<BigEndian>()?;
320 if version != V1 {
321 return Err(super::Error::InvalidVersion);
322 }
323
324 let mut cipher_name_buf = [0u8; LUKS_CIPHERNAME_L];
325 let cipher_name_len = cursor.read(&mut cipher_name_buf)?;
326 if cipher_name_len != LUKS_CIPHERNAME_L {
327 return Err(super::Error::HeaderProcessingError);
328 }
329
330 let mut cipher_mode_buf = [0u8; LUKS_CIPHERMODE_L];
331 let cipher_mode_len = cursor.read(&mut cipher_mode_buf)?;
332 if cipher_mode_len != LUKS_CIPHERMODE_L {
333 return Err(super::Error::HeaderProcessingError);
334 }
335
336 let mut hash_spec_buf = [0u8; LUKS_HASHSPEC_L];
337 let hash_spec_len = cursor.read(&mut hash_spec_buf)?;
338 if hash_spec_len != LUKS_HASHSPEC_L {
339 return Err(super::Error::HeaderProcessingError);
340 }
341
342 let payload_offset = cursor.read_u32::<BigEndian>()?;
343 let key_bytes = cursor.read_u32::<BigEndian>()?;
344
345 let mut mk_digest_buf = [0u8; LUKS_DIGESTSIZE];
346 let mk_digest_len = cursor.read(&mut mk_digest_buf)?;
347 if mk_digest_len != LUKS_DIGESTSIZE {
348 return Err(super::Error::HeaderProcessingError);
349 }
350
351 let mut mk_digest_salt_buf = [0u8; LUKS_SALTSIZE];
352 let mk_digest_salt_len = cursor.read(&mut mk_digest_salt_buf)?;
353 if mk_digest_salt_len != LUKS_SALTSIZE {
354 return Err(super::Error::HeaderProcessingError);
355 }
356
357 let mk_digest_iterations = cursor.read_u32::<BigEndian>()?;
358
359 let mut uuid_buf = [0u8; UUID_STRING_L];
360 let uuid_len = cursor.read(&mut uuid_buf)?;
361 if uuid_len != UUID_STRING_L {
362 return Err(super::Error::HeaderProcessingError);
363 }
364
365 let res = luks_phdr {
366 magic: magic_buf,
367 version: version,
368 cipherName: cipher_name_buf,
369 cipherMode: cipher_mode_buf,
370 hashSpec: hash_spec_buf,
371 payloadOffset: payload_offset,
372 keyBytes: key_bytes,
373 mkDigest: mk_digest_buf,
374 mkDigestSalt: mk_digest_salt_buf,
375 mkDigestIterations: mk_digest_iterations,
376 uuid: uuid_buf,
377 };
378
379 Ok(res)
380 }
381 }
382
383 impl luks2_phdr {
384 pub fn from_buf(buf: &[u8]) -> Result<luks2_phdr, super::Error> {
385 if buf.len() < mem::size_of::<luks2_phdr>() {
386 return Err(super::Error::ReadIncorrectHeaderSize);
387 }
388 let mut cursor = Cursor::new(buf);
389 let mut magic_buf = [0u8; LUKS_MAGIC_L];
390 let magic_len = cursor.read(&mut magic_buf)?;
391
392 if magic_len != LUKS_MAGIC_L || magic_buf != &LUKS_MAGIC[..] {
393 return Err(super::Error::InvalidMagic);
394 }
395
396 let version = cursor.read_u16::<BigEndian>()?;
397 if version != V2 {
398 return Err(super::Error::InvalidVersion);
399 }
400
401 let hdr_size = cursor.read_u64::<BigEndian>()?;
402 let seqid = cursor.read_u64::<BigEndian>()?;
403
404 let mut label_buf = [0u8; LUKS2_LABEL_L];
405 let label_len = cursor.read(&mut label_buf)?;
406 if label_len != LUKS2_LABEL_L {
407 return Err(super::Error::HeaderProcessingError);
408 }
409
410 let mut checksum_alg_buf = [0u8; LUKS2_CHECKSUM_ALG_L];
411 let checksum_alg_len = cursor.read(&mut checksum_alg_buf)?;
412 if checksum_alg_len != LUKS2_CHECKSUM_ALG_L {
413 return Err(super::Error::HeaderProcessingError);
414 }
415
416 let mut salt_buf = [0u8; LUKS2_SALT_L];
417 let salt_len = cursor.read(&mut salt_buf)?;
418 if salt_len != LUKS2_SALT_L {
419 return Err(super::Error::HeaderProcessingError);
420 }
421
422 let mut uuid_buf = [0u8; UUID_STRING_L];
423 let uuid_len = cursor.read(&mut uuid_buf)?;
424 if uuid_len != UUID_STRING_L {
425 return Err(super::Error::HeaderProcessingError);
426 }
427
428 let mut subsystem_buf = [0u8; LUKS2_LABEL_L];
429 let subsystem_len = cursor.read(&mut subsystem_buf)?;
430 if subsystem_len != LUKS2_LABEL_L {
431 return Err(super::Error::HeaderProcessingError);
432 }
433
434 let hdr_offset = cursor.read_u64::<BigEndian>()?;
435
436 let mut padding_buf = [0u8; LUKS2_PHDR_PADDING_L];
437 let padding_len = cursor.read(&mut padding_buf)?;
438 if padding_len != LUKS2_PHDR_PADDING_L {
439 return Err(super::Error::HeaderProcessingError);
440 }
441
442 let mut csum_buf = [0u8; LUKS2_CHECKSUM_L];
443 let csum_len = cursor.read(&mut csum_buf)?;
444 if csum_len != LUKS2_CHECKSUM_L {
445 return Err(super::Error::HeaderProcessingError);
446 }
447
448 let res = luks2_phdr {
449 magic: magic_buf,
450 version,
451 hdr_size,
452 seqid,
453 label: label_buf,
454 checksum_alg: checksum_alg_buf,
455 salt: salt_buf,
456 uuid: uuid_buf,
457 subsystem: subsystem_buf,
458 hdr_offset,
459 _padding: padding_buf,
460 csum: csum_buf,
461 };
462
463 Ok(res)
464 }
465 }
466
467 pub fn u8_buf_to_str(buf: &[u8]) -> Result<Option<&str>, super::Error> {
468 if let Some(pos) = buf.iter().position(|&c| c == 0) {
469 if pos == 0 {
470 Ok(None)
471 } else {
472 str::from_utf8(&buf[0..pos]).map_err(From::from).map(|s| Some(s))
473 }
474 } else {
475 str::from_utf8(buf).map_err(From::from).map(|s| Some(s))
476 }
477 }
478
479 pub fn uuid_buf_to_uuid(buf: &[u8; UUID_STRING_L]) -> Result<uuid::Uuid, super::Error> {
480 let uuid_str = u8_buf_to_str(buf)?.ok_or(super::Error::EmptyString)?;
481 uuid::Uuid::parse_str(uuid_str).map_err(From::from)
482 }
483
484 #[cfg(test)]
485 mod tests {
486 use super::*;
487
488 #[test]
489 fn test_luks2_header_from_bytes() {
490 let header = b"LUKS\xba\xbe\x00\x02\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00sha256\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00g\x98\x84>\xba \x87\x16\xff\xdc\xdb\xc8\xe1\xd6\xd5\xf6\x01\x94\x9c^E\x84\x1e\xcc\x1c\xc5\xa6\xeb\xaePf\xde\x7f\x95\xfeL\x07\x1f46B\x95Z\xae\xf5\x8f\x88\xc0uj,\x08\xb4NW\r\x8c\xec\xb6D\x15P\x0e\x8f0748f429-3aad-426d-95b4-82005de5ad36\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>\xc7\x12\xf52$\xac\xd3\xc7G()<\xbb\x8d\x0f\x14\x03\x1e\xe6\x83\xc9\xe8C\x00\xff\xdf\xb8\x8b\x08\x9f4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
491 let luks2_header = luks2_phdr::from_buf(header).expect("luks2 header");
492
493 assert_eq!(luks2_header.version, 2);
494 assert_eq!(luks2_header.hdr_size, 16384);
495 assert_eq!(luks2_header.seqid, 3);
496 assert_eq!(u8_buf_to_str(&luks2_header.label).unwrap(), None);
497 assert_eq!(u8_buf_to_str(&luks2_header.checksum_alg).unwrap(), Some("sha256"));
498 assert_eq!(
499 luks2_header.salt.to_vec(),
500 vec!(
501 103u8, 152, 132, 62, 186, 32, 135, 22, 255, 220, 219, 200, 225, 214, 213, 246, 1, 148, 156, 94, 69,
502 132, 30, 204, 28, 197, 166, 235, 174, 80, 102, 222, 127, 149, 254, 76, 7, 31, 52, 54, 66, 149, 90,
503 174, 245, 143, 136, 192, 117, 106, 44, 8, 180, 78, 87, 13, 140, 236, 182, 68, 21, 80, 14, 143
504 )
505 );
506 assert_eq!(
507 u8_buf_to_str(&luks2_header.uuid).unwrap(),
508 Some("0748f429-3aad-426d-95b4-82005de5ad36")
509 );
510 assert_eq!(u8_buf_to_str(&luks2_header.subsystem).unwrap(), None);
511 assert_eq!(luks2_header.hdr_offset, 0);
512 assert_eq!(
513 luks2_header.csum.to_vec(),
514 vec!(
515 62u8, 199, 18, 245, 50, 36, 172, 211, 199, 71, 40, 41, 60, 187, 141, 15, 20, 3, 30, 230, 131, 201,
516 232, 67, 0, 255, 223, 184, 139, 8, 159, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
517 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
518 )
519 );
520 }
521 }
522}
523
524#[cfg(test)]
525mod tests {
526 use super::*;
527 use std::io::Cursor;
528 use uuid;
529
530 #[test]
531 fn test_luks_header_from_byte_buffer() {
532 let header = b"LUKS\xba\xbe\x00\x01aes\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ecb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00sha256\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00 \xcf^\xb4\xc00q\xbe\xd5\xe6\x90\xc8G\xb3\x00\xbe\xba\xd052qp\x92\x0c\x9c\xa9\x07R\\y_D\x08b\xf1\xe6\x8f\x0c\xa95\xad\xdb\x15+\xa5\xd7\xa7\xbf^\x96B\x90z\x00\x00\x03\xe8a1b49d2d-8a7e-4b04-ab2a-89f3408fd198\x00\x00\x00\x00";
533 let mut cursor: Cursor<&[u8]> = Cursor::new(header);
534 let header = LuksHeader::read(&mut cursor).unwrap();
535
536 if let LuksHeader::Luks1(luks_header) = header {
537 assert_eq!(luks_header.version(), 1);
538 assert_eq!(luks_header.cipher_name().unwrap(), "aes");
539 assert_eq!(luks_header.cipher_mode().unwrap(), "ecb");
540 assert_eq!(luks_header.hash_spec().unwrap(), "sha256");
541 assert_eq!(luks_header.payload_offset(), 4096);
542 assert_eq!(luks_header.key_bytes(), 32);
543 assert_eq!(
544 luks_header.mk_digest(),
545 &[207, 94, 180, 192, 48, 113, 190, 213, 230, 144, 200, 71, 179, 0, 190, 186, 208, 53, 50, 113]
546 );
547 assert_eq!(
548 luks_header.mk_digest_salt(),
549 &[
550 112, 146, 12, 156, 169, 7, 82, 92, 121, 95, 68, 8, 98, 241, 230, 143, 12, 169, 53, 173, 219, 21,
551 43, 165, 215, 167, 191, 94, 150, 66, 144, 122
552 ]
553 );
554 assert_eq!(luks_header.mk_digest_iterations(), 1000);
555 assert_eq!(
556 luks_header.uuid().unwrap(),
557 uuid::Uuid::parse_str("a1b49d2d-8a7e-4b04-ab2a-89f3408fd198").unwrap()
558 );
559 } else {
560 assert!(false, "failed to read luks v1 header");
561 }
562 }
563
564 #[test]
565 fn test_luks2_header_from_byte_buffer() {
566 let header = b"LUKS\xba\xbe\x00\x02\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00sha256\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00g\x98\x84>\xba \x87\x16\xff\xdc\xdb\xc8\xe1\xd6\xd5\xf6\x01\x94\x9c^E\x84\x1e\xcc\x1c\xc5\xa6\xeb\xaePf\xde\x7f\x95\xfeL\x07\x1f46B\x95Z\xae\xf5\x8f\x88\xc0uj,\x08\xb4NW\r\x8c\xec\xb6D\x15P\x0e\x8f0748f429-3aad-426d-95b4-82005de5ad36\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00>\xc7\x12\xf52$\xac\xd3\xc7G()<\xbb\x8d\x0f\x14\x03\x1e\xe6\x83\xc9\xe8C\x00\xff\xdf\xb8\x8b\x08\x9f4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
567 let mut cursor: Cursor<&[u8]> = Cursor::new(header);
568 let header = LuksHeader::read(&mut cursor).unwrap();
569
570 if let LuksHeader::Luks2(luks2_header) = header {
571 assert_eq!(luks2_header.version(), 2);
572 assert_eq!(
573 luks2_header.uuid().unwrap(),
574 uuid::Uuid::parse_str("0748f429-3aad-426d-95b4-82005de5ad36").unwrap()
575 );
576 } else {
577 assert!(false, "failed to read luks v2 header");
578 }
579 }
580}