refactor sqlcipher tests into separate files
This commit is contained in:
parent
f615ede679
commit
3bd6262b59
2985
test/crypto.test
2985
test/crypto.test
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,714 @@
|
|||
# SQLCipher
|
||||
# codec.test developed by Stephen Lombardo (Zetetic LLC)
|
||||
# sjlombardo at zetetic dot net
|
||||
# http://zetetic.net
|
||||
#
|
||||
# Copyright (c) 2018, ZETETIC LLC
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the ZETETIC LLC nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing code cipher features.
|
||||
#
|
||||
# NOTE: tester.tcl has overridden the definition of sqlite3 to
|
||||
# automatically pass in a key value. Thus tests in this file
|
||||
# should explicitly close and open db with sqlite_orig in order
|
||||
# to bypass default key assignment.
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/sqlcipher.tcl
|
||||
|
||||
# The database is initially empty.
|
||||
# set an hex key create some basic data
|
||||
# create table and insert operations should work
|
||||
# close database, open it again with the same
|
||||
# hex key. verify that the table is readable
|
||||
# and the data just inserted is visible
|
||||
setup test.db "\"x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836481'\""
|
||||
do_test will-open-with-correct-raw-key {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = "x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836481'";
|
||||
SELECT name FROM sqlite_master WHERE type='table';
|
||||
SELECT * from t1;
|
||||
}
|
||||
} {t1 test1 test2}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# set an encryption key (non-hex) and create some basic data
|
||||
# create table and insert operations should work
|
||||
# close database, open it again with the same
|
||||
# key. verify that the table is readable
|
||||
# and the data just inserted is visible
|
||||
setup test.db "'testkey'"
|
||||
do_test will-open-with-correct-derived-key {
|
||||
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
SELECT name FROM sqlite_master WHERE type='table';
|
||||
SELECT * from t1;
|
||||
}
|
||||
} {t1 test1 test2}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify that a when a standard database is encrypted the first
|
||||
# 16 bytes are not "SQLite format 3\0"
|
||||
do_test test-sqlcipher-header-overwrite {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
CREATE TABLE t1(a,b);
|
||||
}
|
||||
db close
|
||||
set header [hexio_read test.db 0 16]
|
||||
string equal $header "53514C69746520666F726D6174203300"
|
||||
} {0}
|
||||
file delete -force test.db
|
||||
|
||||
# open the database and try to read from it without
|
||||
# providing a passphrase. verify that the
|
||||
# an error is returned from the library
|
||||
setup test.db "'testkey'"
|
||||
do_test wont-open-without-key {
|
||||
sqlite_orig db test.db
|
||||
catchsql {
|
||||
SELECT name FROM sqlite_master WHERE type='table';
|
||||
}
|
||||
} {1 {file is not a database}}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# open the database and try to set an invalid
|
||||
# passphrase. verify that an error is returned
|
||||
# and that data couldn't be read
|
||||
setup test.db "'testkey'"
|
||||
do_test wont-open-with-invalid-derived-key {
|
||||
sqlite_orig db test.db
|
||||
catchsql {
|
||||
PRAGMA key = 'testkey2';
|
||||
SELECT name FROM sqlite_master WHERE type='table';
|
||||
}
|
||||
} {1 {file is not a database}}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# open the database and try to set an invalid
|
||||
# hex key. verify that an error is returned
|
||||
# and that data couldn't be read
|
||||
setup test.db "'testkey'"
|
||||
do_test wont-open-with-invalid-raw-key {
|
||||
sqlite_orig db test.db
|
||||
catchsql {
|
||||
PRAGMA key = "x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836480'";
|
||||
SELECT name FROM sqlite_master WHERE type='table';
|
||||
}
|
||||
} {1 {file is not a database}}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# test a large number of inserts in a transaction to a memory database
|
||||
do_test memory-database {
|
||||
sqlite_orig db :memory:
|
||||
execsql {
|
||||
PRAGMA key = 'testkey3';
|
||||
BEGIN;
|
||||
CREATE TABLE t2(a,b);
|
||||
}
|
||||
for {set i 1} {$i<=25000} {incr i} {
|
||||
set r [expr {int(rand()*500000)}]
|
||||
execsql "INSERT INTO t2 VALUES($i,$r);"
|
||||
}
|
||||
execsql {
|
||||
COMMIT;
|
||||
SELECT count(*) FROM t2;
|
||||
DELETE FROM t2;
|
||||
SELECT count(*) FROM t2;
|
||||
}
|
||||
} {25000 0}
|
||||
db close
|
||||
|
||||
# test a large number of inserts in a transaction for multiple pages
|
||||
do_test multi-page-database {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
CREATE TABLE t2(a,b);
|
||||
BEGIN;
|
||||
}
|
||||
for {set i 1} {$i<=25000} {incr i} {
|
||||
set r [expr {int(rand()*500000)}]
|
||||
execsql "INSERT INTO t2 VALUES($i,$r);"
|
||||
}
|
||||
execsql {
|
||||
COMMIT;
|
||||
SELECT count(*) FROM t2;
|
||||
}
|
||||
} {25000}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# attach an encrypted database
|
||||
# without specifying key, verify it fails
|
||||
# even if the source passwords are the same
|
||||
# because the kdf salts are different
|
||||
setup test.db "'testkey'"
|
||||
do_test attach-database-with-default-key {
|
||||
sqlite_orig db2 test2.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
PRAGMA cipher_add_random = "x'deadbaad'";
|
||||
CREATE TABLE t2(a,b);
|
||||
INSERT INTO t2 VALUES ('test1', 'test2');
|
||||
} db2
|
||||
|
||||
catchsql {
|
||||
ATTACH 'test.db' AS db;
|
||||
} db2
|
||||
|
||||
} {1 {file is not a database}}
|
||||
db2 close
|
||||
file delete -force test.db
|
||||
file delete -force test2.db
|
||||
|
||||
# attach an encrypted database
|
||||
# without specifying key, verify it attaches
|
||||
# correctly when PRAGMA cipher_store_pass = 1
|
||||
# is set.
|
||||
do_test attach-database-with-default-key-using-cipher-store-pass {
|
||||
|
||||
sqlite_orig db1 test.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1(a,b) VALUES('foo', 'bar');
|
||||
} db1
|
||||
db1 close
|
||||
|
||||
sqlite_orig db2 test2.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
CREATE TABLE t2(a,b);
|
||||
INSERT INTO t2 VALUES ('test1', 'test2');
|
||||
} db2
|
||||
db2 close
|
||||
|
||||
sqlite_orig db1 test.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
PRAGMA cipher_store_pass = 1;
|
||||
ATTACH DATABASE 'test2.db' as db2;
|
||||
SELECT sqlcipher_export('db2');
|
||||
DETACH DATABASE db2;
|
||||
} db1
|
||||
db1 close
|
||||
|
||||
sqlite_orig db2 test2.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
SELECT * FROM t1;
|
||||
} db2
|
||||
|
||||
} {foo bar}
|
||||
db2 close
|
||||
file delete -force test.db
|
||||
file delete -force test2.db
|
||||
|
||||
# attach an encrypted database
|
||||
# where both database have the same
|
||||
# key explicitly
|
||||
setup test.db "'testkey'"
|
||||
do_test attach-database-with-same-key {
|
||||
sqlite_orig db2 test2.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
CREATE TABLE t2(a,b);
|
||||
INSERT INTO t2 VALUES ('test1', 'test2');
|
||||
} db2
|
||||
|
||||
execsql {
|
||||
SELECT count(*) FROM t2;
|
||||
ATTACH 'test.db' AS db KEY 'testkey';
|
||||
SELECT count(*) FROM db.t1;
|
||||
} db2
|
||||
|
||||
} {1 1}
|
||||
db2 close
|
||||
file delete -force test.db
|
||||
file delete -force test2.db
|
||||
|
||||
# attach an encrypted database
|
||||
# where databases have different keys
|
||||
setup test.db "'testkey'"
|
||||
do_test attach-database-with-different-keys {
|
||||
sqlite_orig db2 test2.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'testkey2';
|
||||
CREATE TABLE t2(a,b);
|
||||
INSERT INTO t2 VALUES ('test1', 'test2');
|
||||
} db2
|
||||
|
||||
execsql {
|
||||
ATTACH 'test.db' AS db KEY 'testkey';
|
||||
SELECT count(*) FROM db.t1;
|
||||
SELECT count(*) FROM t2;
|
||||
} db2
|
||||
|
||||
} {1 1}
|
||||
db2 close
|
||||
file delete -force test.db
|
||||
file delete -force test2.db
|
||||
|
||||
# test locking across multiple handles
|
||||
setup test.db "'testkey'"
|
||||
do_test locking-across-multiple-handles-start {
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
BEGIN EXCLUSIVE;
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
}
|
||||
|
||||
sqlite_orig dba test.db
|
||||
catchsql {
|
||||
PRAGMA key = 'testkey';
|
||||
SELECT count(*) FROM t1;
|
||||
} dba
|
||||
|
||||
} {1 {database is locked}}
|
||||
|
||||
do_test locking-accross-multiple-handles-finish {
|
||||
execsql {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
execsql {
|
||||
SELECT count(*) FROM t1;
|
||||
} dba
|
||||
} {2}
|
||||
db close
|
||||
dba close
|
||||
file delete -force test.db
|
||||
|
||||
# alter schema
|
||||
setup test.db "'testkey'"
|
||||
do_test alter-schema {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
ALTER TABLE t1 ADD COLUMN c;
|
||||
INSERT INTO t1 VALUES (1,2,3);
|
||||
INSERT INTO t1 VALUES (1,2,4);
|
||||
CREATE TABLE t1a (a);
|
||||
INSERT INTO t1a VALUES ('teststring');
|
||||
}
|
||||
db close
|
||||
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
SELECT count(*) FROM t1 WHERE a IS NOT NULL;
|
||||
SELECT count(*) FROM t1 WHERE c IS NOT NULL;
|
||||
SELECT * FROM t1a;
|
||||
}
|
||||
|
||||
} {3 2 teststring}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# test alterations of KDF iterations and ciphers
|
||||
# rekey then add
|
||||
setup test.db "'testkey'"
|
||||
do_test verify-errors-for-rekey-kdf-and-cipher-changes {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
PRAGMA rekey_kdf_iter = 1000;
|
||||
PRAGMA rekey_cipher = 'aes-256-ecb';
|
||||
}
|
||||
} {{PRAGMA rekey_kdf_iter is no longer supported.} {PRAGMA rekey_cipher is no longer supported.}}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
|
||||
setup test.db "'testkey'"
|
||||
do_test verify-errors-for-cipher-change {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
PRAGMA cipher = 'aes-256-ecb';
|
||||
}
|
||||
} {{PRAGMA cipher is no longer supported.}}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
|
||||
# 1. create a database with a custom page size,
|
||||
# 2. create table and insert operations should work
|
||||
# 3. close database, open it again with the same
|
||||
# key and page size
|
||||
# 4. verify that the table is readable
|
||||
# and the data just inserted is visible
|
||||
do_test custom-pagesize {
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
PRAGMA cipher_page_size = 8192;
|
||||
CREATE table t1(a,b);
|
||||
BEGIN;
|
||||
}
|
||||
|
||||
for {set i 1} {$i<=1000} {incr i} {
|
||||
set r [expr {int(rand()*500000)}]
|
||||
execsql "INSERT INTO t1 VALUES($i,'value $r');"
|
||||
}
|
||||
|
||||
execsql {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
PRAGMA cipher_page_size = 8192;
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
|
||||
} {1000}
|
||||
db close
|
||||
|
||||
# open the database with the default page size
|
||||
## and verfiy that it is not readable
|
||||
do_test custom-pagesize-must-match {
|
||||
sqlite_orig db test.db
|
||||
catchsql {
|
||||
PRAGMA key = 'testkey';
|
||||
SELECT name FROM sqlite_master WHERE type='table';
|
||||
}
|
||||
} {1 {file is not a database}}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# 1. create a database and insert a bunch of data, close the database
|
||||
# 2. seek to the middle of a database page and write some junk
|
||||
# 3. Open the database and verify that the database is no longer readable
|
||||
do_test hmac-tamper-resistence {
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
CREATE table t1(a,b);
|
||||
BEGIN;
|
||||
}
|
||||
|
||||
for {set i 1} {$i<=1000} {incr i} {
|
||||
set r [expr {int(rand()*500000)}]
|
||||
execsql "INSERT INTO t1 VALUES($i,'value $r');"
|
||||
}
|
||||
|
||||
execsql {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
db close
|
||||
|
||||
# write some junk into the hmac segment, leaving
|
||||
# the page data valid but with an invalid signature
|
||||
hexio_write test.db 1000 0000
|
||||
|
||||
sqlite_orig db test.db
|
||||
|
||||
catchsql {
|
||||
PRAGMA key = 'testkey';
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
|
||||
} {1 {file is not a database}}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# 1. create a database and insert a bunch of data, close the database
|
||||
# 2. seek to the middle of a database page and write some junk
|
||||
# 3. Open the database and verify that the database is still readable
|
||||
do_test nohmac-not-tamper-resistent {
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
PRAGMA cipher_use_hmac = OFF;
|
||||
PRAGMA cipher_page_size = 1024;
|
||||
CREATE table t1(a,b);
|
||||
BEGIN;
|
||||
}
|
||||
|
||||
for {set i 1} {$i<=1000} {incr i} {
|
||||
set r [expr {int(rand()*500000)}]
|
||||
execsql "INSERT INTO t1 VALUES($i,'value $r');"
|
||||
}
|
||||
|
||||
execsql {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
db close
|
||||
|
||||
# write some junk into the middle of the page
|
||||
hexio_write test.db 2560 00
|
||||
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
PRAGMA cipher_use_hmac = OFF;
|
||||
PRAGMA cipher_page_size = 1024;
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
|
||||
} {1000}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# 1. create a database with WAL journal mode
|
||||
# 2. create table and insert operations should work
|
||||
# 3. close database, open it again
|
||||
# 4. verify that the table is present, readable, and that
|
||||
# the journal mode is WAL
|
||||
do_test journal-mode-wal {
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
PRAGMA journal_mode = WAL;
|
||||
CREATE table t1(a,b);
|
||||
BEGIN;
|
||||
}
|
||||
|
||||
for {set i 1} {$i<=1000} {incr i} {
|
||||
set r [expr {int(rand()*500000)}]
|
||||
execsql "INSERT INTO t1 VALUES($i,'value $r');"
|
||||
}
|
||||
|
||||
execsql {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA journal_mode;
|
||||
}
|
||||
|
||||
} {1000 wal}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
setup test.db "'testkey'"
|
||||
do_test multiple-key-calls-safe-1 {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
PRAGMA cache_size = 0;
|
||||
SELECT name FROM sqlite_master WHERE type='table';
|
||||
}
|
||||
} {t1}
|
||||
|
||||
do_test multiple-key-calls-safe-2 {
|
||||
catchsql {
|
||||
PRAGMA key = 'wrong key';
|
||||
SELECT name FROM sqlite_master WHERE type='table';
|
||||
}
|
||||
} {1 {file is not a database}}
|
||||
|
||||
do_test multiple-key-calls-safe-3 {
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
SELECT name FROM sqlite_master WHERE type='table';
|
||||
}
|
||||
} {t1}
|
||||
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# 1. create a database with a custom hmac kdf iteration count,
|
||||
# 2. create table and insert operations should work
|
||||
# 3. close database, open it again with the same
|
||||
# key and hmac kdf iteration count
|
||||
# 4. verify that the table is readable
|
||||
# and the data just inserted is visible
|
||||
do_test custom-hmac-kdf-iter {
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
PRAGMA fast_kdf_iter = 10;
|
||||
CREATE table t1(a,b);
|
||||
BEGIN;
|
||||
}
|
||||
|
||||
for {set i 1} {$i<=1000} {incr i} {
|
||||
set r [expr {int(rand()*500000)}]
|
||||
execsql "INSERT INTO t1 VALUES($i,'value $r');"
|
||||
}
|
||||
|
||||
execsql {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
PRAGMA fast_kdf_iter = 10;
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
|
||||
} {1000}
|
||||
db close
|
||||
|
||||
# open the database with the default hmac
|
||||
# kdf iteration count
|
||||
# to verify that it is not readable
|
||||
do_test custom-hmac-kdf-iter-must-match {
|
||||
sqlite_orig db test.db
|
||||
catchsql {
|
||||
PRAGMA key = 'testkey';
|
||||
SELECT name FROM sqlite_master WHERE type='table';
|
||||
}
|
||||
} {1 {file is not a database}}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# open the database and turn on auto_vacuum
|
||||
# then insert a bunch of data, delete it
|
||||
# and verify that the file has become smaller
|
||||
# but can still be opened with the proper
|
||||
# key
|
||||
do_test auto-vacuum {
|
||||
sqlite_orig db test.db
|
||||
set rc {}
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
PRAGMA auto_vacuum=FULL;
|
||||
CREATE table t1(a,b);
|
||||
BEGIN;
|
||||
}
|
||||
|
||||
for {set i 1} {$i<=10000} {incr i} {
|
||||
set r [expr {int(rand()*500000)}]
|
||||
execsql "INSERT INTO t1 VALUES($i,'value $r');"
|
||||
}
|
||||
|
||||
lappend rc [execsql {
|
||||
COMMIT;
|
||||
SELECT count(*) FROM t1;
|
||||
}]
|
||||
|
||||
# grab current size of file
|
||||
set sz [file size test.db]
|
||||
|
||||
# delete some records, and verify
|
||||
# autovacuum removes them
|
||||
execsql {
|
||||
DELETE FROM t1 WHERE rowid > 5000;
|
||||
}
|
||||
|
||||
db close
|
||||
|
||||
# grab new file size, post
|
||||
# autovacuum
|
||||
set sz2 [file size test.db]
|
||||
|
||||
# verify that the new size is
|
||||
# smaller than the old size
|
||||
if {$sz > $sz2} { lappend rc true }
|
||||
|
||||
sqlite_orig db test.db
|
||||
|
||||
lappend rc [execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
SELECT count(*) FROM t1;
|
||||
}]
|
||||
|
||||
} {10000 true 5000}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# test kdf_iter and other pragmas
|
||||
# before a key is set. Verify that they
|
||||
# are no-ops
|
||||
do_test cipher-options-before-keys {
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA kdf_iter = 1000;
|
||||
PRAGMA cipher_page_size = 8192;
|
||||
PRAGMA cipher_use_hmac = OFF;
|
||||
PRAGMA key = 'testkey';
|
||||
CREATE table t1(a,b);
|
||||
INSERT INTO t1 VALUES(1,2);
|
||||
}
|
||||
db close
|
||||
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
|
||||
} {1}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify memory security behavior
|
||||
# initially should report ON
|
||||
# then disable, check that it is off
|
||||
# turn it back on, then check.
|
||||
do_test verify-memory-security {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA cipher_memory_security;
|
||||
PRAGMA cipher_memory_security = OFF;
|
||||
PRAGMA cipher_memory_security;
|
||||
PRAGMA cipher_memory_security = ON;
|
||||
PRAGMA cipher_memory_security;
|
||||
|
||||
}
|
||||
} {1 0 1}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
finish_test
|
|
@ -0,0 +1,434 @@
|
|||
# SQLCipher
|
||||
# codec.test developed by Stephen Lombardo (Zetetic LLC)
|
||||
# sjlombardo at zetetic dot net
|
||||
# http://zetetic.net
|
||||
#
|
||||
# Copyright (c) 2018, ZETETIC LLC
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the ZETETIC LLC nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing code cipher features.
|
||||
#
|
||||
# NOTE: tester.tcl has overridden the definition of sqlite3 to
|
||||
# automatically pass in a key value. Thus tests in this file
|
||||
# should explicitly close and open db with sqlite_orig in order
|
||||
# to bypass default key assignment.
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/sqlcipher.tcl
|
||||
|
||||
set hexkeyspec "\"x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C483648101010101010101010101010101010101'\""
|
||||
|
||||
# verify pragma cipher_salt returns the first 16 bytes
|
||||
# of an existing database
|
||||
do_test test-pragma-salt-get {
|
||||
sqlite_orig db test.db
|
||||
set salt [execsql {
|
||||
PRAGMA key = 'test';
|
||||
CREATE TABLE t1(a,b);
|
||||
PRAGMA cipher_salt;
|
||||
}]
|
||||
set header [string tolower [hexio_read test.db 0 16]]
|
||||
string equal $header $salt
|
||||
} {1}
|
||||
file delete -force test.db
|
||||
|
||||
# explicitly set the salt of a new database
|
||||
do_test test-pragma-salt-set {
|
||||
set rc {}
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_salt = "x'01010101010101010101010101010101'";
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1(a,b) VALUES (1,2);
|
||||
}
|
||||
db close
|
||||
|
||||
lappend rc [hexio_read test.db 0 16]
|
||||
|
||||
sqlite_orig db test.db
|
||||
lappend rc [execsql "
|
||||
PRAGMA key = 'test';
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA cipher_salt;
|
||||
"]
|
||||
|
||||
} {01010101010101010101010101010101 {1 01010101010101010101010101010101}}
|
||||
file delete -force test.db
|
||||
|
||||
|
||||
# verify that a raw key with a fixed salt will work
|
||||
# the first 16 bytes of database should be equal to the specified salt
|
||||
# which is the last 32 characters of the hex key spec.
|
||||
# also verify return value of cipher_salt
|
||||
do_test test-raw-key-with-salt-spec {
|
||||
set rc {}
|
||||
sqlite_orig db test.db
|
||||
execsql "
|
||||
PRAGMA key = $hexkeyspec;
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1(a,b) VALUES (1,2);
|
||||
"
|
||||
db close
|
||||
|
||||
lappend rc [hexio_read test.db 0 16]
|
||||
|
||||
sqlite_orig db test.db
|
||||
lappend rc [execsql "
|
||||
PRAGMA key = $hexkeyspec;
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA cipher_salt;
|
||||
"]
|
||||
} {01010101010101010101010101010101 {1 01010101010101010101010101010101}}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify that a raw key with an invalid salt will not work to
|
||||
# open an existing database.
|
||||
# should cause hmac failure due to invalid generated HMAC key
|
||||
do_test test-raw-key-with-invalid-salt-spec {
|
||||
sqlite_orig db test.db
|
||||
execsql "
|
||||
PRAGMA key = $hexkeyspec;
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1(a,b) VALUES (1,2);
|
||||
"
|
||||
db close
|
||||
|
||||
sqlite_orig db test.db
|
||||
catchsql {
|
||||
PRAGMA key="x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C483648100000000000000000000000000000001'";
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
} {1 {file is not a database}}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify that a raw key with a bad salt *will* work if page HMAC is disabled
|
||||
# in this case the salt will not actually be used for anything
|
||||
# because the encryption key is provided explicitly
|
||||
do_test test-raw-key-with-invalid-salt-spec-no-hmac {
|
||||
sqlite_orig db test.db
|
||||
execsql "
|
||||
PRAGMA key = $hexkeyspec;
|
||||
PRAGMA cipher_use_hmac = OFF;
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1(a,b) VALUES (1,2);
|
||||
"
|
||||
db close
|
||||
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key="x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C483648100000000000000000000000000000001'";
|
||||
PRAGMA cipher_use_hmac = OFF;
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
} {1}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify that invalid cipher_plaintext_header_sizes don't work
|
||||
# 1. less than zero
|
||||
# 2. Larger than available page size
|
||||
# 2. Not a multiple of block size
|
||||
do_test test-invalid-plaintext-header-sizes {
|
||||
set rc {}
|
||||
sqlite_orig db test.db
|
||||
lappend rc [catchsql "
|
||||
PRAGMA key = $hexkeyspec;
|
||||
PRAGMA cipher_plaintext_header_size = -1;
|
||||
CREATE TABLE t1(a,b);
|
||||
"]
|
||||
db close
|
||||
sqlite_orig db test.db
|
||||
lappend rc [catchsql "
|
||||
PRAGMA key = $hexkeyspec;
|
||||
PRAGMA cipher_plaintext_header_size = 4096;
|
||||
CREATE TABLE t1(a,b);
|
||||
"]
|
||||
db close
|
||||
sqlite_orig db test.db
|
||||
lappend rc [catchsql "
|
||||
PRAGMA key = $hexkeyspec;
|
||||
PRAGMA cipher_plaintext_header_size = 24;
|
||||
CREATE TABLE t1(a,b);
|
||||
"]
|
||||
} {{1 {SQL logic error}} {1 {SQL logic error}} {1 {SQL logic error}}}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify that a valid cipher_plaintext_header_size leaves the
|
||||
# start of the database unencrypted, i.e. "SQLite format 3\0"
|
||||
do_test test-valid-plaintext-header-size {
|
||||
set rc {}
|
||||
sqlite_orig db test.db
|
||||
execsql "
|
||||
PRAGMA key = $hexkeyspec;
|
||||
PRAGMA cipher_plaintext_header_size = 16;
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1(a,b) VALUES (1,2);
|
||||
"
|
||||
db close
|
||||
|
||||
lappend rc [hexio_read test.db 0 16]
|
||||
|
||||
sqlite_orig db test.db
|
||||
lappend rc [execsql "
|
||||
PRAGMA key = $hexkeyspec;
|
||||
PRAGMA cipher_plaintext_header_size = 16;
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA cipher_plaintext_header_size;
|
||||
"]
|
||||
} {53514C69746520666F726D6174203300 {1 16}}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# when using a standard mode database and 32 byte
|
||||
# plaintext header, ensure that bytes 16 - 19
|
||||
# corresponding to the page size and file versions, and reserve size
|
||||
# are readable and equal to 1024, 1, 1, and 80 respectively
|
||||
do_test test-plaintext-header-journal-delete-mode-readable {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_plaintext_header_size = 32;
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1(a,b) VALUES (1,2);
|
||||
}
|
||||
db close
|
||||
string equal [hexio_read test.db 16 5] "1000010150"
|
||||
} {1}
|
||||
file delete -force test.db
|
||||
|
||||
|
||||
# when using a WAL mode database and 32 byte
|
||||
# plaintext header, ensure that bytes 16 - 19
|
||||
# corresponding to the page size and file versions, and reserve size
|
||||
# are readable and equal to 1024, 2, 2 and 80 respectively
|
||||
do_test test-plaintext-header-journal-wal-mode-readable {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_plaintext_header_size = 32;
|
||||
PRAGMA journal_mode = WAL;
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1(a,b) VALUES (1,2);
|
||||
}
|
||||
db close
|
||||
string equal [hexio_read test.db 16 5] "1000020250"
|
||||
} {1}
|
||||
file delete -force test.db
|
||||
|
||||
# verify that a valid default_cipher_plaintext_header_size leaves the
|
||||
# start of the database unencrypted right from the start
|
||||
# , i.e. "SQLite format 3\0"
|
||||
do_test test-valid-default-plaintext-header-size {
|
||||
set rc {}
|
||||
sqlite_orig db test.db
|
||||
set salt [execsql {
|
||||
PRAGMA cipher_default_plaintext_header_size = 16;
|
||||
PRAGMA key = 'test';
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1(a,b) VALUES (1,2);
|
||||
PRAGMA cipher_salt;
|
||||
}]
|
||||
db close
|
||||
|
||||
lappend rc [hexio_read test.db 0 16]
|
||||
|
||||
sqlite_orig db test.db
|
||||
lappend rc [execsql "
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_salt = \"x'$salt'\";
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA cipher_plaintext_header_size;
|
||||
"]
|
||||
|
||||
# reset the default back to 0 or subsequent tests will fail
|
||||
execsql "PRAGMA cipher_default_plaintext_header_size = 0;"
|
||||
|
||||
lappend rc [string equal $salt "53514c69746520666f726d6174203300"]
|
||||
} {53514C69746520666F726D6174203300 {1 16} 0}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify that a valid default_cipher_plaintext_header_size
|
||||
# operates properly on an attached database, and that the
|
||||
# salt pragma operates on the attached database as well
|
||||
do_test test-valid-default-plaintext-header-size-attach {
|
||||
set rc {}
|
||||
sqlite_orig db test.db
|
||||
set salt [execsql {
|
||||
PRAGMA cipher_default_plaintext_header_size = 16;
|
||||
PRAGMA key = 'test';
|
||||
CREATE TABLE temp(a);
|
||||
ATTACH DATABASE 'test2.db' as db2;
|
||||
CREATE TABLE db2.t2(a,b);
|
||||
INSERT INTO db2.t2(a,b) VALUES (1,2);
|
||||
PRAGMA db2.cipher_salt;
|
||||
DETACH DATABASE db2;
|
||||
}]
|
||||
db close
|
||||
lappend rc [hexio_read test2.db 0 16]
|
||||
|
||||
sqlite_orig db test2.db
|
||||
lappend rc [execsql "
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_salt = \"x'$salt'\";
|
||||
SELECT count(*) FROM t2;
|
||||
PRAGMA cipher_plaintext_header_size;
|
||||
"]
|
||||
|
||||
# reset the default back to 0 or subsequent tests will fail
|
||||
execsql "PRAGMA cipher_default_plaintext_header_size = 0;"
|
||||
|
||||
lappend rc [string equal $salt "53514c69746520666f726d6174203300"]
|
||||
} {53514C69746520666F726D6174203300 {1 16} 0}
|
||||
db close
|
||||
file delete -force test.db
|
||||
file delete -force test2.db
|
||||
|
||||
|
||||
# migrate a standard database in place to use a
|
||||
# plaintext header offset by opening it, adjusting
|
||||
# the pragma, and rewriting the first page
|
||||
do_test test-plaintext-header-migrate-journal-delete {
|
||||
set rc {}
|
||||
sqlite_orig db test.db
|
||||
execsql "
|
||||
PRAGMA key = $hexkeyspec;
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1(a,b) VALUES (1,2);
|
||||
"
|
||||
db close
|
||||
|
||||
lappend rc [hexio_read test.db 0 16]
|
||||
|
||||
sqlite_orig db test.db
|
||||
execsql "
|
||||
PRAGMA key = $hexkeyspec;
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA cipher_plaintext_header_size = 32;
|
||||
PRAGMA user_version = 1;
|
||||
"
|
||||
db close
|
||||
lappend rc [hexio_read test.db 0 21]
|
||||
|
||||
sqlite_orig db test.db
|
||||
lappend rc [execsql "
|
||||
PRAGMA key = $hexkeyspec;
|
||||
PRAGMA cipher_plaintext_header_size = 32;
|
||||
SELECT count(*) FROM t1;
|
||||
"]
|
||||
|
||||
} {01010101010101010101010101010101 53514C69746520666F726D61742033001000010150 1}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# migrate a wal mode database in place to use a
|
||||
# plaintext header offset by opening it, adjusting
|
||||
# the pragma, and rewriting the first page
|
||||
do_test test-plaintext-header-migrate-journal-wal {
|
||||
set rc {}
|
||||
sqlite_orig db test.db
|
||||
execsql "
|
||||
PRAGMA key = $hexkeyspec;
|
||||
PRAGMA journal_mode = WAL;
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1(a,b) VALUES (1,2);
|
||||
"
|
||||
db close
|
||||
|
||||
lappend rc [hexio_read test.db 0 16]
|
||||
|
||||
sqlite_orig db test.db
|
||||
lappend rc [execsql "
|
||||
PRAGMA key = $hexkeyspec;
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA journal_mode;
|
||||
PRAGMA cipher_plaintext_header_size = 32;
|
||||
PRAGMA user_version = 1;
|
||||
PRAGMA wal_checkpoint(FULL);
|
||||
"]
|
||||
db close
|
||||
lappend rc [hexio_read test.db 0 21]
|
||||
|
||||
sqlite_orig db test.db
|
||||
lappend rc [execsql "
|
||||
PRAGMA key = $hexkeyspec;
|
||||
PRAGMA cipher_plaintext_header_size = 32;
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA journal_mode;
|
||||
"]
|
||||
|
||||
} {01010101010101010101010101010101 {1 wal 0 1 1} 53514C69746520666F726D61742033001000020250 {1 wal}}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# migrate a wal mode database in place to use a plaintext header
|
||||
# but instead of using a raw key syntax, use a derived key
|
||||
# but explicitly set the salt using cipher_salt
|
||||
do_test test-plaintext-header-migrate-journal-wal-string-key-random-salt {
|
||||
set rc {}
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA journal_mode = WAL;
|
||||
CREATE TABLE t1(a,b);
|
||||
INSERT INTO t1(a,b) VALUES (1,2);
|
||||
}
|
||||
db close
|
||||
|
||||
set salt [hexio_read test.db 0 16]
|
||||
|
||||
sqlite_orig db test.db
|
||||
lappend rc [execsql "
|
||||
PRAGMA key = 'test';
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA journal_mode;
|
||||
PRAGMA cipher_plaintext_header_size = 32;
|
||||
PRAGMA user_version = 1;
|
||||
PRAGMA wal_checkpoint(FULL);
|
||||
"]
|
||||
db close
|
||||
|
||||
lappend rc [hexio_read test.db 0 21]
|
||||
|
||||
sqlite_orig db test.db
|
||||
lappend rc [execsql "
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_salt = \"x'$salt'\";
|
||||
PRAGMA cipher_plaintext_header_size = 32;
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA journal_mode;
|
||||
"]
|
||||
|
||||
|
||||
} {{1 wal 0 1 1} 53514C69746520666F726D61742033001000020250 {1 wal}}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
|
||||
finish_test
|
|
@ -0,0 +1,379 @@
|
|||
# SQLCipher
|
||||
# codec.test developed by Stephen Lombardo (Zetetic LLC)
|
||||
# sjlombardo at zetetic dot net
|
||||
# http://zetetic.net
|
||||
#
|
||||
# Copyright (c) 2018, ZETETIC LLC
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the ZETETIC LLC nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing code cipher features.
|
||||
#
|
||||
# NOTE: tester.tcl has overridden the definition of sqlite3 to
|
||||
# automatically pass in a key value. Thus tests in this file
|
||||
# should explicitly close and open db with sqlite_orig in order
|
||||
# to bypass default key assignment.
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/sqlcipher.tcl
|
||||
|
||||
# verify the pragma cipher_version
|
||||
# returns the currently configured
|
||||
# sqlcipher version
|
||||
do_test verify-pragma-cipher-version {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA cipher_version;
|
||||
}
|
||||
} {3.4.2}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma cipher_use_hmac
|
||||
# is set to true be default
|
||||
do_test verify-pragma-cipher-use-hmac-default {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_use_hmac;
|
||||
}
|
||||
} {1}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma cipher_use_hmac
|
||||
# reports the flag turned off
|
||||
do_test verify-pragma-cipher-use-hmac-off {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_use_hmac = off;
|
||||
PRAGMA cipher_use_hmac;
|
||||
}
|
||||
} {0}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma default_cipher_use_hmac
|
||||
# is set to true by default
|
||||
do_test verify-pragma-cipher-default-use-hmac-default {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA cipher_default_use_hmac;
|
||||
}
|
||||
} {1}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma default_cipher_use_hmac
|
||||
# reports the flag turned off
|
||||
do_test verify-pragma-cipher-default-use-hmac-off {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA cipher_default_use_hmac = off;
|
||||
PRAGMA cipher_default_use_hmac;
|
||||
-- Be sure to turn cipher_default_use_hmac
|
||||
-- back on or it will break later tests
|
||||
-- (it's a global flag)
|
||||
PRAGMA cipher_default_use_hmac = ON;
|
||||
}
|
||||
} {0}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma default_cipher_kdf_iter
|
||||
# is set to 256000 by default
|
||||
do_test verify-pragma-cipher-default-kdf-iter-default {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA cipher_default_kdf_iter;
|
||||
}
|
||||
} {256000}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
|
||||
# verify the pragma default_cipher_kdf_ter
|
||||
# reports changes
|
||||
do_test verify-pragma-cipher-default-use-hmac-off {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA cipher_default_kdf_iter = 1000;
|
||||
PRAGMA cipher_default_kdf_iter;
|
||||
PRAGMA cipher_default_kdf_iter = 256000;
|
||||
}
|
||||
} {1000}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma kdf_iter
|
||||
# reports the default value
|
||||
do_test verify-pragma-kdf-iter-reports-default {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA kdf_iter;
|
||||
}
|
||||
} {256000}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma kdf_iter
|
||||
# reports value changed
|
||||
do_test verify-pragma-kdf-iter-reports-value-changed {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA kdf_iter = 8000;
|
||||
PRAGMA kdf_iter;
|
||||
}
|
||||
} {8000}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma fast_kdf_iter
|
||||
# reports the default value
|
||||
do_test verify-pragma-fast-kdf-iter-reports-default {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA fast_kdf_iter;
|
||||
}
|
||||
} {2}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma fast_kdf_iter
|
||||
# reports value changed
|
||||
do_test verify-pragma-kdf-iter-reports-value-changed {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA fast_kdf_iter = 4000;
|
||||
PRAGMA fast_kdf_iter;
|
||||
}
|
||||
} {4000}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma cipher_page_size
|
||||
# reports default value
|
||||
do_test verify-pragma-cipher-page-size-default {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_page_size;
|
||||
}
|
||||
} {4096}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma cipher_page_size
|
||||
# reports change in value
|
||||
do_test verify-pragma-cipher-page-size-changed {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_page_size = 8192;
|
||||
PRAGMA cipher_page_size;
|
||||
}
|
||||
} {8192}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify setting cipher_store_pass before key
|
||||
# does not cause segfault
|
||||
do_test verify-cipher-store-pass-before-key-does-not-segfault {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA cipher_store_pass = 1;
|
||||
PRAGMA key = 'test';
|
||||
}
|
||||
} {}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma cipher
|
||||
# reports the default value
|
||||
if_built_with_openssl verify-pragma-cipher-default {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher;
|
||||
}
|
||||
} {AES-256-CBC}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma cipher_hmac_salt_mask reports default
|
||||
do_test verify-pragma-hmac-salt-mask-reports-default {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_hmac_salt_mask;
|
||||
}
|
||||
} {3a}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma cipher_hmac_salt_mask reports
|
||||
# reports value changed
|
||||
do_test verify-pragma-hmac-salt-mask-reports-value-changed {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_hmac_salt_mask = "x'11'";
|
||||
PRAGMA cipher_hmac_salt_mask;
|
||||
}
|
||||
} {11}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma cipher_hmac_pgno reports default
|
||||
do_test verify-pragma-hmac-pgno-reports-default {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_hmac_pgno;
|
||||
}
|
||||
} {le}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma cipher_hmac_pgno
|
||||
# reports value changed
|
||||
do_test verify-pragma-hmac-pgno-reports-value-changed {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_hmac_pgno = be;
|
||||
PRAGMA cipher_hmac_pgno;
|
||||
PRAGMA cipher_hmac_pgno = native;
|
||||
PRAGMA cipher_hmac_pgno;
|
||||
PRAGMA cipher_hmac_pgno = le;
|
||||
PRAGMA cipher_hmac_pgno;
|
||||
}
|
||||
} {be native le}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma cipher_hmac_algorithm works properly
|
||||
do_test verify-pragma-cipher-hmac-algorithm-reports-default {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_hmac_algorithm;
|
||||
}
|
||||
} {HMAC_SHA512}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
do_test verify-pragma-cipher-hmac-algorithm-reports-value-changed {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_hmac_algorithm = HMAC_SHA1;
|
||||
PRAGMA cipher_hmac_algorithm;
|
||||
}
|
||||
} {HMAC_SHA1}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
do_test verify-pragma-cipher-default-hmac-algorithm {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA cipher_default_hmac_algorithm;
|
||||
PRAGMA cipher_default_hmac_algorithm = HMAC_SHA1;
|
||||
PRAGMA cipher_default_hmac_algorithm;
|
||||
PRAGMA cipher_default_hmac_algorithm = HMAC_SHA512;
|
||||
}
|
||||
} {HMAC_SHA512 HMAC_SHA1}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# verify the pragma cipher_kdf_algorithm works properly
|
||||
do_test verify-pragma-cipher-kdf-algorithm-reports-default {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_kdf_algorithm;
|
||||
}
|
||||
} {PBKDF2_HMAC_SHA512}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
do_test verify-pragma-cipher-kdf-algorithm-reports-value-changed {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;
|
||||
PRAGMA cipher_kdf_algorithm;
|
||||
}
|
||||
} {PBKDF2_HMAC_SHA1}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
do_test verify-pragma-cipher-default-kdf-algorithm {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA cipher_default_kdf_algorithm;
|
||||
PRAGMA cipher_default_kdf_algorithm = PBKDF2_HMAC_SHA1;
|
||||
PRAGMA cipher_default_kdf_algorithm;
|
||||
PRAGMA cipher_default_kdf_algorithm = PBKDF2_HMAC_SHA512;
|
||||
}
|
||||
} {PBKDF2_HMAC_SHA512 PBKDF2_HMAC_SHA1}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
if_built_with_openssl verify-default-cipher {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key='test';
|
||||
PRAGMA cipher;
|
||||
}
|
||||
} {AES-256-CBC}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
if_built_with_libtomcrypt verify-default-cipher {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key='test';
|
||||
PRAGMA cipher;
|
||||
}
|
||||
} {aes-256-cbc}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
if_built_with_commoncrypto verify-default-cipher {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key='test';
|
||||
PRAGMA cipher;
|
||||
}
|
||||
} {aes-256-cbc}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
finish_test
|
|
@ -0,0 +1,329 @@
|
|||
# SQLCipher
|
||||
# codec.test developed by Stephen Lombardo (Zetetic LLC)
|
||||
# sjlombardo at zetetic dot net
|
||||
# http://zetetic.net
|
||||
#
|
||||
# Copyright (c) 2018, ZETETIC LLC
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the ZETETIC LLC nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing code cipher features.
|
||||
#
|
||||
# NOTE: tester.tcl has overridden the definition of sqlite3 to
|
||||
# automatically pass in a key value. Thus tests in this file
|
||||
# should explicitly close and open db with sqlite_orig in order
|
||||
# to bypass default key assignment.
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/sqlcipher.tcl
|
||||
|
||||
# Test rekey as first operation on an empty database. should be a no-op
|
||||
do_test rekey-as-first-op {
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA rekey = 'testkey';
|
||||
CREATE table t1(a,b);
|
||||
BEGIN;
|
||||
}
|
||||
|
||||
for {set i 1} {$i<=100} {incr i} {
|
||||
set r [expr {int(rand()*500000)}]
|
||||
execsql "INSERT INTO t1 VALUES($i,'value $r');"
|
||||
}
|
||||
|
||||
execsql {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA rekey = 'testkey';
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
|
||||
} {100}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# Test rekey as first operation follwed by key
|
||||
do_test rekey-then-key-as-first-ops {
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA rekey = '1234';
|
||||
PRAGMA key = 'testkey';
|
||||
CREATE table t1(a,b);
|
||||
BEGIN;
|
||||
}
|
||||
|
||||
for {set i 1} {$i<=100} {incr i} {
|
||||
set r [expr {int(rand()*500000)}]
|
||||
execsql "INSERT INTO t1 VALUES($i,'value $r');"
|
||||
}
|
||||
|
||||
execsql {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
db close
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA rekey = '4321';
|
||||
PRAGMA key = 'testkey';
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
|
||||
} {100}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
|
||||
# test a rekey operation as the first op on a database
|
||||
# then test that now the new key opens the database
|
||||
# now close database re-open with new key
|
||||
setup test.db "'testkey'"
|
||||
do_test rekey-as-first-operation {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
PRAGMA rekey = 'testkeynew';
|
||||
}
|
||||
db close
|
||||
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkeynew';
|
||||
SELECT name FROM sqlite_master WHERE type='table';
|
||||
}
|
||||
} {t1}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# create a new database, insert some data
|
||||
# then rekey it with the same password
|
||||
do_test rekey-same-passkey {
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'test123';
|
||||
CREATE TABLE t1(a,b);
|
||||
BEGIN;
|
||||
}
|
||||
|
||||
for {set i 1} {$i<=1000} {incr i} {
|
||||
set r [expr {int(rand()*500000)}]
|
||||
execsql "INSERT INTO t1 VALUES($i,'value $r');"
|
||||
}
|
||||
|
||||
execsql {
|
||||
COMMIT;
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA rekey = 'test123';
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
} {1000 1000}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# create a new database, insert some data
|
||||
# then rekey it. Make sure it is immediately
|
||||
# readable. Then close it and make sure it can be
|
||||
# read back
|
||||
do_test rekey-and-query-1 {
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'test123';
|
||||
CREATE TABLE t1(a,b);
|
||||
BEGIN;
|
||||
}
|
||||
|
||||
for {set i 1} {$i<=1000} {incr i} {
|
||||
set r [expr {int(rand()*500000)}]
|
||||
execsql "INSERT INTO t1 VALUES($i,'value $r');"
|
||||
}
|
||||
|
||||
execsql {
|
||||
COMMIT;
|
||||
SELECT count(*) FROM t1;
|
||||
PRAGMA rekey = 'test321';
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
} {1000 1000}
|
||||
|
||||
db close
|
||||
|
||||
do_test rekey-and-query-2 {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test321';
|
||||
SELECT count(*) FROM t1;
|
||||
}
|
||||
} {1000}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# create a new database, insert some data
|
||||
# delete about 50% of the data
|
||||
# write some new data
|
||||
# delete another 50%
|
||||
# then rekey it. Make sure it is immediately
|
||||
# readable. Then close it and make sure it can be
|
||||
# read back. This test will ensure that Secure Delete
|
||||
# is enabled and all pages are being written and are not
|
||||
# being optimized out by sqlite3PagerDontWrite
|
||||
do_test rekey-delete-and-query-1 {
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'test123';
|
||||
CREATE TABLE t1(a,b);
|
||||
CREATE INDEX ta_a ON t1(a);
|
||||
BEGIN;
|
||||
}
|
||||
|
||||
for {set i 1} {$i<1000} {incr i} {
|
||||
set r [expr {int(rand()*32767)}]
|
||||
set r1 [expr {int(rand()*32767)}]
|
||||
execsql "INSERT INTO t1 VALUES($r,$r1);"
|
||||
}
|
||||
set r [expr {int(rand()*32767)}]
|
||||
set r1 [expr {int(rand()*32767)}]
|
||||
execsql "UPDATE t1 SET b = $r WHERE a < $r1;"
|
||||
|
||||
set r [expr {int(rand()*32767)}]
|
||||
|
||||
execsql "DELETE FROM t1 WHERE a < $r;"
|
||||
|
||||
execsql {
|
||||
COMMIT;
|
||||
SELECT (count(*) > 0) FROM t1;
|
||||
}
|
||||
} {1}
|
||||
db close
|
||||
|
||||
do_test rekey-delete-and-query-2 {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test123';
|
||||
PRAGMA rekey = 'test321';
|
||||
SELECT count(*) > 1 FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
}
|
||||
} {1 ok}
|
||||
db close
|
||||
|
||||
do_test rekey-delete-and-query-3 {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test321';
|
||||
SELECT count(*) > 1 FROM t1;
|
||||
}
|
||||
} {1}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
|
||||
# same as previous test, but use WAL
|
||||
do_test rekey-delete-and-query-wal-1 {
|
||||
sqlite_orig db test.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'test123';
|
||||
PRAGMA journal_mode = WAL;
|
||||
CREATE TABLE t1(a,b);
|
||||
CREATE INDEX ta_a ON t1(a);
|
||||
BEGIN;
|
||||
}
|
||||
|
||||
for {set i 1} {$i<1000} {incr i} {
|
||||
set r [expr {int(rand()*32767)}]
|
||||
set r1 [expr {int(rand()*32767)}]
|
||||
execsql "INSERT INTO t1 VALUES($r,$r1);"
|
||||
}
|
||||
set r [expr {int(rand()*32767)}]
|
||||
set r1 [expr {int(rand()*32767)}]
|
||||
execsql "UPDATE t1 SET b = $r WHERE a < $r1;"
|
||||
|
||||
set r [expr {int(rand()*32767)}]
|
||||
|
||||
execsql "DELETE FROM t1 WHERE a < $r;"
|
||||
|
||||
execsql {
|
||||
COMMIT;
|
||||
SELECT (count(*) > 0) FROM t1;
|
||||
}
|
||||
} {1}
|
||||
db close
|
||||
|
||||
do_test rekey-delete-and-query-wal-2 {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test123';
|
||||
PRAGMA journal_mode = WAL;
|
||||
PRAGMA rekey = 'test321';
|
||||
SELECT count(*) > 1 FROM t1;
|
||||
PRAGMA integrity_check;
|
||||
}
|
||||
} {wal 1 ok}
|
||||
db close
|
||||
|
||||
do_test rekey-delete-and-query-wal-3 {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'test321';
|
||||
PRAGMA journal_mode = WAL;
|
||||
SELECT count(*) > 1 FROM t1;
|
||||
}
|
||||
} {wal 1}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
do_test rekey-database-by-name {
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
attach database 'new.db' as new;
|
||||
pragma new.key = 'foo';
|
||||
create table new.t1(a,b);
|
||||
insert into new.t1(a,b) values('foo', 'bar');
|
||||
pragma new.rekey = 'bar';
|
||||
detach database new;
|
||||
}
|
||||
db close
|
||||
|
||||
sqlite_orig db new.db
|
||||
execsql {
|
||||
pragma key = 'bar';
|
||||
select * from t1;
|
||||
}
|
||||
} {foo bar}
|
||||
db close
|
||||
file delete -force test.db
|
||||
file delete -force new.db
|
||||
|
||||
finish_test
|
|
@ -0,0 +1,41 @@
|
|||
# SQLCipher
|
||||
# codec.test developed by Stephen Lombardo (Zetetic LLC)
|
||||
# sjlombardo at zetetic dot net
|
||||
# http://zetetic.net
|
||||
#
|
||||
# Copyright (c) 2018, ZETETIC LLC
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the ZETETIC LLC nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing code cipher features.
|
||||
#
|
||||
# NOTE: tester.tcl has overridden the definition of sqlite3 to
|
||||
# automatically pass in a key value. Thus tests in this file
|
||||
# should explicitly close and open db with sqlite_orig in order
|
||||
# to bypass default key assignment.
|
||||
|
||||
#set testdir [file dirname $argv0]
|
||||
#source $testdir/tester.tcl
|
||||
#source $testdir/sqlcipher.tcl
|
||||
|
||||
#finish_test
|
|
@ -0,0 +1,107 @@
|
|||
# codec.test developed by Stephen Lombardo (Zetetic LLC)
|
||||
# sjlombardo at zetetic dot net
|
||||
# http://zetetic.net
|
||||
#
|
||||
# Copyright (c) 2018, ZETETIC LLC
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the ZETETIC LLC nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing code cipher features.
|
||||
#
|
||||
# NOTE: tester.tcl has overridden the definition of sqlite3 to
|
||||
# automatically pass in a key value. Thus tests in this file
|
||||
# should explicitly close and open db with sqlite_orig in order
|
||||
# to bypass default key assignment.
|
||||
|
||||
|
||||
file delete -force test.db
|
||||
file delete -force test2.db
|
||||
file delete -force test3.db
|
||||
file delete -force test4.db
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
set sampleDir [file normalize [file dirname [file dirname $argv0]]]
|
||||
|
||||
# If the library is not compiled with has_codec support then
|
||||
# skip all tests in this file.
|
||||
if {![sqlite_orig -has-codec]} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
proc setup {file key} {
|
||||
sqlite_orig db $file
|
||||
execsql "PRAGMA key=$key;"
|
||||
execsql {
|
||||
CREATE table t1(a,b);
|
||||
INSERT INTO t1 VALUES ('test1', 'test2');
|
||||
} db
|
||||
db close
|
||||
}
|
||||
|
||||
proc get_cipher_provider {} {
|
||||
sqlite_orig db test.db
|
||||
return [execsql {
|
||||
PRAGMA key = 'test';
|
||||
PRAGMA cipher_provider;
|
||||
}];
|
||||
}
|
||||
|
||||
proc if_built_with_openssl {name cmd expected} {
|
||||
if {[get_cipher_provider] == "openssl"} {
|
||||
do_test $name $cmd $expected
|
||||
}
|
||||
}
|
||||
|
||||
proc if_built_with_libtomcrypt {name cmd expected} {
|
||||
if {[get_cipher_provider] == "libtomcrypt"} {
|
||||
do_test $name $cmd $expected
|
||||
}
|
||||
}
|
||||
|
||||
proc if_built_with_commoncrypto {name cmd expected} {
|
||||
if {[get_cipher_provider] == "commoncrypto"} {
|
||||
do_test $name $cmd $expected
|
||||
}
|
||||
}
|
||||
|
||||
proc cmpFilesChunked {file1 file2 {chunksize 16384}} {
|
||||
set f1 [open $file1]; fconfigure $f1 -translation binary
|
||||
set f2 [open $file2]; fconfigure $f2 -translation binary
|
||||
while {1} {
|
||||
set d1 [read $f1 $chunksize]
|
||||
set d2 [read $f2 $chunksize]
|
||||
set diff [string compare $d1 $d2]
|
||||
if {$diff != 0 || [eof $f1] || [eof $f2]} {
|
||||
close $f1; close $f2
|
||||
return $diff
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
proc trace_proc sql {
|
||||
global TRACE_OUT
|
||||
lappend TRACE_OUT [string trim $sql]
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
# codec.test developed by Stephen Lombardo (Zetetic LLC)
|
||||
# sjlombardo at zetetic dot net
|
||||
# http://zetetic.net
|
||||
#
|
||||
# Copyright (c) 2018, ZETETIC LLC
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the ZETETIC LLC nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is testing code cipher features.
|
||||
#
|
||||
# NOTE: tester.tcl has overridden the definition of sqlite3 to
|
||||
# automatically pass in a key value. Thus tests in this file
|
||||
# should explicitly close and open db with sqlite_orig in order
|
||||
# to bypass default key assignment.
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/sqlcipher.tcl
|
||||
|
||||
if {[file exist "$testdir/sqlcipher-license.test"]} {
|
||||
slave_test_file $testdir/sqlcipher-license.test
|
||||
}
|
||||
|
||||
slave_test_file $testdir/sqlcipher-core.test
|
||||
slave_test_file $testdir/sqlcipher-compatibility.test
|
||||
slave_test_file $testdir/sqlcipher-rekey.test
|
||||
slave_test_file $testdir/sqlcipher-plaintext-header.test
|
||||
slave_test_file $testdir/sqlcipher-rekey.test
|
||||
slave_test_file $testdir/sqlcipher-pragmas.test
|
||||
|
||||
finish_test
|
Loading…
Reference in New Issue