rework some pragma related interfaces
[sqlcipher.git] / src / crypto.c
blob262318b7454024e16e8a6f0b1bdec5d9d07da4bf
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( zRight ) {
112 if(ctx) sqlcipher_codec_ctx_set_kdf_iter(ctx, atoi(zRight), 2); // change of RW PBKDF2 iteration
113 } else {
114 if(ctx) {
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 && zRight ){
122 if(ctx) sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, atoi(zRight), 2); // change of RW PBKDF2 iteration
123 }else
124 if( sqlite3StrICmp(zLeft, "rekey_kdf_iter")==0 && zRight ){
125 if(ctx) sqlcipher_codec_ctx_set_kdf_iter(ctx, atoi(zRight), 1); // write iterations only
126 }else
127 if( sqlite3StrICmp(zLeft,"cipher_page_size")==0 ){
128 if(ctx) {
129 if( zRight ) {
130 int size = atoi(zRight);
131 rc = sqlcipher_codec_ctx_set_pagesize(ctx, size);
132 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
133 rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
134 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
135 } else {
136 char * page_size = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_pagesize(ctx));
137 codec_vdbe_return_static_string(pParse, "cipher_page_size", page_size);
138 sqlite3_free(page_size);
141 }else
142 if( sqlite3StrICmp(zLeft,"cipher_default_use_hmac")==0 ){
143 if( zRight ) {
144 sqlcipher_set_default_use_hmac(sqlite3GetBoolean(zRight,1));
145 } else {
146 char *default_use_hmac = sqlite3_mprintf("%d", sqlcipher_get_default_use_hmac());
147 codec_vdbe_return_static_string(pParse, "cipher_default_use_hmac", default_use_hmac);
148 sqlite3_free(default_use_hmac);
150 }else
151 if( sqlite3StrICmp(zLeft,"cipher_use_hmac")==0 ){
153 if( zRight ) {
154 if(ctx) {
155 rc = sqlcipher_codec_ctx_set_use_hmac(ctx, sqlite3GetBoolean(zRight,1));
156 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
157 /* since the use of hmac has changed, the page size may also change */
158 rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
159 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
161 } else {
162 if(ctx) {
163 char *hmac_flag = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_use_hmac(ctx, 2));
164 codec_vdbe_return_static_string(pParse, "cipher_use_hmac", hmac_flag);
165 sqlite3_free(hmac_flag);
168 }else
169 if( sqlite3StrICmp(zLeft,"cipher_hmac_pgno")==0 ){
170 // clear both pgno endian flags
171 if(sqlite3StrICmp(zRight, "le") == 0) {
172 sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO);
173 sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_LE_PGNO);
174 } else if(sqlite3StrICmp(zRight, "be") == 0) {
175 sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO);
176 sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_BE_PGNO);
177 } else if(sqlite3StrICmp(zRight, "native") == 0) {
178 sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO);
179 sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO);
181 }else
182 if( sqlite3StrICmp(zLeft,"cipher_hmac_salt_mask")==0 ){
183 if(zRight) {
184 if (sqlite3StrNICmp(zRight ,"x'", 2) == 0 && sqlite3Strlen30(zRight) == 5) {
185 unsigned char mask = 0;
186 const char *hex = zRight+2;
187 cipher_hex2bin(hex,2,&mask);
188 sqlcipher_set_hmac_salt_mask(mask);
191 }else {
192 return 0;
194 return 1;
198 * sqlite3Codec can be called in multiple modes.
199 * encrypt mode - expected to return a pointer to the
200 * encrypted data without altering pData.
201 * decrypt mode - expected to return a pointer to pData, with
202 * the data decrypted in the input buffer
204 void* sqlite3Codec(void *iCtx, void *data, Pgno pgno, int mode) {
205 codec_ctx *ctx = (codec_ctx *) iCtx;
206 int offset = 0, rc = 0;
207 int page_sz = sqlcipher_codec_ctx_get_pagesize(ctx);
208 unsigned char *pData = (unsigned char *) data;
209 void *buffer = sqlcipher_codec_ctx_get_data(ctx);
210 void *kdf_salt = sqlcipher_codec_ctx_get_kdf_salt(ctx);
211 CODEC_TRACE(("sqlite3Codec: entered pgno=%d, mode=%d, page_sz=%d\n", pgno, mode, page_sz));
213 /* call to derive keys if not present yet */
214 if((rc = sqlcipher_codec_key_derive(ctx)) != SQLITE_OK) {
215 sqlcipher_codec_ctx_set_error(ctx, rc);
216 return NULL;
219 if(pgno == 1) offset = FILE_HEADER_SZ; /* adjust starting pointers in data page for header offset on first page*/
221 CODEC_TRACE(("sqlite3Codec: switch mode=%d offset=%d\n", mode, offset));
222 switch(mode) {
223 case 0: /* decrypt */
224 case 2:
225 case 3:
226 if(pgno == 1) memcpy(buffer, SQLITE_FILE_HEADER, FILE_HEADER_SZ); /* copy file header to the first 16 bytes of the page */
227 rc = sqlcipher_page_cipher(ctx, CIPHER_READ_CTX, pgno, CIPHER_DECRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset);
228 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
229 memcpy(pData, buffer, page_sz); /* copy buffer data back to pData and return */
230 return pData;
231 break;
232 case 6: /* encrypt */
233 if(pgno == 1) memcpy(buffer, kdf_salt, FILE_HEADER_SZ); /* copy salt to output buffer */
234 rc = sqlcipher_page_cipher(ctx, CIPHER_WRITE_CTX, pgno, CIPHER_ENCRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset);
235 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
236 return buffer; /* return persistent buffer data, pData remains intact */
237 break;
238 case 7:
239 if(pgno == 1) memcpy(buffer, kdf_salt, FILE_HEADER_SZ); /* copy salt to output buffer */
240 rc = sqlcipher_page_cipher(ctx, CIPHER_READ_CTX, pgno, CIPHER_ENCRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset);
241 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
242 return buffer; /* return persistent buffer data, pData remains intact */
243 break;
244 default:
245 return pData;
246 break;
250 void sqlite3FreeCodecArg(void *pCodecArg) {
251 codec_ctx *ctx = (codec_ctx *) pCodecArg;
252 if(pCodecArg == NULL) return;
253 sqlcipher_codec_ctx_free(&ctx); // wipe and free allocated memory for the context
254 sqlcipher_deactivate(); /* cleanup related structures, OpenSSL etc, when codec is detatched */
257 int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) {
258 struct Db *pDb = &db->aDb[nDb];
260 CODEC_TRACE(("sqlite3CodecAttach: entered nDb=%d zKey=%s, nKey=%d\n", nDb, (char *)zKey, nKey));
263 if(nKey && zKey && pDb->pBt) {
264 int rc;
265 Pager *pPager = pDb->pBt->pBt->pPager;
266 sqlite3_file *fd = sqlite3Pager_get_fd(pPager);
267 codec_ctx *ctx;
269 sqlcipher_activate(); /* perform internal initialization for sqlcipher */
271 /* point the internal codec argument against the contet to be prepared */
272 rc = sqlcipher_codec_ctx_init(&ctx, pDb, pDb->pBt->pBt->pPager, fd, zKey, nKey);
274 if(rc != SQLITE_OK) return rc; /* initialization failed, do not attach potentially corrupted context */
276 sqlite3_mutex_enter(db->mutex);
278 sqlite3pager_sqlite3PagerSetCodec(sqlite3BtreePager(pDb->pBt), sqlite3Codec, NULL, sqlite3FreeCodecArg, (void *) ctx);
280 codec_set_btree_to_codec_pagesize(db, pDb, ctx);
282 /* force secure delete. This has the benefit of wiping internal data when deleted
283 and also ensures that all pages are written to disk (i.e. not skipped by
284 sqlite3PagerDontWrite optimizations) */
285 sqlite3BtreeSecureDelete(pDb->pBt, 1);
287 /* if fd is null, then this is an in-memory database and
288 we dont' want to overwrite the AutoVacuum settings
289 if not null, then set to the default */
290 if(fd != NULL) {
291 sqlite3BtreeSetAutoVacuum(pDb->pBt, SQLITE_DEFAULT_AUTOVACUUM);
293 sqlite3_mutex_leave(db->mutex);
295 return SQLITE_OK;
298 void sqlite3_activate_see(const char* in) {
299 /* do nothing, security enhancements are always active */
302 int sqlite3_key(sqlite3 *db, const void *pKey, int nKey) {
303 CODEC_TRACE(("sqlite3_key: entered db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey));
304 /* attach key if db and pKey are not null and nKey is > 0 */
305 if(db && pKey && nKey) {
306 return sqlite3CodecAttach(db, 0, pKey, nKey); // operate only on the main db
308 return SQLITE_ERROR;
311 /* sqlite3_rekey
312 ** Given a database, this will reencrypt the database using a new key.
313 ** There is only one possible modes of operation - to encrypt a database
314 ** that is already encrpyted. If the database is not already encrypted
315 ** this should do nothing
316 ** The proposed logic for this function follows:
317 ** 1. Determine if the database is already encryptped
318 ** 2. If there is NOT already a key present do nothing
319 ** 3. If there is a key present, re-encrypt the database with the new key
321 int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) {
322 CODEC_TRACE(("sqlite3_rekey: entered db=%p pKey=%s, nKey=%d\n", db, (char *)pKey, nKey));
323 if(db && pKey && nKey) {
324 struct Db *pDb = &db->aDb[0];
325 CODEC_TRACE(("sqlite3_rekey: database pDb=%p\n", pDb));
326 if(pDb->pBt) {
327 codec_ctx *ctx;
328 int rc, page_count;
329 Pgno pgno;
330 PgHdr *page;
331 Pager *pPager = pDb->pBt->pBt->pPager;
333 sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
335 if(ctx == NULL) {
336 /* there was no codec attached to this database, so this should do nothing! */
337 CODEC_TRACE(("sqlite3_rekey: no codec attached to db, exiting\n"));
338 return SQLITE_OK;
341 sqlite3_mutex_enter(db->mutex);
343 codec_set_pass_key(db, 0, pKey, nKey, CIPHER_WRITE_CTX);
345 /* do stuff here to rewrite the database
346 ** 1. Create a transaction on the database
347 ** 2. Iterate through each page, reading it and then writing it.
348 ** 3. If that goes ok then commit and put ctx->rekey into ctx->key
349 ** note: don't deallocate rekey since it may be used in a subsequent iteration
351 rc = sqlite3BtreeBeginTrans(pDb->pBt, 1); /* begin write transaction */
352 sqlite3PagerPagecount(pPager, &page_count);
353 for(pgno = 1; rc == SQLITE_OK && pgno <= page_count; pgno++) { /* pgno's start at 1 see pager.c:pagerAcquire */
354 if(!sqlite3pager_is_mj_pgno(pPager, pgno)) { /* skip this page (see pager.c:pagerAcquire for reasoning) */
355 rc = sqlite3PagerGet(pPager, pgno, &page);
356 if(rc == SQLITE_OK) { /* write page see pager_incr_changecounter for example */
357 rc = sqlite3PagerWrite(page);
358 if(rc == SQLITE_OK) {
359 sqlite3PagerUnref(page);
360 } else {
361 CODEC_TRACE(("sqlite3_rekey: error %d occurred writing page %d\n", rc, pgno));
363 } else {
364 CODEC_TRACE(("sqlite3_rekey: error %d occurred getting page %d\n", rc, pgno));
369 /* if commit was successful commit and copy the rekey data to current key, else rollback to release locks */
370 if(rc == SQLITE_OK) {
371 CODEC_TRACE(("sqlite3_rekey: committing\n"));
372 rc = sqlite3BtreeCommit(pDb->pBt);
373 sqlcipher_codec_key_copy(ctx, CIPHER_WRITE_CTX);
374 } else {
375 CODEC_TRACE(("sqlite3_rekey: rollback\n"));
376 sqlite3BtreeRollback(pDb->pBt, SQLITE_ABORT_ROLLBACK);
379 sqlite3_mutex_leave(db->mutex);
381 return SQLITE_OK;
383 return SQLITE_ERROR;
386 void sqlite3CodecGetKey(sqlite3* db, int nDb, void **zKey, int *nKey) {
387 struct Db *pDb = &db->aDb[nDb];
388 CODEC_TRACE(("sqlite3CodecGetKey: entered db=%p, nDb=%d\n", db, nDb));
390 if( pDb->pBt ) {
391 codec_ctx *ctx;
392 sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
394 if(ctx) { /* if the codec has an attached codec_context user the raw key data */
395 sqlcipher_codec_get_pass(ctx, zKey, nKey);
396 } else {
397 *zKey = NULL;
398 *nKey = 0;
404 /* END CRYPTO */
405 #endif