Question

Have a (rather complex) app that works fine on iOS 4 but fails on iOS 5 with a decryption problem. It's decrypting a SQLite DB page, and the last 16 bytes do not appear to be properly decrypted.

Does this ring a bell with anyone?

Update

I've determined that, when CCCryptorUpdate is given a buffer length of 1008 (1024 - 16) it only decrypts 992 bytes (as reported in the dataOutMoved parameter). This would be OK if CCCryptorFinal returned the remaining bytes, but it reports zero bytes moved. However, CCCryptorFinal is reporting a -4304 return code (which is an unhelpful kCCDecodeError).

Update 2

I've pretty nailed it as an out-and-out bug. I've compared byte-for-byte the output from encryption and the input to decryption, and compared the keys. Identical. But if buffer length is 1008 then decryption always fails, even when the decryptor is given a larger output buffer (it says it needs 1024 in that case). I assume it works fine for 1024, though I haven't gotten past the first oddball sized buffer to tell.

Etc

Well, it appears that nothing decrypts. This is using the "all in one" CCCrypt() interface that removes any chance of an error with the sequencing of CCCryptorCreate/Update/Final. I wonder if it's a problem with AES128?

A curious thing is that when page 1 of the DB is encrypted the encryption always reports back 16 bytes more moved than what I tell it -- if I tell it 1008 it reports 1024, if I tell it 1024 it reports 1040. No other page does that, and I don't see how the CCCrypt could know what page it's processing. Like I said, curious.

Found it (I think)

The old code was specifying kCCOptionPKCS7Padding, which, as I understand it, should only be used for encrypting where the buffer length is not a multiple of the block length (and where additional output buffer space is provided). This caused virtually all decrypt operations to fail with -4304. But in iOS 4 the operations would still move the data they had decrypted (which was essentially all of it), while iOS 5 changed such that all data movement was suppressed if the operation failed (and the last block would almost always fail).

Turning off the padding option makes the code work without posting any errors.

Was it helpful?

Solution

As described above, there was a change from iOS 4 to iOS 5 in that data is no longer copied to the target buffer if there is an error. So in iOS 4 one could be ignoring errors and still get good results, while that doesn't work in iOS 5. (I didn't write the original code -- I never would have ignored the errors.)

The errors were due to having kCCOptionPKCS7Padding specified while doing fixed-length block-multiple operations. (Not entirely sure how one arranges the buffers when doing padding, but it's not something I need to do.) Removing that option causes the operations to be error-free.

OTHER TIPS

When removing kCCOptionPKCS7Padding on kCCDecrypt, and if original data before kCCEncrypt is not a multiple of the block length, the output data length after kCCDecrypt is different length than original data before kCCEncrypt.

So there is no error but the result is wrong.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top