3 ** http://sqlcipher.net
5 ** Copyright (c) 2008 - 2013, ZETETIC LLC
6 ** All rights reserved.
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.
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.
32 #ifdef SQLITE_HAS_CODEC
33 #ifdef SQLCIPHER_CRYPTO_NSS
35 #include "sqlcipher.h"
36 #include <nss/blapit.h>
38 #include <nss/pk11pub.h>
40 static NSSInitContext
* nss_init_context
= NULL
;
41 static unsigned int nss_init_count
= 0;
43 int sqlcipher_nss_setup(sqlcipher_provider
*p
);
45 static int sqlcipher_nss_activate(void *ctx
) {
47 CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
48 sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE
));
49 CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
50 if (nss_init_context
== NULL
) {
51 nss_init_context
= NSS_InitContext("", "", "", "", NULL
,
52 NSS_INIT_READONLY
| NSS_INIT_NOCERTDB
| NSS_INIT_NOMODDB
|
53 NSS_INIT_FORCEOPEN
| NSS_INIT_OPTIMIZESPACE
| NSS_INIT_NOROOTINIT
);
56 CODEC_TRACE_MUTEX("sqlcipher_nss_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
57 sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE
));
58 CODEC_TRACE_MUTEX("sqlcipher_nss_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
62 static int sqlcipher_nss_deactivate(void *ctx
) {
63 CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
64 sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE
));
65 CODEC_TRACE_MUTEX("sqlcipher_nss_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
68 if (nss_init_count
== 0 && nss_init_context
!= NULL
) {
69 NSS_ShutdownContext(nss_init_context
);
70 nss_init_context
= NULL
;
73 CODEC_TRACE_MUTEX("sqlcipher_nss_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
74 sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE
));
75 CODEC_TRACE_MUTEX("sqlcipher_nss_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE\n");
79 static int sqlcipher_nss_add_random(void *ctx
, void *buffer
, int length
) {
83 /* generate a defined number of random bytes */
84 static int sqlcipher_nss_random (void *ctx
, void *buffer
, int length
) {
85 // PK11_GenerateRandom should be thread-safe.
86 return (PK11_GenerateRandom((unsigned char *)buffer
, length
) == SECSuccess
) ? SQLITE_OK
: SQLITE_ERROR
;
89 static const char* sqlcipher_nss_get_provider_name(void *ctx
) {
93 static const char* sqlcipher_nss_get_provider_version(void *ctx
) {
94 return NSS_GetVersion();
97 static const char* sqlcipher_nss_get_cipher(void *ctx
) {
101 static int sqlcipher_nss_get_key_sz(void *ctx
) {
102 return AES_256_KEY_LENGTH
;
105 static int sqlcipher_nss_get_iv_sz(void *ctx
) {
106 return AES_BLOCK_SIZE
;
109 static int sqlcipher_nss_get_block_sz(void *ctx
) {
110 return AES_BLOCK_SIZE
;
113 static int sqlcipher_nss_get_hmac_sz(void *ctx
, int algorithm
) {
115 case SQLCIPHER_HMAC_SHA1
:
118 case SQLCIPHER_HMAC_SHA256
:
119 return SHA256_LENGTH
;
121 case SQLCIPHER_HMAC_SHA512
:
122 return SHA512_LENGTH
;
129 static int sqlcipher_nss_hmac(void *ctx
, int algorithm
, unsigned char *hmac_key
, int key_sz
, unsigned char *in
, int in_sz
, unsigned char *in2
, int in2_sz
, unsigned char *out
) {
133 PK11Context
* context
= NULL
;
134 PK11SlotInfo
* slot
= NULL
;
135 PK11SymKey
* symKey
= NULL
;
136 if(in
== NULL
) goto error
;
137 CK_MECHANISM_TYPE mech
;
139 case SQLCIPHER_HMAC_SHA1
:
140 mech
= CKM_SHA_1_HMAC
;
142 case SQLCIPHER_HMAC_SHA256
:
143 mech
= CKM_SHA256_HMAC
;
145 case SQLCIPHER_HMAC_SHA512
:
146 mech
= CKM_SHA512_HMAC
;
151 length
= sqlcipher_nss_get_hmac_sz(ctx
, algorithm
);
152 slot
= PK11_GetInternalSlot();
153 if (slot
== NULL
) goto error
;
155 keyItem
.data
= hmac_key
;
156 keyItem
.len
= key_sz
;
157 symKey
= PK11_ImportSymKey(slot
, mech
, PK11_OriginUnwrap
,
158 CKA_SIGN
, &keyItem
, NULL
);
159 if (symKey
== NULL
) goto error
;
163 context
= PK11_CreateContextBySymKey(mech
, CKA_SIGN
, symKey
, &noParams
);
164 if (context
== NULL
) goto error
;
165 if (PK11_DigestBegin(context
) != SECSuccess
) goto error
;
166 if (PK11_DigestOp(context
, in
, in_sz
) != SECSuccess
) goto error
;
168 if (PK11_DigestOp(context
, in2
, in2_sz
) != SECSuccess
) goto error
;
170 if (PK11_DigestFinal(context
, out
, &outLen
, length
) != SECSuccess
) goto error
;
176 if (context
) PK11_DestroyContext(context
, PR_TRUE
);
177 if (symKey
) PK11_FreeSymKey(symKey
);
178 if (slot
) PK11_FreeSlot(slot
);
182 static int sqlcipher_nss_kdf(void *ctx
, int algorithm
, const unsigned char *pass
, int pass_sz
, unsigned char* salt
, int salt_sz
, int workfactor
, int key_sz
, unsigned char *key
) {
184 PK11SlotInfo
* slot
= NULL
;
185 SECAlgorithmID
* algid
= NULL
;
186 PK11SymKey
* symKey
= NULL
;
189 case SQLCIPHER_HMAC_SHA1
:
190 oidtag
= SEC_OID_HMAC_SHA1
;
192 case SQLCIPHER_HMAC_SHA256
:
193 oidtag
= SEC_OID_HMAC_SHA256
;
195 case SQLCIPHER_HMAC_SHA512
:
196 oidtag
= SEC_OID_HMAC_SHA512
;
203 secSalt
.len
= salt_sz
;
204 // Always pass SEC_OID_HMAC_SHA1 (i.e. PBMAC1) as this parameter
205 // is unused for key generation. It is currently only used
206 // for PBKDF2 authentication or key (un)wrapping when specifying an
207 // encryption algorithm (PBES2).
208 algid
= PK11_CreatePBEV2AlgorithmID(SEC_OID_PKCS5_PBKDF2
, SEC_OID_HMAC_SHA1
,
209 oidtag
, key_sz
, workfactor
, &secSalt
);
210 if (algid
== NULL
) goto error
;
211 slot
= PK11_GetInternalSlot();
212 if (slot
== NULL
) goto error
;
214 pwItem
.data
= (unsigned char *) pass
; // PK11_PBEKeyGen doesn't modify the key.
215 pwItem
.len
= pass_sz
;
216 symKey
= PK11_PBEKeyGen(slot
, algid
, &pwItem
, PR_FALSE
, NULL
);
217 if (symKey
== NULL
) goto error
;
218 if (PK11_ExtractKeyValue(symKey
) != SECSuccess
) goto error
;
219 // No need to free keyData as it is a buffer managed by symKey.
220 SECItem
* keyData
= PK11_GetKeyData(symKey
);
221 if (keyData
== NULL
) goto error
;
222 memcpy(key
, keyData
->data
, key_sz
);
228 if (slot
) PK11_FreeSlot(slot
);
229 if (algid
) SECOID_DestroyAlgorithmID(algid
, PR_TRUE
);
230 if (symKey
) PK11_FreeSymKey(symKey
);
234 static int sqlcipher_nss_cipher(void *ctx
, int mode
, unsigned char *key
, int key_sz
, unsigned char *iv
, unsigned char *in
, int in_sz
, unsigned char *out
) {
236 PK11SlotInfo
* slot
= NULL
;
237 PK11SymKey
* symKey
= NULL
;
241 params
.len
= sqlcipher_nss_get_iv_sz(ctx
);
242 slot
= PK11_GetInternalSlot();
243 if (slot
== NULL
) goto error
;
246 keyItem
.len
= key_sz
;
247 symKey
= PK11_ImportSymKey(slot
, CKM_AES_CBC
, PK11_OriginUnwrap
,
248 CKA_ENCRYPT
, &keyItem
, NULL
);
249 if (symKey
== NULL
) goto error
;
251 if (mode
== CIPHER_ENCRYPT
) {
252 rv
= PK11_Encrypt(symKey
, CKM_AES_CBC
, ¶ms
, out
, &outLen
,
253 in_sz
+ 16, in
, in_sz
);
255 rv
= PK11_Decrypt(symKey
, CKM_AES_CBC
, ¶ms
, out
, &outLen
,
256 in_sz
+ 16, in
, in_sz
);
258 if (rv
!= SECSuccess
) goto error
;
264 if (slot
) PK11_FreeSlot(slot
);
265 if (symKey
) PK11_FreeSymKey(symKey
);
269 static int sqlcipher_nss_ctx_init(void **ctx
) {
270 sqlcipher_nss_activate(NULL
);
274 static int sqlcipher_nss_ctx_free(void **ctx
) {
275 sqlcipher_nss_deactivate(NULL
);
279 static int sqlcipher_nss_fips_status(void *ctx
) {
283 int sqlcipher_nss_setup(sqlcipher_provider
*p
) {
284 p
->activate
= sqlcipher_nss_activate
;
285 p
->deactivate
= sqlcipher_nss_deactivate
;
286 p
->random
= sqlcipher_nss_random
;
287 p
->get_provider_name
= sqlcipher_nss_get_provider_name
;
288 p
->hmac
= sqlcipher_nss_hmac
;
289 p
->kdf
= sqlcipher_nss_kdf
;
290 p
->cipher
= sqlcipher_nss_cipher
;
291 p
->get_cipher
= sqlcipher_nss_get_cipher
;
292 p
->get_key_sz
= sqlcipher_nss_get_key_sz
;
293 p
->get_iv_sz
= sqlcipher_nss_get_iv_sz
;
294 p
->get_block_sz
= sqlcipher_nss_get_block_sz
;
295 p
->get_hmac_sz
= sqlcipher_nss_get_hmac_sz
;
296 p
->ctx_init
= sqlcipher_nss_ctx_init
;
297 p
->ctx_free
= sqlcipher_nss_ctx_free
;
298 p
->add_random
= sqlcipher_nss_add_random
;
299 p
->fips_status
= sqlcipher_nss_fips_status
;
300 p
->get_provider_version
= sqlcipher_nss_get_provider_version
;