Replaces use of deprecated WINAPI_FAMILY_APP macro with WINAPI_FAMILY_PC_APP
[sqlcipher.git] / src / crypto_nss.c
blob167ede9048445cf933444408db26e131bd44d095
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.
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.
31 /* BEGIN SQLCIPHER */
32 #ifdef SQLITE_HAS_CODEC
33 #ifdef SQLCIPHER_CRYPTO_NSS
34 #include "sqlcipher.h"
35 #include <nss/blapit.h>
36 #include <nss/nss.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);
54 nss_init_count++;
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");
58 return SQLITE_OK;
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");
66 nss_init_count--;
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");
75 return SQLITE_OK;
78 static int sqlcipher_nss_add_random(void *ctx, void *buffer, int length) {
79 return SQLITE_OK;
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) {
89 return "nss";
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) {
97 return "aes-256-cbc";
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) {
113 switch(algorithm) {
114 case SQLCIPHER_HMAC_SHA1:
115 return SHA1_LENGTH;
116 break;
117 case SQLCIPHER_HMAC_SHA256:
118 return SHA256_LENGTH;
119 break;
120 case SQLCIPHER_HMAC_SHA512:
121 return SHA512_LENGTH;
122 break;
123 default:
124 return 0;
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) {
129 int rc = SQLITE_OK;
130 unsigned int length;
131 unsigned int outLen;
132 PK11Context* context = NULL;
133 PK11SlotInfo * slot = NULL;
134 PK11SymKey* symKey = NULL;
135 if(in == NULL) goto error;
136 CK_MECHANISM_TYPE mech;
137 switch(algorithm) {
138 case SQLCIPHER_HMAC_SHA1:
139 mech = CKM_SHA_1_HMAC;
140 break;
141 case SQLCIPHER_HMAC_SHA256:
142 mech = CKM_SHA256_HMAC;
143 break;
144 case SQLCIPHER_HMAC_SHA512:
145 mech = CKM_SHA512_HMAC;
146 break;
147 default:
148 goto error;
150 length = sqlcipher_nss_get_hmac_sz(ctx, algorithm);
151 slot = PK11_GetInternalSlot();
152 if (slot == NULL) goto error;
153 SECItem keyItem;
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;
159 SECItem noParams;
160 noParams.data = 0;
161 noParams.len = 0;
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;
166 if (in2 != NULL) {
167 if (PK11_DigestOp(context, in2, in2_sz) != SECSuccess) goto error;
169 if (PK11_DigestFinal(context, out, &outLen, length) != SECSuccess) goto error;
171 goto cleanup;
172 error:
173 rc = SQLITE_ERROR;
174 cleanup:
175 if (context) PK11_DestroyContext(context, PR_TRUE);
176 if (symKey) PK11_FreeSymKey(symKey);
177 if (slot) PK11_FreeSlot(slot);
178 return rc;
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) {
182 int rc = SQLITE_OK;
183 PK11SlotInfo * slot = NULL;
184 SECAlgorithmID * algid = NULL;
185 PK11SymKey* symKey = NULL;
186 SECOidTag oidtag;
187 switch(algorithm) {
188 case SQLCIPHER_HMAC_SHA1:
189 oidtag = SEC_OID_HMAC_SHA1;
190 break;
191 case SQLCIPHER_HMAC_SHA256:
192 oidtag = SEC_OID_HMAC_SHA256;
193 break;
194 case SQLCIPHER_HMAC_SHA512:
195 oidtag = SEC_OID_HMAC_SHA512;
196 break;
197 default:
198 goto error;
200 SECItem secSalt;
201 secSalt.data = salt;
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;
212 SECItem pwItem;
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);
223 goto cleanup;
224 error:
225 rc = SQLITE_ERROR;
226 cleanup:
227 if (slot) PK11_FreeSlot(slot);
228 if (algid) SECOID_DestroyAlgorithmID(algid, PR_TRUE);
229 if (symKey) PK11_FreeSymKey(symKey);
230 return rc;
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) {
234 int rc = SQLITE_OK;
235 PK11SlotInfo * slot = NULL;
236 PK11SymKey* symKey = NULL;
237 unsigned int outLen;
238 SECItem params;
239 params.data = iv;
240 params.len = sqlcipher_nss_get_iv_sz(ctx);
241 slot = PK11_GetInternalSlot();
242 if (slot == NULL) goto error;
243 SECItem keyItem;
244 keyItem.data = key;
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;
249 SECStatus rv;
250 if (mode == CIPHER_ENCRYPT) {
251 rv = PK11_Encrypt(symKey, CKM_AES_CBC, &params, out, &outLen,
252 in_sz + 16, in, in_sz);
253 } else {
254 rv = PK11_Decrypt(symKey, CKM_AES_CBC, &params, out, &outLen,
255 in_sz + 16, in, in_sz);
257 if (rv != SECSuccess) goto error;
259 goto cleanup;
260 error:
261 rc = SQLITE_ERROR;
262 cleanup:
263 if (slot) PK11_FreeSlot(slot);
264 if (symKey) PK11_FreeSymKey(symKey);
265 return rc;
268 static int sqlcipher_nss_ctx_init(void **ctx) {
269 sqlcipher_nss_activate(NULL);
270 return SQLITE_OK;
273 static int sqlcipher_nss_ctx_free(void **ctx) {
274 sqlcipher_nss_deactivate(NULL);
275 return SQLITE_OK;
278 static int sqlcipher_nss_fips_status(void *ctx) {
279 return 0;
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;
300 return SQLITE_OK;
303 #endif
304 #endif
305 /* END SQLCIPHER */