Skip to content

Commit

Permalink
Improve VFS error reporting, fix issue #167
Browse files Browse the repository at this point in the history
If decrypting a page failed due to a wrong passphrase, the error was detected at VFS level, but not communicated properly to higher level SQLite functions. In debug mode that could lead to raising an assertion, although the error was detected and handled by SQLite later on.
  • Loading branch information
utelle committed Jun 9, 2024
1 parent d55dcd0 commit 4856e93
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 7 deletions.
27 changes: 23 additions & 4 deletions src/cipher_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ sqlite3mcCodecInit(Codec* codec)
memset(codec->m_page, 0, sizeof(codec->m_page));
codec->m_pageSize = 0;
codec->m_reserved = 0;
codec->m_lastError = SQLITE_OK;
codec->m_hasKeySalt = 0;
memset(codec->m_keySalt, 0, sizeof(codec->m_keySalt));
}
Expand Down Expand Up @@ -428,25 +429,40 @@ sqlite3mcGetPageSizeWriteCipher(Codec* codec)
SQLITE_PRIVATE int
sqlite3mcGetReservedReadCipher(Codec* codec)
{
int reserved = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? globalCodecDescriptorTable[codec->m_readCipherType-1].m_getReserved(codec->m_readCipher) : 0;
int reserved = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? globalCodecDescriptorTable[codec->m_readCipherType-1].m_getReserved(codec->m_readCipher) : -1;
return reserved;
}

SQLITE_PRIVATE int
sqlite3mcGetReservedWriteCipher(Codec* codec)
{
int reserved = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? globalCodecDescriptorTable[codec->m_writeCipherType-1].m_getReserved(codec->m_writeCipher) : 0;
int reserved = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? globalCodecDescriptorTable[codec->m_writeCipherType-1].m_getReserved(codec->m_writeCipher) : -1;
return reserved;
}

SQLITE_PRIVATE int
sqlite3mcReservedEqual(Codec* codec)
{
int readReserved = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? globalCodecDescriptorTable[codec->m_readCipherType-1].m_getReserved(codec->m_readCipher) : 0;
int writeReserved = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? globalCodecDescriptorTable[codec->m_writeCipherType-1].m_getReserved(codec->m_writeCipher) : 0;
int readReserved = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? globalCodecDescriptorTable[codec->m_readCipherType-1].m_getReserved(codec->m_readCipher) : -1;
int writeReserved = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? globalCodecDescriptorTable[codec->m_writeCipherType-1].m_getReserved(codec->m_writeCipher) : -1;
return (readReserved == writeReserved);
}

SQLITE_PRIVATE void
sqlite3mcSetCodecLastError(Codec* codec, int error)
{
if (codec)
{
codec->m_lastError = error;
}
}

SQLITE_PRIVATE int
sqlite3mcGetCodecLastError(Codec* codec)
{
return codec ? codec->m_lastError : SQLITE_OK;
}

SQLITE_PRIVATE unsigned char*
sqlite3mcGetSaltWriteCipher(Codec* codec)
{
Expand Down Expand Up @@ -500,6 +516,9 @@ sqlite3mcCodecCopy(Codec* codec, Codec* other)
codec->m_bt = other->m_bt;
#endif
codec->m_btShared = other->m_btShared;

codec->m_lastError = SQLITE_OK;

return rc;
}

Expand Down
4 changes: 4 additions & 0 deletions src/cipher_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ typedef struct _Codec
unsigned char m_page[SQLITE_MAX_PAGE_SIZE + 24];
int m_pageSize;
int m_reserved;
int m_lastError;
int m_hasKeySalt;
unsigned char m_keySalt[KEYSALT_LENGTH];
} Codec;
Expand Down Expand Up @@ -158,6 +159,9 @@ SQLITE_PRIVATE int sqlite3mcGetReservedWriteCipher(Codec* codec);

SQLITE_PRIVATE int sqlite3mcReservedEqual(Codec* codec);

SQLITE_PRIVATE void sqlite3mcSetCodecLastError(Codec* codec, int error);
SQLITE_PRIVATE int sqlite3mcGetCodecLastError(Codec* codec);

SQLITE_PRIVATE unsigned char* sqlite3mcGetSaltWriteCipher(Codec* codec);

SQLITE_PRIVATE int sqlite3mcCodecCopy(Codec* codec, Codec* other);
Expand Down
16 changes: 13 additions & 3 deletions src/codecext.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,15 @@ mcReportCodecError(BtShared* pBt, int error)
{
pBt->pPager->eState = PAGER_ERROR;
}
setGetterMethod(pBt->pPager);
if (error == SQLITE_OK)
{
/* Clear cache to force reread of database after a new passphrase has been set */
sqlite3PagerClearCache(pBt->pPager);
/* unlock required?
pager_unlock(pBt->pPager);
*/
}
setGetterMethod(pBt->pPager);
}

