pragma allows le, be, or native pgno ordering plus tests
This commit is contained in:
parent
7f2b44c8e2
commit
f1ea44e3ef
Binary file not shown.
13
src/crypto.c
13
src/crypto.c
|
@ -129,6 +129,19 @@ int codec_pragma(sqlite3* db, int iDb, Parse *pParse, const char *zLeft, const c
|
|||
rc = codec_set_btree_to_codec_pagesize(db, pDb, ctx);
|
||||
if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
|
||||
}
|
||||
}else
|
||||
if( sqlite3StrICmp(zLeft,"cipher_hmac_pgno")==0 ){
|
||||
// clear both pgno endian flags
|
||||
if(sqlite3StrICmp(zRight, "le") == 0) {
|
||||
sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO);
|
||||
sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_LE_PGNO);
|
||||
} else if(sqlite3StrICmp(zRight, "be") == 0) {
|
||||
sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO);
|
||||
sqlcipher_codec_ctx_set_flag(ctx, CIPHER_FLAG_BE_PGNO);
|
||||
} else if(sqlite3StrICmp(zRight, "native") == 0) {
|
||||
sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_LE_PGNO);
|
||||
sqlcipher_codec_ctx_unset_flag(ctx, CIPHER_FLAG_BE_PGNO);
|
||||
}
|
||||
}else {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
/* possible flags for cipher_ctx->flags */
|
||||
#define CIPHER_FLAG_HMAC 0x01
|
||||
#define CIPHER_FLAG_LE_PGNO 0x02
|
||||
#define CIPHER_FLAG_BE_PGNO 0x04
|
||||
|
||||
#ifndef DEFAULT_CIPHER_FLAGS
|
||||
#define DEFAULT_CIPHER_FLAGS CIPHER_FLAG_HMAC | CIPHER_FLAG_LE_PGNO
|
||||
|
|
|
@ -497,6 +497,7 @@ void sqlcipher_codec_ctx_free(codec_ctx **iCtx) {
|
|||
sqlcipher_free(ctx, sizeof(codec_ctx));
|
||||
}
|
||||
|
||||
/** convert a 32bit unsigned integer to little endian byte ordering */
|
||||
static inline void sqlcipher_put4byte_le(unsigned char *p, u32 v) {
|
||||
p[0] = (u8)v;
|
||||
p[1] = (u8)(v>>8);
|
||||
|
@ -505,29 +506,31 @@ static inline void sqlcipher_put4byte_le(unsigned char *p, u32 v) {
|
|||
}
|
||||
|
||||
int sqlcipher_page_hmac(cipher_ctx *ctx, Pgno pgno, unsigned char *in, int in_sz, unsigned char *out) {
|
||||
unsigned char pgno_le[4];
|
||||
/* convert page number to consistent representation before calculating MAC for
|
||||
unsigned char pgno_raw[sizeof(pgno)];
|
||||
/* we may convert page number to consistent representation before calculating MAC for
|
||||
compatibility across big-endian and little-endian platforms.
|
||||
|
||||
Note: The public release of sqlcipher 2.0.0 to 2.0.6 had a bug where the bytes of pgno
|
||||
were used directly in the MAC. So, we convert to little endian instead of big endian, to
|
||||
preserve backwards compatibility on the most popular platform */
|
||||
sqlcipher_put4byte_le(pgno_le, pgno);
|
||||
were used directly in the MAC. SQLCipher convert's to little endian by default to preserve
|
||||
backwards compatibility on the most popular platforms, but can optionally be configured
|
||||
to use either big endian or native byte ordering via pragma. */
|
||||
|
||||
if(ctx->flags & CIPHER_FLAG_LE_PGNO) { /* compute hmac using little endian pgno*/
|
||||
sqlcipher_put4byte_le(pgno_raw, pgno);
|
||||
} else if(ctx->flags & CIPHER_FLAG_BE_PGNO) { /* compute hmac using big endian pgno */
|
||||
sqlite3Put4byte(pgno_raw, pgno); /* sqlite3Put4byte converts 32bit uint to big endian */
|
||||
} else { /* use native byte ordering */
|
||||
memcpy(pgno_raw, &pgno, sizeof(pgno));
|
||||
}
|
||||
|
||||
HMAC_CTX_init(&ctx->hctx);
|
||||
|
||||
HMAC_Init_ex(&ctx->hctx, ctx->hmac_key, ctx->key_sz, EVP_sha1(), NULL);
|
||||
|
||||
/* include the encrypted page data, initialization vector, and page number in HMAC. This will
|
||||
prevent both tampering with the ciphertext, manipulation of the IV, or resequencing otherwise
|
||||
valid pages out of order in a database */
|
||||
HMAC_Update(&ctx->hctx, in, in_sz);
|
||||
|
||||
if(ctx->flags & CIPHER_FLAG_LE_PGNO) /* default compute hmac using little endian */
|
||||
HMAC_Update(&ctx->hctx, (const unsigned char*) pgno_le, sizeof(pgno_le));
|
||||
else /* legacy setting - compute using native byte ordering */
|
||||
HMAC_Update(&ctx->hctx, (const unsigned char*) &pgno, sizeof(pgno));
|
||||
|
||||
HMAC_Update(&ctx->hctx, (const unsigned char*) pgno_raw, sizeof(pgno));
|
||||
HMAC_Final(&ctx->hctx, out, NULL);
|
||||
HMAC_CTX_cleanup(&ctx->hctx);
|
||||
return SQLITE_OK;
|
||||
|
|
|
@ -1556,9 +1556,10 @@ do_test multipage-schema-autovacuum-shortread-wal {
|
|||
db close
|
||||
file delete -force test.db
|
||||
|
||||
# open a 2.0 database verify it can be opened
|
||||
do_test open-2.0-database {
|
||||
sqlite_orig db sqlcipher-2.0-testkey.db
|
||||
# open a 2.0 database with little endian hmac page numbers (default)
|
||||
# verify it can be opened
|
||||
do_test open-2.0-le-database {
|
||||
sqlite_orig db sqlcipher-2.0-le-testkey.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
SELECT count(*) FROM t1;
|
||||
|
@ -1567,4 +1568,44 @@ do_test open-2.0-database {
|
|||
} {4 1 1 one one 1 2 one two}
|
||||
db close
|
||||
|
||||
# open a 2.0 database with big-endian hmac page numbers
|
||||
# verify it can be opened
|
||||
do_test open-2.0-be-database {
|
||||
sqlite_orig db sqlcipher-2.0-be-testkey.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
PRAGMA cipher_hmac_pgno = be;
|
||||
SELECT count(*) FROM t1;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {4 1 1 one one 1 2 one two}
|
||||
db close
|
||||
|
||||
# open a 2.0 database with big-endian hmac page numbers
|
||||
# attach a new database with little endian page numbers (default)
|
||||
# copy schema between the two, and verify the latter
|
||||
# can be opened
|
||||
do_test be-to-le-migration {
|
||||
sqlite_orig db sqlcipher-2.0-be-testkey.db
|
||||
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
PRAGMA cipher_hmac_pgno = be;
|
||||
ATTACH DATABASE 'test.db' AS db2 KEY 'testkey';
|
||||
CREATE TABLE db2.t1(a,b);
|
||||
INSERT INTO db2.t1 SELECT * FROM main.t1;
|
||||
DETACH DATABASE db2;
|
||||
}
|
||||
db close
|
||||
|
||||
sqlite_orig db test.db
|
||||
execsql {
|
||||
PRAGMA key = 'testkey';
|
||||
SELECT count(*) FROM t1;
|
||||
SELECT * FROM t1;
|
||||
}
|
||||
} {4 1 1 one one 1 2 one two}
|
||||
db close
|
||||
file delete -force test.db
|
||||
|
||||
finish_test
|
||||
|
|
Loading…
Reference in New Issue