2 # codec.test developed by Stephen Lombardo (Zetetic LLC)
3 # sjlombardo at zetetic dot net
6 # Copyright (c) 2009, ZETETIC LLC
9 # Redistribution and use in source and binary forms, with or without
10 # modification, are permitted provided that the following conditions are met:
11 # * Redistributions of source code must retain the above copyright
12 # notice, this list of conditions and the following disclaimer.
13 # * Redistributions in binary form must reproduce the above copyright
14 # notice, this list of conditions and the following disclaimer in the
15 # documentation and/or other materials provided with the distribution.
16 # * Neither the name of the ZETETIC LLC nor the
17 # names of its contributors may be used to endorse or promote products
18 # derived from this software without specific prior written permission.
20 # THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
21 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 # DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
24 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 # This file implements regression tests for SQLite library. The
32 # focus of this script is testing code cipher features.
34 # NOTE: tester.tcl has overridden the definition of sqlite3 to
35 # automatically pass in a key value. Thus tests in this file
36 # should explicitly close and open db with sqlite_orig in order
37 # to bypass default key assignment.
40 file delete -force test.db
41 file delete -force test2.db
42 file delete -force test3.db
43 file delete -force test4.db
45 set testdir [file dirname $argv0]
46 source $testdir/tester.tcl
48 # If the library is not compiled with has_codec support then
49 # skip all tests in this file.
50 if {![sqlite_orig -has-codec]} {
55 proc setup {file key} {
57 execsql "PRAGMA key=$key;"
60 INSERT INTO t1 VALUES ('test1', 'test2');
65 # The database is initially empty.
66 # set an hex key create some basic data
67 # create table and insert operations should work
68 # close database, open it again with the same
69 # hex key. verify that the table is readable
70 # and the data just inserted is visible
71 setup test.db "\"x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836481'\""
73 sqlite_orig db test.db
75 PRAGMA key = "x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836481'";
76 SELECT name FROM sqlite_master WHERE type='table';
81 file delete -force test.db
83 # set an encryption key (non-hex) and create some basic data
84 # create table and insert operations should work
85 # close database, open it again with the same
86 # key. verify that the table is readable
87 # and the data just inserted is visible
88 setup test.db "'testkey'"
91 sqlite_orig db test.db
93 PRAGMA key = 'testkey';
94 SELECT name FROM sqlite_master WHERE type='table';
99 file delete -force test.db
101 # open the database and try to read from it without
102 # providing a passphrase. verify that the
103 # an error is returned from the library
104 setup test.db "'testkey'"
106 sqlite_orig db test.db
108 SELECT name FROM sqlite_master WHERE type='table';
110 } {1 {file is encrypted or is not a database}}
112 file delete -force test.db
114 # open the database and try to set an invalid
115 # passphrase. verify that an error is returned
116 # and that data couldn't be read
117 setup test.db "'testkey'"
118 do_test codec-1.3.1 {
119 sqlite_orig db test.db
121 PRAGMA key = 'testkey2';
122 SELECT name FROM sqlite_master WHERE type='table';
124 } {1 {file is encrypted or is not a database}}
126 file delete -force test.db
128 setup test.db "'testkey'"
129 do_test codec-1.3.2 {
130 sqlite_orig db test.db
132 PRAGMA key = "x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836480'";
133 SELECT name FROM sqlite_master WHERE type='table';
136 } {1 {file is encrypted or is not a database}}
138 file delete -force test.db
140 # open the database and try to set an invalid
141 # hex key. verify that an error is returned
142 # and that data couldn't be read
143 setup test.db "'testkey'"
145 sqlite_orig db test.db
147 PRAGMA key = "x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C4836480'";
148 SELECT name FROM sqlite_master WHERE type='table';
150 } {1 {file is encrypted or is not a database}}
152 file delete -force test.db
154 # test a large number of inserts in a transaction to a memory database
156 sqlite_orig db :memory:
158 PRAGMA key = 'testkey3';
160 CREATE TABLE t2(a,b);
162 for {set i 1} {$i<=25000} {incr i} {
163 set r [expr {int(rand()*500000)}]
164 execsql "INSERT INTO t2 VALUES($i,$r);"
168 SELECT count(*) FROM t2;
170 SELECT count(*) FROM t2;
175 # test a large number of inserts in a transaction for multiple pages
177 sqlite_orig db test.db
179 PRAGMA key = 'testkey';
180 CREATE TABLE t2(a,b);
183 for {set i 1} {$i<=25000} {incr i} {
184 set r [expr {int(rand()*500000)}]
185 execsql "INSERT INTO t2 VALUES($i,$r);"
189 SELECT count(*) FROM t2;
193 file delete -force test.db
195 # test a rekey operation as the first op on a database
196 # then test that now the new key opens the database
197 # now close database re-open with new key
198 setup test.db "'testkey'"
200 sqlite_orig db test.db
202 PRAGMA key = 'testkey';
203 PRAGMA rekey = 'testkeynew';
207 sqlite_orig db test.db
209 PRAGMA key = 'testkeynew';
210 SELECT name FROM sqlite_master WHERE type='table';
214 file delete -force test.db
216 # attach an encrypted database
217 # where both database have the same
219 setup test.db "'testkey'"
221 sqlite_orig db2 test2.db
224 PRAGMA key = 'testkey';
225 CREATE TABLE t2(a,b);
226 INSERT INTO t2 VALUES ('test1', 'test2');
230 SELECT count(*) FROM t2;
231 ATTACH 'test.db' AS db;
232 SELECT count(*) FROM db.t1;
237 file delete -force test.db
238 file delete -force test2.db
240 # attach an encrypted database
241 # where databases have different keys
242 setup test.db "'testkey'"
244 sqlite_orig db2 test2.db
247 PRAGMA key = 'testkey2';
248 CREATE TABLE t2(a,b);
249 INSERT INTO t2 VALUES ('test1', 'test2');
253 ATTACH 'test.db' AS db KEY 'testkey';
254 SELECT count(*) FROM db.t1;
255 SELECT count(*) FROM t2;
260 file delete -force test.db
261 file delete -force test2.db
263 # test locking across multiple handles
264 setup test.db "'testkey'"
266 sqlite_orig db test.db
269 PRAGMA key = 'testkey';
271 INSERT INTO t1 VALUES(1,2);
274 sqlite_orig dba test.db
276 PRAGMA key = 'testkey';
277 SELECT count(*) FROM t1;
280 } {1 {database is locked}}
282 do_test codec-1.12.1 {
288 SELECT count(*) FROM t1;
293 file delete -force test.db
296 setup test.db "'testkey'"
298 sqlite_orig db test.db
300 PRAGMA key = 'testkey';
301 ALTER TABLE t1 ADD COLUMN c;
302 INSERT INTO t1 VALUES (1,2,3);
303 INSERT INTO t1 VALUES (1,2,4);
304 CREATE TABLE t1a (a);
305 INSERT INTO t1a VALUES ('teststring');
309 sqlite_orig db test.db
311 PRAGMA key = 'testkey';
312 SELECT count(*) FROM t1 WHERE a IS NOT NULL;
313 SELECT count(*) FROM t1 WHERE c IS NOT NULL;
319 file delete -force test.db
321 # test alterations of KDF iterations and ciphers
323 setup test.db "'testkey'"
325 sqlite_orig db test.db
327 PRAGMA key = 'testkey';
328 PRAGMA rekey_kdf_iter = 1000;
329 PRAGMA rekey_cipher = 'aes-256-cfb';
330 PRAGMA rekey = 'testkey2';
331 INSERT INTO t1 VALUES (1,2);
335 sqlite_orig db test.db
337 PRAGMA key = 'testkey2';
338 PRAGMA kdf_iter = 1000;
339 PRAGMA cipher = 'aes-256-cfb';
340 SELECT count(*) FROM t1;
345 file delete -force test.db
347 # test alterations of CIPHER from CBC Mode requiring
348 # IV to ECB mode that does not
349 setup test.db "'testkey'"
351 sqlite_orig db test.db
353 PRAGMA key = 'testkey';
357 for {set i 1} {$i<=1000} {incr i} {
358 set r [expr {int(rand()*500000)}]
359 execsql "INSERT INTO t1 VALUES($i,$r);"
364 PRAGMA rekey_kdf_iter = 1000;
365 PRAGMA rekey_cipher = 'aes-128-ecb';
366 PRAGMA rekey = 'testkey';
370 sqlite_orig db test.db
372 PRAGMA key = 'testkey';
373 PRAGMA kdf_iter = 1000;
374 PRAGMA cipher = 'aes-128-ecb';
375 SELECT count(*) FROM t1;
380 file delete -force test.db
382 # test alterations of CIPHER from ECB Mode (no IV) to CBC Mode
384 sqlite_orig db test.db
386 PRAGMA key = 'testkey';
387 PRAGMA cipher = 'aes-256-ecb';
388 CREATE table t1(a,b);
392 for {set i 1} {$i<=1000} {incr i} {
393 set r [expr {int(rand()*500000)}]
394 execsql "INSERT INTO t1 VALUES($i,$r);"
399 PRAGMA rekey_cipher = 'aes-256-cbc';
400 PRAGMA rekey = 'testkey';
404 sqlite_orig db test.db
406 PRAGMA key = 'testkey';
407 SELECT count(*) FROM t1;
412 file delete -force test.db
414 # create an unencrypted database, attach a new encrypted volume
415 # copy data between, verify the encypted database is good afterwards
416 do_test unencryped-attach {
417 sqlite_orig db test.db
420 CREATE TABLE t1(a,b);
424 for {set i 1} {$i<=1000} {incr i} {
425 set r [expr {int(rand()*500000)}]
426 execsql "INSERT INTO t1 VALUES($i,$r);"
431 ATTACH DATABASE 'test2.db' AS db2 KEY 'testkey';
432 CREATE TABLE db2.t1(a,b);
433 INSERT INTO db2.t1 SELECT * FROM t1;
437 sqlite_orig db2 test2.db
439 PRAGMA key='testkey';
440 SELECT count(*) FROM t1;
444 file delete -force test.db
445 file delete -force test2.db
447 # create an encrypted database, attach an unencrypted volume
448 # copy data between, verify the unencypted database is good afterwards
449 do_test encryped-attach-unencrypted {
450 sqlite_orig db test.db
453 CREATE TABLE t1(a,b);
456 sqlite_orig db2 test2.db
458 PRAGMA key='testkey';
459 CREATE TABLE t1(a,b);
463 for {set i 1} {$i<=1000} {incr i} {
464 set r [expr {int(rand()*500000)}]
465 execsql "INSERT INTO t1 VALUES($i,$r);" db2
470 ATTACH DATABASE 'test.db' AS test KEY '';
471 INSERT INTO test.t1 SELECT * FROM t1;
472 DETACH DATABASE test;
476 SELECT count(*) FROM t1;
481 file delete -force test.db
482 file delete -force test2.db
484 # create an unencrypted database, attach an unencrypted volume
485 # copy data between, verify the unencypted database is good afterwards
486 do_test unencryped-attach-unencrypted {
487 sqlite_orig db test.db
490 CREATE TABLE t1(a,b);
493 sqlite_orig db2 test2.db
495 CREATE TABLE t1(a,b);
499 for {set i 1} {$i<=1000} {incr i} {
500 set r [expr {int(rand()*500000)}]
501 execsql "INSERT INTO t1 VALUES($i,$r);" db2
506 ATTACH DATABASE 'test.db' AS test;
507 INSERT INTO test.t1 SELECT * FROM t1;
508 DETACH DATABASE test;
512 SELECT count(*) FROM t1;
517 file delete -force test.db
518 file delete -force test2.db
520 # 1. create a database with a custom page size,
521 # 2. create table and insert operations should work
522 # 3. close database, open it again with the same
524 # 4. verify that the table is readable
525 # and the data just inserted is visible
526 do_test custom-pagesize {
527 sqlite_orig db test.db
530 PRAGMA key = 'testkey';
531 PRAGMA cipher_page_size = 4096;
532 CREATE table t1(a,b);
536 for {set i 1} {$i<=1000} {incr i} {
537 set r [expr {int(rand()*500000)}]
538 execsql "INSERT INTO t1 VALUES($i,'value $r');"
546 sqlite_orig db test.db
549 PRAGMA key = 'testkey';
550 PRAGMA cipher_page_size = 4096;
551 SELECT count(*) FROM t1;
557 # open the database with the default page size
558 ## and verfiy that it is not readable
559 do_test custom-pagesize-must-match {
560 sqlite_orig db test.db
562 PRAGMA key = 'testkey';
563 SELECT name FROM sqlite_master WHERE type='table';
565 } {1 {file is encrypted or is not a database}}
567 file delete -force test.db
569 # 1. create a database and insert a bunch of data, close the database
570 # 2. seek to the middle of a database page and write some junk
571 # 3. Open the database and verify that the database is no longer readable
572 do_test hmac-tamper-resistence {
573 sqlite_orig db test.db
576 PRAGMA key = 'testkey';
577 CREATE table t1(a,b);
581 for {set i 1} {$i<=1000} {incr i} {
582 set r [expr {int(rand()*500000)}]
583 execsql "INSERT INTO t1 VALUES($i,'value $r');"
592 # write some junk into the middle of the page
593 hexio_write test.db 2560 00
595 sqlite_orig db test.db
598 PRAGMA key = 'testkey';
599 SELECT count(*) FROM t1;
602 } {1 {database disk image is malformed}}
604 file delete -force test.db
606 # 1. create a database and insert a bunch of data, close the database
607 # 2. seek to the middle of a database page and write some junk
608 # 3. Open the database and verify that the database is still readable
609 do_test nohmac-not-tamper-resistent {
610 sqlite_orig db test.db
613 PRAGMA key = 'testkey';
614 PRAGMA cipher_use_hmac = OFF;
615 PRAGMA cipher_page_size = 1024;
616 CREATE table t1(a,b);
620 for {set i 1} {$i<=1000} {incr i} {
621 set r [expr {int(rand()*500000)}]
622 execsql "INSERT INTO t1 VALUES($i,'value $r');"
631 # write some junk into the middle of the page
632 hexio_write test.db 2560 00
634 sqlite_orig db test.db
637 PRAGMA key = 'testkey';
638 PRAGMA cipher_use_hmac = OFF;
639 PRAGMA cipher_page_size = 1024;
640 SELECT count(*) FROM t1;
645 file delete -force test.db
647 # open a 1.1.8 database using the new code, HMAC disabled
648 do_test open-1.1.8-database {
649 sqlite_orig db sqlcipher-1.1.8-testkey.db
651 PRAGMA key = 'testkey';
652 PRAGMA cipher_use_hmac = OFF;
653 SELECT count(*) FROM t1;
656 } {4 1 1 one one 1 2 one two}
660 # open a 1.1.8 database without hmac, then copy the data
661 do_test attach-and-copy-1.1.8 {
662 sqlite_orig db sqlcipher-1.1.8-testkey.db
665 PRAGMA key = 'testkey';
666 PRAGMA cipher_use_hmac = OFF;
667 ATTACH DATABASE 'test.db' AS db2 KEY 'testkey-hmac';
668 CREATE TABLE db2.t1(a,b);
669 INSERT INTO db2.t1 SELECT * FROM main.t1;
674 sqlite_orig db test.db
676 PRAGMA key = 'testkey-hmac';
677 SELECT count(*) FROM t1;
680 } {4 1 1 one one 1 2 one two}
682 file delete -force test.db
684 # open a standard database, then attach a new
685 # database with completely different options.
686 # copy data between them, and verify that the
687 # new database can be opened with the proper data
688 do_test attached-database-pragmas {
689 sqlite_orig db test.db
692 PRAGMA key = 'testkey';
693 CREATE TABLE t1(a,b);
697 for {set i 1} {$i<=1000} {incr i} {
698 set r [expr {int(rand()*500000)}]
699 execsql "INSERT INTO t1 VALUES($i,'value $r');"
704 ATTACH DATABASE 'test2.db' AS db2 KEY 'testkey2';
705 PRAGMA db2.cipher_page_size = 4096;
706 PRAGMA db2.cipher = 'aes-128-cbc';
707 PRAGMA db2.kdf_iter = 1000;
708 PRAGMA db2.cipher_use_hmac = OFF;
709 CREATE TABLE db2.t1(a,b);
710 INSERT INTO db2.t1 SELECT * FROM main.t1;
715 sqlite_orig db test2.db
717 PRAGMA key = 'testkey2';
718 PRAGMA cipher_page_size = 4096;
719 PRAGMA cipher = 'aes-128-cbc';
720 PRAGMA kdf_iter = 1000;
721 PRAGMA cipher_use_hmac = OFF;
722 SELECT count(*) FROM t1;
726 file delete -force test.db
727 file delete -force test2.db
729 # use the sqlcipher_export function
730 # on a non-existent database. Verify
731 # the error gets through.
732 do_test export-error {
733 sqlite_orig db test.db
736 PRAGMA key = 'testkey';
737 CREATE TABLE t1(a,b);
738 SELECT sqlcipher_export('nodb');
740 } {1 {unknown database nodb}}
742 file delete -force test.db
744 # use the sqlcipher_export function
745 # to copy a complicated database.
746 # tests autoincrement fields,
747 # indexes, views, and triggers
748 do_test export-database {
749 sqlite_orig db test.db
752 PRAGMA key = 'testkey';
753 CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b, c);
754 CREATE UNIQUE INDEX b_idx ON t1(b);
755 CREATE INDEX c_idx ON t1(c);
757 CREATE TABLE t2(a,b);
758 CREATE TRIGGER t2_after_insert AFTER INSERT ON t2
760 INSERT INTO t1(b,c) VALUES (new.a, new.b);
769 for {set i 1} {$i<=1000} {incr i} {
770 set r [expr {int(rand()*500000)}]
771 execsql "INSERT INTO t2 VALUES($i,'value $r');"
776 ATTACH DATABASE 'test2.db' AS db2 KEY 'testkey2';
777 PRAGMA db2.cipher_page_size = 4096;
779 SELECT sqlcipher_export('db2');
785 sqlite_orig db test2.db
787 PRAGMA key = 'testkey2';
788 PRAGMA cipher_page_size = 4096;
789 SELECT count(*) FROM t1;
790 SELECT count(*) FROM v1;
791 SELECT count(*) FROM sqlite_sequence;
792 SELECT seq FROM sqlite_sequence WHERE name = 't1';
793 INSERT INTO t2 VALUES(1001, 'value 938383');
794 SELECT count(*) FROM t1; -- verify the trigger worked
795 SELECT seq FROM sqlite_sequence WHERE name = 't1'; -- verify that autoincrement worked
797 } {1000 1000 1 1000 1001 1001}
799 file delete -force test.db
800 file delete -force test2.db
802 # 1. create a database with WAL journal mode
803 # 2. create table and insert operations should work
804 # 3. close database, open it again
805 # 4. verify that the table is present, readable, and that
806 # the journal mode is WAL
807 do_test journal-mode-wal {
808 sqlite_orig db test.db
811 PRAGMA key = 'testkey';
812 PRAGMA journal_mode = WAL;
813 CREATE table t1(a,b);
817 for {set i 1} {$i<=1000} {incr i} {
818 set r [expr {int(rand()*500000)}]
819 execsql "INSERT INTO t1 VALUES($i,'value $r');"
827 sqlite_orig db test.db
830 PRAGMA key = 'testkey';
831 SELECT count(*) FROM t1;
837 file delete -force test.db
839 # Test rekey as first operation on an empty database. should be a no-op
840 do_test rekey-as-first-op {
841 sqlite_orig db test.db
844 PRAGMA rekey = 'testkey';
845 CREATE table t1(a,b);
849 for {set i 1} {$i<=100} {incr i} {
850 set r [expr {int(rand()*500000)}]
851 execsql "INSERT INTO t1 VALUES($i,'value $r');"
859 sqlite_orig db test.db
862 PRAGMA rekey = 'testkey';
863 SELECT count(*) FROM t1;
868 file delete -force test.db
870 # Test rekey as first operation follwed by key
871 do_test rekey-then-key-as-first-ops {
872 sqlite_orig db test.db
875 PRAGMA rekey = '1234';
876 PRAGMA key = 'testkey';
877 CREATE table t1(a,b);
881 for {set i 1} {$i<=100} {incr i} {
882 set r [expr {int(rand()*500000)}]
883 execsql "INSERT INTO t1 VALUES($i,'value $r');"
891 sqlite_orig db test.db
894 PRAGMA rekey = '4321';
895 PRAGMA key = 'testkey';
896 SELECT count(*) FROM t1;