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
34 #include "sqlcipher.h"
35 #include <nss/blapit.h>
37 #include <nss/pk11pub.h>
39 static NSSInitContext
* nss_init_context
= NULL
;
40 static unsigned int nss_init_count
= 0;
42 int sqlcipher_nss_setup(sqlcipher_provider
*p
);
44 static int sqlcipher_nss_activate(void *ctx
) {
46 sqlcipher_log(SQLCIPHER_LOG_TRACE
, SQLCIPHER_LOG_MUTEX
, "sqlcipher_nss_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
47 sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE
));
48 sqlcipher_log(SQLCIPHER_LOG_TRACE
, SQLCIPHER_LOG_MUTEX
, "sqlcipher_nss_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
49 if (nss_init_context
== NULL
) {
50 nss_init_context
= NSS_InitContext("", "", "", "", NULL
,
51 NSS_INIT_READONLY
| NSS_INIT_NOCERTDB
| NSS_INIT_NOMODDB
|
52 NSS_INIT_FORCEOPEN
| NSS_INIT_OPTIMIZESPACE
| NSS_INIT_NOROOTINIT
);
55 sqlcipher_log(SQLCIPHER_LOG_TRACE
, SQLCIPHER_LOG_MUTEX
, "sqlcipher_nss_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
56 sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE
));
57 sqlcipher_log(SQLCIPHER_LOG_TRACE
, SQLCIPHER_LOG_MUTEX
, "sqlcipher_nss_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
61 static int sqlcipher_nss_deactivate(void *ctx
) {
62 sqlcipher_log(SQLCIPHER_LOG_TRACE
, SQLCIPHER_LOG_MUTEX
, "sqlcipher_nss_activate: entering SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
63 sqlite3_mutex_enter(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE
));
64 sqlcipher_log(SQLCIPHER_LOG_TRACE
, SQLCIPHER_LOG_MUTEX
, "sqlcipher_nss_activate: entered SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
67 if (nss_init_count
== 0 && nss_init_context
!= NULL
) {
68 NSS_ShutdownContext(nss_init_context
);
69 nss_init_context
= NULL
;
72 sqlcipher_log(SQLCIPHER_LOG_TRACE
, SQLCIPHER_LOG_MUTEX
, "sqlcipher_nss_activate: leaving SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
73 sqlite3_mutex_leave(sqlcipher_mutex(SQLCIPHER_MUTEX_PROVIDER_ACTIVATE
));
74 sqlcipher_log(SQLCIPHER_LOG_TRACE
, SQLCIPHER_LOG_MUTEX
, "sqlcipher_nss_activate: left SQLCIPHER_MUTEX_PROVIDER_ACTIVATE");
78 static int sqlcipher_nss_add_random(void *ctx
, void *buffer
, int length
) {
82 /* generate a defined number of random bytes */
83 static int sqlcipher_nss_random (void *ctx
, void *buffer
, int length
) {
84 // PK11_GenerateRandom should be thread-safe.
85 return (PK11_GenerateRandom((unsigned char *)buffer
, length
) == SECSuccess
) ? SQLITE_OK
: SQLITE_ERROR
;
88 static const char* sqlcipher_nss_get_provider_name(void *ctx
) {
92 static const char* sqlcipher_nss_get_provider_version(void *ctx
) {
93 return NSS_GetVersion();
96 static const char* sqlcipher_nss_get_cipher(void *ctx
) {
100 static int sqlcipher_nss_get_key_sz(void *ctx
) {
101 return AES_256_KEY_LENGTH
;
104 static int sqlcipher_nss_get_iv_sz(void *ctx
) {
105 return AES_BLOCK_SIZE
;
108 static int sqlcipher_nss_get_block_sz(void *ctx
) {
109 return AES_BLOCK_SIZE
;
112 static int sqlcipher_nss_get_hmac_sz(void *ctx
, int algorithm
) {
114 case SQLCIPHER_HMAC_SHA1
:
117 case SQLCIPHER_HMAC_SHA256
:
118 return SHA256_LENGTH
;
120 case SQLCIPHER_HMAC_SHA512
:
121 return SHA512_LENGTH
;
128 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
) {
132 PK11Context
* context
= NULL
;
133 PK11SlotInfo
* slot
= NULL
;
134 PK11SymKey
* symKey
= NULL
;
135 if(in
== NULL
) goto error
;
136 CK_MECHANISM_TYPE mech
;
138 case SQLCIPHER_HMAC_SHA1
:
139 mech
= CKM_SHA_1_HMAC
;
141 case SQLCIPHER_HMAC_SHA256
:
142 mech
= CKM_SHA256_HMAC
;
144 case SQLCIPHER_HMAC_SHA512
:
145 mech
= CKM_SHA512_HMAC
;
150 length
= sqlcipher_nss_get_hmac_sz(ctx
, algorithm
);
151 slot
= PK11_GetInternalSlot();
152 if (slot
== NULL
) goto error
;
154 keyItem
.data
= hmac_key
;
155 keyItem
.len
= key_sz
;
156 symKey
= PK11_ImportSymKey(slot
, mech
, PK11_OriginUnwrap
,
157 CKA_SIGN
, &keyItem
, NULL
);
158 if (symKey
== NULL
) goto error
;
162 context
= PK11_CreateContextBySymKey(mech
, CKA_SIGN
, symKey
, &noParams
);
163 if (context
== NULL
) goto error
;
164 if (PK11_DigestBegin(context
) != SECSuccess
) goto error
;
165 if (PK11_DigestOp(context
, in
, in_sz
) != SECSuccess
) goto error
;
167 if (PK11_DigestOp(context
, in2
, in2_sz
) != SECSuccess
) goto error
;
169 if (PK11_DigestFinal(context
, out
, &outLen
, length
) != SECSuccess
) goto error
;
175 if (context
) PK11_DestroyContext(context
, PR_TRUE
);
176 if (symKey
) PK11_FreeSymKey(symKey
);
177 if (slot
) PK11_FreeSlot(slot
);
181 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
) {
183 PK11SlotInfo
* slot
= NULL
;
184 SECAlgorithmID
* algid
= NULL
;
185 PK11SymKey
* symKey
= NULL
;
188 case SQLCIPHER_HMAC_SHA1
:
189 oidtag
= SEC_OID_HMAC_SHA1
;
191 case SQLCIPHER_HMAC_SHA256
:
192 oidtag
= SEC_OID_HMAC_SHA256
;
194 case SQLCIPHER_HMAC_SHA512
:
195 oidtag
= SEC_OID_HMAC_SHA512
;
202 secSalt
.len
= salt_sz
;
203 // Always pass SEC_OID_HMAC_SHA1 (i.e. PBMAC1) as this parameter
204 // is unused for key generation. It is currently only used
205 // for PBKDF2 authentication or key (un)wrapping when specifying an
206 // encryption algorithm (PBES2).
207 algid
= PK11_CreatePBEV2AlgorithmID(SEC_OID_PKCS5_PBKDF2
, SEC_OID_HMAC_SHA1
,
208 oidtag
, key_sz
, workfactor
, &secSalt
);
209 if (algid
== NULL
) goto error
;
210 slot
= PK11_GetInternalSlot();
211 if (slot
== NULL
) goto error
;
213 pwItem
.data
= (unsigned char *) pass
; // PK11_PBEKeyGen doesn't modify the key.
214 pwItem
.len
= pass_sz
;
215 symKey
= PK11_PBEKeyGen(slot
, algid
, &pwItem
, PR_FALSE
, NULL
);
216 if (symKey
== NULL
) goto error
;
217 if (PK11_ExtractKeyValue(symKey
) != SECSuccess
) goto error
;
218 // No need to free keyData as it is a buffer managed by symKey.
219 SECItem
* keyData
= PK11_GetKeyData(symKey
);
220 if (keyData
== NULL
) goto error
;
221 memcpy(key
, keyData
->data
, key_sz
);
227 if (slot
) PK11_FreeSlot(slot
);
228 if (algid
) SECOID_DestroyAlgorithmID(algid
, PR_TRUE
);
229 if (symKey
) PK11_FreeSymKey(symKey
);
233 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
) {
235 PK11SlotInfo
* slot
= NULL
;
236 PK11SymKey
* symKey
= NULL
;
240 params
.len
= sqlcipher_nss_get_iv_sz(ctx
);
241 slot
= PK11_GetInternalSlot();
242 if (slot
== NULL
) goto error
;
245 keyItem
.len
= key_sz
;
246 symKey
= PK11_ImportSymKey(slot
, CKM_AES_CBC
, PK11_OriginUnwrap
,
247 CKA_ENCRYPT
, &keyItem
, NULL
);
248 if (symKey
== NULL
) goto error
;
250 if (mode
== CIPHER_ENCRYPT
) {
251 rv
= PK11_Encrypt(symKey
, CKM_AES_CBC
, ¶ms
, out
, &outLen
,
252 in_sz
+ 16, in
, in_sz
);
254 rv
= PK11_Decrypt(symKey
, CKM_AES_CBC
, ¶ms
, out
, &outLen
,
255 in_sz
+ 16, in
, in_sz
);
257 if (rv
!= SECSuccess
) goto error
;
263 if (slot
) PK11_FreeSlot(slot
);
264 if (symKey
) PK11_FreeSymKey(symKey
);
268 static int sqlcipher_nss_ctx_init(void **ctx
) {
269 sqlcipher_nss_activate(NULL
);
273 static int sqlcipher_nss_ctx_free(void **ctx
) {
274 sqlcipher_nss_deactivate(NULL
);
278 static int sqlcipher_nss_fips_status(void *ctx
) {
282 int sqlcipher_nss_setup(sqlcipher_provider
*p
) {
283 p
->activate
= sqlcipher_nss_activate
;
284 p
->deactivate
= sqlcipher_nss_deactivate
;
285 p
->random
= sqlcipher_nss_random
;
286 p
->get_provider_name
= sqlcipher_nss_get_provider_name
;
287 p
->hmac
= sqlcipher_nss_hmac
;
288 p
->kdf
= sqlcipher_nss_kdf
;
289 p
->cipher
= sqlcipher_nss_cipher
;
290 p
->get_cipher
= sqlcipher_nss_get_cipher
;
291 p
->get_key_sz
= sqlcipher_nss_get_key_sz
;
292 p
->get_iv_sz
= sqlcipher_nss_get_iv_sz
;
293 p
->get_block_sz
= sqlcipher_nss_get_block_sz
;
294 p
->get_hmac_sz
= sqlcipher_nss_get_hmac_sz
;
295 p
->ctx_init
= sqlcipher_nss_ctx_init
;
296 p
->ctx_free
= sqlcipher_nss_ctx_free
;
297 p
->add_random
= sqlcipher_nss_add_random
;
298 p
->fips_status
= sqlcipher_nss_fips_status
;
299 p
->get_provider_version
= sqlcipher_nss_get_provider_version
;