Replaced system SQLite with SQLCipher to support encrypted database

This commit is contained in:
Oleksii Zghurskyi
2025-06-07 18:11:17 +03:00
parent f4198d62a7
commit 177d74700f
534 changed files with 362771 additions and 21 deletions

View File

@@ -0,0 +1,79 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
#ifdef LTC_PBES
/**
Decrypt Data encrypted via either PBES1 or PBES2
@param arg The according PBES parameters
@param dec_data [out] The decrypted data
@param dec_size [in/out] The length of the encrypted resp. decrypted data
@return CRYPT_OK on success
*/
int pbes_decrypt(const pbes_arg *arg, unsigned char *dec_data, unsigned long *dec_size)
{
int err, hid, cid;
unsigned char k[32], *iv;
unsigned long klen, keylen, dlen;
long diff;
symmetric_CBC cbc;
LTC_ARGCHK(arg != NULL);
LTC_ARGCHK(arg->type.kdf != NULL);
LTC_ARGCHK(dec_data != NULL);
LTC_ARGCHK(dec_size != NULL);
hid = find_hash(arg->type.h);
if (hid == -1) return CRYPT_INVALID_HASH;
cid = find_cipher(arg->type.c);
if (cid == -1) return CRYPT_INVALID_CIPHER;
klen = arg->type.keylen;
/* RC2 special case */
if (arg->key_bits != 0) {
/* We can't handle odd lengths of Key Bits */
if ((arg->key_bits % 8) != 0) return CRYPT_INVALID_KEYSIZE;
/* Internally we use bytes, not bits */
klen = arg->key_bits / 8;
}
keylen = klen;
if (arg->iv != NULL) {
iv = arg->iv->data;
} else {
iv = k + klen;
klen += arg->type.blocklen;
}
if (klen > sizeof(k)) return CRYPT_INVALID_ARG;
if ((err = arg->type.kdf(&arg->pw, arg->salt->data, arg->salt->size, arg->iterations, hid, k, &klen)) != CRYPT_OK) goto LBL_ERROR;
if ((err = cbc_start(cid, iv, k, keylen, 0, &cbc)) != CRYPT_OK) goto LBL_ERROR;
if ((err = cbc_decrypt(arg->enc_data->data, dec_data, arg->enc_data->size, &cbc)) != CRYPT_OK) goto LBL_ERROR;
if ((err = cbc_done(&cbc)) != CRYPT_OK) goto LBL_ERROR;
dlen = arg->enc_data->size;
if ((err = padding_depad(dec_data, &dlen, LTC_PAD_PKCS7)) != CRYPT_OK) goto LBL_ERROR;
diff = (long)arg->enc_data->size - (long)dlen;
if ((diff <= 0) || (diff > cipher_descriptor[cid].block_length)) {
err = CRYPT_PK_INVALID_PADDING;
goto LBL_ERROR;
}
*dec_size = dlen;
return CRYPT_OK;
LBL_ERROR:
zeromem(k, sizeof(k));
zeromem(dec_data, *dec_size);
return err;
}
#endif
#pragma clang diagnostic pop

View File

