123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- #ifndef SQLITE_OMIT_DISKIO
- #ifdef SQLITE_HAS_CODEC
- #include "codec.h"
- void sqlite3_activate_see(const char *info)
- {
- }
- /*
- // Free the encryption data structure associated with a pager instance.
- // (called from the modified code in pager.c)
- */
- void sqlite3CodecFree(void *pCodecArg)
- {
- if (pCodecArg)
- {
- CodecTerm(pCodecArg);
- sqlite3_free(pCodecArg);
- }
- }
- void sqlite3CodecSizeChange(void *pArg, int pageSize, int reservedSize)
- {
- }
- /*
- // Encrypt/Decrypt functionality, called by pager.c
- */
- void* sqlite3Codec(void* pCodecArg, void* data, Pgno nPageNum, int nMode)
- {
- Codec* codec = NULL;
- int pageSize;
- if (pCodecArg == NULL)
- {
- return data;
- }
- codec = (Codec*) pCodecArg;
- if (!CodecIsEncrypted(codec))
- {
- return data;
- }
-
- pageSize = sqlite3BtreeGetPageSize(CodecGetBtree(codec));
- switch(nMode)
- {
- case 0: /* Undo a "case 7" journal file encryption */
- case 2: /* Reload a page */
- case 3: /* Load a page */
- if (CodecHasReadKey(codec))
- {
- CodecDecrypt(codec, nPageNum, (unsigned char*) data, pageSize);
- }
- break;
- case 6: /* Encrypt a page for the main database file */
- if (CodecHasWriteKey(codec))
- {
- unsigned char* pageBuffer = CodecGetPageBuffer(codec);
- memcpy(pageBuffer, data, pageSize);
- data = pageBuffer;
- CodecEncrypt(codec, nPageNum, (unsigned char*) data, pageSize, 1);
- }
- break;
- case 7: /* Encrypt a page for the journal file */
- /* Under normal circumstances, the readkey is the same as the writekey. However,
- when the database is being rekeyed, the readkey is not the same as the writekey.
- The rollback journal must be written using the original key for the
- database file because it is, by nature, a rollback journal.
- Therefore, for case 7, when the rollback is being written, always encrypt using
- the database's readkey, which is guaranteed to be the same key that was used to
- read the original data.
- */
- if (CodecHasReadKey(codec))
- {
- unsigned char* pageBuffer = CodecGetPageBuffer(codec);
- memcpy(pageBuffer, data, pageSize);
- data = pageBuffer;
- CodecEncrypt(codec, nPageNum, (unsigned char*) data, pageSize, 0);
- }
- break;
- }
- return data;
- }
- void* mySqlite3PagerGetCodec(
- Pager *pPager
- );
- void mySqlite3PagerSetCodec(
- Pager *pPager,
- void *(*xCodec)(void*,void*,Pgno,int),
- void (*xCodecSizeChng)(void*,int,int),
- void (*xCodecFree)(void*),
- void *pCodec
- );
- int sqlite3CodecAttach(sqlite3* db, int nDb, const void* zKey, int nKey)
- {
- /* Attach a key to a database. */
- Codec* codec = (Codec*) sqlite3_malloc(sizeof(Codec));
- CodecInit(codec);
- sqlite3_mutex_enter(db->mutex);
- /* No key specified, could mean either use the main db's encryption or no encryption */
- if (zKey == NULL || nKey <= 0)
- {
- /* No key specified */
- if (nDb != 0 && nKey > 0)
- {
- Codec* mainCodec = (Codec*) mySqlite3PagerGetCodec(sqlite3BtreePager(db->aDb[0].pBt));
- /* Attached database, therefore use the key of main database, if main database is encrypted */
- if (mainCodec != NULL && CodecIsEncrypted(mainCodec))
- {
- CodecCopy(codec, mainCodec);
- CodecSetBtree(codec, db->aDb[nDb].pBt);
- #if (SQLITE_VERSION_NUMBER >= 3006016)
- mySqlite3PagerSetCodec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, sqlite3CodecSizeChange, sqlite3CodecFree, codec);
- #else
- #if (SQLITE_VERSION_NUMBER >= 3003014)
- sqlite3PagerSetCodec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, codec);
- #else
- sqlite3pager_set_codec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, codec);
- #endif
- db->aDb[nDb].pAux = codec;
- db->aDb[nDb].xFreeAux = sqlite3CodecFree;
- #endif
- }
- else
- {
- CodecSetIsEncrypted(codec, 0);
- sqlite3_free(codec);
- }
- }
- }
- else
- {
- /* Key specified, setup encryption key for database */
- CodecSetIsEncrypted(codec, 1);
- CodecSetHasReadKey(codec, 1);
- CodecSetHasWriteKey(codec, 1);
- CodecGenerateReadKey(codec, (char*) zKey, nKey);
- CodecCopyKey(codec, 1);
- CodecSetBtree(codec, db->aDb[nDb].pBt);
- #if (SQLITE_VERSION_NUMBER >= 3006016)
- mySqlite3PagerSetCodec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, sqlite3CodecSizeChange, sqlite3CodecFree, codec);
- #else
- #if (SQLITE_VERSION_NUMBER >= 3003014)
- sqlite3PagerSetCodec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, codec);
- #else
- sqlite3pager_set_codec(sqlite3BtreePager(db->aDb[nDb].pBt), sqlite3Codec, codec);
- #endif
- db->aDb[nDb].pAux = codec;
- db->aDb[nDb].xFreeAux = sqlite3CodecFree;
- #endif
- }
- sqlite3_mutex_leave(db->mutex);
- return SQLITE_OK;
- }
- void sqlite3CodecGetKey(sqlite3* db, int nDb, void** zKey, int* nKey)
- {
- /*
- // The unencrypted password is not stored for security reasons
- // therefore always return NULL
- // If the main database is encrypted a key length of 1 is returned.
- // In that case an attached database will get the same encryption key
- // as the main database if no key was explicitly given for the attached database.
- */
- Codec* mainCodec = (Codec*) mySqlite3PagerGetCodec(sqlite3BtreePager(db->aDb[0].pBt));
- int keylen = (mainCodec != NULL && CodecIsEncrypted(mainCodec)) ? 1 : 0;
- *zKey = NULL;
- *nKey = keylen;
- }
- static int dbFindIndex(sqlite3* db, const char* zDb)
- {
- int dbIndex = 0;
- if (zDb != NULL)
- {
- int found = 0;
- int index;
- for (index = 0; found == 0 && index < db->nDb; ++index)
- {
- struct Db* pDb = &db->aDb[index];
- if (strcmp(pDb->zName, zDb) == 0)
- {
- found = 1;
- dbIndex = index;
- }
- }
- if (found == 0) dbIndex = 0;
- }
- return dbIndex;
- }
- int sqlite3_key(sqlite3 *db, const void *zKey, int nKey)
- {
- /* The key is only set for the main database, not the temp database */
- return sqlite3_key_v2(db, "main", zKey, nKey);
- }
- int sqlite3_key_v2(sqlite3 *db, const char *zDbName, const void *zKey, int nKey)
- {
- /* The key is only set for the main database, not the temp database */
- int dbIndex = dbFindIndex(db, zDbName);
- return sqlite3CodecAttach(db, dbIndex, zKey, nKey);
- }
- int sqlite3_rekey_v2(sqlite3 *db, const char *zDbName, const void *zKey, int nKey)
- {
- /* Changes the encryption key for an existing database. */
- int dbIndex = dbFindIndex(db, zDbName);
- int rc = SQLITE_ERROR;
- Btree* pbt = db->aDb[dbIndex].pBt;
- Pager* pPager = sqlite3BtreePager(pbt);
- Codec* codec = (Codec*) mySqlite3PagerGetCodec(pPager);
- if ((zKey == NULL || nKey == 0) && (codec == NULL || !CodecIsEncrypted(codec)))
- {
- /*
- // Database not encrypted and key not specified
- // therefore do nothing
- */
- return SQLITE_OK;
- }
- if (codec == NULL || !CodecIsEncrypted(codec))
- {
- /*
- // Database not encrypted, but key specified
- // therefore encrypt database
- */
- if (codec == NULL)
- {
- codec = (Codec*) sqlite3_malloc(sizeof(Codec));
- CodecInit(codec);
- }
- CodecSetIsEncrypted(codec, 1);
- CodecSetHasReadKey(codec, 0); /* Original database is not encrypted */
- CodecSetHasWriteKey(codec, 1);
- CodecGenerateWriteKey(codec, (char*) zKey, nKey);
- CodecSetBtree(codec, pbt);
- #if (SQLITE_VERSION_NUMBER >= 3006016)
- mySqlite3PagerSetCodec(pPager, sqlite3Codec, sqlite3CodecSizeChange, sqlite3CodecFree, codec);
- #else
- #if (SQLITE_VERSION_NUMBER >= 3003014)
- sqlite3PagerSetCodec(pPager, sqlite3Codec, codec);
- #else
- sqlite3pager_set_codec(pPager, sqlite3Codec, codec);
- #endif
- db->aDb[dbIndex].pAux = codec;
- db->aDb[dbIndex].xFreeAux = sqlite3CodecFree;
- #endif
- }
- else if (zKey == NULL || nKey == 0)
- {
- /*
- // Database encrypted, but key not specified
- // therefore decrypt database
- // Keep read key, drop write key
- */
- CodecSetHasWriteKey(codec, 0);
- }
- else
- {
- /*
- // Database encrypted and key specified
- // therefore re-encrypt database with new key
- // Keep read key, change write key to new key
- */
- CodecGenerateWriteKey(codec, (char*) zKey, nKey);
- CodecSetHasWriteKey(codec, 1);
- }
- sqlite3_mutex_enter(db->mutex);
- /* Start transaction */
- rc = sqlite3BtreeBeginTrans(pbt, 1);
- if (!rc)
- {
- int pageSize = sqlite3BtreeGetPageSize(pbt);
- Pgno nSkip = WX_PAGER_MJ_PGNO(pageSize);
- #if (SQLITE_VERSION_NUMBER >= 3003014)
- DbPage *pPage;
- #else
- void *pPage;
- #endif
- Pgno n;
- /* Rewrite all pages using the new encryption key (if specified) */
- #if (SQLITE_VERSION_NUMBER >= 3007001)
- Pgno nPage;
- int nPageCount = -1;
- sqlite3PagerPagecount(pPager, &nPageCount);
- nPage = nPageCount;
- #elif (SQLITE_VERSION_NUMBER >= 3006000)
- int nPageCount = -1;
- int rc = sqlite3PagerPagecount(pPager, &nPageCount);
- Pgno nPage = (Pgno) nPageCount;
- #elif (SQLITE_VERSION_NUMBER >= 3003014)
- Pgno nPage = sqlite3PagerPagecount(pPager);
- #else
- Pgno nPage = sqlite3pager_pagecount(pPager);
- #endif
- for (n = 1; rc == SQLITE_OK && n <= nPage; n++)
- {
- if (n == nSkip) continue;
- #if (SQLITE_VERSION_NUMBER >= 3010000)
- rc = sqlite3PagerGet(pPager, n, &pPage, 0);
- #elif (SQLITE_VERSION_NUMBER >= 3003014)
- rc = sqlite3PagerGet(pPager, n, &pPage);
- #else
- rc = sqlite3pager_get(pPager, n, &pPage);
- #endif
- if (!rc)
- {
- #if (SQLITE_VERSION_NUMBER >= 3003014)
- rc = sqlite3PagerWrite(pPage);
- sqlite3PagerUnref(pPage);
- #else
- rc = sqlite3pager_write(pPage);
- sqlite3pager_unref(pPage);
- #endif
- }
- }
- }
- if (rc == SQLITE_OK)
- {
- /* Commit transaction if all pages could be rewritten */
- rc = sqlite3BtreeCommit(pbt);
- }
- if (rc != SQLITE_OK)
- {
- /* Rollback in case of error */
- #if (SQLITE_VERSION_NUMBER >= 3008007)
- /* Unfortunately this change was introduced in version 3.8.7.2 which cannot be detected using the SQLITE_VERSION_NUMBER */
- /* That is, compilation will fail for version 3.8.7 or 3.8.7.1 ==> Please change manually ... or upgrade to 3.8.7.2 or higher */
- sqlite3BtreeRollback(pbt, SQLITE_OK, 0);
- #elif (SQLITE_VERSION_NUMBER >= 3007011)
- sqlite3BtreeRollback(pbt, SQLITE_OK);
- #else
- sqlite3BtreeRollback(pbt);
- #endif
- }
- sqlite3_mutex_leave(db->mutex);
- if (rc == SQLITE_OK)
- {
- /* Set read key equal to write key if necessary */
- if (CodecHasWriteKey(codec))
- {
- CodecCopyKey(codec, 0);
- CodecSetHasReadKey(codec, 1);
- }
- else
- {
- CodecSetIsEncrypted(codec, 0);
- }
- }
- else
- {
- /* Restore write key if necessary */
- if (CodecHasReadKey(codec))
- {
- CodecCopyKey(codec, 1);
- }
- else
- {
- CodecSetIsEncrypted(codec, 0);
- }
- }
- if (!CodecIsEncrypted(codec))
- {
- /* Remove codec for unencrypted database */
- #if (SQLITE_VERSION_NUMBER >= 3006016)
- mySqlite3PagerSetCodec(pPager, NULL, NULL, NULL, NULL);
- #else
- #if (SQLITE_VERSION_NUMBER >= 3003014)
- sqlite3PagerSetCodec(pPager, NULL, NULL);
- #else
- sqlite3pager_set_codec(pPager, NULL, NULL);
- #endif
- db->aDb[dbIndex].pAux = NULL;
- db->aDb[dbIndex].xFreeAux = NULL;
- sqlite3CodecFree(codec);
- #endif
- }
- return rc;
- }
- int sqlite3_rekey(sqlite3 *db, const void *zKey, int nKey)
- {
- return sqlite3_rekey_v2(db, "main", zKey, nKey);
- }
- #endif /* SQLITE_HAS_CODEC */
- #endif /* SQLITE_OMIT_DISKIO */
|