support for delphi 11.1
This commit is contained in:
666
contrib/mORMot/SQLite3/amalgamation/ciphers/cipher_common.c
Normal file
666
contrib/mORMot/SQLite3/amalgamation/ciphers/cipher_common.c
Normal file
@@ -0,0 +1,666 @@
|
||||
/*
|
||||
** Name: cipher_common.c
|
||||
** Purpose: Implementation of SQLite codecs
|
||||
** Author: Ulrich Telle
|
||||
** Created: 2020-02-02
|
||||
** Copyright: (c) 2006-2020 Ulrich Telle
|
||||
** License: MIT
|
||||
*/
|
||||
|
||||
#include "cipher_common.h"
|
||||
|
||||
static unsigned char padding[] =
|
||||
"\x28\xBF\x4E\x5E\x4E\x75\x8A\x41\x64\x00\x4E\x56\xFF\xFA\x01\x08\x2E\x2E\x00\xB6\xD0\x68\x3E\x80\x2F\x0C\xA9\xFE\x64\x53\x69\x7A";
|
||||
|
||||
/* --- Codec Descriptor Table --- */
|
||||
|
||||
/*
|
||||
** Common configuration parameters
|
||||
**
|
||||
** - cipher : default cipher type
|
||||
** - hmac_check : flag whether page hmac should be verified on read
|
||||
*/
|
||||
|
||||
static CipherParams commonParams[] =
|
||||
{
|
||||
{ "cipher", CODEC_TYPE, CODEC_TYPE, 1, CODEC_TYPE_MAX },
|
||||
{ "hmac_check", 1, 1, 0, 1 },
|
||||
CIPHER_PARAMS_SENTINEL
|
||||
};
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetCipherParameter(CipherParams* cipherParams, const char* paramName)
|
||||
{
|
||||
int value = -1;
|
||||
for (; strlen(cipherParams->m_name) > 0; ++cipherParams)
|
||||
{
|
||||
if (sqlite3_stricmp(paramName, cipherParams->m_name) == 0) break;
|
||||
}
|
||||
if (strlen(cipherParams->m_name) > 0)
|
||||
{
|
||||
value = cipherParams->m_value;
|
||||
cipherParams->m_value = cipherParams->m_default;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static CodecParameter globalCodecParameterTable[] =
|
||||
{
|
||||
{ "global", CODEC_TYPE_UNKNOWN, commonParams },
|
||||
#if HAVE_CIPHER_AES_128_CBC
|
||||
{ "aes128cbc", CODEC_TYPE_AES128, mcAES128Params },
|
||||
#endif
|
||||
#if HAVE_CIPHER_AES_256_CBC
|
||||
{ "aes256cbc", CODEC_TYPE_AES256, mcAES256Params },
|
||||
#endif
|
||||
#if HAVE_CIPHER_CHACHA20
|
||||
{ "chacha20", CODEC_TYPE_CHACHA20, mcChaCha20Params },
|
||||
#endif
|
||||
#if HAVE_CIPHER_SQLCIPHER
|
||||
{ "sqlcipher", CODEC_TYPE_SQLCIPHER, mcSQLCipherParams },
|
||||
#endif
|
||||
#if HAVE_CIPHER_RC4
|
||||
{ "rc4", CODEC_TYPE_RC4, mcRC4Params },
|
||||
#endif
|
||||
{ "", CODEC_TYPE_UNKNOWN, NULL }
|
||||
};
|
||||
|
||||
#define CODEC_TYPE_UNKNOWN 0
|
||||
#define CODEC_TYPE_AES128 1
|
||||
#define CODEC_TYPE_AES256 2
|
||||
#define CODEC_TYPE_CHACHA20 3
|
||||
#define CODEC_TYPE_SQLCIPHER 4
|
||||
#define CODEC_TYPE_RC4 5
|
||||
|
||||
SQLITE_PRIVATE CodecParameter*
|
||||
sqlite3mcCloneCodecParameterTable()
|
||||
{
|
||||
/* Count number of codecs and cipher parameters */
|
||||
int nTables = 0;
|
||||
int nParams = 0;
|
||||
int j, k, n;
|
||||
CipherParams* cloneCipherParams;
|
||||
CodecParameter* cloneCodecParams;
|
||||
|
||||
for (j = 0; strlen(globalCodecParameterTable[j].m_name) > 0; ++j)
|
||||
{
|
||||
CipherParams* params = globalCodecParameterTable[j].m_params;
|
||||
for (k = 0; strlen(params[k].m_name) > 0; ++k);
|
||||
nParams += k;
|
||||
}
|
||||
nTables = j;
|
||||
|
||||
/* Allocate memory for cloned codec parameter tables (including sentinel for each table) */
|
||||
cloneCipherParams = (CipherParams*) sqlite3_malloc((nParams + nTables) * sizeof(CipherParams));
|
||||
cloneCodecParams = (CodecParameter*) sqlite3_malloc((nTables + 1) * sizeof(CodecParameter));
|
||||
|
||||
/* Create copy of tables */
|
||||
if (cloneCodecParams != NULL)
|
||||
{
|
||||
int offset = 0;
|
||||
for (j = 0; j < nTables; ++j)
|
||||
{
|
||||
CipherParams* params = globalCodecParameterTable[j].m_params;
|
||||
cloneCodecParams[j].m_name = globalCodecParameterTable[j].m_name;
|
||||
cloneCodecParams[j].m_params = &cloneCipherParams[offset];
|
||||
for (n = 0; strlen(params[n].m_name) > 0; ++n);
|
||||
/* Copy all parameters of the current table (including sentinel) */
|
||||
for (k = 0; k <= n; ++k)
|
||||
{
|
||||
cloneCipherParams[offset + k].m_name = params[k].m_name;
|
||||
cloneCipherParams[offset + k].m_value = params[k].m_value;
|
||||
cloneCipherParams[offset + k].m_default = params[k].m_default;
|
||||
cloneCipherParams[offset + k].m_minValue = params[k].m_minValue;
|
||||
cloneCipherParams[offset + k].m_maxValue = params[k].m_maxValue;
|
||||
}
|
||||
offset += (n + 1);
|
||||
}
|
||||
cloneCodecParams[nTables].m_name = globalCodecParameterTable[nTables].m_name;
|
||||
cloneCodecParams[nTables].m_params = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
sqlite3_free(cloneCipherParams);
|
||||
}
|
||||
return cloneCodecParams;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcFreeCodecParameterTable(CodecParameter* codecParams)
|
||||
{
|
||||
sqlite3_free(codecParams[0].m_params);
|
||||
sqlite3_free(codecParams);
|
||||
}
|
||||
|
||||
static const CipherDescriptor mcSentinelDescriptor =
|
||||
{
|
||||
"", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
static const CipherDescriptor mcDummyDescriptor =
|
||||
{
|
||||
"@dummy@", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
};
|
||||
|
||||
static const CipherDescriptor* codecDescriptorTable[] =
|
||||
{
|
||||
#if HAVE_CIPHER_AES_128_CBC
|
||||
&mcAES128Descriptor,
|
||||
#else
|
||||
&mcDummyDescriptor,
|
||||
#endif
|
||||
#if HAVE_CIPHER_AES_256_CBC
|
||||
&mcAES256Descriptor,
|
||||
#else
|
||||
&mcDummyDescriptor,
|
||||
#endif
|
||||
#if HAVE_CIPHER_CHACHA20
|
||||
&mcChaCha20Descriptor,
|
||||
#else
|
||||
&mcDummyDescriptor,
|
||||
#endif
|
||||
#if HAVE_CIPHER_SQLCIPHER
|
||||
&mcSQLCipherDescriptor,
|
||||
#else
|
||||
&mcDummyDescriptor,
|
||||
#endif
|
||||
#if HAVE_CIPHER_RC4
|
||||
&mcRC4Descriptor,
|
||||
#else
|
||||
&mcDummyDescriptor,
|
||||
#endif
|
||||
&mcSentinelDescriptor
|
||||
};
|
||||
|
||||
/* --- Codec --- */
|
||||
|
||||
SQLITE_PRIVATE CodecParameter*
|
||||
sqlite3mcGetCodecParams(sqlite3* db);
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetCipherType(sqlite3* db)
|
||||
{
|
||||
CodecParameter* codecParams = (db != NULL) ? sqlite3mcGetCodecParams(db) : globalCodecParameterTable;
|
||||
CipherParams* cipherParamTable = (codecParams != NULL) ? codecParams[0].m_params : commonParams;
|
||||
int cipherType = CODEC_TYPE;
|
||||
CipherParams* cipher = cipherParamTable;
|
||||
for (; strlen(cipher->m_name) > 0; ++cipher)
|
||||
{
|
||||
if (sqlite3_stricmp("cipher", cipher->m_name) == 0) break;
|
||||
}
|
||||
if (strlen(cipher->m_name) > 0)
|
||||
{
|
||||
cipherType = cipher->m_value;
|
||||
cipher->m_value = cipher->m_default;
|
||||
}
|
||||
return cipherType;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE CipherParams*
|
||||
sqlite3mcGetCipherParams(sqlite3* db, int cypherType)
|
||||
{
|
||||
CodecParameter* codecParams = (db != NULL) ? sqlite3mcGetCodecParams(db) : globalCodecParameterTable;
|
||||
CipherParams* cipherParamTable = (codecParams != NULL) ? codecParams[cypherType].m_params : globalCodecParameterTable[cypherType].m_params;
|
||||
return cipherParamTable;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcCodecInit(Codec* codec)
|
||||
{
|
||||
int rc = SQLITE_OK;
|
||||
if (codec != NULL)
|
||||
{
|
||||
codec->m_isEncrypted = 0;
|
||||
codec->m_hmacCheck = 1;
|
||||
|
||||
codec->m_hasReadCipher = 0;
|
||||
codec->m_readCipherType = CODEC_TYPE_UNKNOWN;
|
||||
codec->m_readCipher = NULL;
|
||||
codec->m_readReserved = -1;
|
||||
|
||||
codec->m_hasWriteCipher = 0;
|
||||
codec->m_writeCipherType = CODEC_TYPE_UNKNOWN;
|
||||
codec->m_writeCipher = NULL;
|
||||
codec->m_writeReserved = -1;
|
||||
|
||||
codec->m_db = NULL;
|
||||
codec->m_bt = NULL;
|
||||
codec->m_btShared = NULL;
|
||||
memset(codec->m_page, 0, sizeof(codec->m_page));
|
||||
codec->m_pageSize = 0;
|
||||
codec->m_reserved = 0;
|
||||
codec->m_hasKeySalt = 0;
|
||||
memset(codec->m_keySalt, 0, sizeof(codec->m_keySalt));
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcCodecTerm(Codec* codec)
|
||||
{
|
||||
if (codec->m_readCipher != NULL)
|
||||
{
|
||||
codecDescriptorTable[codec->m_readCipherType - 1]->m_freeCipher(codec->m_readCipher);
|
||||
codec->m_readCipher = NULL;
|
||||
}
|
||||
if (codec->m_writeCipher != NULL)
|
||||
{
|
||||
codecDescriptorTable[codec->m_writeCipherType - 1]->m_freeCipher(codec->m_writeCipher);
|
||||
codec->m_writeCipher = NULL;
|
||||
}
|
||||
memset(codec, 0, sizeof(Codec));
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcClearKeySalt(Codec* codec)
|
||||
{
|
||||
codec->m_hasKeySalt = 0;
|
||||
memset(codec->m_keySalt, 0, sizeof(codec->m_keySalt));
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcCodecSetup(Codec* codec, int cipherType, char* userPassword, int passwordLength)
|
||||
{
|
||||
int rc = SQLITE_OK;
|
||||
CipherParams* globalParams = sqlite3mcGetCipherParams(codec->m_db, 0);
|
||||
codec->m_isEncrypted = 1;
|
||||
codec->m_hmacCheck = sqlite3mcGetCipherParameter(globalParams, "hmac_check");
|
||||
codec->m_hasReadCipher = 1;
|
||||
codec->m_hasWriteCipher = 1;
|
||||
codec->m_readCipherType = cipherType;
|
||||
codec->m_readCipher = codecDescriptorTable[codec->m_readCipherType-1]->m_allocateCipher(codec->m_db);
|
||||
if (codec->m_readCipher != NULL)
|
||||
{
|
||||
unsigned char* keySalt = (codec->m_hasKeySalt != 0) ? codec->m_keySalt : NULL;
|
||||
sqlite3mcGenerateReadKey(codec, userPassword, passwordLength, keySalt);
|
||||
rc = sqlite3mcCopyCipher(codec, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcSetupWriteCipher(Codec* codec, int cipherType, char* userPassword, int passwordLength)
|
||||
{
|
||||
int rc = SQLITE_OK;
|
||||
CipherParams* globalParams = sqlite3mcGetCipherParams(codec->m_db, 0);
|
||||
if (codec->m_writeCipher != NULL)
|
||||
{
|
||||
codecDescriptorTable[codec->m_writeCipherType-1]->m_freeCipher(codec->m_writeCipher);
|
||||
}
|
||||
codec->m_isEncrypted = 1;
|
||||
codec->m_hmacCheck = sqlite3mcGetCipherParameter(globalParams, "hmac_check");
|
||||
codec->m_hasWriteCipher = 1;
|
||||
codec->m_writeCipherType = cipherType;
|
||||
codec->m_writeCipher = codecDescriptorTable[codec->m_writeCipherType-1]->m_allocateCipher(codec->m_db);
|
||||
if (codec->m_writeCipher != NULL)
|
||||
{
|
||||
unsigned char* keySalt = (codec->m_hasKeySalt != 0) ? codec->m_keySalt : NULL;
|
||||
sqlite3mcGenerateWriteKey(codec, userPassword, passwordLength, keySalt);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetIsEncrypted(Codec* codec, int isEncrypted)
|
||||
{
|
||||
codec->m_isEncrypted = isEncrypted;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetReadCipherType(Codec* codec, int cipherType)
|
||||
{
|
||||
codec->m_readCipherType = cipherType;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetWriteCipherType(Codec* codec, int cipherType)
|
||||
{
|
||||
codec->m_writeCipherType = cipherType;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetHasReadCipher(Codec* codec, int hasReadCipher)
|
||||
{
|
||||
codec->m_hasReadCipher = hasReadCipher;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetHasWriteCipher(Codec* codec, int hasWriteCipher)
|
||||
{
|
||||
codec->m_hasWriteCipher = hasWriteCipher;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetDb(Codec* codec, sqlite3* db)
|
||||
{
|
||||
codec->m_db = db;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetBtree(Codec* codec, Btree* bt)
|
||||
{
|
||||
codec->m_bt = bt;
|
||||
codec->m_btShared = bt->pBt;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetReadReserved(Codec* codec, int reserved)
|
||||
{
|
||||
codec->m_readReserved = reserved;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcSetWriteReserved(Codec* codec, int reserved)
|
||||
{
|
||||
codec->m_writeReserved = reserved;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcIsEncrypted(Codec* codec)
|
||||
{
|
||||
return codec->m_isEncrypted;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcHasReadCipher(Codec* codec)
|
||||
{
|
||||
return codec->m_hasReadCipher;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcHasWriteCipher(Codec* codec)
|
||||
{
|
||||
return codec->m_hasWriteCipher;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE Btree*
|
||||
sqlite3mcGetBtree(Codec* codec)
|
||||
{
|
||||
return codec->m_bt;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE BtShared*
|
||||
sqlite3mcGetBtShared(Codec* codec)
|
||||
{
|
||||
return codec->m_btShared;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetPageSize(Codec* codec)
|
||||
{
|
||||
return codec->m_btShared->pageSize;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetReadReserved(Codec* codec)
|
||||
{
|
||||
return codec->m_readReserved;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetWriteReserved(Codec* codec)
|
||||
{
|
||||
return codec->m_writeReserved;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE unsigned char*
|
||||
sqlite3mcGetPageBuffer(Codec* codec)
|
||||
{
|
||||
return &codec->m_page[4];
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetLegacyReadCipher(Codec* codec)
|
||||
{
|
||||
int legacy = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? codecDescriptorTable[codec->m_readCipherType - 1]->m_getLegacy(codec->m_readCipher) : 0;
|
||||
return legacy;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetLegacyWriteCipher(Codec* codec)
|
||||
{
|
||||
int legacy = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType - 1]->m_getLegacy(codec->m_writeCipher) : -1;
|
||||
return legacy;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetPageSizeReadCipher(Codec* codec)
|
||||
{
|
||||
int pageSize = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? codecDescriptorTable[codec->m_readCipherType - 1]->m_getPageSize(codec->m_readCipher) : 0;
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetPageSizeWriteCipher(Codec* codec)
|
||||
{
|
||||
int pageSize = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType - 1]->m_getPageSize(codec->m_writeCipher) : -1;
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetReservedReadCipher(Codec* codec)
|
||||
{
|
||||
int reserved = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? codecDescriptorTable[codec->m_readCipherType-1]->m_getReserved(codec->m_readCipher) : -1;
|
||||
return reserved;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcGetReservedWriteCipher(Codec* codec)
|
||||
{
|
||||
int reserved = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType-1]->m_getReserved(codec->m_writeCipher) : -1;
|
||||
return reserved;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcReservedEqual(Codec* codec)
|
||||
{
|
||||
int readReserved = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? codecDescriptorTable[codec->m_readCipherType-1]->m_getReserved(codec->m_readCipher) : -1;
|
||||
int writeReserved = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType-1]->m_getReserved(codec->m_writeCipher) : -1;
|
||||
return (readReserved == writeReserved);
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE unsigned char*
|
||||
sqlite3mcGetSaltWriteCipher(Codec* codec)
|
||||
{
|
||||
unsigned char* salt = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType - 1]->m_getSalt(codec->m_writeCipher) : NULL;
|
||||
return salt;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcCodecCopy(Codec* codec, Codec* other)
|
||||
{
|
||||
int rc = SQLITE_OK;
|
||||
codec->m_isEncrypted = other->m_isEncrypted;
|
||||
codec->m_hmacCheck = other->m_hmacCheck;
|
||||
codec->m_hasReadCipher = other->m_hasReadCipher;
|
||||
codec->m_hasWriteCipher = other->m_hasWriteCipher;
|
||||
codec->m_readCipherType = other->m_readCipherType;
|
||||
codec->m_writeCipherType = other->m_writeCipherType;
|
||||
codec->m_readCipher = NULL;
|
||||
codec->m_writeCipher = NULL;
|
||||
codec->m_readReserved = other->m_readReserved;
|
||||
codec->m_writeReserved = other->m_writeReserved;
|
||||
|
||||
if (codec->m_hasReadCipher)
|
||||
{
|
||||
codec->m_readCipher = codecDescriptorTable[codec->m_readCipherType - 1]->m_allocateCipher(codec->m_db);
|
||||
if (codec->m_readCipher != NULL)
|
||||
{
|
||||
codecDescriptorTable[codec->m_readCipherType - 1]->m_cloneCipher(codec->m_readCipher, other->m_readCipher);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if (codec->m_hasWriteCipher)
|
||||
{
|
||||
codec->m_writeCipher = codecDescriptorTable[codec->m_writeCipherType - 1]->m_allocateCipher(codec->m_db);
|
||||
if (codec->m_writeCipher != NULL)
|
||||
{
|
||||
codecDescriptorTable[codec->m_writeCipherType - 1]->m_cloneCipher(codec->m_writeCipher, other->m_writeCipher);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
codec->m_db = other->m_db;
|
||||
codec->m_bt = other->m_bt;
|
||||
codec->m_btShared = other->m_btShared;
|
||||
return rc;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcCodecCompare(Codec* codec1, Codec* codec2)
|
||||
{
|
||||
int equal = 0;
|
||||
if (codec1->m_hasReadCipher == codec2->m_hasReadCipher &&
|
||||
codec1->m_hasWriteCipher == codec2->m_hasWriteCipher)
|
||||
{
|
||||
int eqRead = (codec1->m_hasReadCipher) ? codec1->m_readCipherType == codec2->m_readCipherType : 1;
|
||||
int eqWrite = (codec1->m_hasWriteCipher) ? codec1->m_writeCipherType == codec2->m_writeCipherType : 1;
|
||||
if (eqRead && eqWrite)
|
||||
{
|
||||
eqRead = (codec1->m_hasReadCipher) ? codecDescriptorTable[codec1->m_readCipherType - 1]->m_compareCipher(codec1->m_readCipher, codec2->m_readCipher) : 1;
|
||||
eqWrite = (codec1->m_hasWriteCipher) ? codecDescriptorTable[codec1->m_writeCipherType - 1]->m_compareCipher(codec1->m_writeCipher, codec2->m_writeCipher) : 1;
|
||||
equal = eqRead && eqWrite;
|
||||
}
|
||||
}
|
||||
return equal;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcCopyCipher(Codec* codec, int read2write)
|
||||
{
|
||||
int rc = SQLITE_OK;
|
||||
if (read2write)
|
||||
{
|
||||
if (codec->m_writeCipher != NULL && codec->m_writeCipherType != codec->m_readCipherType)
|
||||
{
|
||||
codecDescriptorTable[codec->m_writeCipherType-1]->m_freeCipher(codec->m_writeCipher);
|
||||
codec->m_writeCipher = NULL;
|
||||
}
|
||||
if (codec->m_writeCipher == NULL)
|
||||
{
|
||||
codec->m_writeCipherType = codec->m_readCipherType;
|
||||
codec->m_writeCipher = codecDescriptorTable[codec->m_writeCipherType-1]->m_allocateCipher(codec->m_db);
|
||||
}
|
||||
if (codec->m_writeCipher != NULL)
|
||||
{
|
||||
codecDescriptorTable[codec->m_writeCipherType-1]->m_cloneCipher(codec->m_writeCipher, codec->m_readCipher);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (codec->m_readCipher != NULL && codec->m_readCipherType != codec->m_writeCipherType)
|
||||
{
|
||||
codecDescriptorTable[codec->m_readCipherType-1]->m_freeCipher(codec->m_readCipher);
|
||||
codec->m_readCipher = NULL;
|
||||
}
|
||||
if (codec->m_readCipher == NULL)
|
||||
{
|
||||
codec->m_readCipherType = codec->m_writeCipherType;
|
||||
codec->m_readCipher = codecDescriptorTable[codec->m_readCipherType-1]->m_allocateCipher(codec->m_db);
|
||||
}
|
||||
if (codec->m_readCipher != NULL)
|
||||
{
|
||||
codecDescriptorTable[codec->m_readCipherType-1]->m_cloneCipher(codec->m_readCipher, codec->m_writeCipher);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcPadPassword(char* password, int pswdlen, unsigned char pswd[32])
|
||||
{
|
||||
int j;
|
||||
int p = 0;
|
||||
int m = pswdlen;
|
||||
if (m > 32) m = 32;
|
||||
|
||||
for (j = 0; j < m; j++)
|
||||
{
|
||||
pswd[p++] = (unsigned char) password[j];
|
||||
}
|
||||
for (j = 0; p < 32 && j < 32; j++)
|
||||
{
|
||||
pswd[p++] = padding[j];
|
||||
}
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcGenerateReadKey(Codec* codec, char* userPassword, int passwordLength, unsigned char* cipherSalt)
|
||||
{
|
||||
codecDescriptorTable[codec->m_readCipherType-1]->m_generateKey(codec->m_readCipher, codec->m_btShared, userPassword, passwordLength, 0, cipherSalt);
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcGenerateWriteKey(Codec* codec, char* userPassword, int passwordLength, unsigned char* cipherSalt)
|
||||
{
|
||||
codecDescriptorTable[codec->m_writeCipherType-1]->m_generateKey(codec->m_writeCipher, codec->m_btShared, userPassword, passwordLength, 1, cipherSalt);
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcEncrypt(Codec* codec, int page, unsigned char* data, int len, int useWriteKey)
|
||||
{
|
||||
int cipherType = (useWriteKey) ? codec->m_writeCipherType : codec->m_readCipherType;
|
||||
void* cipher = (useWriteKey) ? codec->m_writeCipher : codec->m_readCipher;
|
||||
int reserved = (useWriteKey) ? (codec->m_writeReserved >= 0) ? codec->m_writeReserved : codec->m_reserved
|
||||
: (codec->m_readReserved >= 0) ? codec->m_readReserved : codec->m_reserved;
|
||||
return codecDescriptorTable[cipherType-1]->m_encryptPage(cipher, page, data, len, reserved);
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE int
|
||||
sqlite3mcDecrypt(Codec* codec, int page, unsigned char* data, int len)
|
||||
{
|
||||
int cipherType = codec->m_readCipherType;
|
||||
void* cipher = codec->m_readCipher;
|
||||
int reserved = (codec->m_readReserved >= 0) ? codec->m_readReserved : codec->m_reserved;
|
||||
return codecDescriptorTable[cipherType-1]->m_decryptPage(cipher, page, data, len, reserved, codec->m_hmacCheck);
|
||||
}
|
||||
|
||||
SQLITE_PRIVATE void
|
||||
sqlite3mcConfigureSQLCipherVersion(sqlite3* db, int configDefault, int legacyVersion)
|
||||
{
|
||||
static char* stdNames[] = { "legacy_page_size", "kdf_iter", "hmac_use", "kdf_algorithm", "hmac_algorithm", NULL };
|
||||
static char* defNames[] = { "default:legacy_page_size", "default:kdf_iter", "default:hmac_use", "default:kdf_algorithm", "default:hmac_algorithm", NULL };
|
||||
static int versionParams[SQLCIPHER_VERSION_MAX][5] =
|
||||
{
|
||||
{ 1024, 4000, 0, SQLCIPHER_KDF_ALGORITHM_SHA1, SQLCIPHER_HMAC_ALGORITHM_SHA1 },
|
||||
{ 1024, 4000, 1, SQLCIPHER_KDF_ALGORITHM_SHA1, SQLCIPHER_HMAC_ALGORITHM_SHA1 },
|
||||
{ 1024, 64000, 1, SQLCIPHER_KDF_ALGORITHM_SHA1, SQLCIPHER_HMAC_ALGORITHM_SHA1 },
|
||||
{ 4096, 256000, 1, SQLCIPHER_KDF_ALGORITHM_SHA512, SQLCIPHER_HMAC_ALGORITHM_SHA512 }
|
||||
};
|
||||
if (legacyVersion > 0 && legacyVersion <= SQLCIPHER_VERSION_MAX)
|
||||
{
|
||||
char** names = (configDefault != 0) ? defNames : stdNames;
|
||||
int* values = &versionParams[legacyVersion - 1][0];
|
||||
int j;
|
||||
for (j = 0; names[j] != NULL; ++j)
|
||||
{
|
||||
sqlite3mc_config_cipher(db, "sqlcipher", names[j], values[j]);
|
||||
}
|
||||
}
|
||||
}
|
233
contrib/mORMot/SQLite3/amalgamation/ciphers/cipher_common.h
Normal file
233
contrib/mORMot/SQLite3/amalgamation/ciphers/cipher_common.h
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
** Name: cipher_common.h
|
||||
** Purpose: Header for the ciphers of SQLite3 Multiple Ciphers
|
||||
** Author: Ulrich Telle
|
||||
** Created: 2020-02-02
|
||||
** Copyright: (c) 2006-2020 Ulrich Telle
|
||||
** License: MIT
|
||||
*/
|
||||
|
||||
#ifndef CIPHER_COMMON_H_
|
||||
#define CIPHER_COMMON_H_
|
||||
|
||||
#include "sqlite3mc.h"
|
||||
|
||||
/*
|
||||
// ATTENTION: Macro similar to that in pager.c
|
||||
// TODO: Check in case of new version of SQLite
|
||||
*/
|
||||
#define WX_PAGER_MJ_PGNO(x) ((PENDING_BYTE/(x))+1)
|
||||
|
||||
#define CODEC_TYPE_DEFAULT CODEC_TYPE_CHACHA20
|
||||
|
||||
#ifndef CODEC_TYPE
|
||||
#define CODEC_TYPE CODEC_TYPE_DEFAULT
|
||||
#endif
|
||||
|
||||
#if CODEC_TYPE < 1 || CODEC_TYPE > CODEC_TYPE_MAX
|
||||
#error "Invalid codec type selected"
|
||||
#endif
|
||||
|
||||
#define MAXKEYLENGTH 32
|
||||
#define KEYLENGTH_AES128 16
|
||||
#define KEYLENGTH_AES256 32
|
||||
#define KEYSALT_LENGTH 16
|
||||
|
||||
#define CODEC_SHA_ITER 4001
|
||||
|
||||
typedef struct _Codec
|
||||
{
|
||||
int m_isEncrypted;
|
||||
int m_hmacCheck;
|
||||
/* Read cipher */
|
||||
int m_hasReadCipher;
|
||||
int m_readCipherType;
|
||||
void* m_readCipher;
|
||||
int m_readReserved;
|
||||
/* Write cipher */
|
||||
int m_hasWriteCipher;
|
||||
int m_writeCipherType;
|
||||
void* m_writeCipher;
|
||||
int m_writeReserved;
|
||||
|
||||
sqlite3* m_db; /* Pointer to DB */
|
||||
Btree* m_bt; /* Pointer to B-tree used by DB */
|
||||
BtShared* m_btShared; /* Pointer to shared B-tree used by DB */
|
||||
unsigned char m_page[SQLITE_MAX_PAGE_SIZE + 24];
|
||||
int m_pageSize;
|
||||
int m_reserved;
|
||||
int m_hasKeySalt;
|
||||
unsigned char m_keySalt[KEYSALT_LENGTH];
|
||||
} Codec;
|
||||
|
||||
#define CIPHER_PARAMS_SENTINEL { "", 0, 0, 0, 0 }
|
||||
#define CIPHER_PAGE1_OFFSET 24
|
||||
|
||||
typedef struct _CipherParams
|
||||
{
|
||||
char* m_name;
|
||||
int m_value;
|
||||
int m_default;
|
||||
int m_minValue;
|
||||
int m_maxValue;
|
||||
} CipherParams;
|
||||
|
||||
typedef struct _CodecParameter
|
||||
{
|
||||
char* m_name;
|
||||
int m_id;
|
||||
CipherParams* m_params;
|
||||
} CodecParameter;
|
||||
|
||||
typedef void* (*AllocateCipher_t)(sqlite3* db);
|
||||
typedef void (*FreeCipher_t)(void* cipher);
|
||||
typedef void (*CloneCipher_t)(void* cipherTo, void* cipherFrom);
|
||||
typedef int (*CompareCipher_t)(void* cipher1, void* cipher2);
|
||||
typedef int (*GetLegacy_t)(void* cipher);
|
||||
typedef int (*GetPageSize_t)(void* cipher);
|
||||
typedef int (*GetReserved_t)(void* cipher);
|
||||
typedef unsigned char* (*GetSalt_t)(void* cipher);
|
||||
typedef void (*GenerateKey_t)(void* cipher, BtShared* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt);
|
||||
typedef int (*EncryptPage_t)(void* cipher, int page, unsigned char* data, int len, int reserved);
|
||||
typedef int (*DecryptPage_t)(void* cipher, int page, unsigned char* data, int len, int reserved, int hmacCheck);
|
||||
|
||||
typedef struct _CodecDescriptor
|
||||
{
|
||||
char m_name[32];
|
||||
AllocateCipher_t m_allocateCipher;
|
||||
FreeCipher_t m_freeCipher;
|
||||
CloneCipher_t m_cloneCipher;
|
||||
CompareCipher_t m_compareCipher;
|
||||
GetLegacy_t m_getLegacy;
|
||||
GetPageSize_t m_getPageSize;
|
||||
GetReserved_t m_getReserved;
|
||||
GetSalt_t m_getSalt;
|
||||
GenerateKey_t m_generateKey;
|
||||
EncryptPage_t m_encryptPage;
|
||||
DecryptPage_t m_decryptPage;
|
||||
} CipherDescriptor;
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcGetCipherParameter(CipherParams* cipherParams, const char* paramName);
|
||||
SQLITE_PRIVATE int sqlite3mcGetCipherType(sqlite3* db);
|
||||
SQLITE_PRIVATE CipherParams* sqlite3mcGetCipherParams(sqlite3* db, int cypherType);
|
||||
SQLITE_PRIVATE int sqlite3mcCodecInit(Codec* codec);
|
||||
SQLITE_PRIVATE void sqlite3mcCodecTerm(Codec* codec);
|
||||
SQLITE_PRIVATE void sqlite3mcClearKeySalt(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcCodecSetup(Codec* codec, int cipherType, char* userPassword, int passwordLength);
|
||||
SQLITE_PRIVATE int sqlite3mcSetupWriteCipher(Codec* codec, int cipherType, char* userPassword, int passwordLength);
|
||||
SQLITE_PRIVATE void sqlite3mcSetIsEncrypted(Codec* codec, int isEncrypted);
|
||||
SQLITE_PRIVATE void sqlite3mcSetReadCipherType(Codec* codec, int cipherType);
|
||||
SQLITE_PRIVATE void sqlite3mcSetWriteCipherType(Codec* codec, int cipherType);
|
||||
SQLITE_PRIVATE void sqlite3mcSetHasReadCipher(Codec* codec, int hasReadCipher);
|
||||
SQLITE_PRIVATE void sqlite3mcSetHasWriteCipher(Codec* codec, int hasWriteCipher);
|
||||
SQLITE_PRIVATE void sqlite3mcSetDb(Codec* codec, sqlite3* db);
|
||||
SQLITE_PRIVATE void sqlite3mcSetBtree(Codec* codec, Btree* bt);
|
||||
SQLITE_PRIVATE void sqlite3mcSetReadReserved(Codec* codec, int reserved);
|
||||
SQLITE_PRIVATE void sqlite3mcSetWriteReserved(Codec* codec, int reserved);
|
||||
SQLITE_PRIVATE int sqlite3mcIsEncrypted(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcHasReadCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcHasWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE Btree* sqlite3mcGetBtree(Codec* codec);
|
||||
SQLITE_PRIVATE BtShared* sqlite3mcGetBtShared(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetPageSize(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetReadReserved(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetWriteReserved(Codec* codec);
|
||||
SQLITE_PRIVATE unsigned char* sqlite3mcGetPageBuffer(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetLegacyReadCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetLegacyWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetPageSizeReadCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetPageSizeWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetReservedReadCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetReservedWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcReservedEqual(Codec* codec);
|
||||
SQLITE_PRIVATE unsigned char* sqlite3mcGetSaltWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcCodecCopy(Codec* codec, Codec* other);
|
||||
SQLITE_PRIVATE int sqlite3mcCodecCompare(Codec* codec1, Codec* codec2);
|
||||
|
||||
SQLITE_PRIVATE void sqlite3mcGenerateReadKey(Codec* codec, char* userPassword, int passwordLength, unsigned char* cipherSalt);
|
||||
|
||||
SQLITE_PRIVATE void sqlite3mcGenerateWriteKey(Codec* codec, char* userPassword, int passwordLength, unsigned char* cipherSalt);
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcEncrypt(Codec* codec, int page, unsigned char* data, int len, int useWriteKey);
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcDecrypt(Codec* codec, int page, unsigned char* data, int len);
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcCopyCipher(Codec* codec, int read2write);
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcCodecSetup(Codec* codec, int cipherType, char* userPassword, int passwordLength);
|
||||
SQLITE_PRIVATE int sqlite3mcSetupWriteCipher(Codec* codec, int cipherType, char* userPassword, int passwordLength);
|
||||
|
||||
SQLITE_PRIVATE void sqlite3mcSetIsEncrypted(Codec* codec, int isEncrypted);
|
||||
SQLITE_PRIVATE void sqlite3mcSetReadCipherType(Codec* codec, int cipherType);
|
||||
SQLITE_PRIVATE void sqlite3mcSetWriteCipherType(Codec* codec, int cipherType);
|
||||
SQLITE_PRIVATE void sqlite3mcSetHasReadCipher(Codec* codec, int hasReadCipher);
|
||||
SQLITE_PRIVATE void sqlite3mcSetHasWriteCipher(Codec* codec, int hasWriteCipher);
|
||||
SQLITE_PRIVATE void sqlite3mcSetDb(Codec* codec, sqlite3* db);
|
||||
SQLITE_PRIVATE void sqlite3mcSetBtree(Codec* codec, Btree* bt);
|
||||
SQLITE_PRIVATE void sqlite3mcSetReadReserved(Codec* codec, int reserved);
|
||||
SQLITE_PRIVATE void sqlite3mcSetWriteReserved(Codec* codec, int reserved);
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcIsEncrypted(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcHasReadCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcHasWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE Btree* sqlite3mcGetBtree(Codec* codec);
|
||||
SQLITE_PRIVATE BtShared* sqlite3mcGetBtShared(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetPageSize(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetReadReserved(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetWriteReserved(Codec* codec);
|
||||
SQLITE_PRIVATE unsigned char* sqlite3mcGetPageBuffer(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetLegacyReadCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetLegacyWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetPageSizeReadCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetPageSizeWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetReservedReadCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcGetReservedWriteCipher(Codec* codec);
|
||||
SQLITE_PRIVATE int sqlite3mcReservedEqual(Codec* codec);
|
||||
|
||||
SQLITE_PRIVATE void sqlite3mcPadPassword(char* password, int pswdlen, unsigned char pswd[32]);
|
||||
SQLITE_PRIVATE void sqlite3mcRC4(unsigned char* key, int keylen, unsigned char* textin, int textlen, unsigned char* textout);
|
||||
SQLITE_PRIVATE void sqlite3mcGetMD5Binary(unsigned char* data, int length, unsigned char* digest);
|
||||
SQLITE_PRIVATE void sqlite3mcGetSHABinary(unsigned char* data, int length, unsigned char* digest);
|
||||
SQLITE_PRIVATE void sqlite3mcGenerateInitialVector(int seed, unsigned char iv[16]);
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcIsHexKey(const unsigned char* hex, int len);
|
||||
SQLITE_PRIVATE int sqlite3mcConvertHex2Int(char c);
|
||||
SQLITE_PRIVATE void sqlite3mcConvertHex2Bin(const unsigned char* hex, int len, unsigned char* bin);
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcConfigureFromUri(sqlite3* db, const char *zDbName, int configDefault);
|
||||
SQLITE_PRIVATE void sqlite3mcConfigureSQLCipherVersion(sqlite3* db, int configDefault, int legacyVersion);
|
||||
|
||||
SQLITE_PRIVATE int sqlite3mcCodecAttach(sqlite3* db, int nDb, const char* zPath, const void* zKey, int nKey);
|
||||
SQLITE_PRIVATE void sqlite3mcCodecGetKey(sqlite3* db, int nDb, void** zKey, int* nKey);
|
||||
|
||||
/* Debugging */
|
||||
|
||||
#if 0
|
||||
#define SQLITE3MC_DEBUG
|
||||
#define SQLITE3MC_DEBUG_DATA
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE3MC_DEBUG
|
||||
#define SQLITE3MC_DEBUG_LOG(...) { fprintf(stdout, __VA_ARGS__); fflush(stdout); }
|
||||
#else
|
||||
#define SQLITE3MC_DEBUG_LOG(...)
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE3MC_DEBUG_DATA
|
||||
#define SQLITE3MC_DEBUG_HEX(DESC,BUFFER,LEN) \
|
||||
{ \
|
||||
int count; \
|
||||
printf(DESC); \
|
||||
for (count = 0; count < LEN; ++count) \
|
||||
{ \
|
||||
if (count % 16 == 0) printf("\n%05x: ", count); \
|
||||
printf("%02x ", ((unsigned char*) BUFFER)[count]); \
|
||||
} \
|
||||
printf("\n"); \
|
||||
fflush(stdout); \
|
||||
}
|
||||
#else
|
||||
#define SQLITE3MC_DEBUG_HEX(DESC,BUFFER,LEN)
|
||||
#endif
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user