1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
11 #include <android/log.h>
14 #include "ElfLoader.h"
17 #define LOG(x...) __android_log_print(ANDROID_LOG_INFO, "GeckoJNI", x)
22 static bool initialized
= false;
24 #define NSS_WRAPPER_INT(name) name ## _t f_ ## name;
25 NSS_WRAPPER_INT(NSS_Initialize
)
26 NSS_WRAPPER_INT(NSS_Shutdown
)
27 NSS_WRAPPER_INT(SECITEM_ZfreeItem
)
28 NSS_WRAPPER_INT(PK11SDR_Encrypt
)
29 NSS_WRAPPER_INT(PK11SDR_Decrypt
)
30 NSS_WRAPPER_INT(PK11_GetInternalKeySlot
)
31 NSS_WRAPPER_INT(PK11_NeedUserInit
)
32 NSS_WRAPPER_INT(PK11_InitPin
)
33 NSS_WRAPPER_INT(PR_ErrorToString
)
34 NSS_WRAPPER_INT(PR_GetError
)
35 NSS_WRAPPER_INT(PR_Free
)
36 NSS_WRAPPER_INT(PL_Base64Encode
)
37 NSS_WRAPPER_INT(PL_Base64Decode
)
38 NSS_WRAPPER_INT(PL_strfree
)
41 setup_nss_functions(void *nss_handle
,
45 if (nss_handle
== nullptr || nspr_handle
== nullptr || plc_handle
== nullptr) {
46 LOG("Missing handle\n");
49 #define GETFUNC(name) f_ ## name = (name ## _t) (uintptr_t) __wrap_dlsym(nss_handle, #name); \
50 if (!f_ ##name) { __android_log_print(ANDROID_LOG_ERROR, "GeckoJNI", "missing %s", #name); return FAILURE; }
51 GETFUNC(NSS_Initialize
);
52 GETFUNC(NSS_Shutdown
);
53 GETFUNC(PK11SDR_Encrypt
);
54 GETFUNC(PK11SDR_Decrypt
);
55 GETFUNC(PK11_GetInternalKeySlot
);
56 GETFUNC(PK11_NeedUserInit
);
57 GETFUNC(PK11_InitPin
);
58 GETFUNC(SECITEM_ZfreeItem
);
60 #define NSPRFUNC(name) f_ ## name = (name ## _t) (uintptr_t) __wrap_dlsym(nspr_handle, #name); \
61 if (!f_ ##name) { __android_log_print(ANDROID_LOG_ERROR, "GeckoJNI", "missing %s", #name); return FAILURE; }
62 NSPRFUNC(PR_ErrorToString
);
63 NSPRFUNC(PR_GetError
);
66 #define PLCFUNC(name) f_ ## name = (name ## _t) (uintptr_t) __wrap_dlsym(plc_handle, #name); \
67 if (!f_ ##name) { __android_log_print(ANDROID_LOG_ERROR, "GeckoJNI", "missing %s", #name); return FAILURE; }
68 PLCFUNC(PL_Base64Encode
);
69 PLCFUNC(PL_Base64Decode
);
76 /* Throws the current NSS error. */
78 throwError(JNIEnv
* jenv
, const char * funcString
) {
81 PRErrorCode perr
= f_PR_GetError();
82 char * errString
= f_PR_ErrorToString(perr
, 0);
83 asprintf(&msg
, "%s returned error %d: %s\n", funcString
, perr
, errString
);
84 LOG("Throwing error: %s\n", msg
);
86 JNI_Throw(jenv
, "java/lang/Exception", msg
);
88 LOG("Error thrown\n");
91 extern "C" NS_EXPORT jstring JNICALL
92 Java_org_mozilla_gecko_NSSBridge_nativeEncrypt(JNIEnv
* jenv
, jclass
,
96 jstring ret
= jenv
->NewStringUTF("");
99 path
= jenv
->GetStringUTFChars(jPath
, nullptr);
102 value
= jenv
->GetStringUTFChars(jValue
, nullptr);
105 SECStatus rv
= doCrypto(jenv
, path
, value
, &result
, true);
106 if (rv
== SECSuccess
) {
107 ret
= jenv
->NewStringUTF(result
);
111 jenv
->ReleaseStringUTFChars(jValue
, value
);
112 jenv
->ReleaseStringUTFChars(jPath
, path
);
117 extern "C" NS_EXPORT jstring JNICALL
118 Java_org_mozilla_gecko_NSSBridge_nativeDecrypt(JNIEnv
* jenv
, jclass
,
122 jstring ret
= jenv
->NewStringUTF("");
125 path
= jenv
->GetStringUTFChars(jPath
, nullptr);
128 value
= jenv
->GetStringUTFChars(jValue
, nullptr);
131 SECStatus rv
= doCrypto(jenv
, path
, value
, &result
, false);
132 if (rv
== SECSuccess
) {
133 ret
= jenv
->NewStringUTF(result
);
137 jenv
->ReleaseStringUTFChars(jValue
, value
);
138 jenv
->ReleaseStringUTFChars(jPath
, path
);
144 /* Encrypts or decrypts a string. result should be freed with free() when done */
146 doCrypto(JNIEnv
* jenv
, const char *path
, const char *value
, char** result
, bool encrypt
)
151 LOG("Initialize crypto in %s\n", path
);
152 rv
= f_NSS_Initialize(path
, "", "", "secmod.db", NSS_INIT_NOROOTINIT
);
153 if (rv
!= SECSuccess
) {
154 throwError(jenv
, "NSS_Initialize");
160 slot
= f_PK11_GetInternalKeySlot();
162 throwError(jenv
, "PK11_GetInternalKeySlot");
166 if (f_PK11_NeedUserInit(slot
)) {
167 LOG("Initializing key3.db with default blank password.\n");
168 rv
= f_PK11_InitPin(slot
, nullptr, nullptr);
169 if (rv
!= SECSuccess
) {
170 throwError(jenv
, "PK11_InitPin");
182 // This can print sensitive data. Uncomment if you need it.
183 // LOG("Encrypting: %s\n", value);
184 request
.data
= (unsigned char*)value
;
185 request
.len
= strlen(value
);
190 rv
= f_PK11SDR_Encrypt(&keyid
, &request
, &reply
, nullptr);
192 if (rv
!= SECSuccess
) {
193 throwError(jenv
, "PK11SDR_Encrypt");
197 rv
= encode(reply
.data
, reply
.len
, result
);
198 if (rv
!= SECSuccess
) {
199 throwError(jenv
, "encode");
202 LOG("Encrypted: %s\n", *result
);
204 LOG("Decoding: %s\n", value
);
205 rv
= decode(value
, &request
.data
, (int32_t*)&request
.len
);
206 if (rv
!= SECSuccess
) {
207 throwError(jenv
, "decode");
211 rv
= f_PK11SDR_Decrypt(&request
, &reply
, nullptr);
212 if (rv
!= SECSuccess
) {
213 throwError(jenv
, "PK11SDR_Decrypt");
217 *result
= (char *)malloc(reply
.len
+1);
218 strncpy(*result
, (char *)reply
.data
, reply
.len
);
219 (*result
)[reply
.len
] = '\0';
221 // This can print sensitive data. Uncomment if you need it.
222 // LOG("Decoded %i letters: %s\n", reply.len, *result);
227 f_SECITEM_ZfreeItem(&reply
, false);
232 * Base64 encodes the data passed in. The caller must deallocate _retval using free();
235 encode(const unsigned char *data
, int32_t dataLen
, char **_retval
)
237 SECStatus rv
= SECSuccess
;
238 char *encoded
= f_PL_Base64Encode((const char *)data
, dataLen
, nullptr);
244 if (rv
== SECSuccess
) {
245 *_retval
= (char *)malloc(strlen(encoded
)+1);
246 strcpy(*_retval
, encoded
);
257 * Base64 decodes the data passed in. The caller must deallocate result using free();
260 decode(const char *data
, unsigned char **result
, int32_t *length
)
262 SECStatus rv
= SECSuccess
;
263 uint32_t len
= strlen(data
);
266 /* Compute length adjustment */
267 if (len
> 0 && data
[len
-1] == '=') {
269 if (data
[len
-2] == '=') adjust
++;
273 decoded
= f_PL_Base64Decode(data
, len
, nullptr);
281 *length
= (len
*3)/4 - adjust
;
282 LOG("Decoded %i chars into %i chars\n", len
, *length
);
284 *result
= (unsigned char*)malloc((size_t)len
);
289 memcpy((char*)*result
, decoded
, len
);