pragma to print hmac salt mask
[sqlcipher.git] / src / crypto.c
blob32d5bf98b4fffa74041d60c2bc56cd46778b809e
1 /*
2 ** SQLCipher
3 ** crypto.c developed by Stephen Lombardo (Zetetic LLC)
4 ** sjlombardo at zetetic dot net
5 ** http://zetetic.net
6 **
7 ** Copyright (c) 2009, ZETETIC LLC
8 ** All rights reserved.
9 **
10 ** Redistribution and use in source and binary forms, with or without
11 ** modification, are permitted provided that the following conditions are met:
12 ** * Redistributions of source code must retain the above copyright
13 ** notice, this list of conditions and the following disclaimer.
14 ** * Redistributions in binary form must reproduce the above copyright
15 ** notice, this list of conditions and the following disclaimer in the
16 ** documentation and/or other materials provided with the distribution.
17 ** * Neither the name of the ZETETIC LLC nor the
18 ** names of its contributors may be used to endorse or promote products
19 ** derived from this software without specific prior written permission.
20 **
21 ** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
22 ** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 ** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
25 ** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 ** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 ** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 **
33 /* BEGIN CRYPTO */
34 #ifdef SQLITE_HAS_CODEC
36 #include <assert.h>
37 #include "sqliteInt.h"
38 #include "btreeInt.h"
39 #include "crypto.h"
41 const char* codec_get_cipher_version() {
42 return CIPHER_VERSION;
45 /* Generate code to return a string value */
46 void codec_vdbe_return_static_string(Parse *pParse, const char *zLabel, const char *value){
47 Vdbe *v = sqlite3GetVdbe(pParse);
48 sqlite3VdbeSetNumCols(v, 1);
49 sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC);
50 sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, value, 0);
51 sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1);
54 static int codec_set_btree_to_codec_pagesize(sqlite3 *db, Db *pDb, codec_ctx *ctx) {
55 int rc, page_sz, reserve_sz;
57 page_sz = sqlcipher_codec_ctx_get_pagesize(ctx);
58 reserve_sz = sqlcipher_codec_ctx_get_reservesize(ctx);
60 sqlite3_mutex_enter(db->mutex);
61 db->nextPagesize = page_sz;
63 /* before forcing the page size we need to unset the BTS_PAGESIZE_FIXED flag, else
64 sqliteBtreeSetPageSize will block the change */
65 pDb->pBt->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED;
66 CODEC_TRACE(("codec_set_btree_to_codec_pagesize: sqlite3BtreeSetPageSize() size=%d reserve=%d\n", page_sz, reserve_sz));
67 rc = sqlite3BtreeSetPageSize(pDb->pBt, page_sz, reserve_sz, 0);
68 sqlite3_mutex_leave(db->mutex);
69 return rc;
72 int codec_set_pass_key(sqlite3* db, int nDb, const void *zKey, int nKey, int for_ctx) {
73 struct Db *pDb = &db->aDb[nDb];
74 CODEC_TRACE(("codec_set_pass_key: entered db=%p nDb=%d zKey=%s nKey=%d for_ctx=%d\n", db, nDb, (char *)zKey, nKey, for_ctx));
75 if(pDb->pBt) {
76 codec_ctx *ctx;
77 sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
78 if(ctx) return sqlcipher_codec_ctx_set_pass(ctx, zKey, nKey, for_ctx);
80 return SQLITE_ERROR;
83 int codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const char *zRight) {
84 struct Db *pDb = &db->aDb[iDb];
85 codec_ctx *ctx = NULL;
86 int rc;
88 if(pDb->pBt) {
89 sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
92 CODEC_TRACE(("codec_pragma: entered db=%p iDb=%d pParse=%p zLeft=%s zRight=%s ctx=%p\n", db, iDb, pParse, zLeft, zRight, ctx));
94 if( sqlite3StrICmp(zLeft, "cipher_version")==0 && !zRight ){
95 codec_vdbe_return_static_string(pParse, "cipher_version", codec_get_cipher_version());
96 }else
97 if( sqlite3StrICmp(zLeft, "cipher")==0 ){
98 if( zRight ) {
99 if(ctx) sqlcipher_codec_ctx_set_cipher(ctx, zRight, 2); // change cipher for both
100 }else {
101 if(ctx) {
102 codec_vdbe_return_static_string(pParse, "cipher",
103 sqlcipher_codec_ctx_get_cipher(ctx, 2));
106 }else
107 if( sqlite3StrICmp(zLeft, "rekey_cipher")==0 && zRight ){
108 if(ctx) sqlcipher_codec_ctx_set_cipher(ctx, zRight, 1); // change write cipher only
109 }else
110 if( sqlite3StrICmp(zLeft, "kdf_iter")==0 ){
111 if(ctx) {
112 if( zRight ) {
113 sqlcipher_codec_ctx_set_kdf_iter(ctx, atoi(zRight), 2); // change of RW PBKDF2 iteration
114 } else {
115 char *kdf_iter = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_kdf_iter(ctx, 2));
116 codec_vdbe_return_static_string(pParse, "kdf_iter", kdf_iter);
117 sqlite3_free(kdf_iter);
120 }else
121 if( sqlite3StrICmp(zLeft, "fast_kdf_iter")==0){
122 if(ctx) {
123 if( zRight ) {
124 sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, atoi(zRight), 2); // change of RW PBKDF2 iteration
125 } else {
126 char *fast_kdf_iter = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_fast_kdf_iter(ctx, 2));
127 codec_vdbe_return_static_string(pParse, "fast_kdf_iter", fast_kdf_iter);
128 sqlite3_free(fast_kdf_iter);
131 }else
132 if( sqlite3StrICmp(zLeft, "rekey_kdf_iter")==0 && zRight ){
133 if(ctx) sqlcipher_codec_ctx_set_kdf_iter(ctx, atoi(zRight), 1); // write iterations only
134 }else
135 if( sqlite3StrICmp(zLeft,"cipher_page_size")==0 ){
136 if(ctx) {
137 if( zRight ) {
138 int size = atoi(zRight);
139 rc = sqlcipher_codec_ctx_set_pagesize(ctx, size);
140 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
141 rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
142 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
143 } else {
144 char * page_size = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_pagesize(ctx));
145 codec_vdbe_return_static_string(pParse, "cipher_page_size", page_size);
146 sqlite3_free(page_size);
149 }else
150 if( sqlite3StrICmp(zLeft,"cipher_default_use_hmac")==0 ){
151 if( zRight ) {
152 sqlcipher_set_default_use_hmac(sqlite3GetBoolean(zRight,1));
153 } else {
154 char *default_use_hmac = sqlite3_mprintf("%d", sqlcipher_get_default_use_hmac());
155 codec_vdbe_return_static_string(pParse, "cipher_default_use_hmac", default_use_hmac);
156 sqlite3_free(default_use_hmac);
158 }else
159 if( sqlite3StrICmp(zLeft,"cipher_use_hmac")==0 ){
161 if( zRight ) {
162 if(ctx) {
163 rc = sqlcipher_codec_ctx_set_use_hmac(ctx, sqlite3GetBoolean(zRight,1));
164 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
165 /* since the use of hmac has changed, the page size may also change */
166 rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
167 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
169 } else {
170 if(ctx) {
171 char *hmac_flag = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_use_hmac(ctx, 2));
172 codec_vdbe_return_static_string(pParse, "cipher_use_hmac", hmac_flag);
173 sqlite3_free(hmac_flag);
176 }else
177 if( sqlite3StrICmp(zLeft,"cipher_hmac_pgno")==0 ){
178 // clear both pgno endian flags
179 if(sqlite3StrICmp(zRight, "le") == 0) {
180 sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO);
181 sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_LE_PGNO);
182 } else if(sqlite3StrICmp(zRight, "be") == 0) {
183 sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO);
184 sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_BE_PGNO);
185 } else if(sqlite3StrICmp(zRight, "native") == 0) {
186 sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO);
187 sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO);
189 }else
190 if( sqlite3StrICmp(zLeft,"cipher_hmac_salt_mask")==0 ){
191 if(ctx) {
192 if(zRight) {
193 if (sqlite3StrNICmp(zRight ,"x'", 2) == 0 && sqlite3Strlen30(zRight) == 5) {
194 unsigned char mask = 0;
195 const char *hex = zRight+2;
196 cipher_hex2bin(hex,2,&mask);
197 sqlcipher_set_hmac_salt_mask(mask);
199 } else {
200 char *hmac_salt_mask = sqlite3_mprintf("%02x", sqlcipher_get_hmac_salt_mask());
201 codec_vdbe_return_static_string(pParse, "cipher_hmac_salt_mask", hmac_salt_mask);
202 sqlite3_free(hmac_salt_mask);
205 }else {
206 return 0;
208 return 1;
212 * sqlite3Codec can be called in multiple modes.
213 * encrypt mode - expected to return a pointer to the
214 * encrypted data without altering pData.
215 * decrypt mode - expected to return a pointer to pData, with
216 * the data decrypted in the input buffer
218 void* sqlite3Codec(void *iCtx, void *data, Pgno pgno, int mode) {
219 codec_ctx *ctx = (codec_ctx *) iCtx;
220 int offset = 0, rc = 0;
221 int page_sz = sqlcipher_codec_ctx_get_pagesize(ctx);
222 unsigned char *pData = (unsigned char *) data;
223 void *buffer = sqlcipher_codec_ctx_get_data(ctx);
224 void *kdf_salt = sqlcipher_codec_ctx_get_kdf_salt(ctx);
225 CODEC_TRACE(("sqlite3Codec: entered pgno=%d, mode=%d, page_sz=%d\n", pgno, mode, page_sz));
227 /* call to derive keys if not present yet */
228 if((rc = sqlcipher_codec_key_derive(ctx)) != SQLITE_OK) {
229 sqlcipher_codec_ctx_set_error(ctx, rc);
230 return NULL;
233 if(pgno == 1) offset = FILE_HEADER_SZ; /* adjust starting pointers in data page for header offset on first page*/
235 CODEC_TRACE(("sqlite3Codec: switch mode=%d offset=%d\n", mode, offset));
236 switch(mode) {
237 case 0: /* decrypt */
238 case 2:
239 case 3:
240 if(pgno == 1) memcpy(buffer, SQLITE_FILE_HEADER, FILE_HEADER_SZ); /* copy file header to the first 16 bytes of the page */
241 rc = sqlcipher_page_cipher(ctx, CIPHER_READ_CTX, pgno, CIPHER_DECRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset);
242 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
243 memcpy(pData, buffer, page_sz); /* copy buffer data back to pData and return */
244 return pData;
245 break;
246 case 6: /* encrypt */
247 if(pgno == 1) memcpy(buffer, kdf_salt, FILE_HEADER_SZ); /* copy salt to output buffer */
248 rc = sqlcipher_page_cipher(ctx, CIPHER_WRITE_CTX, pgno, CIPHER_ENCRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset);
249 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
250 return buffer; /* return persistent buffer data, pData remains intact */
251 break;
252 case 7:
253 if(pgno == 1) memcpy(buffer, kdf_salt, FILE_HEADER_SZ); /* copy salt to output buffer */
254 rc = sqlcipher_page_cipher(ctx, CIPHER_READ_CTX, pgno, CIPHER_ENCRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset);
255 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
256 return buffer; /* return persistent buffer data, pData remains intact */
257 break;
258 default:
259 return pData;
260 break;
264 void sqlite3FreeCodecArg(void *pCodecArg) {
265 codec_ctx *ctx = (codec_ctx *) pCodecArg;
266 if(pCodecArg == NULL) return;
267 sqlcipher_codec_ctx_free(&ctx); // wipe and free allocated memory for the context
268 sqlcipher_deactivate(); /* cleanup related structures, OpenSSL etc, when codec is detatched */
271 int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) {
272 struct Db *pDb = &db->aDb[nDb];
274 CODEC_TRACE(("sqlite3CodecAttach: entered nDb=%d zKey=%s, nKey=%d\n", nDb, (char *)zKey, nKey));
277 if(nKey && zKey && pDb->pBt) {
278 int rc;
279 Pager *pPager = pDb->pBt->pBt->pPager;
280 sqlite3_file *fd = sqlite3Pager_get_fd(pPager);
281 codec_ctx *ctx;
283 sqlcipher_activate(); /* perform internal initialization for sqlcipher */
285 /* point the internal codec argument against the contet to be prepared */
286 rc = sqlcipher_codec_ctx_init(&ctx, pDb, pDb->pBt->pBt->pPager, fd, zKey, nKey);
288 if(rc != SQLITE_OK) return rc; /* initialization failed, do not attach potentially corrupted context */
290 sqlite3_mutex_enter(db->mutex);
292 sqlite3pager_sqlite3PagerSetCodec(sqlite3BtreePager(pDb->pBt), sqlite3Codec, NULL, sqlite3FreeCodecArg, (void *) ctx);
294 codec_set_btree_to_codec_pagesize(db, pDb, ctx);
296 /* force secure delete. This has the benefit of wiping internal data when deleted
297 and also ensures that all pages are written to disk (i.e. not skipped by
298 sqlite3PagerDontWrite optimizations) */
299 sqlite3BtreeSecureDelete(pDb->pBt, 1);
301 /* if fd is null, then this is an in-memory database and
302 we dont' want to overwrite the AutoVacuum settings
303 if not null, then set to the default */
304 if(fd != NULL) {
305 sqlite3BtreeSetAutoVacuum(pDb->pBt, SQLITE_DEFAULT_AUTOVACUUM);
307 sqlite3_mutex_leave(db->mutex);
309 return SQLITE_OK;
312 void sqlite3_activate_see(const char* in) {
313 /* do nothing, security enhancements are always active */
316 int sqlite3_key(sqlite3 *db, const void *pKey, int nKey) {
317 CODEC_TRACE(("sqlite3_key: entered db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey));
318 /* attach key if db and pKey are not null and nKey is > 0 */
319 if(db && pKey && nKey) {
320 return sqlite3CodecAttach(db, 0, pKey, nKey); // operate only on the main db
322 return SQLITE_ERROR;
325 /* sqlite3_rekey
326 ** Given a database, this will reencrypt the database using a new key.
327 ** There is only one possible modes of operation - to encrypt a database
328 ** that is already encrpyted. If the database is not already encrypted
329 ** this should do nothing
330 ** The proposed logic for this function follows:
331 ** 1. Determine if the database is already encryptped
332 ** 2. If there is NOT already a key present do nothing
333 ** 3. If there is a key present, re-encrypt the database with the new key
335 int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) {
336 CODEC_TRACE(("sqlite3_rekey: entered db=%p pKey=%s, nKey=%d\n", db, (char *)pKey, nKey));
337 if(db && pKey && nKey) {
338 struct Db *pDb = &db->aDb[0];
339 CODEC_TRACE(("sqlite3_rekey: database pDb=%p\n", pDb));
340 if(pDb->pBt) {
341 codec_ctx *ctx;
342 int rc, page_count;
343 Pgno pgno;
344 PgHdr *page;
345 Pager *pPager = pDb->pBt->pBt->pPager;
347 sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
349 if(ctx == NULL) {
350 /* there was no codec attached to this database, so this should do nothing! */
351 CODEC_TRACE(("sqlite3_rekey: no codec attached to db, exiting\n"));
352 return SQLITE_OK;
355 sqlite3_mutex_enter(db->mutex);
357 codec_set_pass_key(db, 0, pKey, nKey, CIPHER_WRITE_CTX);
359 /* do stuff here to rewrite the database
360 ** 1. Create a transaction on the database
361 ** 2. Iterate through each page, reading it and then writing it.
362 ** 3. If that goes ok then commit and put ctx->rekey into ctx->key
363 ** note: don't deallocate rekey since it may be used in a subsequent iteration
365 rc = sqlite3BtreeBeginTrans(pDb->pBt, 1); /* begin write transaction */
366 sqlite3PagerPagecount(pPager, &page_count);
367 for(pgno = 1; rc == SQLITE_OK && pgno <= page_count; pgno++) { /* pgno's start at 1 see pager.c:pagerAcquire */
368 if(!sqlite3pager_is_mj_pgno(pPager, pgno)) { /* skip this page (see pager.c:pagerAcquire for reasoning) */
369 rc = sqlite3PagerGet(pPager, pgno, &page);
370 if(rc == SQLITE_OK) { /* write page see pager_incr_changecounter for example */
371 rc = sqlite3PagerWrite(page);
372 if(rc == SQLITE_OK) {
373 sqlite3PagerUnref(page);
374 } else {
375 CODEC_TRACE(("sqlite3_rekey: error %d occurred writing page %d\n", rc, pgno));
377 } else {
378 CODEC_TRACE(("sqlite3_rekey: error %d occurred getting page %d\n", rc, pgno));
383 /* if commit was successful commit and copy the rekey data to current key, else rollback to release locks */
384 if(rc == SQLITE_OK) {
385 CODEC_TRACE(("sqlite3_rekey: committing\n"));
386 rc = sqlite3BtreeCommit(pDb->pBt);
387 sqlcipher_codec_key_copy(ctx, CIPHER_WRITE_CTX);
388 } else {
389 CODEC_TRACE(("sqlite3_rekey: rollback\n"));
390 sqlite3BtreeRollback(pDb->pBt, SQLITE_ABORT_ROLLBACK);
393 sqlite3_mutex_leave(db->mutex);
395 return SQLITE_OK;
397 return SQLITE_ERROR;
400 void sqlite3CodecGetKey(sqlite3* db, int nDb, void **zKey, int *nKey) {
401 struct Db *pDb = &db->aDb[nDb];
402 CODEC_TRACE(("sqlite3CodecGetKey: entered db=%p, nDb=%d\n", db, nDb));
404 if( pDb->pBt ) {
405 codec_ctx *ctx;
406 sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
408 if(ctx) { /* if the codec has an attached codec_context user the raw key data */
409 sqlcipher_codec_get_pass(ctx, zKey, nKey);
410 } else {
411 *zKey = NULL;
412 *nKey = 0;
418 /* END CRYPTO */
419 #endif