Skip to content

Commit 9483f9f

Browse files
committed
Simplify and unify raw key and salt specification
- raw keys (and optionally salt) can be given in both formats, SQLCipher or sqleet, for all cipher schemes supporting raw key specification (chacha20, sqlcipher, ascon128, aegis) - the cipher salt can now also be specified via "pragma cipher_salt" - pragma takes precedence over URI parameter - the "cipher" URI parameter is no longer necessary for the default cipher scheme
1 parent 6073fd3 commit 9483f9f

File tree

9 files changed

+183
-160
lines changed

9 files changed

+183
-160
lines changed

src/cipher_aegis.c

Lines changed: 4 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,6 @@ static void
253253
GenerateKeyAegisCipher(void* cipher, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt)
254254
{
255255
AegisCipher* aegisCipher = (AegisCipher*) cipher;
256-
int bypass = 0;
257256

258257
int keyOnly = 1;
259258
if (rekey || cipherSalt == NULL)
@@ -266,51 +265,10 @@ GenerateKeyAegisCipher(void* cipher, char* userPassword, int passwordLength, int
266265
memcpy(aegisCipher->m_salt, cipherSalt, SALTLENGTH_AEGIS);
267266
}
268267

269-
/* Bypass key derivation if the key string starts with "raw:" */
270-
if (passwordLength > 4 && !memcmp(userPassword, "raw:", 4))
271-
{
272-
const int nRaw = passwordLength - 4;
273-
const unsigned char* zRaw = (const unsigned char*) userPassword + 4;
274-
if (nRaw == aegisCipher->m_keyLength)
275-
{
276-
/* Binary key */
277-
memcpy(aegisCipher->m_key, zRaw, aegisCipher->m_keyLength);
278-
bypass = 1;
279-
}
280-
else if (nRaw == aegisCipher->m_keyLength + SALTLENGTH_AEGIS)
281-
{
282-
/* Binary key and salt) */
283-
if (!keyOnly)
284-
{
285-
memcpy(aegisCipher->m_salt, zRaw + aegisCipher->m_keyLength, SALTLENGTH_AEGIS);
286-
}
287-
memcpy(aegisCipher->m_key, zRaw, aegisCipher->m_keyLength);
288-
bypass = 1;
289-
}
290-
else if (nRaw == 2 * aegisCipher->m_keyLength)
291-
{
292-
/* Hex-encoded key */
293-
if (sqlite3mcIsHexKey(zRaw, nRaw) != 0)
294-
{
295-
sqlite3mcConvertHex2Bin(zRaw, nRaw, aegisCipher->m_key);
296-
bypass = 1;
297-
}
298-
}
299-
else if (nRaw == 2 * (aegisCipher->m_keyLength + SALTLENGTH_AEGIS))
300-
{
301-
/* Hex-encoded key and salt */
302-
if (sqlite3mcIsHexKey(zRaw, nRaw) != 0)
303-
{
304-
sqlite3mcConvertHex2Bin(zRaw, 2 * aegisCipher->m_keyLength, aegisCipher->m_key);
305-
if (!keyOnly)
306-
{
307-
sqlite3mcConvertHex2Bin(zRaw + 2 * aegisCipher->m_keyLength, 2 * SALTLENGTH_AEGIS, aegisCipher->m_salt);
308-
}
309-
bypass = 1;
310-
}
311-
}
312-
}
313-
268+
/* Bypass key derivation, if raw key (and optionally salt) are given */
269+
int bypass = sqlite3mcExtractRawKey(userPassword, passwordLength,
270+
keyOnly, aegisCipher->m_keyLength, SALTLENGTH_AEGIS,
271+
aegisCipher->m_key, aegisCipher->m_salt);
314272
if (!bypass)
315273
{
316274
int rc = argon2id_hash_raw((uint32_t) aegisCipher->m_argon2Tcost,

src/cipher_ascon.c

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ static void
122122
GenerateKeyAscon128Cipher(void* cipher, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt)
123123
{
124124
Ascon128Cipher* ascon128Cipher = (Ascon128Cipher*) cipher;
125-
int bypass = 0;
126125

127126
int keyOnly = 1;
128127
if (rekey || cipherSalt == NULL)
@@ -135,52 +134,10 @@ GenerateKeyAscon128Cipher(void* cipher, char* userPassword, int passwordLength,
135134
memcpy(ascon128Cipher->m_salt, cipherSalt, SALTLENGTH_ASCON128);
136135
}
137136

138-
/* Bypass key derivation if the key string starts with "raw:" */
139-
if (passwordLength > 4 && !memcmp(userPassword, "raw:", 4))
140-
{
141-
const int nRaw = passwordLength - 4;
142-
const unsigned char* zRaw = (const unsigned char*) userPassword + 4;
143-
switch (nRaw)
144-
{
145-
/* Binary key (and salt) */
146-
case KEYLENGTH_ASCON128 + SALTLENGTH_ASCON128:
147-
if (!keyOnly)
148-
{
149-
memcpy(ascon128Cipher->m_salt, zRaw + KEYLENGTH_ASCON128, SALTLENGTH_ASCON128);
150-
}
151-
/* fall-through */
152-
case KEYLENGTH_ASCON128:
153-
memcpy(ascon128Cipher->m_key, zRaw, KEYLENGTH_ASCON128);
154-
bypass = 1;
155-
break;
156-
157-
/* Hex-encoded key */
158-
case 2 * KEYLENGTH_ASCON128:
159-
if (sqlite3mcIsHexKey(zRaw, nRaw) != 0)
160-
{
161-
sqlite3mcConvertHex2Bin(zRaw, nRaw, ascon128Cipher->m_key);
162-
bypass = 1;
163-
}
164-
break;
165-
166-
/* Hex-encoded key and salt */
167-
case 2 * (KEYLENGTH_ASCON128 + SALTLENGTH_ASCON128):
168-
if (sqlite3mcIsHexKey(zRaw, nRaw) != 0)
169-
{
170-
sqlite3mcConvertHex2Bin(zRaw, 2 * KEYLENGTH_ASCON128, ascon128Cipher->m_key);
171-
if (!keyOnly)
172-
{
173-
sqlite3mcConvertHex2Bin(zRaw + 2 * KEYLENGTH_ASCON128, 2 * SALTLENGTH_ASCON128, ascon128Cipher->m_salt);
174-
}
175-
bypass = 1;
176-
}
177-
break;
178-
179-
default:
180-
break;
181-
}
182-
}
183-
137+
/* Bypass key derivation, if raw key (and optionally salt) are given */
138+
int bypass = sqlite3mcExtractRawKey(userPassword, passwordLength,
139+
keyOnly, KEYLENGTH_ASCON128, SALTLENGTH_ASCON128,
140+
ascon128Cipher->m_key, ascon128Cipher->m_salt);
184141
if (!bypass)
185142
{
186143
ascon_pbkdf2(ascon128Cipher->m_key, KEYLENGTH_ASCON128,

src/cipher_chacha20.c

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ static void
148148
GenerateKeyChaCha20Cipher(void* cipher, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt)
149149
{
150150
ChaCha20Cipher* chacha20Cipher = (ChaCha20Cipher*) cipher;
151-
int bypass = 0;
152151

153152
int keyOnly = 1;
154153
if (rekey || cipherSalt == NULL)
@@ -161,52 +160,10 @@ GenerateKeyChaCha20Cipher(void* cipher, char* userPassword, int passwordLength,
161160
memcpy(chacha20Cipher->m_salt, cipherSalt, SALTLENGTH_CHACHA20);
162161
}
163162

164-
/* Bypass key derivation if the key string starts with "raw:" */
165-
if (passwordLength > 4 && !memcmp(userPassword, "raw:", 4))
166-
{
167-
const int nRaw = passwordLength - 4;
168-
const unsigned char* zRaw = (const unsigned char*) userPassword + 4;
169-
switch (nRaw)
170-
{
171-
/* Binary key (and salt) */
172-
case KEYLENGTH_CHACHA20 + SALTLENGTH_CHACHA20:
173-
if (!keyOnly)
174-
{
175-
memcpy(chacha20Cipher->m_salt, zRaw + KEYLENGTH_CHACHA20, SALTLENGTH_CHACHA20);
176-
}
177-
/* fall-through */
178-
case KEYLENGTH_CHACHA20:
179-
memcpy(chacha20Cipher->m_key, zRaw, KEYLENGTH_CHACHA20);
180-
bypass = 1;
181-
break;
182-
183-
/* Hex-encoded key */
184-
case 2 * KEYLENGTH_CHACHA20:
185-
if (sqlite3mcIsHexKey(zRaw, nRaw) != 0)
186-
{
187-
sqlite3mcConvertHex2Bin(zRaw, nRaw, chacha20Cipher->m_key);
188-
bypass = 1;
189-
}
190-
break;
191-
192-
/* Hex-encoded key and salt */
193-
case 2 * (KEYLENGTH_CHACHA20 + SALTLENGTH_CHACHA20):
194-
if (sqlite3mcIsHexKey(zRaw, nRaw) != 0)
195-
{
196-
sqlite3mcConvertHex2Bin(zRaw, 2 * KEYLENGTH_CHACHA20, chacha20Cipher->m_key);
197-
if (!keyOnly)
198-
{
199-
sqlite3mcConvertHex2Bin(zRaw + 2 * KEYLENGTH_CHACHA20, 2 * SALTLENGTH_CHACHA20, chacha20Cipher->m_salt);
200-
}
201-
bypass = 1;
202-
}
203-
break;
204-
205-
default:
206-
break;
207-
}
208-
}
209-
163+
/* Bypass key derivation, if raw key (and optionally salt) are given */
164+
int bypass = sqlite3mcExtractRawKey(userPassword, passwordLength,
165+
keyOnly, KEYLENGTH_CHACHA20, SALTLENGTH_CHACHA20,
166+
chacha20Cipher->m_key, chacha20Cipher->m_salt);
210167
if (!bypass)
211168
{
212169
fastpbkdf2_hmac_sha256((unsigned char*)userPassword, passwordLength,

src/cipher_common.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ static unsigned char padding[] =
2323

2424
static CipherParams commonParams[] =
2525
{
26-
{ "cipher", CODEC_TYPE_UNKNOWN, CODEC_TYPE_UNKNOWN, 1, CODEC_COUNT_MAX },
27-
{ "hmac_check", 1, 1, 0, 1 },
28-
{ "mc_legacy_wal", SQLITE3MC_LEGACY_WAL, SQLITE3MC_LEGACY_WAL, 0, 1 },
26+
{ "cipher", CODEC_TYPE_UNKNOWN, CODEC_TYPE_UNKNOWN, 1, CODEC_COUNT_MAX },
27+
{ "hmac_check", 1, 1, 0, 1 },
28+
{ "mc_legacy_wal", SQLITE3MC_LEGACY_WAL, SQLITE3MC_LEGACY_WAL, 0, 1 },
2929
CIPHER_PARAMS_SENTINEL
3030
};
3131

src/cipher_common.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656

5757
#define CODEC_SHA_ITER 4001
5858

59+
/* Restrict possible plaintext header size to db header size */
60+
#define PLAINTEXT_HEADER_MAX 100
61+
5962
typedef struct _CodecParameter
6063
{
6164
char* m_name;
@@ -192,6 +195,10 @@ SQLITE_PRIVATE int sqlite3mcConvertHex2Int(char c);
192195

193196
SQLITE_PRIVATE void sqlite3mcConvertHex2Bin(const unsigned char* hex, int len, unsigned char* bin);
194197

198+
SQLITE_PRIVATE int sqlite3mcExtractRawKey(const char* password, int passwordLength,
199+
int keyOnly, int keyLength, int saltLength,
200+
char* key, char* salt);
201+
195202
SQLITE_PRIVATE int sqlite3mcConfigureFromUri(sqlite3* db, const char *zDbName, int configDefault);
196203

197204
SQLITE_PRIVATE void sqlite3mcConfigureSQLCipherVersion(sqlite3* db, int configDefault, int legacyVersion);

src/cipher_config.c

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@ sqlite3mcConfigParams(sqlite3_context* context, int argc, sqlite3_value** argv)
707707
}
708708

709709
SQLITE_PRIVATE int
710-
sqlite3mcConfigureFromUri(sqlite3* db, const char *zDbName, int configDefault)
710+
sqlite3mcConfigureFromUri(sqlite3* db, const char* zDbName, int configDefault)
711711
{
712712
int rc = SQLITE_OK;
713713

@@ -717,6 +717,15 @@ sqlite3mcConfigureFromUri(sqlite3* db, const char *zDbName, int configDefault)
717717
{
718718
/* Check whether cipher is specified */
719719
const char* cipherName = sqlite3_uri_parameter(dbFileName, "cipher");
720+
if (cipherName == NULL)
721+
{
722+
int defaultCipherIndex = sqlite3mc_config(db, "cipher", -1);
723+
if (defaultCipherIndex > 0)
724+
{
725+
cipherName = sqlite3mc_cipher_name(defaultCipherIndex);
726+
sqlite3mc_config(db, "cipher", defaultCipherIndex);
727+
}
728+
}
720729
if (cipherName != NULL)
721730
{
722731
int j = 0;
@@ -929,6 +938,69 @@ sqlite3mcFileControlPragma(sqlite3* db, const char* zDbName, int op, void* pArg)
929938
((char**)pArg)[0] = sqlite3_mprintf("%d", value);
930939
rc = SQLITE_OK;
931940
}
941+
else if (sqlite3StrICmp(pragmaName, "cipher_salt") == 0)
942+
{
943+
Codec* codec = sqlite3mcGetCodec(db, (zDbName) ? zDbName : "main");
944+
if (codec == NULL)
945+
{
946+
/* Codec not yet set up */
947+
if (pragmaValue && *pragmaValue != 0)
948+
{
949+
/* Save given cipher salt */
950+
if (sqlite3Strlen30(pragmaValue) >= 2 * KEYSALT_LENGTH &&
951+
sqlite3mcIsHexKey(pragmaValue, 2 * KEYSALT_LENGTH))
952+
{
953+
char* cipherSalt = sqlite3_mprintf("%s", pragmaValue);
954+
if (sqlite3_set_clientdata(db, "sqlite3mc_cipher_salt", cipherSalt, sqlite3_free) != SQLITE_OK)
955+
{
956+
((char**)pArg)[0] = sqlite3_mprintf("Out of memory. Cipher salt not saved.");
957+
rc = SQLITE_ERROR;
958+
}
959+
else
960+
{
961+
((char**)pArg)[0] = sqlite3_mprintf("ok");
962+
rc = SQLITE_OK;
963+
}
964+
}
965+
else
966+
{
967+
((char**)pArg)[0] = sqlite3_mprintf("Invalid cipher salt. Length < %d or invalid hex digits.", 2 * KEYSALT_LENGTH);
968+
rc = SQLITE_ERROR;
969+
}
970+
}
971+
else
972+
{
973+
char* cipherSalt = sqlite3_get_clientdata(db, "sqlite3mc_cipher_salt");
974+
if (cipherSalt)
975+
{
976+
((char**)pArg)[0] = sqlite3_mprintf("%s", cipherSalt);
977+
}
978+
}
979+
}
980+
else if (sqlite3mcIsEncrypted(codec) && sqlite3mcHasWriteCipher(codec))
981+
{
982+
/* Database encrypted */
983+
if (pragmaValue && *pragmaValue != 0)
984+
{
985+
((char**)pArg)[0] = sqlite3_mprintf("Cipher salt can't be changed.");
986+
rc = SQLITE_ERROR;
987+
}
988+
else
989+
{
990+
char* cipherSalt = (char*) sqlite3mc_codec_data(db, (zDbName) ? zDbName : "main", "cipher_salt");
991+
if (cipherSalt)
992+
{
993+
((char**)pArg)[0] = cipherSalt;
994+
}
995+
rc = SQLITE_OK;
996+
}
997+
}
998+
else
999+
{
1000+
((char**)pArg)[0] = sqlite3_mprintf("Database not encrypted.");
1001+
rc = SQLITE_ERROR;
1002+
}
1003+
}
9321004
else if (sqlite3StrICmp(pragmaName, "key") == 0)
9331005
{
9341006
rc = sqlite3_key_v2(db, zDbName, pragmaValue, -1);

src/cipher_sqlcipher.c

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -244,29 +244,22 @@ GenerateKeySQLCipherCipher(void* cipher, char* userPassword, int passwordLength,
244244
{
245245
SQLCipherCipher* sqlCipherCipher = (SQLCipherCipher*) cipher;
246246

247+
int keyOnly = 1;
247248
if (rekey || cipherSalt == NULL)
248249
{
249250
chacha20_rng(sqlCipherCipher->m_salt, SALTLENGTH_SQLCIPHER);
251+
keyOnly = 0;
250252
}
251253
else
252254
{
253255
memcpy(sqlCipherCipher->m_salt, cipherSalt, SALTLENGTH_SQLCIPHER);
254256
}
255257

256-
if (passwordLength == ((KEYLENGTH_SQLCIPHER * 2) + 3) &&
257-
sqlite3_strnicmp(userPassword, "x'", 2) == 0 &&
258-
sqlite3mcIsHexKey((unsigned char*) (userPassword + 2), KEYLENGTH_SQLCIPHER * 2) != 0)
259-
{
260-
sqlite3mcConvertHex2Bin((unsigned char*) (userPassword + 2), passwordLength - 3, sqlCipherCipher->m_key);
261-
}
262-
else if (passwordLength == (((KEYLENGTH_SQLCIPHER + SALTLENGTH_SQLCIPHER) * 2) + 3) &&
263-
sqlite3_strnicmp(userPassword, "x'", 2) == 0 &&
264-
sqlite3mcIsHexKey((unsigned char*) (userPassword + 2), (KEYLENGTH_SQLCIPHER + SALTLENGTH_SQLCIPHER) * 2) != 0)
265-
{
266-
sqlite3mcConvertHex2Bin((unsigned char*) (userPassword + 2), KEYLENGTH_SQLCIPHER * 2, sqlCipherCipher->m_key);
267-
sqlite3mcConvertHex2Bin((unsigned char*) (userPassword + 2 + KEYLENGTH_SQLCIPHER * 2), SALTLENGTH_SQLCIPHER * 2, sqlCipherCipher->m_salt);
268-
}
269-
else
258+
/* Bypass key derivation, if raw key (and optionally salt) are given */
259+
int bypass = sqlite3mcExtractRawKey(userPassword, passwordLength,
260+
keyOnly, KEYLENGTH_SQLCIPHER, SALTLENGTH_SQLCIPHER,
261+
sqlCipherCipher->m_key, sqlCipherCipher->m_salt);
262+
if (!bypass)
270263
{
271264
switch (sqlCipherCipher->m_kdfAlgorithm)
272265
{

0 commit comments

Comments
 (0)