/*
Expand All @@ -113,6 +116,7 @@ sqlite3mcCodec(void* pCodecArg, void* data, Pgno nPageNum, int nMode)
codec = (Codec*) pCodecArg;
if (!sqlite3mcIsEncrypted(codec))
{
sqlite3mcSetCodecLastError(codec, rc);
return data;
}

Expand All @@ -126,7 +130,11 @@ sqlite3mcCodec(void* pCodecArg, void* data, Pgno nPageNum, int nMode)
if (sqlite3mcHasReadCipher(codec))
{
rc = sqlite3mcDecrypt(codec, nPageNum, (unsigned char*) data, pageSize);
if (rc != SQLITE_OK) mcReportCodecError(sqlite3mcGetBtShared(codec), rc);
if (rc != SQLITE_OK)
{
mcReportCodecError(sqlite3mcGetBtShared(codec), rc);
memset(data, 0, pageSize);
}
}
break;

Expand Down Expand Up @@ -160,6 +168,7 @@ sqlite3mcCodec(void* pCodecArg, void* data, Pgno nPageNum, int nMode)
}
break;
}
sqlite3mcSetCodecLastError(codec, rc);
return data;
}

Expand All @@ -184,11 +193,12 @@ mcAdjustBtree(Btree* pBt, int nPageSize, int nReserved, int isLegacy)
/* Adjust the page size and the reserved area */
if (pager->pageSize != pagesize || pager->nReserve != nReserved)
{
int reserved = (nReserved >= 0) ? nReserved : 0;
if (isLegacy != 0)
{
pBt->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED;
}
rc = sqlite3BtreeSetPageSize(pBt, pagesize, nReserved, 0);
rc = sqlite3BtreeSetPageSize(pBt, pagesize, reserved, 0);
}
return rc;
}
Expand Down
6 changes: 6 additions & 0 deletions src/sqlite3mc_vfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,7 @@ static int mcReadMainDb(sqlite3_file* pFile, void* buffer, int count, sqlite3_in
*/
pageNo = prevOffset / pageSize + 1;
bufferDecrypted = sqlite3mcCodec(mcFile->codec, pageBuffer, pageNo, 3);
rc = sqlite3mcGetCodecLastError(mcFile->codec);

/*
** Return the requested content
Expand Down Expand Up @@ -684,6 +685,7 @@ static int mcReadMainDb(sqlite3_file* pFile, void* buffer, int count, sqlite3_in
for (iPage = 0; iPage < nPages; ++iPage)
{
void* bufferDecrypted = sqlite3mcCodec(mcFile->codec, data, pageNo, 3);
rc = sqlite3mcGetCodecLastError(mcFile->codec);
data += pageSize;
offset += pageSize;
++pageNo;
Expand Down Expand Up @@ -712,6 +714,7 @@ static int mcReadMainJournal(sqlite3_file* pFile, const void* buffer, int count,
** Decrypt the page buffer, but only if the page number is valid
*/
void* bufferDecrypted = sqlite3mcCodec(codec, (char*) buffer, mcFile->pageNo, 3);
rc = sqlite3mcGetCodecLastError(codec);
mcFile->pageNo = 0;
}
else if (count == 4)
Expand Down Expand Up @@ -745,6 +748,7 @@ static int mcReadSubJournal(sqlite3_file* pFile, const void* buffer, int count,
** Decrypt the page buffer, but only if the page number is valid
*/
void* bufferDecrypted = sqlite3mcCodec(codec, (char*) buffer, mcFile->pageNo, 3);
rc = sqlite3mcGetCodecLastError(codec);
}
else if (count == 4)
{
Expand Down Expand Up @@ -793,6 +797,7 @@ static int mcReadWal(sqlite3_file* pFile, const void* buffer, int count, sqlite3
if (pageNo != 0)
{
void* bufferDecrypted = sqlite3mcCodec(codec, (char*)buffer, pageNo, 3);
rc = sqlite3mcGetCodecLastError(codec);
}
}
else if (codec->m_walLegacy != 0 && count == pageSize + walFrameHeaderSize)
Expand All @@ -805,6 +810,7 @@ static int mcReadWal(sqlite3_file* pFile, const void* buffer, int count, sqlite3
if (pageNo != 0)
{
void* bufferDecrypted = sqlite3mcCodec(codec, (char*)buffer+walFrameHeaderSize, pageNo, 3);
rc = sqlite3mcGetCodecLastError(codec);
}
}
}
Expand Down

0 comments on commit 4856e93

Please sign in to comment.