Exemplo n.º 1
0
int sqlite3CodecAttach(sqlite3 *db, int nDb, const void *zKey, int nKey)
{
    BOTANSQLITE_TRACE("sqlite3CodecAttach");
    void *pCodec = NULL;

    if (!zKey || nKey <= 0)
    {
        Pager *pager = sqlite3BtreePager(db->aDb[nDb].pBt);

        // No key specified, could mean either use the main db's encryption or no encryption
        if (nDb != 0 && nKey < 0)
        {
            // Is an attached database, therefore use the key of main database, if main database is encrypted
            void *pMainCodec = sqlite3PagerGetCodec(sqlite3BtreePager(db->aDb[0].pBt));
            if (pMainCodec)
            {
                pCodec = InitializeFromOtherCodec(pMainCodec, db);
                sqlite3PagerSetCodec(
                            pager,
                            Codec,
                            CodecSizeChange,
                            PagerFreeCodec,
                            pCodec);
            }
        }
        else
        {
            // No encryption requested
            sqlite3PagerSetCodec(pager, NULL, NULL, NULL, NULL);
        }
    }
    else
    {
        // Key specified, setup encryption key for database
        pCodec = InitializeNewCodec(db);
        assert(nKey >= 0);
        SetWriteKey(pCodec, (const char*) zKey, (size_t) nKey);

        if (HandleError(pCodec))
        {
            DeleteCodec(pCodec);
            return SQLITE_ERROR;
        }

        SetReadIsWrite(pCodec);
        sqlite3PagerSetCodec(
                    sqlite3BtreePager(db->aDb[nDb].pBt),
                    Codec,
                    CodecSizeChange,
                    PagerFreeCodec,
                    pCodec);
    }

    if (HandleError(pCodec)) return SQLITE_ERROR;

    return SQLITE_OK;
}
Exemplo n.º 2
0
int sqlite3CodecAttach(sqlite3 *db, int nDb, const void *zKey, int nKey)
{
    void *pCodec;

    if (zKey == NULL || nKey <= 0)
    {
        // No key specified, could mean either use the main db's encryption or no encryption
        if (nDb != 0 && nKey < 0)
        {
            //Is an attached database, therefore use the key of main database, if main database is encrypted
            void *pMainCodec = sqlite3PagerGetCodec(sqlite3BtreePager(db->aDb[0].pBt));
            if (pMainCodec != NULL)
            {
                pCodec = InitializeFromOtherCodec(pMainCodec, db);
                sqlite3PagerSetCodec(sqlite3BtreePager(db->aDb[nDb].pBt),
                                    sqlite3Codec,
                                    sqlite3CodecSizeChange,
                                    sqlite3PagerFreeCodec, pCodec);
            }
        }
    }
    else
    {
        // Key specified, setup encryption key for database
        pCodec = InitializeNewCodec(db);
        GenerateWriteKey(pCodec, (const char*) zKey, nKey);
        SetReadIsWrite(pCodec);
        sqlite3PagerSetCodec(sqlite3BtreePager(db->aDb[nDb].pBt),
                            sqlite3Codec,
                            sqlite3CodecSizeChange,
                            sqlite3PagerFreeCodec, pCodec);
    }

    if (HandleError(pCodec))
        return SQLITE_ERROR;

    return SQLITE_OK;
}
Exemplo n.º 3
0
int sqlite3_rekey(sqlite3 *db, const void *zKey, int nKey)
{
    BOTANSQLITE_TRACE("sqlite3_rekey");
    // Changes the encryption key for an existing database.
    int rc = SQLITE_ERROR;
    Btree *pbt = db->aDb[0].pBt;
    Pager *pPager = sqlite3BtreePager(pbt);
    void *pCodec = sqlite3PagerGetCodec(pPager);

    if ((!zKey || nKey <= 0) && !pCodec)
    {
        // Database not encrypted and key not specified. Do nothing
        return SQLITE_OK;
    }

    if (!pCodec)
    {
        // Database not encrypted, but key specified. Encrypt database
        pCodec = InitializeNewCodec(db);
        assert(nKey >= 0);
        SetWriteKey(pCodec, (const char*) zKey, (size_t) nKey);
        
        if (HandleError(pCodec))
        {
            DeleteCodec(pCodec);
            return SQLITE_ERROR;
        }

        sqlite3PagerSetCodec(pPager, Codec, CodecSizeChange, PagerFreeCodec, pCodec);
    }
    else if (!zKey || nKey <= 0)
    {
        // Database encrypted, but key not specified. Decrypt database
        // Keep read key, drop write key
        DropWriteKey(pCodec);
    }
    else
    {
        // Database encrypted and key specified. Re-encrypt database with new key
        // Keep read key, change write key to new key
        assert(nKey >= 0);
        SetWriteKey(pCodec, (const char*) zKey, (size_t) nKey);
        if (HandleError(pCodec)) return SQLITE_ERROR;
    }

    // Start transaction
    rc = sqlite3BtreeBeginTrans(pbt, 1);
    if (rc == SQLITE_OK)
    {
        // Rewrite all pages using the new encryption key (if specified)
        int nPageCount = -1;
        sqlite3PagerPagecount(pPager, &nPageCount);
        Pgno nPage = (Pgno) nPageCount;

        Pgno nSkip = PAGER_MJ_PGNO(pPager);
        DbPage *pPage;

        Pgno n;
        for (n = 1; rc == SQLITE_OK && n <= nPage; n++)
        {
            if (n == nSkip) continue;

            rc = sqlite3PagerGet(pPager, n, &pPage, 0);

            if (rc == SQLITE_OK)
            {
                rc = sqlite3PagerWrite(pPage);
                sqlite3PagerUnref(pPage);
            }
            else
            {
                sqlite3ErrorWithMsg(db, SQLITE_ERROR, "%s", "Error while rekeying database page. Transaction Canceled.");
            }
        }
    }
    else
    {
        sqlite3ErrorWithMsg(db, SQLITE_ERROR, "%s", "Error beginning rekey transaction. Make sure that the current encryption key is correct.");
    }

    if (rc == SQLITE_OK)
    {
        // All good, commit
        rc = sqlite3BtreeCommit(pbt);

        if (rc == SQLITE_OK)
        {
            //Database rekeyed and committed successfully, update read key
            if (HasWriteKey(pCodec))
            {
                SetReadIsWrite(pCodec);
            }
            else //No write key == no longer encrypted
            {
                sqlite3PagerSetCodec(pPager, NULL, NULL, NULL, NULL); 
            }
        }
        else
        {
            //FIXME: can't trigger this, not sure if rollback is needed, reference implementation didn't rollback
            sqlite3ErrorWithMsg(db, SQLITE_ERROR, "%s", "Could not commit rekey transaction.");
        }
    }
    else
    {
        // Rollback, rekey failed
        sqlite3BtreeRollback(pbt, SQLITE_ERROR, 0);

        // go back to read key
        if (HasReadKey(pCodec))
        {
            SetWriteIsRead(pCodec);
        }
        else //Database wasn't encrypted to start with
        {
            sqlite3PagerSetCodec(pPager, NULL, NULL, NULL, NULL); 
        }
    }

    return rc;
}