/* * sqlite3Codec can be called in multiple modes. * encrypt mode - expected to return a pointer to the * encrypted data without altering pData. * decrypt mode - expected to return a pointer to pData, with * the data decrypted in the input buffer */ void* sqlite3Codec(void *iCtx, void *data, Pgno pgno, int mode) { codec_ctx *ctx = (codec_ctx *) iCtx; int pg_sz = SQLITE_DEFAULT_PAGE_SIZE; int offset = 0; unsigned char *pData = (unsigned char *) data; CODEC_TRACE(("sqlite3Codec: entered pgno=%d, mode=%d, ctx->mode_rekey=%d, pg_sz=%d\n", pgno, mode, ctx->mode_rekey, pg_sz)); /* derive key on first use if necessary */ if(ctx->read_ctx->derive_key) { codec_key_derive(ctx, ctx->read_ctx); ctx->read_ctx->derive_key = 0; } if(ctx->write_ctx->derive_key) { if(cipher_ctx_cmp(ctx->write_ctx, ctx->read_ctx) == 0) { cipher_ctx_copy(ctx->write_ctx, ctx->read_ctx); // the relevant parameters are the same, just copy read key } else { codec_key_derive(ctx, ctx->write_ctx); ctx->write_ctx->derive_key = 0; } } if(pgno == 1) offset = FILE_HEADER_SZ; /* adjust starting pointers in data page for header offset on first page*/ CODEC_TRACE(("sqlite3Codec: switch mode=%d offset=%d\n", mode, offset)); switch(mode) { case 0: /* decrypt */ case 2: case 3: if(pgno == 1) memcpy(ctx->buffer, SQLITE_FILE_HEADER, FILE_HEADER_SZ); /* copy file header to the first 16 bytes of the page */ codec_cipher(ctx->read_ctx, pgno, CIPHER_DECRYPT, pg_sz - offset, pData + offset, ctx->buffer + offset); memcpy(pData, ctx->buffer, pg_sz); /* copy buffer data back to pData and return */ return pData; break; case 6: /* encrypt */ if(pgno == 1) memcpy(ctx->buffer, ctx->kdf_salt, FILE_HEADER_SZ); /* copy salt to output buffer */ codec_cipher(ctx->write_ctx, pgno, CIPHER_ENCRYPT, pg_sz - offset, pData + offset, ctx->buffer + offset); return ctx->buffer; /* return persistent buffer data, pData remains intact */ break; case 7: if(pgno == 1) memcpy(ctx->buffer, ctx->kdf_salt, FILE_HEADER_SZ); /* copy salt to output buffer */ codec_cipher(ctx->read_ctx, pgno, CIPHER_ENCRYPT, pg_sz - offset, pData + offset, ctx->buffer + offset); return ctx->buffer; /* return persistent buffer data, pData remains intact */ break; default: return pData; break; } }
/* * sqlite3Codec can be called in multiple modes. * encrypt mode - expected to return a pointer to the * encrypted data without altering pData. * decrypt mode - expected to return a pointer to pData, with * the data decrypted in the input buffer */ void* sqlite3Codec(void *iCtx, void *pData, Pgno pgno, int mode) { int emode; codec_ctx *ctx = (codec_ctx *) iCtx; int pg_sz = sqlite3BtreeGetPageSize(ctx->pBt); switch(mode) { case 0: /* decrypt */ case 2: case 3: emode = CIPHER_DECRYPT; break; case 6: /* encrypt */ case 7: emode = CIPHER_ENCRYPT; break; default: return pData; break; } if(pgno == 1) { /* if this is a read & decrypt operation on the first page then copy the first 16 bytes off the page into the context's random salt buffer */ if(emode == CIPHER_ENCRYPT) { memcpy(ctx->buffer, ctx->salt, FILE_HEADER_SZ); } else { memcpy(ctx->buffer, SQLITE_FILE_HEADER, FILE_HEADER_SZ); } /* adjust starting pointers in data page for header offset */ codec_cipher(ctx, pgno, emode, pg_sz - FILE_HEADER_SZ, pData + FILE_HEADER_SZ, ctx->buffer + FILE_HEADER_SZ); } else { codec_cipher(ctx, pgno, emode, pg_sz, pData, ctx->buffer); } if(emode == CIPHER_ENCRYPT) { return ctx->buffer; /* return persistent buffer data, pData remains intact */ } else { memcpy(pData, ctx->buffer, pg_sz); /* copy buffer data back to pData and return */ return pData; } }