diff --git a/scripts/patchsqlite3.sh b/scripts/patchsqlite3.sh index 3062548..5a689f5 100644 --- a/scripts/patchsqlite3.sh +++ b/scripts/patchsqlite3.sh @@ -17,7 +17,7 @@ die() { # 1) Intercept VFS pragma handling # 2) Add handling of KEY parameter in ATTACH statements sed 's/sqlite3_file_control\(.*SQLITE_FCNTL_PRAGMA\)/sqlite3mcFileControlPragma\1/' "$INPUT" \ - | sed '/\#endif \/\* SQLITE3\_H \*\//a \ \n\/\* Function prototypes of SQLite3 Multiple Ciphers \*\/\nSQLITE_PRIVATE int sqlite3mcCheckVfs(const char*);\nSQLITE_PRIVATE int sqlite3mcFileControlPragma(sqlite3*, const char*, int, void*);\nSQLITE_PRIVATE int sqlite3mcHandleAttachKey(sqlite3*, const char*, const char*, sqlite3_value*, char**);\nSQLITE_PRIVATE int sqlite3mcHandleMainKey(sqlite3*, const char*);\ntypedef struct PgHdr PgHdrMC;\nSQLITE_PRIVATE void* sqlite3mcPagerCodec(PgHdrMC* pPg);\ntypedef struct Pager PagerMC;\nSQLITE_PRIVATE int sqlite3mcPagerHasCodec(PagerMC* pPager);\nSQLITE_PRIVATE void sqlite3mcInitMemoryMethods();' \ + | sed '/\#endif \/\* SQLITE3\_H \*\//a \ \n\/\* Function prototypes of SQLite3 Multiple Ciphers \*\/\nSQLITE_PRIVATE int sqlite3mcCheckVfs(const char*);\nSQLITE_PRIVATE int sqlite3mcFileControlPragma(sqlite3*, const char*, int, void*);\nSQLITE_PRIVATE int sqlite3mcHandleAttachKey(sqlite3*, const char*, const char*, sqlite3_value*, char**);\nSQLITE_PRIVATE int sqlite3mcHandleMainKey(sqlite3*, const char*);\ntypedef struct PgHdr PgHdrMC;\nSQLITE_PRIVATE void* sqlite3mcPagerCodec(PgHdrMC* pPg);\ntypedef struct Pager PagerMC;\nSQLITE_PRIVATE int sqlite3mcPagerHasCodec(PagerMC* pPager);\nSQLITE_PRIVATE void sqlite3mcInitMemoryMethods();\nSQLITE_PRIVATE int sqlite3mcIsBackupSupported(sqlite3*, const char*, sqlite3*, const char*);' \ | sed '/\#define MAX\_PATHNAME 512/c #if SQLITE3MC\_MAX\_PATHNAME \> 512\n#define MAX_PATHNAME SQLITE3MC\_MAX\_PATHNAME\n#else\n#define MAX_PATHNAME 512\n#endif' \ | sed '/pData = pPage->pData;/c \ if( (pData = sqlite3mcPagerCodec(pPage))==0 ) return SQLITE_NOMEM_BKPT;' \ | sed '/pData = p->pData;/c \ if( (pData = sqlite3mcPagerCodec(p))==0 ) return SQLITE_NOMEM;' \ @@ -26,4 +26,5 @@ sed 's/sqlite3_file_control\(.*SQLITE_FCNTL_PRAGMA\)/sqlite3mcFileControlPragma\ | sed '/sqlite3_free_filename(zOpen);/i \\n \/\* Handle encryption related URI parameters. \*\/\n if( rc==SQLITE_OK ){\n rc = sqlite3mcHandleMainKey(db, zOpen);\n }' \ | sed '/^ if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;/a \ if( sqlite3mcPagerHasCodec(pPager) != 0 ) return 0;' \ | sed '/^ }else if( USEFETCH(pPager) ){/c \ }else if( USEFETCH(pPager) && sqlite3mcPagerHasCodec(pPager) == 0 ){' \ - | sed '/^ if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0));/a \\n \/\* Initialize wrapper for memory management.\*\/\n if( rc==SQLITE_OK ) {\n sqlite3mcInitMemoryMethods();\n }\n' + | sed '/^ if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0));/a \\n \/\* Initialize wrapper for memory management.\*\/\n if( rc==SQLITE_OK ) {\n sqlite3mcInitMemoryMethods();\n }\n' \ + | sed '/Lock the source database handle./i \ \/\* Check whether databases are compatible with backup \*\/\n if (!sqlite3mcIsBackupSupported(pSrcDb, zSrcDb, pDestDb, zDestDb)){\n sqlite3ErrorWithMsg(pDestDb, SQLITE_ERROR, \"backup is not supported with incompatible source and target databases\");\n return NULL;\n }\n' diff --git a/src/ascon/aead.c b/src/ascon/aead.c index 1d9132e..a92fc45 100644 --- a/src/ascon/aead.c +++ b/src/ascon/aead.c @@ -88,7 +88,7 @@ forceinline void ascon_adata(ascon_state_t* s, const uint8_t* ad, ASCON_P(s, nr); } /* domain separation */ - s->x[4] ^= 1; + s->x[4] ^= ASCON_DSEP(); ascon_printstate("domain separation", s); } diff --git a/src/ascon/word.h b/src/ascon/word.h index cfd960a..972b55d 100644 --- a/src/ascon/word.h +++ b/src/ascon/word.h @@ -15,6 +15,8 @@ typedef union { #define ASCON_U64TOWORD(x) ASCON_U64BIG(x) #define ASCON_WORDTOU64(x) ASCON_U64BIG(x) +#define ASCON_LOAD(b, n) ASCON_LOADBYTES(b, n) +#define ASCON_STORE(b, w, n) ASCON_STOREBYTES(b, w, n) forceinline uint64_t ASCON_ROR(uint64_t x, int n) { return x >> n | x << (-n & 63); } @@ -32,6 +34,8 @@ forceinline int ASCON_NOTZERO(uint64_t a, uint64_t b) { forceinline uint64_t ASCON_PAD(int i) { return 0x80ull << (56 - 8 * i); } +forceinline uint64_t ASCON_DSEP() { return 0x01; } + forceinline uint64_t ASCON_PRFS_MLEN(uint64_t len) { return len << 51; } forceinline uint64_t ASCON_CLEAR(uint64_t w, int n) { @@ -45,16 +49,6 @@ forceinline uint64_t ASCON_MASK(int n) { return ~0ull >> (64 - 8 * n); } -forceinline uint64_t ASCON_LOAD(const uint8_t* bytes, int n) { - uint64_t x = *(uint64_t*)bytes & ASCON_MASK(n); - return ASCON_U64TOWORD(x); -} - -forceinline void ASCON_STORE(uint8_t* bytes, uint64_t w, int n) { - *(uint64_t*)bytes &= ~ASCON_MASK(n); - *(uint64_t*)bytes |= ASCON_WORDTOU64(w); -} - forceinline uint64_t ASCON_LOADBYTES(const uint8_t* bytes, int n) { uint64_t x = 0; memcpy(&x, bytes, n); diff --git a/src/cipher_sqlcipher.c b/src/cipher_sqlcipher.c index e97467f..0e7b2bf 100644 --- a/src/cipher_sqlcipher.c +++ b/src/cipher_sqlcipher.c @@ -356,7 +356,7 @@ EncryptPageSQLCipherCipher(void* cipher, int page, unsigned char* data, int len, int n = len - nReserved; int offset = (page == 1) ? (sqlCipherCipher->m_legacy != 0) ? 16 : 24 : 0; int blen; - unsigned char iv[64]; + unsigned char iv[128]; int usePlaintextHeader = 0; /* Check whether a plaintext header should be used */ @@ -373,10 +373,10 @@ EncryptPageSQLCipherCipher(void* cipher, int page, unsigned char* data, int len, } /* Generate nonce (64 bytes) */ - memset(iv, 0, 64); + memset(iv, 0, 128); if (nReserved > 0) { - chacha20_rng(iv, 64); + chacha20_rng(iv, 128); } else { diff --git a/src/sqlite3mc_vfs.c b/src/sqlite3mc_vfs.c index 0f1e4d5..c126af4 100644 --- a/src/sqlite3mc_vfs.c +++ b/src/sqlite3mc_vfs.c @@ -301,6 +301,29 @@ SQLITE_PRIVATE Codec* sqlite3mcGetMainCodec(sqlite3* db) return sqlite3mcGetCodec(db, "main"); } +SQLITE_PRIVATE int sqlite3mcIsBackupSupported(sqlite3* pSrc, const char* zSrc, sqlite3* pDest, const char* zDest) +{ + int ok = 1; + if (pSrc != pDest) + { + Codec* codecSrc = sqlite3mcGetCodec(pSrc, zSrc); + Codec* codecDest = sqlite3mcGetCodec(pDest, zDest); + if (codecSrc && codecDest) + { + /* Both databases have a codec */ + ok = sqlite3mcIsEncrypted(codecSrc) && sqlite3mcIsEncrypted(codecDest) && + (sqlite3mcGetReadReserved(codecSrc) == sqlite3mcGetWriteReserved(codecDest)); + } + else + { + /* At least one database has no codec */ + /* Backup supported if both databases are plain databases */ + ok = !codecSrc && !codecDest; + } + } + return ok; +} + /* ** Set the codec of the database file with the given database file name. ** diff --git a/src/sqlite3patched.c b/src/sqlite3patched.c index dd361c1..3acf59b 100644 --- a/src/sqlite3patched.c +++ b/src/sqlite3patched.c @@ -11170,6 +11170,7 @@ SQLITE_PRIVATE void* sqlite3mcPagerCodec(PgHdrMC* pPg); typedef struct Pager PagerMC; SQLITE_PRIVATE int sqlite3mcPagerHasCodec(PagerMC* pPager); SQLITE_PRIVATE void sqlite3mcInitMemoryMethods(); +SQLITE_PRIVATE int sqlite3mcIsBackupSupported(sqlite3*, const char*, sqlite3*, const char*); /******** Begin file sqlite3rtree.h *********/ /* @@ -82186,6 +82187,12 @@ SQLITE_API sqlite3_backup *sqlite3_backup_init( } #endif + /* Check whether databases are compatible with backup */ + if (!sqlite3mcIsBackupSupported(pSrcDb, zSrcDb, pDestDb, zDestDb)){ + sqlite3ErrorWithMsg(pDestDb, SQLITE_ERROR, "backup is not supported with incompatible source and target databases"); + return NULL; + } + /* Lock the source database handle. The destination database ** handle is not locked in this routine, but it is locked in ** sqlite3_backup_step(). The user is required to ensure that no