@@ -9,7 +9,6 @@ import ReadiumInternal
99import ReadiumShared
1010
1111private let lcpScheme = " http://readium.org/2014/01/lcp "
12- private let AESBlockSize : UInt64 = 16 // bytes
1312
1413/// Decrypts a resource protected with LCP.
1514final class LCPDecryptor {
@@ -117,7 +116,7 @@ final class LCPDecryptor {
117116 guard let length = length else {
118117 return failure ( . requiredEstimatedLength)
119118 }
120- guard length >= 2 * AESBlockSize else {
119+ guard length. isValidAESChunk else {
121120 return failure ( . invalidCBCData)
122121 }
123122
@@ -207,6 +206,10 @@ final class LCPDecryptor {
207206private extension LCPLicense {
208207 func decryptFully( data: ReadResult < Data > , isDeflated: Bool ) async -> ReadResult < Data > {
209208 data. flatMap {
209+ guard UInt64 ( $0. count) . isValidAESChunk else {
210+ return . failure( . decoding( LCPDecryptor . Error. invalidCBCData) )
211+ }
212+
210213 do {
211214 // Decrypts the resource.
212215 guard var data = try self . decipher ( $0) else {
@@ -242,3 +245,15 @@ private extension ReadiumShared.Encryption {
242245 algorithm == " http://www.w3.org/2001/04/xmlenc#aes256-cbc "
243246 }
244247}
248+
249+ private let AESBlockSize : UInt64 = 16 // bytes
250+
251+ private extension UInt64 {
252+ /// Checks if this number is a valid CBC length - i.e. a multiple of AES
253+ /// block size.
254+ /// If not, the file is likely not actually encrypted despite being declared
255+ /// as such.
256+ var isValidAESChunk : Bool {
257+ self >= 2 * AESBlockSize && self % AESBlockSize == 0
258+ }
259+ }
0 commit comments