-
Notifications
You must be signed in to change notification settings - Fork 55
Description
The entire world apparently calls what BitLocker uses to wrap keys "AES-CCM". Unfortunately, that's not what is actually implemented. The algorithm implemented by libcaes_crypt_ccm isn't CCM: it doesn't have a MAC, it doesn't have associated data, and it doesn't use the first keystream block for that. That makes it just AES-CTR.
The only thing "CCM" about it is that the nonce is prepended with a byte of value 15 - (uint8_t) nonce_size - 1 (which CCM does, and is not inherent to CTR mode). There's none of the other bits that would make it compliant with the CCM specification (RFC3610). Crucially, BitLocker key unwrapping can be implemented using a standard AES-CTR implementation (just prepend 0x02 to the nonce), but cannot be implemented using a standard AES-CCM implementation (because there is no way to disable the whole MAC machinery).
I would recommend renaming all mentions of CCM to CTR, to avoid confusion. I just spent a few hours wondering why using PyCryptodome yielded incorrect decryptions of BitLocker wrapped keys. Instead, CTR mode is what you want. In PyCryptodome:
python
def decrypt(p, k):
nonce = p[:12]
nonce = bytes([15 - len(nonce) - 1]) + nonce
aes = AES.new(k, AES.MODE_CTR, nonce=nonce)
a = aes.decrypt(p[12:])
return a
~~
is the code you'd want to unwrap a BitLocker wrapped key, with MODE_CTR, not MODE_CCM.