Skip to content

Commit a66332f

Browse files
authored
Update to SQLite 3.51.1 and SQLCipher 4.12 (#12)
1 parent c95a5b5 commit a66332f

File tree

6 files changed

+5321
-2068
lines changed

6 files changed

+5321
-2068
lines changed

Package.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ let package = Package(
6565
.define("HAVE_GETHOSTUUID", to: "0"),
6666
.define("HAVE_STDINT_H"),
6767
.define("SQLCIPHER_CRYPTO_LIBTOMCRYPT"),
68+
.define("SQLCIPHER_CRYPTO_CUSTOM", to: "sqlcipher_ltc_setup"),
6869
],
6970
linkerSettings: [.linkedLibrary("log", .when(platforms: [.android]))]),
7071
.testTarget(

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ library (e.g., Android, Windows).
1414
## Features
1515

1616
- A pure-Swift interface
17-
- Embeds a modern and consistent sqlite ([3.50.4](https://www.sqlite.org/releaselog/3_50_4.html)) and sqlcipher ([4.11.0](https://github.com/sqlcipher/sqlcipher/releases/tag/v4.11.0)) build in the library
17+
- Embeds a modern and consistent sqlite ([3.51.1](https://www.sqlite.org/releaselog/3_51_1.html)) and sqlcipher ([4.12.0](https://github.com/sqlcipher/sqlcipher/releases/tag/v4.12.0)) build in the library
1818
- Works on iOS, macOS, Android, Windows, and Linux
1919
- A type-safe, optional-aware SQL expression builder
2020
- A flexible, chainable, lazy-executing query layer
Lines changed: 326 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,326 @@
1+
/*
2+
** SQLCipher
3+
** http://sqlcipher.net
4+
**
5+
** Copyright (c) 2008 - 2013, ZETETIC LLC
6+
** All rights reserved.
7+
**
8+
** Redistribution and use in source and binary forms, with or without
9+
** modification, are permitted provided that the following conditions are met:
10+
** * Redistributions of source code must retain the above copyright
11+
** notice, this list of conditions and the following disclaimer.
12+
** * Redistributions in binary form must reproduce the above copyright
13+
** notice, this list of conditions and the following disclaimer in the
14+
** documentation and/or other materials provided with the distribution.
15+
** * Neither the name of the ZETETIC LLC nor the
16+
** names of its contributors may be used to endorse or promote products
17+
** derived from this software without specific prior written permission.
18+
**
19+
** THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY
20+
** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21+
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22+
** DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY
23+
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24+
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25+
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26+
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28+
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
**
30+
*/
31+
32+
// Support for LibTomCrypt in SQLCipher is now maintained externally
33+
// due to https://github.com/sqlcipher/sqlcipher/issues/564
34+
//
35+
// This file was obtained from the last known release:
36+
// https://raw.githubusercontent.com/sqlcipher/sqlcipher/refs/tags/v4.11.0/src/crypto_libtomcrypt.c
37+
//
38+
// Note that this file is not compiled directly, but instead is
39+
// added to the SQLite amalgamation by scripts/build_sqlcipher.sh
40+
41+
/* BEGIN SQLCIPHER */
42+
#ifdef SQLITE_HAS_CODEC
43+
#ifdef SQLCIPHER_CRYPTO_LIBTOMCRYPT
44+
//#include "sqliteInt.h"
45+
//#include "sqlcipher.h"
46+
#include <tomcrypt.h>
47+
48+
#define FORTUNA_MAX_SZ 32
49+
static prng_state prng;
50+
static volatile unsigned int ltc_init = 0;
51+
static volatile unsigned int ltc_ref_count = 0;
52+
53+
#define LTC_CIPHER "rijndael"
54+
55+
static int sqlcipher_ltc_add_random(void *ctx, const void *buffer, int length) {
56+
int rc = 0;
57+
int data_to_read = length;
58+
int block_sz = data_to_read < FORTUNA_MAX_SZ ? data_to_read : FORTUNA_MAX_SZ;
59+
const unsigned char * data = (const unsigned char *)buffer;
60+
61+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_add_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND");
62+
sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
63+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_add_random: entered SQLCIPHER_MUTEX_PROVIDER_RAND");
64+
65+
while(data_to_read > 0){
66+
rc = fortuna_add_entropy(data, block_sz, &prng);
67+
rc = rc != CRYPT_OK ? SQLITE_ERROR : SQLITE_OK;
68+
if(rc != SQLITE_OK){
69+
break;
70+
}
71+
data_to_read -= block_sz;
72+
data += block_sz;
73+
block_sz = data_to_read < FORTUNA_MAX_SZ ? data_to_read : FORTUNA_MAX_SZ;
74+
}
75+
fortuna_ready(&prng);
76+
77+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_add_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND");
78+
sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
79+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_add_random: left SQLCIPHER_MUTEX_PROVIDER_RAND");
80+
81+
return rc;
82+
}
83+
84+
static int sqlcipher_ltc_activate(void *ctx) {
85+
unsigned char random_buffer[FORTUNA_MAX_SZ];
86+
int bytes = 0;
87+
88+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
89+
sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
90+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
91+
92+
sqlcipher_memset(random_buffer, 0, FORTUNA_MAX_SZ);
93+
if(ltc_init == 0) {
94+
if(register_prng(&fortuna_desc) < 0) return SQLITE_ERROR;
95+
if(register_cipher(&rijndael_desc) < 0) return SQLITE_ERROR;
96+
if(register_hash(&sha512_desc) < 0) return SQLITE_ERROR;
97+
if(register_hash(&sha256_desc) < 0) return SQLITE_ERROR;
98+
if(register_hash(&sha1_desc) < 0) return SQLITE_ERROR;
99+
if(fortuna_start(&prng) != CRYPT_OK) {
100+
return SQLITE_ERROR;
101+
}
102+
103+
ltc_init = 1;
104+
}
105+
ltc_ref_count++;
106+
107+
#ifndef SQLCIPHER_TEST
108+
bytes = rng_get_bytes(random_buffer, FORTUNA_MAX_SZ, NULL);
109+
#endif
110+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_PROVIDER, "sqlcipher_ltc_activate: seeded fortuna with %d bytes from rng_get_bytes", bytes);
111+
112+
if(sqlcipher_ltc_add_random(ctx, random_buffer, FORTUNA_MAX_SZ) != SQLITE_OK) {
113+
return SQLITE_ERROR;
114+
}
115+
sqlcipher_memset(random_buffer, 0, FORTUNA_MAX_SZ);
116+
117+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
118+
sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
119+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
120+
121+
return SQLITE_OK;
122+
}
123+
124+
static int sqlcipher_ltc_deactivate(void *ctx) {
125+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_deactivate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
126+
sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
127+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_deactivate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
128+
129+
ltc_ref_count--;
130+
if(ltc_ref_count == 0){
131+
fortuna_done(&prng);
132+
sqlcipher_memset((void *)&prng, 0, sizeof(prng));
133+
}
134+
135+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_deactivate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
136+
sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE));
137+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_deactivate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
138+
139+
return SQLITE_OK;
140+
}
141+
142+
static const char* sqlcipher_ltc_get_provider_name(void *ctx) {
143+
return "libtomcrypt";
144+
}
145+
146+
static const char* sqlcipher_ltc_get_provider_version(void *ctx) {
147+
return SCRYPT;
148+
}
149+
150+
static int sqlcipher_ltc_random(void *ctx, void *buffer, int length) {
151+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_random: entering SQLCIPHER_MUTEX_PROVIDER_RAND");
152+
sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
153+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_random: entered SQLCIPHER_MUTEX_PROVIDER_RAND");
154+
155+
fortuna_read(buffer, length, &prng);
156+
157+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_random: leaving SQLCIPHER_MUTEX_PROVIDER_RAND");
158+
sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_RAND));
159+
sqlcipher_log(SQLCIPHER_LOG_TRACE, SQLCIPHER_LOG_MUTEX, "sqlcipher_ltc_random: left SQLCIPHER_MUTEX_PROVIDER_RAND");
160+
161+
return SQLITE_OK;
162+
}
163+
164+
static int sqlcipher_ltc_hmac(
165+
void *ctx, int algorithm,
166+
const unsigned char *hmac_key, int key_sz,
167+
const unsigned char *in, int in_sz,
168+
const unsigned char *in2, int in2_sz,
169+
unsigned char *out
170+
) {
171+
int rc, hash_idx;
172+
hmac_state hmac;
173+
unsigned long outlen;
174+
switch(algorithm) {
175+
case SQLCIPHER_HMAC_SHA1:
176+
hash_idx = find_hash("sha1");
177+
break;
178+
case SQLCIPHER_HMAC_SHA256:
179+
hash_idx = find_hash("sha256");
180+
break;
181+
case SQLCIPHER_HMAC_SHA512:
182+
hash_idx = find_hash("sha512");
183+
break;
184+
default:
185+
return SQLITE_ERROR;
186+
}
187+
188+
if(hash_idx < 0) return SQLITE_ERROR;
189+
outlen = hash_descriptor[hash_idx].hashsize;
190+
191+
if(in == NULL) return SQLITE_ERROR;
192+
if((rc = hmac_init(&hmac, hash_idx, hmac_key, key_sz)) != CRYPT_OK) return SQLITE_ERROR;
193+
if((rc = hmac_process(&hmac, in, in_sz)) != CRYPT_OK) return SQLITE_ERROR;
194+
if(in2 != NULL && (rc = hmac_process(&hmac, in2, in2_sz)) != CRYPT_OK) return SQLITE_ERROR;
195+
if((rc = hmac_done(&hmac, out, &outlen)) != CRYPT_OK) return SQLITE_ERROR;
196+
return SQLITE_OK;
197+
}
198+
199+
static int sqlcipher_ltc_kdf(
200+
void *ctx, int algorithm,
201+
const unsigned char *pass, int pass_sz,
202+
const unsigned char* salt, int salt_sz,
203+
int workfactor,
204+
int key_sz, unsigned char *key
205+
) {
206+
int rc, hash_idx;
207+
unsigned long outlen = key_sz;
208+
209+
switch(algorithm) {
210+
case SQLCIPHER_HMAC_SHA1:
211+
hash_idx = find_hash("sha1");
212+
break;
213+
case SQLCIPHER_HMAC_SHA256:
214+
hash_idx = find_hash("sha256");
215+
break;
216+
case SQLCIPHER_HMAC_SHA512:
217+
hash_idx = find_hash("sha512");
218+
break;
219+
default:
220+
return SQLITE_ERROR;
221+
}
222+
if(hash_idx < 0) return SQLITE_ERROR;
223+
224+
if((rc = pkcs_5_alg2(pass, pass_sz, salt, salt_sz,
225+
workfactor, hash_idx, key, &outlen)) != CRYPT_OK) {
226+
return SQLITE_ERROR;
227+
}
228+
return SQLITE_OK;
229+
}
230+
231+
static const char* sqlcipher_ltc_get_cipher(void *ctx) {
232+
return "aes-256-cbc";
233+
}
234+
235+
static int sqlcipher_ltc_cipher(
236+
void *ctx, int mode,
237+
const unsigned char *key, int key_sz,
238+
const unsigned char *iv,
239+
const unsigned char *in, int in_sz,
240+
unsigned char *out
241+
) {
242+
int rc, cipher_idx;
243+
symmetric_CBC cbc;
244+
245+
if((cipher_idx = find_cipher(LTC_CIPHER)) == -1) return SQLITE_ERROR;
246+
if((rc = cbc_start(cipher_idx, iv, key, key_sz, 0, &cbc)) != CRYPT_OK) return SQLITE_ERROR;
247+
rc = mode == SQLCIPHER_ENCRYPT ? cbc_encrypt(in, out, in_sz, &cbc) : cbc_decrypt(in, out, in_sz, &cbc);
248+
if(rc != CRYPT_OK) return SQLITE_ERROR;
249+
cbc_done(&cbc);
250+
return SQLITE_OK;
251+
}
252+
253+
static int sqlcipher_ltc_get_key_sz(void *ctx) {
254+
int cipher_idx = find_cipher(LTC_CIPHER);
255+
return cipher_descriptor[cipher_idx].max_key_length;
256+
}
257+
258+
static int sqlcipher_ltc_get_iv_sz(void *ctx) {
259+
int cipher_idx = find_cipher(LTC_CIPHER);
260+
return cipher_descriptor[cipher_idx].block_length;
261+
}
262+
263+
static int sqlcipher_ltc_get_block_sz(void *ctx) {
264+
int cipher_idx = find_cipher(LTC_CIPHER);
265+
return cipher_descriptor[cipher_idx].block_length;
266+
}
267+
268+
static int sqlcipher_ltc_get_hmac_sz(void *ctx, int algorithm) {
269+
int hash_idx;
270+
switch(algorithm) {
271+
case SQLCIPHER_HMAC_SHA1:
272+
hash_idx = find_hash("sha1");
273+
break;
274+
case SQLCIPHER_HMAC_SHA256:
275+
hash_idx = find_hash("sha256");
276+
break;
277+
case SQLCIPHER_HMAC_SHA512:
278+
hash_idx = find_hash("sha512");
279+
break;
280+
default:
281+
return 0;
282+
}
283+
284+
if(hash_idx < 0) return 0;
285+
286+
return hash_descriptor[hash_idx].hashsize;
287+
}
288+
289+
static int sqlcipher_ltc_ctx_init(void **ctx) {
290+
sqlcipher_ltc_activate(NULL);
291+
return SQLITE_OK;
292+
}
293+
294+
static int sqlcipher_ltc_ctx_free(void **ctx) {
295+
sqlcipher_ltc_deactivate(&ctx);
296+
return SQLITE_OK;
297+
}
298+
299+
static int sqlcipher_ltc_fips_status(void *ctx) {
300+
return 0;
301+
}
302+
303+
int sqlcipher_ltc_setup(sqlcipher_provider *p) {
304+
p->init = NULL;
305+
p->shutdown = NULL;
306+
p->get_provider_name = sqlcipher_ltc_get_provider_name;
307+
p->random = sqlcipher_ltc_random;
308+
p->hmac = sqlcipher_ltc_hmac;
309+
p->kdf = sqlcipher_ltc_kdf;
310+
p->cipher = sqlcipher_ltc_cipher;
311+
p->get_cipher = sqlcipher_ltc_get_cipher;
312+
p->get_key_sz = sqlcipher_ltc_get_key_sz;
313+
p->get_iv_sz = sqlcipher_ltc_get_iv_sz;
314+
p->get_block_sz = sqlcipher_ltc_get_block_sz;
315+
p->get_hmac_sz = sqlcipher_ltc_get_hmac_sz;
316+
p->ctx_init = sqlcipher_ltc_ctx_init;
317+
p->ctx_free = sqlcipher_ltc_ctx_free;
318+
p->add_random = sqlcipher_ltc_add_random;
319+
p->fips_status = sqlcipher_ltc_fips_status;
320+
p->get_provider_version = sqlcipher_ltc_get_provider_version;
321+
return SQLITE_OK;
322+
}
323+
324+
#endif
325+
#endif
326+
/* END SQLCIPHER */

0 commit comments

Comments
 (0)