2 # codec.test developed by Stephen Lombardo (Zetetic LLC)
3 # sjlombardo at zetetic dot net
6 # Copyright (c) 2018, ZETETIC LLC
7 # Redistribution and use in source and binary forms, with or without
8 # modification, are permitted provided that the following conditions are met:
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above copyright
12 # notice, this list of conditions and the following disclaimer in the
13 # documentation and/or other materials provided with the distribution.
14 # * Neither the name of the ZETETIC LLC nor the
15 # names of its contributors may be used to endorse or promote products
16 # derived from this software without specific prior written permission.
18 # THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
19 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 # DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
22 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 # This file implements regression tests for SQLite library. The
30 # focus of this script is testing code cipher features.
32 # NOTE: tester.tcl has overridden the definition of sqlite3 to
33 # automatically pass in a key value. Thus tests in this file
34 # should explicitly close and open db with sqlite_orig in order
35 # to bypass default key assignment.
37 set testdir [file dirname $argv0]
38 source $testdir/tester.tcl
39 source $testdir/sqlcipher.tcl
41 # 1. create a database and insert a bunch of data, close the database
42 # 2. seek to the middle of the first database page and write some junk
43 # 3. Open the database and verify that the database is no longer readable
44 do_test hmac-tamper-resistence-first-page {
45 sqlite_orig db test.db
48 PRAGMA key = 'testkey';
53 for {set i 1} {$i<=1000} {incr i} {
54 set r [expr {int(rand()*500000)}]
55 execsql "INSERT INTO t1 VALUES($i,'value $r');"
64 # write some junk into the hmac segment, leaving
65 # the page data valid but with an invalid signature
66 hexio_write test.db 1000 000000
68 sqlite_orig db test.db
71 PRAGMA key = 'testkey';
72 SELECT count(*) FROM t1;
75 } {1 {file is not a database}}
77 file delete -force test.db
79 # 1. create a database and insert a bunch of data, close the database
80 # 2. seek to the middle of a database page and write some junk
81 # 3. Open the database and verify that the database is still readable
82 do_test nohmac-not-tamper-resistent {
83 sqlite_orig db test.db
86 PRAGMA key = 'testkey';
87 PRAGMA cipher_use_hmac = OFF;
88 PRAGMA cipher_page_size = 1024;
93 for {set i 1} {$i<=1000} {incr i} {
94 set r [expr {int(rand()*500000)}]
95 execsql "INSERT INTO t1 VALUES($i,'value $r');"
104 # write some junk into the middle of the page
105 hexio_write test.db 2560 000000
107 sqlite_orig db test.db
110 PRAGMA key = 'testkey';
111 PRAGMA cipher_use_hmac = OFF;
112 PRAGMA cipher_page_size = 1024;
113 SELECT count(*) FROM t1;
118 file delete -force test.db
120 # 1. create a database and insert a bunch of data, close the database
121 # 2. seek to the middle of a database page (not the first page) and write bad data
122 # 3. Open the database and verify that the database is no longer readable
123 do_test hmac-tamper-resistence {
124 sqlite_orig db test.db
127 PRAGMA key = 'testkey';
128 CREATE table t1(a,b);
132 for {set i 1} {$i<=1000} {incr i} {
133 set r [expr {int(rand()*500000)}]
134 execsql "INSERT INTO t1 VALUES($i,'value $r');"
143 # write some junk into the hmac segment, leaving
144 # the page data valid but with an invalid signature
145 hexio_write test.db 16500 000000
147 sqlite_orig db test.db
150 PRAGMA key = 'testkey';
151 SELECT count(*) FROM t1;
154 } {1 {database disk image is malformed}}
156 file delete -force test.db
158 # test that integrity checks work on a pristine
159 # newly created database
160 do_test integrity-check-clean-database {
161 sqlite_orig db test.db
164 PRAGMA key = 'testkey';
165 CREATE table t1(a,b);
169 for {set i 1} {$i<=10000} {incr i} {
170 execsql "INSERT INTO t1 VALUES($i,'value $i');"
179 sqlite_orig db test.db
181 PRAGMA key = 'testkey';
182 PRAGMA cipher_integrity_check;
183 PRAGMA integrity_check;
184 SELECT count(*) FROM t1;
189 file delete -force test.db
191 # try cipher_integrity_check on an in-memory database
192 # which should fail because the file doesn't exist
193 do_test memory-integrity-check-should-fail {
194 sqlite_orig db :memory:
196 PRAGMA key = 'testkey';
197 CREATE TABLE t1(a,b);
198 INSERT INTO t1(a,b) values (1,2);
199 PRAGMA cipher_integrity_check;
201 } {ok {database file is undefined}}
204 # try cipher_integrity_check on a valid 1.1.8 database
205 # should fail because version 1.0 doesn't use HMAC
206 do_test version-1-integrity-check-fail-no-hmac {
207 file copy -force $sampleDir/sqlcipher-1.1.8-testkey.db test.db
208 sqlite_orig db test.db
210 PRAGMA key = 'testkey';
211 PRAGMA cipher_compatibility = 1;
212 PRAGMA cipher_integrity_check;
214 } {ok {HMAC is not enabled, unable to integrity check}}
216 file delete -force test.db
218 # try cipher_integrity_check on a valid 2 database
219 do_test version-2-integrity-check-valid {
220 file copy -force $sampleDir/sqlcipher-2.0-le-testkey.db test.db
221 sqlite_orig db test.db
223 PRAGMA key = 'testkey';
224 PRAGMA cipher_compatibility = 2;
225 PRAGMA cipher_integrity_check;
229 file delete -force test.db
231 # try cipher_integrity_check on a corrupted version 2 database
232 do_test version-2-integrity-check-invalid {
233 file copy -force $sampleDir/sqlcipher-2.0-le-testkey.db test.db
234 hexio_write test.db 8202 000000
235 hexio_write test.db 10250 000000
236 sqlite_orig db test.db
238 PRAGMA key = 'testkey';
239 PRAGMA cipher_compatibility = 2;
240 PRAGMA cipher_integrity_check;
242 } {ok {HMAC verification failed for page 9} {HMAC verification failed for page 11}}
244 file delete -force test.db
246 # try cipher_integrity_check on a valid version 3 database
247 do_test version-3-integrity-check-valid {
248 file copy -force $sampleDir/sqlcipher-3.0-testkey.db test.db
249 sqlite_orig db test.db
251 PRAGMA key = 'testkey';
252 PRAGMA cipher_compatibility = 3;
253 PRAGMA cipher_integrity_check;
257 file delete -force test.db
259 # try cipher_integrity_check on a corrupted version 3 database
260 do_test version-3-integrity-check-invalid {
261 file copy -force $sampleDir/sqlcipher-3.0-testkey.db test.db
262 hexio_write test.db 8202 000000
263 hexio_write test.db 10250 000000
264 sqlite_orig db test.db
266 PRAGMA key = 'testkey';
267 PRAGMA cipher_compatibility = 3;
268 PRAGMA cipher_integrity_check;
270 } {ok {HMAC verification failed for page 9} {HMAC verification failed for page 11}}
272 file delete -force test.db
274 # try cipher_integrity_check on a valid version 4 database
275 do_test version-4-integrity-check-valid {
276 file copy -force $sampleDir/sqlcipher-4.0-testkey.db test.db
277 sqlite_orig db test.db
279 PRAGMA key = 'testkey';
280 PRAGMA cipher_integrity_check;
284 file delete -force test.db
286 # try cipher_integrity_check on a corrupted version 4 database
287 do_test version-4-integrity-check-invalid {
288 file copy -force $sampleDir/sqlcipher-4.0-testkey.db test.db
290 hexio_write test.db 5120 000000
292 hexio_write test.db 12208 000000
293 # corrupt the mac segment
294 hexio_write test.db 16320 000000
295 sqlite_orig db test.db
297 PRAGMA key = 'testkey';
298 PRAGMA cipher_integrity_check;
300 } {ok {HMAC verification failed for page 2} {HMAC verification failed for page 3} {HMAC verification failed for page 4}}
302 file delete -force test.db
304 # try cipher_integrity_check on a corrupted version 4 database
305 do_test version-4-integrity-check-invalid-last-page {
306 file copy -force $sampleDir/sqlcipher-4.0-testkey.db test.db
307 hexio_write test.db 978944 0000
308 sqlite_orig db test.db
310 PRAGMA key = 'testkey';
311 PRAGMA cipher_integrity_check;
313 } {ok {page 240 has an invalid size of 2 bytes}}
315 file delete -force test.db
317 # verify cipher_integrity_check works on a plaintext header db
318 do_test integrity-check-plaintext-header {
319 sqlite_orig db test.db
324 PRAGMA cipher_plaintext_header_size = 32;
325 CREATE TABLE t1(a,b);
326 INSERT INTO t1(a,b) VALUES (1,2);
329 lappend rc [execsql {
330 PRAGMA cipher_integrity_check;
333 lappend rc [string equal [hexio_read test.db 16 5] "1000010150"]
335 hexio_write test.db 120 000000
336 hexio_write test.db 5120 000000
338 lappend rc [execsql {
339 PRAGMA cipher_integrity_check;
341 } {{} 1 {{HMAC verification failed for page 1} {HMAC verification failed for page 2}}}
342 file delete -force test.db
344 # test that changing the key in the middle of database operations does
345 # not cause a corruption
346 do_test change-key-middle {
347 sqlite_orig db test.db
352 PRAGMA key = 'testkey';
353 CREATE table t1(a,b);
356 for {set i 1} {$i<=1000} {incr i} {
357 execsql "INSERT INTO t1 VALUES($i,'value $i');"
361 PRAGMA key = 'diffkey';
364 for {set i 1} {$i<=1000} {incr i} {
365 execsql "INSERT INTO t1 VALUES($i,'value $i');"
370 sqlite_orig db test.db
372 PRAGMA key = 'testkey';
373 SELECT name FROM sqlite_schema;
374 PRAGMA cipher_integrity_check;
375 PRAGMA integrity_check;
376 SELECT count(*) FROM t1;
380 file delete -force test.db