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 set hexkeyspec "\"x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C483648101010101010101010101010101010101'\""
43 # verify default plaintext header size is 0
44 do_test test-default-plaintext-header-size {
45 sqlite_orig db :memory:
47 PRAGMA cipher_default_plaintext_header_size;
51 # verify pragma cipher_salt returns the first 16 bytes
52 # of an existing database
53 do_test test-pragma-salt-get {
54 sqlite_orig db test.db
55 execsql { PRAGMA key = 'test'; }
60 set header [string tolower [hexio_read test.db 0 16]]
61 string equal $header $salt
63 file delete -force test.db
65 # explicitly set the salt of a new database
66 do_test test-pragma-salt-set {
68 sqlite_orig db test.db
71 PRAGMA cipher_salt = "x'01010101010101010101010101010101'";
73 INSERT INTO t1(a,b) VALUES (1,2);
77 lappend rc [hexio_read test.db 0 16]
79 sqlite_orig db test.db
82 SELECT count(*) FROM t1;
86 } {01010101010101010101010101010101 {ok 1 01010101010101010101010101010101}}
87 file delete -force test.db
90 # verify that a raw key with a fixed salt will work
91 # the first 16 bytes of database should be equal to the specified salt
92 # which is the last 32 characters of the hex key spec.
93 # also verify return value of cipher_salt
94 do_test test-raw-key-with-salt-spec {
96 sqlite_orig db test.db
98 PRAGMA key = $hexkeyspec;
100 INSERT INTO t1(a,b) VALUES (1,2);
104 lappend rc [hexio_read test.db 0 16]
106 sqlite_orig db test.db
107 lappend rc [execsql "
108 PRAGMA key = $hexkeyspec;
109 SELECT count(*) FROM t1;
112 } {01010101010101010101010101010101 {ok 1 01010101010101010101010101010101}}
114 file delete -force test.db
116 # verify that a raw key with an invalid salt will not work to
117 # open an existing database.
118 # should cause hmac failure due to invalid generated HMAC key
119 do_test test-raw-key-with-invalid-salt-spec {
120 sqlite_orig db test.db
122 PRAGMA key = $hexkeyspec;
123 CREATE TABLE t1(a,b);
124 INSERT INTO t1(a,b) VALUES (1,2);
128 sqlite_orig db test.db
130 PRAGMA key="x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C483648100000000000000000000000000000001'";
131 SELECT count(*) FROM t1;
133 } {1 {file is not a database}}
135 file delete -force test.db
137 # verify that a raw key with a bad salt *will* work if page HMAC is disabled
138 # in this case the salt will not actually be used for anything
139 # because the encryption key is provided explicitly
140 do_test test-raw-key-with-invalid-salt-spec-no-hmac {
141 sqlite_orig db test.db
143 PRAGMA key = $hexkeyspec;
144 PRAGMA cipher_use_hmac = OFF;
145 CREATE TABLE t1(a,b);
146 INSERT INTO t1(a,b) VALUES (1,2);
150 sqlite_orig db test.db
152 PRAGMA key="x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C483648100000000000000000000000000000001'";
153 PRAGMA cipher_use_hmac = OFF;
154 SELECT count(*) FROM t1;
158 file delete -force test.db
160 # verify that invalid cipher_plaintext_header_sizes don't work
162 # 2. Larger than available page size
163 # 2. Not a multiple of block size
164 do_test test-invalid-plaintext-header-sizes {
166 sqlite_orig db test.db
167 lappend rc [catchsql "
168 PRAGMA key = $hexkeyspec;
169 PRAGMA cipher_plaintext_header_size = -1;
170 CREATE TABLE t1(a,b);
173 sqlite_orig db test.db
174 lappend rc [catchsql "
175 PRAGMA key = $hexkeyspec;
176 PRAGMA cipher_plaintext_header_size = 4096;
177 CREATE TABLE t1(a,b);
180 sqlite_orig db test.db
181 lappend rc [catchsql "
182 PRAGMA key = $hexkeyspec;
183 PRAGMA cipher_plaintext_header_size = 24;
184 CREATE TABLE t1(a,b);
186 } {{1 {out of memory}} {1 {out of memory}} {1 {out of memory}}}
188 file delete -force test.db
190 # verify that a valid cipher_plaintext_header_size leaves the
191 # start of the database unencrypted, i.e. "SQLite format 3\0"
192 do_test test-valid-plaintext-header-size {
194 sqlite_orig db test.db
196 PRAGMA key = $hexkeyspec;
197 PRAGMA cipher_plaintext_header_size = 16;
198 CREATE TABLE t1(a,b);
199 INSERT INTO t1(a,b) VALUES (1,2);
203 lappend rc [hexio_read test.db 0 16]
205 sqlite_orig db test.db
206 lappend rc [execsql "
207 PRAGMA key = $hexkeyspec;
208 PRAGMA cipher_plaintext_header_size = 16;
209 SELECT count(*) FROM t1;
210 PRAGMA cipher_plaintext_header_size;
212 } {53514C69746520666F726D6174203300 {ok 1 16}}
214 file delete -force test.db
216 # when using a standard mode database and 32 byte
217 # plaintext header, ensure that bytes 16 - 19
218 # corresponding to the page size and file versions, and reserve size
219 # are readable and equal to 1024, 1, 1, and 80 respectively
220 do_test test-plaintext-header-journal-delete-mode-readable {
221 sqlite_orig db test.db
224 PRAGMA cipher_plaintext_header_size = 32;
225 CREATE TABLE t1(a,b);
226 INSERT INTO t1(a,b) VALUES (1,2);
229 string equal [hexio_read test.db 16 5] "1000010150"
231 file delete -force test.db
234 # when using a WAL mode database and 32 byte
235 # plaintext header, ensure that bytes 16 - 19
236 # corresponding to the page size and file versions, and reserve size
237 # are readable and equal to 1024, 2, 2 and 80 respectively
238 do_test test-plaintext-header-journal-wal-mode-readable {
239 sqlite_orig db test.db
242 PRAGMA cipher_plaintext_header_size = 32;
243 PRAGMA journal_mode = WAL;
244 CREATE TABLE t1(a,b);
245 INSERT INTO t1(a,b) VALUES (1,2);
248 string equal [hexio_read test.db 16 5] "1000020250"
250 file delete -force test.db
252 # verify that a valid default_cipher_plaintext_header_size leaves the
253 # start of the database unencrypted right from the start
254 # , i.e. "SQLite format 3\0"
255 do_test test-valid-default-plaintext-header-size {
257 sqlite_orig db test.db
259 PRAGMA cipher_default_plaintext_header_size = 16;
264 CREATE TABLE t1(a,b);
265 INSERT INTO t1(a,b) VALUES (1,2);
270 lappend rc [hexio_read test.db 0 16]
272 sqlite_orig db test.db
273 execsql { PRAGMA key = 'test'; }
274 lappend rc [execsql "
275 PRAGMA cipher_salt = \"x'$salt'\";
276 SELECT count(*) FROM t1;
277 PRAGMA cipher_plaintext_header_size;
280 # reset the default back to 0 or subsequent tests will fail
281 execsql "PRAGMA cipher_default_plaintext_header_size = 0;"
283 lappend rc [string equal $salt "53514c69746520666f726d6174203300"]
284 } {53514C69746520666F726D6174203300 {1 16} 0}
286 file delete -force test.db
288 # verify that a valid default_cipher_plaintext_header_size
289 # operates properly on an attached database, and that the
290 # salt pragma operates on the attached database as well
291 do_test test-valid-default-plaintext-header-size-attach {
293 sqlite_orig db test.db
295 PRAGMA cipher_default_plaintext_header_size = 16;
299 CREATE TABLE temp(a);
300 ATTACH DATABASE 'test2.db' as db2;
301 CREATE TABLE db2.t2(a,b);
302 INSERT INTO db2.t2(a,b) VALUES (1,2);
303 PRAGMA db2.cipher_salt;
307 lappend rc [hexio_read test2.db 0 16]
309 sqlite_orig db test2.db
310 execsql { PRAGMA key = 'test'; }
311 lappend rc [execsql "
312 PRAGMA cipher_salt = \"x'$salt'\";
313 SELECT count(*) FROM t2;
314 PRAGMA cipher_plaintext_header_size;
317 # reset the default back to 0 or subsequent tests will fail
318 execsql "PRAGMA cipher_default_plaintext_header_size = 0;"
320 lappend rc [string equal $salt "53514c69746520666f726d6174203300"]
321 } {53514C69746520666F726D6174203300 {1 16} 0}
323 file delete -force test.db
324 file delete -force test2.db
327 # migrate a standard database in place to use a
328 # plaintext header offset by opening it, adjusting
329 # the pragma, and rewriting the first page
330 do_test test-plaintext-header-migrate-journal-delete {
332 sqlite_orig db test.db
334 PRAGMA key = $hexkeyspec;
335 CREATE TABLE t1(a,b);
336 INSERT INTO t1(a,b) VALUES (1,2);
340 lappend rc [hexio_read test.db 0 16]
342 sqlite_orig db test.db
344 PRAGMA key = $hexkeyspec;
345 SELECT count(*) FROM t1;
346 PRAGMA cipher_plaintext_header_size = 32;
347 PRAGMA user_version = 1;
350 lappend rc [hexio_read test.db 0 21]
352 sqlite_orig db test.db
353 lappend rc [execsql "
354 PRAGMA key = $hexkeyspec;
355 PRAGMA cipher_plaintext_header_size = 32;
356 SELECT count(*) FROM t1;
359 } {01010101010101010101010101010101 53514C69746520666F726D61742033001000010150 {ok 1}}
361 file delete -force test.db
363 # migrate a wal mode database in place to use a
364 # plaintext header offset by opening it, adjusting
365 # the pragma, and rewriting the first page
366 do_test test-plaintext-header-migrate-journal-wal {
368 sqlite_orig db test.db
370 PRAGMA key = $hexkeyspec;
371 PRAGMA journal_mode = WAL;
372 CREATE TABLE t1(a,b);
373 INSERT INTO t1(a,b) VALUES (1,2);
377 lappend rc [hexio_read test.db 0 16]
379 sqlite_orig db test.db
380 lappend rc [execsql "
381 PRAGMA key = $hexkeyspec;
382 SELECT count(*) FROM t1;
384 PRAGMA cipher_plaintext_header_size = 32;
385 PRAGMA user_version = 1;
386 PRAGMA wal_checkpoint(FULL);
389 lappend rc [hexio_read test.db 0 21]
391 sqlite_orig db test.db
392 lappend rc [execsql "
393 PRAGMA key = $hexkeyspec;
394 PRAGMA cipher_plaintext_header_size = 32;
395 SELECT count(*) FROM t1;
399 } {01010101010101010101010101010101 {ok 1 wal 0 1 1} 53514C69746520666F726D61742033001000020250 {ok 1 wal}}
401 file delete -force test.db
403 # migrate a wal mode database in place to use a plaintext header
404 # but instead of using a raw key syntax, use a derived key
405 # but explicitly set the salt using cipher_salt
406 do_test test-plaintext-header-migrate-journal-wal-string-key-random-salt {
408 sqlite_orig db test.db
411 PRAGMA journal_mode = WAL;
412 CREATE TABLE t1(a,b);
413 INSERT INTO t1(a,b) VALUES (1,2);
417 set salt [hexio_read test.db 0 16]
419 sqlite_orig db test.db
420 lappend rc [execsql "
422 SELECT count(*) FROM t1;
424 PRAGMA cipher_plaintext_header_size = 32;
425 PRAGMA user_version = 1;
426 PRAGMA wal_checkpoint(FULL);
430 lappend rc [hexio_read test.db 0 21]
432 sqlite_orig db test.db
433 lappend rc [execsql "
435 PRAGMA cipher_salt = \"x'$salt'\";
436 PRAGMA cipher_plaintext_header_size = 32;
437 SELECT count(*) FROM t1;
442 } {{ok 1 wal 0 1 1} 53514C69746520666F726D61742033001000020250 {ok 1 wal}}
444 file delete -force test.db
446 # when cipher_salt is the first statement a new salt should be generated
447 # and it should match the salt after key derviation occurs. At no point
448 # should the salt be zero
449 do_test plaintext-header-size-salt-first-op {
451 sqlite_orig db test.db
452 execsql { PRAGMA key = 'test'; }
454 PRAGMA cipher_plaintext_header_size = 16;
459 CREATE TABLE t1(a,b);
460 INSERT INTO t1(a,b) VALUES (1,2);
464 lappend rc [string equal $salt1 "00000000000000000000000000000000"]
465 lappend rc [string equal $salt2 "00000000000000000000000000000000"]
466 lappend rc [string equal $salt1 $salt2]
469 file delete -force test.db