w3c / webcrypto

The W3C Web Cryptography API
https://w3c.github.io/webcrypto/
Other
265 stars 53 forks source link

AES-CBC without PKCS#7 padding for 16-byte aligned blocks #295

Open vitaly-castLabs opened 2 years ago

vitaly-castLabs commented 2 years ago

It looks like the current implementations in Chrome (95) and Safari (15) add 16 bytes of padding to already 16-byte aligned blocks prior to encryption (and expect the same when decrypting), and it appears to be correct according to the WebCrypto spec and https://datatracker.ietf.org/doc/html/rfc2315#section-10.3 it is referring.

However this is not compatible with ISO/IEC 23001-7 spec (aka Common Encryption) which doesn't allow any sort of padding whatsoever, all the AES-CBC operations are performed on blocks of size multiple of 16 bytes ("tail" bytes are passed unencrypted). The problem is that ISO/IEC 23001-7 is the base of all the DRM protection frameworks these days and AES-CBC is the only mode which makes Apple, Google, MS and DRM hardware vendors happy at the same time - it answers the question "what's the use case?": https://lists.w3.org/Archives/Public/public-webcrypto-comments/2014Jun/0006.html

Btw WebCrypto's AES-CTR is fully compatible with ISO/IEC 23001-7, I was able to decrypt DRM-protected data with WebCrypto as long as it was AES-CTR, but handling CBC in a compatible way is plain impossible at the moment.

vitaly-castLabs commented 2 years ago

A sensible API in my opinion would be adding disablePadding to https://developer.mozilla.org/en-US/docs/Web/API/AesCbcParams That, when enabled, would produce, just for example, 16-byte long ciphertext when given 23 bytes (i.e. last 7 bytes are skipped) of data. And obviously 16/32/etc-byte input will produce the same size output

twiss commented 2 years ago

Hey :wave:

That, when enabled, would produce, just for example, 16-byte long ciphertext when given 23 bytes (i.e. last 7 bytes are skipped) of data.

That seems like a bad idea, if anything we should throw an error if the plaintext length is not a multiple of the block size.

However, adding more legacy encryption and decryption modes/options purely for compatibility to me seems like not the best use of implementer's time at this point. In general, we want to encourage people to move to newer AEAD encryption modes.

Why do you want to decrypt DRM data using Web Crypto? Isn't this the job of the Encrypted Media Extensions spec?

vitaly-castLabs commented 2 years ago

Yes, throwing an error is fine too.

I wouldn't call those "legacy" for a few reasons: the common encryption spec is the basis of every single DRM protection systems in use atm and there are no plans to replace it any time soon; data authentication is not necessary for content protection, and AEAD overhead, especially for 1:9 encrypted/clear pattern case, would be significant. In the current state of EME/MSE I need to mux elementary streams into fmp4 on-the-fly, so WebCrypto/WebCodecs combo is much much easier to use.

twiss commented 2 years ago

Sorry for the delay. CBC is absolutely a legacy encryption mode, the fact that it's still being used in DRM notwithstanding. Because of that, realistically speaking, browsers are not going to want to implement it. I think you may have better luck convincing them to implement AES-GCM or AES-CTR for DRM.

(FWIW, I still don't understand your use case, if you have the unencrypted video client-side, why not just pass an unencrypted video to the browser? Also, how/why do you have the encryption key client-side? Doesn't this defeat the purpose of DRM?)

vitaly-castLabs commented 2 years ago

It's been a rocky road for DRM. At first everyone was using AES-CTR for DRM, everyone except Apple - they said f you all, we're using CBC (for no particular reason). About a decade later, when everyone was really fed up with having two copies of the same content - one for Apple devices, one for everything else, people came up with CMAF spec which made CBC mandatory 'cause Apple wouldn't budge. I don't have unencrypted video on the client side per se. The video arrives to the client CBC-encrypted (with some metadata like key id), then the client connects to the license server and asks for the decryption key for this particular video.

twiss commented 2 years ago

OK, yeah. To be honest, the most realistic option might be to ship a Web Assembly implementation of AES-CBC. The performance overhead shouldn't be too big (if you run it in a Web Worker), and if security is not a concern, timing attacks etc shouldn't matter to you (which is normally a reason to want Web Crypto).