@@ -0,0 +1,112 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#ifdef LTC_PBES
static int s_pkcs_5_alg1_wrap(const struct password *pwd,
const unsigned char *salt, unsigned long salt_len,
int iteration_count, int hash_idx,
unsigned char *out, unsigned long *outlen)
{
LTC_UNUSED_PARAM(salt_len);
return pkcs_5_alg1(pwd->pw, pwd->l, salt, iteration_count, hash_idx, out, outlen);
}
static int s_pkcs_12_wrap(const struct password *pwd,
const unsigned char *salt, unsigned long salt_len,
int iteration_count, int hash_idx,
unsigned char *out, unsigned long *outlen)
{
int err;
/* convert password to unicode/utf16-be */
unsigned long pwlen = pwd->l * 2;
unsigned char* pw;
if (*outlen < 32) return CRYPT_INVALID_ARG;
pw = XMALLOC(pwlen + 2);
if (pw == NULL) return CRYPT_MEM;
if ((err = pkcs12_utf8_to_utf16(pwd->pw, pwd->l, pw, &pwlen)) != CRYPT_OK) goto LBL_ERROR;
pw[pwlen++] = 0;
pw[pwlen++] = 0;
/* derive KEY */
if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 1, out, 24)) != CRYPT_OK) goto LBL_ERROR;
/* derive IV */
if ((err = pkcs12_kdf(hash_idx, pw, pwlen, salt, salt_len, iteration_count, 2, out+24, 8)) != CRYPT_OK) goto LBL_ERROR;
*outlen = 32;
LBL_ERROR:
zeromem(pw, pwlen);
XFREE(pw);
return err;
}
static const pbes_properties s_pbes1_types[] = {
{ s_pkcs_5_alg1_wrap, "md2", "des", 8, 8 },
{ s_pkcs_5_alg1_wrap, "md2", "rc2", 8, 8 },
{ s_pkcs_5_alg1_wrap, "md5", "des", 8, 8 },
{ s_pkcs_5_alg1_wrap, "md5", "rc2", 8, 8 },
{ s_pkcs_5_alg1_wrap, "sha1", "des", 8, 8 },
{ s_pkcs_5_alg1_wrap, "sha1", "rc2", 8, 8 },
{ s_pkcs_12_wrap, "sha1", "3des", 24, 8 },
};
static const oid_to_pbes s_pbes1_list[] = {
{ &s_pbes1_types[0], "1.2.840.113549.1.5.1" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.1 pbeWithMD2AndDES-CBC */
{ &s_pbes1_types[1], "1.2.840.113549.1.5.4" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.4 pbeWithMD2AndRC2-CBC */
{ &s_pbes1_types[2], "1.2.840.113549.1.5.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.3 pbeWithMD5AndDES-CBC */
{ &s_pbes1_types[3], "1.2.840.113549.1.5.6" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.6 pbeWithMD5AndRC2-CBC */
{ &s_pbes1_types[4], "1.2.840.113549.1.5.10" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.10 pbeWithSHA1AndDES-CBC */
{ &s_pbes1_types[5], "1.2.840.113549.1.5.11" }, /* http://www.oid-info.com/get/1.2.840.113549.1.5.11 pbeWithSHA1AndRC2-CBC */
{ &s_pbes1_types[6], "1.2.840.113549.1.12.1.3" }, /* http://www.oid-info.com/get/1.2.840.113549.1.12.1.3 pbeWithSHAAnd3-KeyTripleDES-CBC */
{ 0 },
};
static int s_pbes1_from_oid(const ltc_asn1_list *oid, pbes_properties *res)
{
unsigned int i;
for (i = 0; s_pbes1_list[i].data != NULL; ++i) {
if (pk_oid_cmp_with_asn1(s_pbes1_list[i].oid, oid) == CRYPT_OK) {
if (res != NULL) *res = *s_pbes1_list[i].data;
return CRYPT_OK;
}
}
return CRYPT_INVALID_ARG;
}
/**
Extract PBES1 parameters
@param s The start of the sequence with potential PBES1 parameters
@param res Pointer to where the extracted parameters should be stored
@return CRYPT_OK on success
*/
int pbes1_extract(const ltc_asn1_list *s, pbes_arg *res)
{
int err;
LTC_ARGCHK(s != NULL);
LTC_ARGCHK(res != NULL);
if ((err = s_pbes1_from_oid(s, &res->type)) != CRYPT_OK) return err;
if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) ||
!LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_OCTET_STRING) ||
!LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_INTEGER)) {
return CRYPT_INVALID_PACKET;
}
/* PBES1: encrypted pkcs8 - pbeWithMD5AndDES-CBC:
* 0:d=0 hl=4 l= 329 cons: SEQUENCE
* 4:d=1 hl=2 l= 27 cons: SEQUENCE
* 6:d=2 hl=2 l= 9 prim: OBJECT :pbeWithMD5AndDES-CBC (== 1.2.840.113549.1.5.3) (== *s)
* 17:d=2 hl=2 l= 14 cons: SEQUENCE (== *lalgparam)
* 19:d=3 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:8EDF749A06CCDE51 (== salt)
* 29:d=3 hl=2 l= 2 prim: INTEGER :0800 (== iterations)
* 33:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data)
*/
res->salt = s->next->child;
res->iterations = ltc_mp_get_int(s->next->child->next->data);
return CRYPT_OK;
}
#endif

View File

@@ -0,0 +1,201 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#ifdef LTC_PBES
static const char * const s_oid_pbes2 = "1.2.840.113549.1.5.13";
static const char * const s_oid_pbkdf2 = "1.2.840.113549.1.5.12";
typedef struct {
const char *oid;
const char *id;
} oid_id_st;
static const oid_id_st s_hmac_oid_names[] = {
{ "1.2.840.113549.2.7", "sha1" },
{ "1.2.840.113549.2.8", "sha224" },
{ "1.2.840.113549.2.9", "sha256" },
{ "1.2.840.113549.2.10", "sha384" },
{ "1.2.840.113549.2.11", "sha512" },
{ "1.2.840.113549.2.12", "sha512-224" },
{ "1.2.840.113549.2.13", "sha512-256" },
};
static int s_pkcs_5_alg2_wrap(const struct password *pwd,
const unsigned char *salt, unsigned long salt_len,
int iteration_count, int hash_idx,
unsigned char *out, unsigned long *outlen)
{
return pkcs_5_alg2(pwd->pw, pwd->l, salt, salt_len, iteration_count, hash_idx, out, outlen);
}
static const pbes_properties s_pbes2_default_types[] = {
{ s_pkcs_5_alg2_wrap, "sha1", "des", 8, 0 },
{ s_pkcs_5_alg2_wrap, "sha1", "rc2", 4, 0 },
{ s_pkcs_5_alg2_wrap, "sha1", "3des", 24, 0 },
{ s_pkcs_5_alg2_wrap, "sha1", "aes", 16, 0 },
{ s_pkcs_5_alg2_wrap, "sha1", "aes", 24, 0 },
{ s_pkcs_5_alg2_wrap, "sha1", "aes", 32, 0 },
};
static const oid_to_pbes s_pbes2_list[] = {
{ &s_pbes2_default_types[0], "1.3.14.3.2.7" }, /* http://www.oid-info.com/get/1.3.14.3.2.7 desCBC */
{ &s_pbes2_default_types[1], "1.2.840.113549.3.2" }, /* http://www.oid-info.com/get/1.2.840.113549.3.2 rc2CBC */
{ &s_pbes2_default_types[2], "1.2.840.113549.3.7" }, /* http://www.oid-info.com/get/1.2.840.113549.3.7 des-EDE3-CBC */
{ &s_pbes2_default_types[3], "2.16.840.1.101.3.4.1.2" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.2 aes128-CBC */
{ &s_pbes2_default_types[4], "2.16.840.1.101.3.4.1.22" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.22 aes192-CBC */
{ &s_pbes2_default_types[5], "2.16.840.1.101.3.4.1.42" }, /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.42 aes256-CBC */
};
static int s_pbes2_from_oid(const ltc_asn1_list *cipher_oid, const ltc_asn1_list *hmac_oid, pbes_properties *res)
{
unsigned int i;
for (i = 0; i < sizeof(s_pbes2_list)/sizeof(s_pbes2_list[0]); ++i) {
if (pk_oid_cmp_with_asn1(s_pbes2_list[i].oid, cipher_oid) == CRYPT_OK) {
*res = *s_pbes2_list[i].data;
break;
}
}
if (res->c == NULL) return CRYPT_INVALID_CIPHER;
if (hmac_oid != NULL) {
for (i = 0; i < sizeof(s_hmac_oid_names)/sizeof(s_hmac_oid_names[0]); ++i) {
if (pk_oid_cmp_with_asn1(s_hmac_oid_names[i].oid, hmac_oid) == CRYPT_OK) {
res->h = s_hmac_oid_names[i].id;
return CRYPT_OK;
}
}
return CRYPT_INVALID_HASH;
}
return CRYPT_OK;
}
/**
Extract PBES2 parameters
@param s The start of the sequence with potential PBES2 parameters
@param res Pointer to where the extracted parameters should be stored
@return CRYPT_OK on success
*/
int pbes2_extract(const ltc_asn1_list *s, pbes_arg *res)
{
unsigned long klen;
ltc_asn1_list *lkdf, *lenc, *loptseq, *liter, *lhmac;
int err;
LTC_ARGCHK(s != NULL);
LTC_ARGCHK(res != NULL);
if ((err = pk_oid_cmp_with_asn1(s_oid_pbes2, s)) != CRYPT_OK) return err;
if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) ||
!LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_SEQUENCE) ||
!LTC_ASN1_IS_TYPE(s->next->child->child, LTC_ASN1_OBJECT_IDENTIFIER) ||
!LTC_ASN1_IS_TYPE(s->next->child->child->next, LTC_ASN1_SEQUENCE) ||
!LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_SEQUENCE) ||
!LTC_ASN1_IS_TYPE(s->next->child->next->child, LTC_ASN1_OBJECT_IDENTIFIER)) {
return CRYPT_INVALID_PACKET;
}
/* PBES2: encrypted pkcs8 - PBES2+PBKDF2+des-ede3-cbc:
* 0:d=0 hl=4 l= 380 cons: SEQUENCE
* 4:d=1 hl=2 l= 78 cons: SEQUENCE
* 6:d=2 hl=2 l= 9 prim: OBJECT :PBES2 (== 1.2.840.113549.1.5.13) (== *s)
* 17:d=2 hl=2 l= 65 cons: SEQUENCE
* 19:d=3 hl=2 l= 41 cons: SEQUENCE
* 21:d=4 hl=2 l= 9 prim: OBJECT :PBKDF2 (== *lkdf)
* 32:d=4 hl=2 l= 28 cons: SEQUENCE
* 34:d=5 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:28BA4ABF6AA76A3D (== res->salt)
* 44:d=5 hl=2 l= 2 prim: INTEGER :0800 (== res->iterations, *liter)
* 48:d=5 hl=2 l= 12 cons: SEQUENCE (== *loptseq - this sequence is optional, may be missing)
* 50:d=6 hl=2 l= 8 prim: OBJECT :hmacWithSHA256 (== *lhmac)
* 60:d=6 hl=2 l= 0 prim: NULL
* 62:d=3 hl=2 l= 20 cons: SEQUENCE
* 64:d=4 hl=2 l= 8 prim: OBJECT :des-ede3-cbc (== *lenc)
* 74:d=4 hl=2 l= 8 prim: OCTET STRING [HEX DUMP]:B1404C4688DC9A5A
* 84:d=1 hl=4 l= 296 prim: OCTET STRING :bytes (== encrypted data)
*/
lkdf = s->next->child->child;
lenc = s->next->child->next->child;
if ((err = pk_oid_cmp_with_asn1(s_oid_pbkdf2, lkdf)) != CRYPT_OK) return err;
if (!LTC_ASN1_IS_TYPE(lkdf->next, LTC_ASN1_SEQUENCE) ||
!LTC_ASN1_IS_TYPE(lkdf->next->child, LTC_ASN1_OCTET_STRING) ||
!LTC_ASN1_IS_TYPE(lkdf->next->child->next, LTC_ASN1_INTEGER)) {
return CRYPT_INVALID_PACKET;
}
liter = lkdf->next->child->next;
loptseq = liter->next;
res->salt = lkdf->next->child;
res->iterations = ltc_mp_get_int(liter->data);
/* There's an optional INTEGER keyLength after the iterations, skip that if it's there.
* c.f. RFC 2898 A.2 PBKDF2 */
if(LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_INTEGER)) {
loptseq = loptseq->next;
}
/* this sequence is optional */
lhmac = NULL;
if (LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_SEQUENCE) &&
LTC_ASN1_IS_TYPE(loptseq->child, LTC_ASN1_OBJECT_IDENTIFIER)) {
lhmac = loptseq->child;
}
if ((err = s_pbes2_from_oid(lenc, lhmac, &res->type)) != CRYPT_OK) return err;
if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_OCTET_STRING)) {
/* 'NON-RC2'-CBC */
res->iv = lenc->next;
} else if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_SEQUENCE)) {
/* RC2-CBC is a bit special ...
*
* RC2-CBC-Parameter ::= SEQUENCE {
* rc2ParameterVersion INTEGER OPTIONAL,
* iv OCTET STRING (SIZE(8)) }
*/
if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_INTEGER) &&
LTC_ASN1_IS_TYPE(lenc->next->child->next, LTC_ASN1_OCTET_STRING)) {
klen = ltc_mp_get_int(lenc->next->child->data);
res->iv = lenc->next->child->next;
/*
* Effective Key Bits Encoding
* 40 160
* 64 120
* 128 58
* b >= 256 b
*/
switch (klen) {
case 160:
res->key_bits = 40;
break;
case 120:
res->key_bits = 64;
break;
case 58:
res->key_bits = 128;
break;
default:
/* We don't handle undefined Key Bits */
if (klen < 256) return CRYPT_INVALID_KEYSIZE;
res->key_bits = klen;
break;
}
} else if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_OCTET_STRING)) {
res->iv = lenc->next->child;
/*
* If the rc2ParameterVersion field is omitted, the "effective key bits"
* defaults to 32.
*/
res->key_bits = 32;
} else {
return CRYPT_INVALID_PACKET;
}
}
return CRYPT_OK;
}
#endif