Fixes default log output to console for macOS
[sqlcipher.git] / test / sqlcipher-plaintext-header.test
blob81e1a8231215c3e5a1609d953f3a75596460796e
1 # SQLCipher
2 # codec.test developed by Stephen Lombardo (Zetetic LLC)
3 # sjlombardo at zetetic dot net
4 # http://zetetic.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:
46   execsql {
47     PRAGMA cipher_default_plaintext_header_size;
48   }
49 } {0}
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'; } 
56   set salt [execsql {
57     CREATE TABLE t1(a,b);
58     PRAGMA cipher_salt;
59   }]
60   set header [string tolower [hexio_read test.db 0 16]]
61   string equal $header $salt
62 } {1}
63 file delete -force test.db
65 # explicitly set the salt of a new database 
66 do_test test-pragma-salt-set {
67   set rc {}
68   sqlite_orig db test.db
69   execsql {
70     PRAGMA key = 'test';
71     PRAGMA cipher_salt = "x'01010101010101010101010101010101'";
72     CREATE TABLE t1(a,b);
73     INSERT INTO t1(a,b) VALUES (1,2);
74   }
75   db close
76   
77   lappend rc [hexio_read test.db 0 16]
79   sqlite_orig db test.db
80   lappend rc [execsql "
81     PRAGMA key = 'test';
82     SELECT count(*) FROM t1;
83     PRAGMA cipher_salt;
84   "]
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 {
95   set rc {}
96   sqlite_orig db test.db
97   execsql " 
98     PRAGMA key = $hexkeyspec;
99     CREATE TABLE t1(a,b);
100     INSERT INTO t1(a,b) VALUES (1,2);
101   " 
102   db close
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;
110     PRAGMA cipher_salt;
111   "]
112 } {01010101010101010101010101010101 {ok 1 01010101010101010101010101010101}}
113 db close
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
121   execsql "
122     PRAGMA key = $hexkeyspec;
123     CREATE TABLE t1(a,b);
124     INSERT INTO t1(a,b) VALUES (1,2);
125   "
126   db close
128   sqlite_orig db test.db
129   catchsql {
130     PRAGMA key="x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C483648100000000000000000000000000000001'";
131     SELECT count(*) FROM t1;
132   } 
133 } {1 {file is not a database}}
134 db close
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
142   execsql "
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);
147   "
148   db close
150   sqlite_orig db test.db
151   execsql {
152     PRAGMA key="x'98483C6EB40B6C31A448C22A66DED3B5E5E8D5119CAC8327B655C8B5C483648100000000000000000000000000000001'";
153     PRAGMA cipher_use_hmac = OFF;
154     SELECT count(*) FROM t1;
155   }
156 } {ok 1}
157 db close
158 file delete -force test.db
160 # verify that invalid cipher_plaintext_header_sizes don't work
161 # 1. less than zero
162 # 2. Larger than available page size
163 # 2. Not a multiple of block size
164 do_test test-invalid-plaintext-header-sizes {
165   set rc {}
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);
171   "]
172   db close
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);
178   "]
179   db close
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);
185   "]
186 } {{1 {out of memory}} {1 {out of memory}} {1 {out of memory}}}
187 db close
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 {
193   set rc {}
194   sqlite_orig db test.db
195   execsql "
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);
200   "
201   db close
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;
211   "]
212 } {53514C69746520666F726D6174203300 {ok 1 16}}
213 db close
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
222   execsql {
223     PRAGMA key = 'test';
224     PRAGMA cipher_plaintext_header_size = 32;
225     CREATE TABLE t1(a,b);
226     INSERT INTO t1(a,b) VALUES (1,2);
227   }
228   db close
229   string equal [hexio_read test.db 16 5] "1000010150"
230 } {1}
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
240   execsql {
241     PRAGMA key = 'test';
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);
246   }
247   db close
248   string equal [hexio_read test.db 16 5] "1000020250"
249 } {1}
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 {
256   set rc {}
257   sqlite_orig db test.db
258   execsql {
259     PRAGMA cipher_default_plaintext_header_size = 16;
260     PRAGMA key = 'test';
261   }
263   set salt [execsql {
264     CREATE TABLE t1(a,b);
265     INSERT INTO t1(a,b) VALUES (1,2);
266     PRAGMA cipher_salt;
267   }]
268   db close
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;
278   "]
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}
285 db close
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 {
292   set rc {}
293   sqlite_orig db test.db
294   execsql {
295     PRAGMA cipher_default_plaintext_header_size = 16;
296     PRAGMA key = 'test';
297   }
298   set salt [execsql {
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;
304     DETACH DATABASE db2;
305   }]
306   db close
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;
315   "]
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}
322 db close
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 {
331   set rc {}
332   sqlite_orig db test.db
333   execsql " 
334     PRAGMA key = $hexkeyspec;
335     CREATE TABLE t1(a,b);
336     INSERT INTO t1(a,b) VALUES (1,2);
337   " 
338   db close
340   lappend rc [hexio_read test.db 0 16]
342   sqlite_orig db test.db
343   execsql "
344     PRAGMA key = $hexkeyspec;
345     SELECT count(*) FROM t1;
346     PRAGMA cipher_plaintext_header_size = 32;
347     PRAGMA user_version = 1;
348   "
349   db close
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;
357   "]
359 } {01010101010101010101010101010101 53514C69746520666F726D61742033001000010150 {ok 1}}
360 db close
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 {
367   set rc {}
368   sqlite_orig db test.db
369   execsql " 
370     PRAGMA key = $hexkeyspec;
371     PRAGMA journal_mode = WAL;
372     CREATE TABLE t1(a,b);
373     INSERT INTO t1(a,b) VALUES (1,2);
374   " 
375   db close
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;
383     PRAGMA journal_mode;
384     PRAGMA cipher_plaintext_header_size = 32;
385     PRAGMA user_version = 1;
386     PRAGMA wal_checkpoint(FULL);
387   "]
388   db close
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;
396     PRAGMA journal_mode;
397   "]
399 } {01010101010101010101010101010101 {ok 1 wal 0 1 1} 53514C69746520666F726D61742033001000020250 {ok 1 wal}}
400 db close
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 {
407   set rc {}
408   sqlite_orig db test.db
409   execsql {
410     PRAGMA key = 'test';
411     PRAGMA journal_mode = WAL;
412     CREATE TABLE t1(a,b);
413     INSERT INTO t1(a,b) VALUES (1,2);
414   }
415   db close
417   set salt [hexio_read test.db 0 16]
419   sqlite_orig db test.db
420   lappend rc [execsql "
421     PRAGMA key = 'test';
422     SELECT count(*) FROM t1;
423     PRAGMA journal_mode;
424     PRAGMA cipher_plaintext_header_size = 32;
425     PRAGMA user_version = 1;
426     PRAGMA wal_checkpoint(FULL);
427   "]
428   db close
430   lappend rc [hexio_read test.db 0 21]
432   sqlite_orig db test.db
433   lappend rc [execsql "
434     PRAGMA key = 'test';
435     PRAGMA cipher_salt = \"x'$salt'\";
436     PRAGMA cipher_plaintext_header_size = 32;
437     SELECT count(*) FROM t1;
438     PRAGMA journal_mode;
439   "]
442 } {{ok 1 wal 0 1 1} 53514C69746520666F726D61742033001000020250 {ok 1 wal}}
443 db close
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 {
450   set rc {}
451   sqlite_orig db test.db
452   execsql { PRAGMA key = 'test'; } 
453   set salt1 [execsql {
454     PRAGMA cipher_plaintext_header_size = 16;
455     PRAGMA cipher_salt;
456   }]
458   set salt2 [execsql {
459     CREATE TABLE t1(a,b);
460     INSERT INTO t1(a,b) VALUES (1,2);
461     PRAGMA cipher_salt;
462   }]
464   lappend rc [string equal $salt1 "00000000000000000000000000000000"] 
465   lappend rc [string equal $salt2 "00000000000000000000000000000000"] 
466   lappend rc [string equal $salt1 $salt2]
467 } {0 0 1}
468 db close
469 file delete -force test.db
471 finish_test