Skip to content

Commit 6b64772

Browse files
gregakespretclaude
andcommitted
Provide RFC 3394 default IV explicitly for AES key wrap
openssl 0.10.80 enforces that any cipher with a defined IV must have one supplied explicitly — passing `None` panics at runtime with "an IV is required for this cipher" inside `Crypter::new` / `decrypt` (see openssl-rs/symm.rs around the IV-required check). The two call sites here are in the RFC 6637 OpenPGP key-wrap helpers and both go through AES Key Wrap (RFC 3394). RFC 3394 §2.2.3.1 defines the "default initial value" for the wrap function as the constant `A6A6A6A6A6A6A6A6`, used when no Alternative Initial Value is supplied. Pass that constant explicitly so the cipher contract is satisfied without changing the wire-level behaviour (the byte stream produced/consumed on the network is identical to what older openssl versions did when `None` was passed). Reproduces with the export-findmy tool against any CloudKit zone that returns PCS-encrypted records (e.g. the FindMy BeaconStore zone) when built against current openssl crate releases. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 9919063 commit 6b64772

1 file changed

Lines changed: 2 additions & 2 deletions

File tree

src/util.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1588,7 +1588,7 @@ pub fn rfc6637_wrap_key<T: HasPublic>(public_key: &CompactECKey<T>, key: &[u8],
15881588
*i = padding_count as u8;
15891589
}
15901590

1591-
let mut c = Crypter::new(Cipher::from_nid(Nid::ID_AES128_WRAP).unwrap(), Mode::Encrypt, &aes_key[..16], None)?;
1591+
let mut c = Crypter::new(Cipher::from_nid(Nid::ID_AES128_WRAP).unwrap(), Mode::Encrypt, &aes_key[..16], Some(&[0xa6u8; 8]))?;
15921592
let mut out = vec![0u8; message.len() + 16];
15931593

15941594
let mut count = c.update(&message, &mut out)?;
@@ -1618,7 +1618,7 @@ pub fn rfc6637_unwrap_key(private_key: &CompactECKey<Private>, wrapped_key: &[u8
16181618
// RFC6637 KDF
16191619
let hash = rfc6637_kdf(fingerprint, &secret);
16201620

1621-
let unwrapped = decrypt(Cipher::from_nid(Nid::ID_AES128_WRAP).unwrap(), &hash[..16], None, &unpacked.wrapped)?;
1621+
let unwrapped = decrypt(Cipher::from_nid(Nid::ID_AES128_WRAP).unwrap(), &hash[..16], Some(&[0xa6u8; 8]), &unpacked.wrapped)?;
16221622

16231623
let padding_len = *unwrapped.last().unwrap() as usize;
16241624
for i in 0..padding_len {

0 commit comments

Comments
 (0)