1use crate::crypto::DecryptionError::InvalidEncryption;
9use crate::crypto::aes::{AES128Cipher, AES256Cipher};
10use crate::crypto::rc4::Rc4;
11use crate::object;
12use crate::object::dict::keys::{
13 CF, CFM, ENCRYPT_META_DATA, FILTER, LENGTH, O, OE, P, R, STM_F, STR_F, U, UE, V,
14};
15use crate::object::{Dict, Name, ObjectIdentifier};
16use crate::sync::HashMap;
17use alloc::string::ToString;
18use alloc::vec;
19use alloc::vec::Vec;
20use core::cmp;
21use core::ops::Deref;
22
23mod aes;
24mod md5;
25mod rc4;
26mod sha256;
27mod sha384;
28mod sha512;
29
30const PASSWORD_PADDING: [u8; 32] = [
31 0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
32 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A,
33];
34
35#[derive(Debug, Copy, Clone, PartialEq, Eq)]
37pub enum DecryptionError {
38 MissingIDEntry,
40 PasswordProtected,
43 InvalidEncryption,
45 UnsupportedAlgorithm,
47}
48
49#[derive(Debug, Copy, Clone, PartialEq, Eq)]
50enum DecryptorTag {
51 None,
52 Rc4,
53 Aes128,
54 Aes256,
55}
56
57impl DecryptorTag {
58 fn from_name(name: &Name) -> Option<Self> {
59 match name.as_str() {
60 "None" | "Identity" => Some(Self::None),
61 "V2" => Some(Self::Rc4),
62 "AESV2" => Some(Self::Aes128),
63 "AESV3" => Some(Self::Aes256),
64 _ => None,
65 }
66 }
67}
68#[derive(Debug, Clone)]
69pub(crate) enum Decryptor {
70 None,
71 Rc4 { key: Vec<u8> },
72 Aes128 { key: Vec<u8>, dict: DecryptorData },
73 Aes256 { key: Vec<u8>, dict: DecryptorData },
74}
75
76#[derive(Debug, Copy, Clone)]
77pub(crate) enum DecryptionTarget {
78 String,
79 Stream,
80}
81
82impl Decryptor {
83 pub(crate) fn decrypt(
84 &self,
85 id: ObjectIdentifier,
86 data: &[u8],
87 target: DecryptionTarget,
88 ) -> Option<Vec<u8>> {
89 match self {
90 Self::None => Some(data.to_vec()),
91 Self::Rc4 { key } => decrypt_rc4(key, data, id),
92 Self::Aes128 { key, dict } | Self::Aes256 { key, dict } => {
93 let crypt_dict = match target {
94 DecryptionTarget::String => dict.string_filter,
95 DecryptionTarget::Stream => dict.stream_filter,
96 };
97
98 match crypt_dict.cfm {
99 DecryptorTag::None => Some(data.to_vec()),
100 DecryptorTag::Rc4 => decrypt_rc4(key, data, id),
101 DecryptorTag::Aes128 => decrypt_aes128(key, data, id),
102 DecryptorTag::Aes256 => decrypt_aes256(key, data),
103 }
104 }
105 }
106 }
107}
108
109pub(crate) fn get(
110 dict: &Dict<'_>,
111 id: &[u8],
112 password: &[u8],
113) -> Result<Decryptor, DecryptionError> {
114 let filter = dict.get::<Name>(FILTER).ok_or(InvalidEncryption)?;
115
116 if filter.deref() != b"Standard" {
117 return Err(DecryptionError::UnsupportedAlgorithm);
118 }
119
120 let encryption_v = dict.get::<u8>(V).ok_or(InvalidEncryption)?;
121 let encrypt_metadata = dict.get::<bool>(ENCRYPT_META_DATA).unwrap_or(true);
122 let revision = dict.get::<u8>(R).ok_or(InvalidEncryption)?;
123 let length = match encryption_v {
124 1 => 40,
125 2 => dict.get::<u16>(LENGTH).unwrap_or(40),
126 4 => dict.get::<u16>(LENGTH).unwrap_or(128),
127 5 => 256,
128 _ => return Err(DecryptionError::UnsupportedAlgorithm),
129 };
130
131 let (algorithm, data) = match encryption_v {
132 1 => (DecryptorTag::Rc4, None),
133 2 => (DecryptorTag::Rc4, None),
134 4 => (
135 DecryptorTag::Aes128,
136 Some(DecryptorData::from_dict(dict, length).ok_or(InvalidEncryption)?),
137 ),
138 5 | 6 => (
139 DecryptorTag::Aes256,
140 Some(DecryptorData::from_dict(dict, length).ok_or(InvalidEncryption)?),
141 ),
142 _ => {
143 return Err(DecryptionError::UnsupportedAlgorithm);
144 }
145 };
146
147 let byte_length = length / 8;
148 if byte_length == 0 {
154 return Err(InvalidEncryption);
155 }
156
157 let owner_string = dict.get::<object::String>(O).ok_or(InvalidEncryption)?;
158 let user_string = dict.get::<object::String>(U).ok_or(InvalidEncryption)?;
159 let permissions = {
160 let raw = dict.get::<i64>(P).ok_or(InvalidEncryption)?;
161
162 if raw < 0 {
163 u32::from_be_bytes((raw as i32).to_be_bytes())
164 } else {
165 raw as u32
166 }
167 };
168
169 let mut decryption_key = if revision <= 4 {
170 let key = decryption_key_rev1234(
171 password,
172 encrypt_metadata,
173 revision,
174 byte_length,
175 &owner_string,
176 permissions,
177 id,
178 )?;
179 authenticate_user_password_rev234(revision, &key, id, &user_string)?;
180
181 key
182 } else {
183 decryption_key_rev56(dict, revision, password, &owner_string, &user_string)?
184 };
185
186 if encryption_v == 4 && decryption_key.len() < 16 {
188 decryption_key.resize(16, 0);
189 }
190
191 match algorithm {
192 DecryptorTag::None => Ok(Decryptor::None),
193 DecryptorTag::Rc4 => Ok(Decryptor::Rc4 {
194 key: decryption_key,
195 }),
196 DecryptorTag::Aes128 => Ok(Decryptor::Aes128 {
197 key: decryption_key,
198 dict: data.ok_or(InvalidEncryption)?,
199 }),
200 DecryptorTag::Aes256 => Ok(Decryptor::Aes256 {
201 key: decryption_key,
202 dict: data.ok_or(InvalidEncryption)?,
203 }),
204 }
205}
206
207fn decrypt_aes256(key: &[u8], data: &[u8]) -> Option<Vec<u8>> {
209 let (iv, data) = data.split_at_checked(16)?;
216 let iv: [u8; 16] = iv.try_into().ok()?;
217 let cipher = AES256Cipher::new(key)?;
218 Some(cipher.decrypt_cbc(data, &iv, true))
219}
220
221fn decrypt_aes128(key: &[u8], data: &[u8], id: ObjectIdentifier) -> Option<Vec<u8>> {
222 decrypt_rc_aes(key, id, true, |key| {
223 let cipher = AES128Cipher::new(key)?;
227 let (iv, data) = data.split_at_checked(16)?;
228 let iv: [u8; 16] = iv.try_into().ok()?;
229
230 Some(cipher.decrypt_cbc(data, &iv, true))
231 })
232}
233
234fn decrypt_rc4(key: &[u8], data: &[u8], id: ObjectIdentifier) -> Option<Vec<u8>> {
235 decrypt_rc_aes(key, id, false, |key| {
236 let mut rc = Rc4::new(key);
237 Some(rc.decrypt(data))
238 })
239}
240
241fn decrypt_rc_aes(
243 key: &[u8],
244 id: ObjectIdentifier,
245 aes: bool,
246 with_key: impl FnOnce(&[u8]) -> Option<Vec<u8>>,
247) -> Option<Vec<u8>> {
248 let n = key.len();
249 let mut key = key.to_vec();
254
255 key.extend(&id.obj_number.to_le_bytes()[..3]);
261 key.extend(&id.gen_number.to_le_bytes()[..2]);
262
263 if aes {
267 key.extend(b"sAlT");
268 }
269
270 let hash = md5::calculate(&key);
273
274 let final_key = &hash[..cmp::min(16, n + 5)];
278
279 with_key(final_key)
280}
281
282#[derive(Debug, Copy, Clone)]
283pub(crate) struct DecryptorData {
284 stream_filter: CryptDictionary,
285 string_filter: CryptDictionary,
286}
287
288impl DecryptorData {
289 fn from_dict(dict: &Dict<'_>, default_length: u16) -> Option<Self> {
290 let mut mappings = HashMap::new();
291
292 if let Some(dict) = dict.get::<Dict<'_>>(CF) {
293 for key in dict.keys() {
294 if let Some(dict) = dict.get::<Dict<'_>>(key.clone())
295 && let Some(crypt_dict) = CryptDictionary::from_dict(&dict, default_length)
296 {
297 mappings.insert(key.as_str().to_string(), crypt_dict);
298 }
299 }
300 }
301
302 let stm_f = *mappings
303 .get(dict.get::<Name>(STM_F)?.as_str())
304 .unwrap_or(&CryptDictionary::identity(default_length));
305 let str_f = *mappings
306 .get(dict.get::<Name>(STR_F)?.as_str())
307 .unwrap_or(&CryptDictionary::identity(default_length));
308
309 Some(Self {
310 stream_filter: stm_f,
311 string_filter: str_f,
312 })
313 }
314}
315
316#[derive(Debug, Copy, Clone)]
317struct CryptDictionary {
318 cfm: DecryptorTag,
319 _length: u16,
320}
321
322impl CryptDictionary {
323 fn from_dict(dict: &Dict<'_>, default_length: u16) -> Option<Self> {
324 let cfm = DecryptorTag::from_name(&dict.get::<Name>(CFM)?)?;
325 let mut length = dict.get::<u16>(LENGTH).unwrap_or(default_length / 8);
330
331 if cfm == DecryptorTag::Aes128 {
334 length = 16;
335 } else if cfm == DecryptorTag::Aes256 {
336 length = 32;
337 }
338
339 Some(Self {
340 cfm,
341 _length: length,
342 })
343 }
344
345 fn identity(default_length: u16) -> Self {
346 Self {
347 cfm: DecryptorTag::None,
348 _length: default_length,
349 }
350 }
351}
352
353fn compute_hash_rev56(
355 password: &[u8],
356 validation_salt: &[u8],
357 user_string: Option<&[u8]>,
358 revision: u8,
359) -> Result<[u8; 32], DecryptionError> {
360 let mut k = {
363 let mut input = Vec::new();
364 input.extend_from_slice(password);
365 input.extend_from_slice(validation_salt);
366
367 if let Some(user_string) = user_string {
368 input.extend_from_slice(user_string);
369 }
370
371 let hash = sha256::calculate(&input);
372
373 if revision == 5 {
375 return Ok(hash);
376 }
377
378 hash.to_vec()
379 };
380
381 let mut round: u16 = 0;
382
383 loop {
385 let k1 = {
391 let mut single: Vec<u8> = vec![];
392 single.extend(password);
393 single.extend(&k);
394
395 if let Some(user_string) = user_string {
396 single.extend(user_string);
397 }
398
399 single.repeat(64)
400 };
401
402 let e = {
406 let aes = AES128Cipher::new(&k[..16]).ok_or(InvalidEncryption)?;
407 let mut res = aes.encrypt_cbc(&k1, &k[16..32].try_into().expect("k is ≥32 bytes"));
408
409 res.truncate(k1.len());
411
412 res
413 };
414
415 let num = u128::from_be_bytes(e[..16].try_into().expect("AES output is ≥16 bytes")) % 3;
420
421 k = match num {
424 0 => sha256::calculate(&e).to_vec(),
425 1 => sha384::calculate(&e).to_vec(),
426 2 => sha512::calculate(&e).to_vec(),
427 _ => unreachable!(),
428 };
429
430 round += 1;
431
432 if round > 63 {
436 let last_byte = *e.last().expect("AES output is non-empty");
440
441 if (last_byte as u16) <= round - 32 {
445 break;
446 }
447 }
448 }
449
450 let mut result = [0_u8; 32];
452 result.copy_from_slice(&k[..32]);
453 Ok(result)
454}
455
456fn decryption_key_rev1234(
458 password: &[u8],
459 encrypt_metadata: bool,
460 revision: u8,
461 byte_length: u16,
462 owner_string: &object::String,
463 permissions: u32,
464 id: &[u8],
465) -> Result<Vec<u8>, DecryptionError> {
466 let byte_length = byte_length.min(16);
469
470 let mut md5_input = vec![];
471
472 let mut padded_password = [0_u8; 32];
475 let copy_len = password.len().min(32);
476 padded_password[..copy_len].copy_from_slice(&password[..copy_len]);
477 if copy_len < 32 {
478 padded_password[copy_len..].copy_from_slice(&PASSWORD_PADDING[..(32 - copy_len)]);
479 }
480
481 md5_input.extend(&padded_password);
484
485 md5_input.extend(owner_string.as_ref());
488
489 md5_input.extend(permissions.to_le_bytes());
492
493 md5_input.extend(id);
495
496 if !encrypt_metadata && revision >= 4 {
499 md5_input.extend(&[0xff, 0xff, 0xff, 0xff]);
500 }
501
502 let mut hash = md5::calculate(&md5_input);
504
505 if revision >= 3 {
510 for _ in 0..50 {
511 hash = md5::calculate(&hash[..byte_length as usize]);
512 }
513 }
514
515 let decryption_key = hash[..byte_length as usize].to_vec();
516 Ok(decryption_key)
517}
518
519fn authenticate_user_password_rev234(
521 revision: u8,
522 decryption_key: &[u8],
523 id: &[u8],
524 user_string: &object::String,
525) -> Result<(), DecryptionError> {
526 let result = match revision {
528 2 => user_password_rev2(decryption_key),
529 3 | 4 => user_password_rev34(decryption_key, id),
530 _ => return Err(InvalidEncryption),
531 };
532
533 match revision {
537 2 => {
538 if result.as_slice() != user_string.as_ref() {
539 return Err(DecryptionError::PasswordProtected);
540 }
541 }
542 3 | 4 => {
543 if Some(&result[..16]) != user_string.as_ref().get(0..16) {
544 return Err(DecryptionError::PasswordProtected);
545 }
546 }
547 _ => unreachable!(),
548 }
549
550 Ok(())
551}
552
553fn user_password_rev2(decryption_key: &[u8]) -> Vec<u8> {
556 let mut rc = Rc4::new(decryption_key);
560 rc.decrypt(&PASSWORD_PADDING)
561}
562
563fn user_password_rev34(decryption_key: &[u8], id: &[u8]) -> Vec<u8> {
566 let mut rc = Rc4::new(decryption_key);
568
569 let mut input = vec![];
570 input.extend(PASSWORD_PADDING);
572
573 input.extend(id);
576 let hash = md5::calculate(&input);
577
578 let mut encrypted = rc.encrypt(&hash);
581
582 for i in 1..=19 {
588 let mut key = decryption_key.to_vec();
589 for byte in &mut key {
590 *byte ^= i;
591 }
592
593 let mut rc = Rc4::new(&key);
594 encrypted = rc.encrypt(&encrypted);
595 }
596
597 encrypted.resize(32, 0);
598 encrypted
599}
600
601fn decryption_key_rev56(
603 dict: &Dict<'_>,
604 revision: u8,
605 password: &[u8],
606 owner_string: &object::String,
607 user_string: &object::String,
608) -> Result<Vec<u8>, DecryptionError> {
609 let password = &password[..password.len().min(127)];
615
616 let string_len = if revision <= 4 { 32 } else { 48 };
617
618 let trimmed_os = owner_string.get(..string_len).ok_or(InvalidEncryption)?;
619
620 let (owner_hash, owner_tail) = trimmed_os.split_at_checked(32).ok_or(InvalidEncryption)?;
621 let (owner_validation_salt, owner_key_salt) =
622 owner_tail.split_at_checked(8).ok_or(InvalidEncryption)?;
623
624 let trimmed_us = user_string.get(..string_len).ok_or(InvalidEncryption)?;
625 let (user_hash, user_tail) = trimmed_us.split_at_checked(32).ok_or(InvalidEncryption)?;
626 let (user_validation_salt, user_key_salt) =
627 user_tail.split_at_checked(8).ok_or(InvalidEncryption)?;
628
629 if compute_hash_rev56(password, owner_validation_salt, Some(trimmed_us), revision)?
634 == owner_hash
635 {
636 let intermediate_owner_key =
641 compute_hash_rev56(password, owner_key_salt, Some(trimmed_us), revision)?;
642
643 let oe_string = dict.get::<object::String>(OE).ok_or(InvalidEncryption)?;
644
645 if oe_string.len() != 32 {
646 return Err(InvalidEncryption);
647 }
648
649 let cipher = AES256Cipher::new(&intermediate_owner_key).ok_or(InvalidEncryption)?;
650 let zero_iv = [0_u8; 16];
651
652 Ok(cipher.decrypt_cbc(&oe_string, &zero_iv, false))
653 } else if compute_hash_rev56(password, user_validation_salt, None, revision)? == user_hash {
654 let intermediate_key = compute_hash_rev56(password, user_key_salt, None, revision)?;
659
660 let ue_string = dict.get::<object::String>(UE).ok_or(InvalidEncryption)?;
661
662 if ue_string.len() != 32 {
663 return Err(InvalidEncryption);
664 }
665
666 let cipher = AES256Cipher::new(&intermediate_key).ok_or(InvalidEncryption)?;
667 let zero_iv = [0_u8; 16];
668
669 Ok(cipher.decrypt_cbc(&ue_string, &zero_iv, false))
670 } else {
671 Err(DecryptionError::PasswordProtected)
672 }
673
674 }
680
681#[cfg(test)]
682mod upstream_hardening_tests {
683 use super::*;
684 use crate::reader::{Reader, ReaderContext, ReaderExt};
685
686 fn encryption_dict(data: &[u8]) -> Dict<'_> {
687 Reader::new(data)
688 .read_with_context::<Dict<'_>>(&ReaderContext::dummy())
689 .expect("the test's own dictionary must parse")
690 }
691
692 #[test]
703 fn an_encryption_length_below_one_byte_is_rejected_not_divided_by() {
704 let dict = encryption_dict(
705 b"<< /Filter /Standard /V 2 /R 2 /Length 4 \
706 /O <0000000000000000000000000000000000000000000000000000000000000000> \
707 /U <0000000000000000000000000000000000000000000000000000000000000000> \
708 /P -1 >>",
709 );
710
711 assert!(matches!(
712 get(&dict, b"", b""),
713 Err(DecryptionError::InvalidEncryption)
714 ));
715 }
716
717 #[test]
721 fn the_ordinary_forty_bit_length_still_derives_a_key() {
722 let dict = encryption_dict(
723 b"<< /Filter /Standard /V 2 /R 2 /Length 40 \
724 /O <0000000000000000000000000000000000000000000000000000000000000000> \
725 /U <0000000000000000000000000000000000000000000000000000000000000000> \
726 /P -1 >>",
727 );
728
729 assert!(!matches!(
732 get(&dict, b"", b""),
733 Err(DecryptionError::InvalidEncryption)
734 ));
735 }
736}