remove internal mutexing and move fortuna initialization to activate
[sqlcipher.git] / src / crypto.c
blob9cae021137e9b300b650aaf8c454494abbe9a88f
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 static const char* codec_get_cipher_version() {
42 return CIPHER_VERSION;
45 /* Generate code to return a string value */
46 static 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 static 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_provider")==0 && !zRight ){
95 if(ctx) { codec_vdbe_return_static_string(pParse, "cipher_provider",
96 sqlcipher_codec_get_cipher_provider(ctx));
98 } else
99 if( sqlite3StrICmp(zLeft, "cipher_version")==0 && !zRight ){
100 codec_vdbe_return_static_string(pParse, "cipher_version", codec_get_cipher_version());
101 }else
102 if( sqlite3StrICmp(zLeft, "cipher")==0 ){
103 if(ctx) {
104 if( zRight ) {
105 sqlcipher_codec_ctx_set_cipher(ctx, zRight, 2); // change cipher for both
106 }else {
107 codec_vdbe_return_static_string(pParse, "cipher",
108 sqlcipher_codec_ctx_get_cipher(ctx, 2));
111 }else
112 if( sqlite3StrICmp(zLeft, "rekey_cipher")==0 && zRight ){
113 if(ctx) sqlcipher_codec_ctx_set_cipher(ctx, zRight, 1); // change write cipher only
114 }else
115 if( sqlite3StrICmp(zLeft, "kdf_iter")==0 ){
116 if(ctx) {
117 if( zRight ) {
118 sqlcipher_codec_ctx_set_kdf_iter(ctx, atoi(zRight), 2); // change of RW PBKDF2 iteration
119 } else {
120 char *kdf_iter = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_kdf_iter(ctx, 2));
121 codec_vdbe_return_static_string(pParse, "kdf_iter", kdf_iter);
122 sqlite3_free(kdf_iter);
125 }else
126 if( sqlite3StrICmp(zLeft, "fast_kdf_iter")==0){
127 if(ctx) {
128 if( zRight ) {
129 sqlcipher_codec_ctx_set_fast_kdf_iter(ctx, atoi(zRight), 2); // change of RW PBKDF2 iteration
130 } else {
131 char *fast_kdf_iter = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_fast_kdf_iter(ctx, 2));
132 codec_vdbe_return_static_string(pParse, "fast_kdf_iter", fast_kdf_iter);
133 sqlite3_free(fast_kdf_iter);
136 }else
137 if( sqlite3StrICmp(zLeft, "rekey_kdf_iter")==0 && zRight ){
138 if(ctx) sqlcipher_codec_ctx_set_kdf_iter(ctx, atoi(zRight), 1); // write iterations only
139 }else
140 if( sqlite3StrICmp(zLeft,"cipher_page_size")==0 ){
141 if(ctx) {
142 if( zRight ) {
143 int size = atoi(zRight);
144 rc = sqlcipher_codec_ctx_set_pagesize(ctx, size);
145 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
146 rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
147 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
148 } else {
149 char * page_size = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_pagesize(ctx));
150 codec_vdbe_return_static_string(pParse, "cipher_page_size", page_size);
151 sqlite3_free(page_size);
154 }else
155 if( sqlite3StrICmp(zLeft,"cipher_default_use_hmac")==0 ){
156 if( zRight ) {
157 sqlcipher_set_default_use_hmac(sqlite3GetBoolean(zRight,1));
158 } else {
159 char *default_use_hmac = sqlite3_mprintf("%d", sqlcipher_get_default_use_hmac());
160 codec_vdbe_return_static_string(pParse, "cipher_default_use_hmac", default_use_hmac);
161 sqlite3_free(default_use_hmac);
163 }else
164 if( sqlite3StrICmp(zLeft,"cipher_use_hmac")==0 ){
165 if(ctx) {
166 if( zRight ) {
167 rc = sqlcipher_codec_ctx_set_use_hmac(ctx, sqlite3GetBoolean(zRight,1));
168 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
169 /* since the use of hmac has changed, the page size may also change */
170 rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
171 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
172 } else {
173 char *hmac_flag = sqlite3_mprintf("%d", sqlcipher_codec_ctx_get_use_hmac(ctx, 2));
174 codec_vdbe_return_static_string(pParse, "cipher_use_hmac", hmac_flag);
175 sqlite3_free(hmac_flag);
178 }else
179 if( sqlite3StrICmp(zLeft,"cipher_hmac_pgno")==0 ){
180 if(ctx) {
181 if(zRight) {
182 // clear both pgno endian flags
183 if(sqlite3StrICmp(zRight, "le") == 0) {
184 sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO);
185 sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_LE_PGNO);
186 } else if(sqlite3StrICmp(zRight, "be") == 0) {
187 sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO);
188 sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_BE_PGNO);
189 } else if(sqlite3StrICmp(zRight, "native") == 0) {
190 sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO);
191 sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO);
193 } else {
194 if(sqlcipher_codec_ctx_get_flag(ctx, CIPHER_FLAG_LE_PGNO, 2)) {
195 codec_vdbe_return_static_string(pParse, "cipher_hmac_pgno", "le");
196 } else if(sqlcipher_codec_ctx_get_flag(ctx, CIPHER_FLAG_BE_PGNO, 2)) {
197 codec_vdbe_return_static_string(pParse, "cipher_hmac_pgno", "be");
198 } else {
199 codec_vdbe_return_static_string(pParse, "cipher_hmac_pgno", "native");
203 }else
204 if( sqlite3StrICmp(zLeft,"cipher_hmac_salt_mask")==0 ){
205 if(ctx) {
206 if(zRight) {
207 if (sqlite3StrNICmp(zRight ,"x'", 2) == 0 && sqlite3Strlen30(zRight) == 5) {
208 unsigned char mask = 0;
209 const char *hex = zRight+2;
210 cipher_hex2bin(hex,2,&mask);
211 sqlcipher_set_hmac_salt_mask(mask);
213 } else {
214 char *hmac_salt_mask = sqlite3_mprintf("%02x", sqlcipher_get_hmac_salt_mask());
215 codec_vdbe_return_static_string(pParse, "cipher_hmac_salt_mask", hmac_salt_mask);
216 sqlite3_free(hmac_salt_mask);
219 }else {
220 return 0;
222 return 1;
226 * sqlite3Codec can be called in multiple modes.
227 * encrypt mode - expected to return a pointer to the
228 * encrypted data without altering pData.
229 * decrypt mode - expected to return a pointer to pData, with
230 * the data decrypted in the input buffer
232 void* sqlite3Codec(void *iCtx, void *data, Pgno pgno, int mode) {
233 codec_ctx *ctx = (codec_ctx *) iCtx;
234 int offset = 0, rc = 0;
235 int page_sz = sqlcipher_codec_ctx_get_pagesize(ctx);
236 unsigned char *pData = (unsigned char *) data;
237 void *buffer = sqlcipher_codec_ctx_get_data(ctx);
238 void *kdf_salt = sqlcipher_codec_ctx_get_kdf_salt(ctx);
239 CODEC_TRACE(("sqlite3Codec: entered pgno=%d, mode=%d, page_sz=%d\n", pgno, mode, page_sz));
241 /* call to derive keys if not present yet */
242 if((rc = sqlcipher_codec_key_derive(ctx)) != SQLITE_OK) {
243 sqlcipher_codec_ctx_set_error(ctx, rc);
244 return NULL;
247 if(pgno == 1) offset = FILE_HEADER_SZ; /* adjust starting pointers in data page for header offset on first page*/
249 CODEC_TRACE(("sqlite3Codec: switch mode=%d offset=%d\n", mode, offset));
250 switch(mode) {
251 case 0: /* decrypt */
252 case 2:
253 case 3:
254 if(pgno == 1) memcpy(buffer, SQLITE_FILE_HEADER, FILE_HEADER_SZ); /* copy file header to the first 16 bytes of the page */
255 rc = sqlcipher_page_cipher(ctx, CIPHER_READ_CTX, pgno, CIPHER_DECRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset);
256 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
257 memcpy(pData, buffer, page_sz); /* copy buffer data back to pData and return */
258 return pData;
259 break;
260 case 6: /* encrypt */
261 if(pgno == 1) memcpy(buffer, kdf_salt, FILE_HEADER_SZ); /* copy salt to output buffer */
262 rc = sqlcipher_page_cipher(ctx, CIPHER_WRITE_CTX, pgno, CIPHER_ENCRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset);
263 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
264 return buffer; /* return persistent buffer data, pData remains intact */
265 break;
266 case 7:
267 if(pgno == 1) memcpy(buffer, kdf_salt, FILE_HEADER_SZ); /* copy salt to output buffer */
268 rc = sqlcipher_page_cipher(ctx, CIPHER_READ_CTX, pgno, CIPHER_ENCRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset);
269 if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
270 return buffer; /* return persistent buffer data, pData remains intact */
271 break;
272 default:
273 return pData;
274 break;
278 void sqlite3FreeCodecArg(void *pCodecArg) {
279 codec_ctx *ctx = (codec_ctx *) pCodecArg;
280 if(pCodecArg == NULL) return;
281 sqlcipher_codec_ctx_free(&ctx); // wipe and free allocated memory for the context
282 sqlcipher_deactivate(); /* cleanup related structures, OpenSSL etc, when codec is detatched */
285 int sqlite3CodecAttach(sqlite3* db, int nDb, const void *zKey, int nKey) {
286 struct Db *pDb = &db->aDb[nDb];
288 CODEC_TRACE(("sqlite3CodecAttach: entered nDb=%d zKey=%s, nKey=%d\n", nDb, (char *)zKey, nKey));
291 if(nKey && zKey && pDb->pBt) {
292 int rc;
293 Pager *pPager = pDb->pBt->pBt->pPager;
294 sqlite3_file *fd = sqlite3Pager_get_fd(pPager);
295 codec_ctx *ctx;
297 sqlcipher_activate(); /* perform internal initialization for sqlcipher */
299 sqlite3_mutex_enter(db->mutex);
301 /* point the internal codec argument against the contet to be prepared */
302 rc = sqlcipher_codec_ctx_init(&ctx, pDb, pDb->pBt->pBt->pPager, fd, zKey, nKey);
304 if(rc != SQLITE_OK) return rc; /* initialization failed, do not attach potentially corrupted context */
306 sqlite3pager_sqlite3PagerSetCodec(sqlite3BtreePager(pDb->pBt), sqlite3Codec, NULL, sqlite3FreeCodecArg, (void *) ctx);
308 codec_set_btree_to_codec_pagesize(db, pDb, ctx);
310 /* force secure delete. This has the benefit of wiping internal data when deleted
311 and also ensures that all pages are written to disk (i.e. not skipped by
312 sqlite3PagerDontWrite optimizations) */
313 sqlite3BtreeSecureDelete(pDb->pBt, 1);
315 /* if fd is null, then this is an in-memory database and
316 we dont' want to overwrite the AutoVacuum settings
317 if not null, then set to the default */
318 if(fd != NULL) {
319 sqlite3BtreeSetAutoVacuum(pDb->pBt, SQLITE_DEFAULT_AUTOVACUUM);
321 sqlite3_mutex_leave(db->mutex);
323 return SQLITE_OK;
326 void sqlite3_activate_see(const char* in) {
327 /* do nothing, security enhancements are always active */
330 int sqlite3_key(sqlite3 *db, const void *pKey, int nKey) {
331 CODEC_TRACE(("sqlite3_key: entered db=%p pKey=%s nKey=%d\n", db, (char *)pKey, nKey));
332 /* attach key if db and pKey are not null and nKey is > 0 */
333 if(db && pKey && nKey) {
334 return sqlite3CodecAttach(db, 0, pKey, nKey); // operate only on the main db
336 return SQLITE_ERROR;
339 /* sqlite3_rekey
340 ** Given a database, this will reencrypt the database using a new key.
341 ** There is only one possible modes of operation - to encrypt a database
342 ** that is already encrpyted. If the database is not already encrypted
343 ** this should do nothing
344 ** The proposed logic for this function follows:
345 ** 1. Determine if the database is already encryptped
346 ** 2. If there is NOT already a key present do nothing
347 ** 3. If there is a key present, re-encrypt the database with the new key
349 int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey) {
350 CODEC_TRACE(("sqlite3_rekey: entered db=%p pKey=%s, nKey=%d\n", db, (char *)pKey, nKey));
351 if(db && pKey && nKey) {
352 struct Db *pDb = &db->aDb[0];
353 CODEC_TRACE(("sqlite3_rekey: database pDb=%p\n", pDb));
354 if(pDb->pBt) {
355 codec_ctx *ctx;
356 int rc, page_count;
357 Pgno pgno;
358 PgHdr *page;
359 Pager *pPager = pDb->pBt->pBt->pPager;
361 sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
363 if(ctx == NULL) {
364 /* there was no codec attached to this database, so this should do nothing! */
365 CODEC_TRACE(("sqlite3_rekey: no codec attached to db, exiting\n"));
366 return SQLITE_OK;
369 sqlite3_mutex_enter(db->mutex);
371 codec_set_pass_key(db, 0, pKey, nKey, CIPHER_WRITE_CTX);
373 /* do stuff here to rewrite the database
374 ** 1. Create a transaction on the database
375 ** 2. Iterate through each page, reading it and then writing it.
376 ** 3. If that goes ok then commit and put ctx->rekey into ctx->key
377 ** note: don't deallocate rekey since it may be used in a subsequent iteration
379 rc = sqlite3BtreeBeginTrans(pDb->pBt, 1); /* begin write transaction */
380 sqlite3PagerPagecount(pPager, &page_count);
381 for(pgno = 1; rc == SQLITE_OK && pgno <= page_count; pgno++) { /* pgno's start at 1 see pager.c:pagerAcquire */
382 if(!sqlite3pager_is_mj_pgno(pPager, pgno)) { /* skip this page (see pager.c:pagerAcquire for reasoning) */
383 rc = sqlite3PagerGet(pPager, pgno, &page);
384 if(rc == SQLITE_OK) { /* write page see pager_incr_changecounter for example */
385 rc = sqlite3PagerWrite(page);
386 if(rc == SQLITE_OK) {
387 sqlite3PagerUnref(page);
388 } else {
389 CODEC_TRACE(("sqlite3_rekey: error %d occurred writing page %d\n", rc, pgno));
391 } else {
392 CODEC_TRACE(("sqlite3_rekey: error %d occurred getting page %d\n", rc, pgno));
397 /* if commit was successful commit and copy the rekey data to current key, else rollback to release locks */
398 if(rc == SQLITE_OK) {
399 CODEC_TRACE(("sqlite3_rekey: committing\n"));
400 rc = sqlite3BtreeCommit(pDb->pBt);
401 sqlcipher_codec_key_copy(ctx, CIPHER_WRITE_CTX);
402 } else {
403 CODEC_TRACE(("sqlite3_rekey: rollback\n"));
404 sqlite3BtreeRollback(pDb->pBt, SQLITE_ABORT_ROLLBACK);
407 sqlite3_mutex_leave(db->mutex);
409 return SQLITE_OK;
411 return SQLITE_ERROR;
414 void sqlite3CodecGetKey(sqlite3* db, int nDb, void **zKey, int *nKey) {
415 struct Db *pDb = &db->aDb[nDb];
416 CODEC_TRACE(("sqlite3CodecGetKey: entered db=%p, nDb=%d\n", db, nDb));
418 if( pDb->pBt ) {
419 codec_ctx *ctx;
420 sqlite3pager_get_codec(pDb->pBt->pBt->pPager, (void **) &ctx);
422 if(ctx) { /* if the codec has an attached codec_context user the raw key data */
423 sqlcipher_codec_get_pass(ctx, zKey, nKey);
424 } else {
425 *zKey = NULL;
426 *nKey = 0;
431 #ifndef OMIT_EXPORT
434 * Implementation of an "export" function that allows a caller
435 * to duplicate the main database to an attached database. This is intended
436 * as a conveneince for users who need to:
438 * 1. migrate from an non-encrypted database to an encrypted database
439 * 2. move from an encrypted database to a non-encrypted database
440 * 3. convert beween the various flavors of encrypted databases.
442 * This implementation is based heavily on the procedure and code used
443 * in vacuum.c, but is exposed as a function that allows export to any
444 * named attached database.
448 ** Finalize a prepared statement. If there was an error, store the
449 ** text of the error message in *pzErrMsg. Return the result code.
451 ** Based on vacuumFinalize from vacuum.c
453 static int sqlcipher_finalize(sqlite3 *db, sqlite3_stmt *pStmt, char **pzErrMsg){
454 int rc;
455 rc = sqlite3VdbeFinalize((Vdbe*)pStmt);
456 if( rc ){
457 sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
459 return rc;
463 ** Execute zSql on database db. Return an error code.
465 ** Based on execSql from vacuum.c
467 static int sqlcipher_execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
468 sqlite3_stmt *pStmt;
469 VVA_ONLY( int rc; )
470 if( !zSql ){
471 return SQLITE_NOMEM;
473 if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
474 sqlite3SetString(pzErrMsg, db, sqlite3_errmsg(db));
475 return sqlite3_errcode(db);
477 VVA_ONLY( rc = ) sqlite3_step(pStmt);
478 assert( rc!=SQLITE_ROW );
479 return sqlcipher_finalize(db, pStmt, pzErrMsg);
483 ** Execute zSql on database db. The statement returns exactly
484 ** one column. Execute this as SQL on the same database.
486 ** Based on execExecSql from vacuum.c
488 static int sqlcipher_execExecSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
489 sqlite3_stmt *pStmt;
490 int rc;
492 rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
493 if( rc!=SQLITE_OK ) return rc;
495 while( SQLITE_ROW==sqlite3_step(pStmt) ){
496 rc = sqlcipher_execSql(db, pzErrMsg, (char*)sqlite3_column_text(pStmt, 0));
497 if( rc!=SQLITE_OK ){
498 sqlcipher_finalize(db, pStmt, pzErrMsg);
499 return rc;
503 return sqlcipher_finalize(db, pStmt, pzErrMsg);
507 * copy database and schema from the main database to an attached database
509 * Based on sqlite3RunVacuum from vacuum.c
511 void sqlcipher_exportFunc(sqlite3_context *context, int argc, sqlite3_value **argv) {
512 sqlite3 *db = sqlite3_context_db_handle(context);
513 const char* attachedDb = (const char*) sqlite3_value_text(argv[0]);
514 int saved_flags; /* Saved value of the db->flags */
515 int saved_nChange; /* Saved value of db->nChange */
516 int saved_nTotalChange; /* Saved value of db->nTotalChange */
517 void (*saved_xTrace)(void*,const char*); /* Saved db->xTrace */
518 int rc = SQLITE_OK; /* Return code from service routines */
519 char *zSql = NULL; /* SQL statements */
520 char *pzErrMsg = NULL;
522 saved_flags = db->flags;
523 saved_nChange = db->nChange;
524 saved_nTotalChange = db->nTotalChange;
525 saved_xTrace = db->xTrace;
526 db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_PreferBuiltin;
527 db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder);
528 db->xTrace = 0;
530 /* Query the schema of the main database. Create a mirror schema
531 ** in the temporary database.
533 zSql = sqlite3_mprintf(
534 "SELECT 'CREATE TABLE %s.' || substr(sql,14) "
535 " FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
536 " AND rootpage>0"
537 , attachedDb);
538 rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
539 if( rc!=SQLITE_OK ) goto end_of_export;
540 sqlite3_free(zSql);
542 zSql = sqlite3_mprintf(
543 "SELECT 'CREATE INDEX %s.' || substr(sql,14)"
544 " FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %%' "
545 , attachedDb);
546 rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
547 if( rc!=SQLITE_OK ) goto end_of_export;
548 sqlite3_free(zSql);
550 zSql = sqlite3_mprintf(
551 "SELECT 'CREATE UNIQUE INDEX %s.' || substr(sql,21) "
552 " FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %%'"
553 , attachedDb);
554 rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
555 if( rc!=SQLITE_OK ) goto end_of_export;
556 sqlite3_free(zSql);
558 /* Loop through the tables in the main database. For each, do
559 ** an "INSERT INTO rekey_db.xxx SELECT * FROM main.xxx;" to copy
560 ** the contents to the temporary database.
562 zSql = sqlite3_mprintf(
563 "SELECT 'INSERT INTO %s.' || quote(name) "
564 "|| ' SELECT * FROM main.' || quote(name) || ';'"
565 "FROM main.sqlite_master "
566 "WHERE type = 'table' AND name!='sqlite_sequence' "
567 " AND rootpage>0"
568 , attachedDb);
569 rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
570 if( rc!=SQLITE_OK ) goto end_of_export;
571 sqlite3_free(zSql);
573 /* Copy over the sequence table
575 zSql = sqlite3_mprintf(
576 "SELECT 'DELETE FROM %s.' || quote(name) || ';' "
577 "FROM %s.sqlite_master WHERE name='sqlite_sequence' "
578 , attachedDb, attachedDb);
579 rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
580 if( rc!=SQLITE_OK ) goto end_of_export;
581 sqlite3_free(zSql);
583 zSql = sqlite3_mprintf(
584 "SELECT 'INSERT INTO %s.' || quote(name) "
585 "|| ' SELECT * FROM main.' || quote(name) || ';' "
586 "FROM %s.sqlite_master WHERE name=='sqlite_sequence';"
587 , attachedDb, attachedDb);
588 rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execExecSql(db, &pzErrMsg, zSql);
589 if( rc!=SQLITE_OK ) goto end_of_export;
590 sqlite3_free(zSql);
592 /* Copy the triggers, views, and virtual tables from the main database
593 ** over to the temporary database. None of these objects has any
594 ** associated storage, so all we have to do is copy their entries
595 ** from the SQLITE_MASTER table.
597 zSql = sqlite3_mprintf(
598 "INSERT INTO %s.sqlite_master "
599 " SELECT type, name, tbl_name, rootpage, sql"
600 " FROM main.sqlite_master"
601 " WHERE type='view' OR type='trigger'"
602 " OR (type='table' AND rootpage=0)"
603 , attachedDb);
604 rc = (zSql == NULL) ? SQLITE_NOMEM : sqlcipher_execSql(db, &pzErrMsg, zSql);
605 if( rc!=SQLITE_OK ) goto end_of_export;
606 sqlite3_free(zSql);
608 zSql = NULL;
609 end_of_export:
610 db->flags = saved_flags;
611 db->nChange = saved_nChange;
612 db->nTotalChange = saved_nTotalChange;
613 db->xTrace = saved_xTrace;
615 sqlite3_free(zSql);
617 if(rc) {
618 if(pzErrMsg != NULL) {
619 sqlite3_result_error(context, pzErrMsg, -1);
620 sqlite3DbFree(db, pzErrMsg);
621 } else {
622 sqlite3_result_error(context, sqlite3ErrStr(rc), -1);
627 #endif
629 /* END CRYPTO */
630 #endif