SQLite offers encryption extensions and of them is the sqlite3-see-cccrypt.c:
This file is a drop-in replacement for the public-domain "sqlite3.c" filef, adding support for the AES-128 and AES-256 encryption algorithms, in OFB mode, using the external CCCrypt encryption. CCCrypt is the default encryption library on MacOS and iOS, and so this implementation of SEE is recommended for those platforms.
The see-ccrypt.c module normally only does AES128 encryption. However, when see-cccrypt is compiled with -DCCCRYPT256, it will use AES256 if and only if the key is exactly 32 bytes long.
I don't know if this is what Apple does use or not.
When you create a database with abc123
key the following happens:
* frame #0: 0x00007fff52a041fb libcommonCrypto.dylib`CCCrypt
frame #1: 0x00007fff21cfca21 libsqlite3.dylib`sqliteCodecCCCrypto + 305
frame #2: 0x00007fff21bc76d3 libsqlite3.dylib`pager_write_pagelist + 243
...
CCCrypt
is utilized. Page size is 4096 bytes. CCrypt
function signature is:
CCCryptorStatus
CCCrypt(CCOperation op, CCAlgorithm alg, CCOptions options, const void *key, size_t keyLength,
const void *iv, const void *dataIn, size_t dataInLength, void *dataOut, size_t dataOutAvailable,
size_t *dataOutMoved)
This function is called with:
op
set to 0
(encrypt)
alg
set to 0
(AES 128),
key
is abc123abc123abc1
(initial key, copied to fit 16 bytes),
dataIn
is a garbage I don't recognize yet (not a plaintet SQLite page),
dataInLength
is 4096,
dataOutMoved
is set to 4096 on the return.
Also iv
value is:
0x01 0x00 0x00 0x00 0xc0 0xa2 0xe8 0xa8
0x44 0x49 0xef 0xa0 0xa4 0x7b 0xec 0x5f
I don't know SQLite internals, but it looks that the first four bytes represents page number and the rest is some random stuff. CCCrypt
is called for every page and consequent pages iv
starts with 0x02 0x00 0x00 0x00
, 0x03 0x00 0x00 0x00
, etc.
When you look at the encrypted sqlite file, last 12 bytes of the iv
are stored at the end of each page:
% hexdump -C db-enc.sqlite| grep "44 49 ef"
00000ff0 e2 a1 77 2a c0 a2 e8 a8 44 49 ef a0 a4 7b ec 5f
^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|- ? |- last 12 bytes of iv
0xff0
= 4080
4080 + 16
= 4096
(= page size)
One would say that AES 128 is used, but ... When I open already existing database, CCCrypt
is called again, but with the operation set to 0
(encrypt). In other words, CCCrypt
is never called with the decrypt operation.
The library is stored:
/Applications/Xcode-beta.app/Contents/Developer/Platforms/
iPhoneOS.platform/Library/Developer/CoreSimulator/
Profiles/Runtimes/iOS.simruntime/Contents/Resources/
RuntimeRoot/usr/lib/libsqlite3.dylib
Symbols to focus on:
_sqlite3CodecAttach
_sqliteCodecCCCrypto
_sqliteCodecCCCryptoSizeChng
_sqliteCodecCCCryptoFree
_loadKeyCCCrypt
Related external symbols:
_CCCrypt:
00000000001ce000 extern function code ; in /usr/lib/libSystem.B.dylib, CODE XREF=imp___stubs__CCCrypt, DATA XREF=_CCCrypt_ptr
_CC_SHA256_Final:
00000000001ce008 extern function code ; in /usr/lib/libSystem.B.dylib, CODE XREF=imp___stubs__CC_SHA256_Final, DATA XREF=_CC_SHA256_Final_ptr
_CC_SHA256_Init:
00000000001ce010 extern function code ; in /usr/lib/libSystem.B.dylib, CODE XREF=imp___stubs__CC_SHA256_Init, DATA XREF=_CC_SHA256_Init_ptr
_CC_SHA256_Update:
00000000001ce018 extern function code
dlopen
calls:
- Opens
/usr/lib/libcompression.dylib
for compression streams
That's what I've found so far. If anyone wants to continue, feel free, I don't have more time for this rabbit hole :)