1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=2 et ft=cpp: tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include <fcntl.h>
8 #include <limits.h>
9 #include <pwd.h>
10 #include <sys/stat.h>
11 #include <sys/types.h>
12
13 #if defined(MOZ_WIDGET_GONK)
14 #include <android/log.h>
15 #define KEYSTORE_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk", args)
16 #else
17 #define KEYSTORE_LOG(args...) printf(args);
18 #endif
19
20 #include "KeyStore.h"
21 #include "jsfriendapi.h"
22 #include "KeyStoreConnector.h"
23 #include "MainThreadUtils.h" // For NS_IsMainThread.
24 #include "nsICryptoHash.h"
25
26 #include "plbase64.h"
27 #include "certdb.h"
28 #include "ScopedNSSTypes.h"
29
30 using namespace mozilla::ipc;
31 #if ANDROID_VERSION >= 18
32 // After Android 4.3, it uses binder to access keystore instead of unix socket.
33 #include <android/log.h>
34 #include <binder/BinderService.h>
35 #include <binder/IPCThreadState.h>
36 #include <binder/IServiceManager.h>
37 #include <security/keystore/include/keystore/IKeystoreService.h>
38 #include <security/keystore/include/keystore/keystore.h>
39
40 using namespace android;
41
42 namespace android {
43 // This class is used to make compiler happy.
44 class BpKeystoreService : public BpInterface<IKeystoreService>
45 {
46 public:
BpKeystoreService(const sp<IBinder> & impl)47 BpKeystoreService(const sp<IBinder>& impl)
48 : BpInterface<IKeystoreService>(impl)
49 {
50 }
51
get(const String16 & name,uint8_t ** item,size_t * itemLength)52 virtual int32_t get(const String16& name, uint8_t** item, size_t* itemLength) {return 0;}
test()53 virtual int32_t test() {return 0;}
insert(const String16 & name,const uint8_t * item,size_t itemLength,int uid,int32_t flags)54 virtual int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int uid, int32_t flags) {return 0;}
del(const String16 & name,int uid)55 virtual int32_t del(const String16& name, int uid) {return 0;}
exist(const String16 & name,int uid)56 virtual int32_t exist(const String16& name, int uid) {return 0;}
saw(const String16 & name,int uid,Vector<String16> * matches)57 virtual int32_t saw(const String16& name, int uid, Vector<String16>* matches) {return 0;}
reset()58 virtual int32_t reset() {return 0;}
password(const String16 & password)59 virtual int32_t password(const String16& password) {return 0;}
lock()60 virtual int32_t lock() {return 0;}
unlock(const String16 & password)61 virtual int32_t unlock(const String16& password) {return 0;}
zero()62 virtual int32_t zero() {return 0;}
import(const String16 & name,const uint8_t * data,size_t length,int uid,int32_t flags)63 virtual int32_t import(const String16& name, const uint8_t* data, size_t length, int uid, int32_t flags) {return 0;}
sign(const String16 & name,const uint8_t * data,size_t length,uint8_t ** out,size_t * outLength)64 virtual int32_t sign(const String16& name, const uint8_t* data, size_t length, uint8_t** out, size_t* outLength) {return 0;}
verify(const String16 & name,const uint8_t * data,size_t dataLength,const uint8_t * signature,size_t signatureLength)65 virtual int32_t verify(const String16& name, const uint8_t* data, size_t dataLength, const uint8_t* signature, size_t signatureLength) {return 0;}
get_pubkey(const String16 & name,uint8_t ** pubkey,size_t * pubkeyLength)66 virtual int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength) {return 0;}
del_key(const String16 & name,int uid)67 virtual int32_t del_key(const String16& name, int uid) {return 0;}
grant(const String16 & name,int32_t granteeUid)68 virtual int32_t grant(const String16& name, int32_t granteeUid) {return 0;}
ungrant(const String16 & name,int32_t granteeUid)69 virtual int32_t ungrant(const String16& name, int32_t granteeUid) {return 0;}
getmtime(const String16 & name)70 virtual int64_t getmtime(const String16& name) {return 0;}
duplicate(const String16 & srcKey,int32_t srcUid,const String16 & destKey,int32_t destUid)71 virtual int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey, int32_t destUid) {return 0;}
clear_uid(int64_t uid)72 virtual int32_t clear_uid(int64_t uid) {return 0;}
73 #if ANDROID_VERSION >= 21
generate(const String16 & name,int32_t uid,int32_t keyType,int32_t keySize,int32_t flags,Vector<sp<KeystoreArg>> * args)74 virtual int32_t generate(const String16& name, int32_t uid, int32_t keyType, int32_t keySize, int32_t flags, Vector<sp<KeystoreArg> >* args) {return 0;}
is_hardware_backed(const String16 & keyType)75 virtual int32_t is_hardware_backed(const String16& keyType) {return 0;}
reset_uid(int32_t uid)76 virtual int32_t reset_uid(int32_t uid) {return 0;}
sync_uid(int32_t sourceUid,int32_t targetUid)77 virtual int32_t sync_uid(int32_t sourceUid, int32_t targetUid) {return 0;}
password_uid(const String16 & password,int32_t uid)78 virtual int32_t password_uid(const String16& password, int32_t uid) {return 0;}
79 #elif ANDROID_VERSION == 18
generate(const String16 & name,int uid,int32_t flags)80 virtual int32_t generate(const String16& name, int uid, int32_t flags) {return 0;}
is_hardware_backed()81 virtual int32_t is_hardware_backed() {return 0;}
82 #else
generate(const String16 & name,int32_t uid,int32_t keyType,int32_t keySize,int32_t flags,Vector<sp<KeystoreArg>> * args)83 virtual int32_t generate(const String16& name, int32_t uid, int32_t keyType, int32_t keySize, int32_t flags, Vector<sp<KeystoreArg> >* args) {return 0;}
is_hardware_backed(const String16 & keyType)84 virtual int32_t is_hardware_backed(const String16& keyType) {return 0;}
85 #endif
86 };
87
88 IMPLEMENT_META_INTERFACE(KeystoreService, "android.security.keystore");
89
90 // Here comes binder requests.
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)91 status_t BnKeystoreService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
92 {
93 switch(code) {
94 case TEST: {
95 CHECK_INTERFACE(IKeystoreService, data, reply);
96 reply->writeNoException();
97 reply->writeInt32(test());
98 return NO_ERROR;
99 } break;
100 case GET: {
101 CHECK_INTERFACE(IKeystoreService, data, reply);
102 String16 name = data.readString16();
103 String8 tmp(name);
104 uint8_t* data = NULL;
105 size_t dataLength = 0;
106 int32_t ret = get(name, &data, &dataLength);
107
108 reply->writeNoException();
109 if (ret == 1) {
110 reply->writeInt32(dataLength);
111 void* buf = reply->writeInplace(dataLength);
112 memcpy(buf, data, dataLength);
113 free(data);
114 } else {
115 reply->writeInt32(-1);
116 }
117 return NO_ERROR;
118 } break;
119 case GET_PUBKEY: {
120 CHECK_INTERFACE(IKeystoreService, data, reply);
121 String16 name = data.readString16();
122 uint8_t* data = nullptr;
123 size_t dataLength = 0;
124 int32_t ret = get_pubkey(name, &data, &dataLength);
125
126 reply->writeNoException();
127 if (dataLength > 0 && data != nullptr) {
128 reply->writeInt32(dataLength);
129 void* buf = reply->writeInplace(dataLength);
130 memcpy(buf, data, dataLength);
131 free(data);
132 } else {
133 reply->writeInt32(-1);
134 }
135 reply->writeInt32(ret);
136 return NO_ERROR;
137 } break;
138 case SIGN: {
139 CHECK_INTERFACE(IKeystoreService, data, reply);
140 String16 name = data.readString16();
141 ssize_t signDataSize = data.readInt32();
142 const uint8_t *signData = nullptr;
143 if (signDataSize >= 0 && (size_t)signDataSize <= data.dataAvail()) {
144 signData = (const uint8_t *)data.readInplace(signDataSize);
145 }
146
147 uint8_t *signResult = nullptr;
148 size_t signResultSize;
149 int32_t ret = sign(name, signData, (size_t)signDataSize, &signResult,
150 &signResultSize);
151
152 reply->writeNoException();
153 if (signResultSize > 0 && signResult != nullptr) {
154 reply->writeInt32(signResultSize);
155 void* buf = reply->writeInplace(signResultSize);
156 memcpy(buf, signResult, signResultSize);
157 free(signResult);
158 } else {
159 reply->writeInt32(-1);
160 }
161 reply->writeInt32(ret);
162 return NO_ERROR;
163 } break;
164 default:
165 return NO_ERROR;
166 }
167 }
168
169 // Provide service for binder.
170 class KeyStoreService : public BnKeystoreService
171 , public nsNSSShutDownObject
172 {
173 public:
test()174 int32_t test() {
175 uid_t callingUid = IPCThreadState::self()->getCallingUid();
176 if (!mozilla::ipc::checkPermission(callingUid)) {
177 return ::PERMISSION_DENIED;
178 }
179
180 return ::NO_ERROR;
181 }
182
get(const String16 & name,uint8_t ** item,size_t * itemLength)183 int32_t get(const String16& name, uint8_t** item, size_t* itemLength) {
184 nsNSSShutDownPreventionLock locker;
185 if (isAlreadyShutDown()) {
186 return ::SYSTEM_ERROR;
187 }
188
189 uid_t callingUid = IPCThreadState::self()->getCallingUid();
190 if (!mozilla::ipc::checkPermission(callingUid)) {
191 return ::PERMISSION_DENIED;
192 }
193
194 String8 certName(name);
195 if (!strncmp(certName.string(), "WIFI_USERKEY_", 13)) {
196 return getPrivateKey(certName.string(), (const uint8_t**)item, itemLength);
197 }
198
199 return getCertificate(certName.string(), (const uint8_t**)item, itemLength);
200 }
201
insert(const String16 & name,const uint8_t * item,size_t itemLength,int uid,int32_t flags)202 int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int uid, int32_t flags) {return ::UNDEFINED_ACTION;}
del(const String16 & name,int uid)203 int32_t del(const String16& name, int uid) {return ::UNDEFINED_ACTION;}
exist(const String16 & name,int uid)204 int32_t exist(const String16& name, int uid) {return ::UNDEFINED_ACTION;}
saw(const String16 & name,int uid,Vector<String16> * matches)205 int32_t saw(const String16& name, int uid, Vector<String16>* matches) {return ::UNDEFINED_ACTION;}
reset()206 int32_t reset() {return ::UNDEFINED_ACTION;}
password(const String16 & password)207 int32_t password(const String16& password) {return ::UNDEFINED_ACTION;}
lock()208 int32_t lock() {return ::UNDEFINED_ACTION;}
unlock(const String16 & password)209 int32_t unlock(const String16& password) {return ::UNDEFINED_ACTION;}
zero()210 int32_t zero() {return ::UNDEFINED_ACTION;}
import(const String16 & name,const uint8_t * data,size_t length,int uid,int32_t flags)211 int32_t import(const String16& name, const uint8_t* data, size_t length, int uid, int32_t flags) {return ::UNDEFINED_ACTION;}
sign(const String16 & name,const uint8_t * data,size_t length,uint8_t ** out,size_t * outLength)212 int32_t sign(const String16& name, const uint8_t* data, size_t length, uint8_t** out, size_t* outLength)
213 {
214 nsNSSShutDownPreventionLock locker;
215 if (isAlreadyShutDown()) {
216 return ::SYSTEM_ERROR;
217 }
218
219 uid_t callingUid = IPCThreadState::self()->getCallingUid();
220 if (!mozilla::ipc::checkPermission(callingUid)) {
221 return ::PERMISSION_DENIED;
222 }
223
224 if (data == nullptr) {
225 return ::SYSTEM_ERROR;
226 }
227
228 String8 keyName(name);
229 if (!strncmp(keyName.string(), "WIFI_USERKEY_", 13)) {
230 return signData(keyName.string(), data, length, out, outLength);
231 }
232
233 return ::UNDEFINED_ACTION;
234 }
235
verify(const String16 & name,const uint8_t * data,size_t dataLength,const uint8_t * signature,size_t signatureLength)236 int32_t verify(const String16& name, const uint8_t* data, size_t dataLength, const uint8_t* signature, size_t signatureLength) {return ::UNDEFINED_ACTION;}
get_pubkey(const String16 & name,uint8_t ** pubkey,size_t * pubkeyLength)237 int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength) {
238 nsNSSShutDownPreventionLock locker;
239 if (isAlreadyShutDown()) {
240 return ::SYSTEM_ERROR;
241 }
242
243 uid_t callingUid = IPCThreadState::self()->getCallingUid();
244 if (!mozilla::ipc::checkPermission(callingUid)) {
245 return ::PERMISSION_DENIED;
246 }
247
248 String8 keyName(name);
249 if (!strncmp(keyName.string(), "WIFI_USERKEY_", 13)) {
250 return getPublicKey(keyName.string(), (const uint8_t**)pubkey, pubkeyLength);
251 }
252
253 return ::UNDEFINED_ACTION;
254 }
255
del_key(const String16 & name,int uid)256 int32_t del_key(const String16& name, int uid) {return ::UNDEFINED_ACTION;}
grant(const String16 & name,int32_t granteeUid)257 int32_t grant(const String16& name, int32_t granteeUid) {return ::UNDEFINED_ACTION;}
ungrant(const String16 & name,int32_t granteeUid)258 int32_t ungrant(const String16& name, int32_t granteeUid) {return ::UNDEFINED_ACTION;}
getmtime(const String16 & name)259 int64_t getmtime(const String16& name) {return ::UNDEFINED_ACTION;}
duplicate(const String16 & srcKey,int32_t srcUid,const String16 & destKey,int32_t destUid)260 int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey, int32_t destUid) {return ::UNDEFINED_ACTION;}
clear_uid(int64_t uid)261 int32_t clear_uid(int64_t uid) {return ::UNDEFINED_ACTION;}
262 #if ANDROID_VERSION >= 21
generate(const String16 & name,int32_t uid,int32_t keyType,int32_t keySize,int32_t flags,Vector<sp<KeystoreArg>> * args)263 virtual int32_t generate(const String16& name, int32_t uid, int32_t keyType, int32_t keySize, int32_t flags, Vector<sp<KeystoreArg> >* args) {return ::UNDEFINED_ACTION;}
is_hardware_backed(const String16 & keyType)264 virtual int32_t is_hardware_backed(const String16& keyType) {return ::UNDEFINED_ACTION;}
reset_uid(int32_t uid)265 virtual int32_t reset_uid(int32_t uid) {return ::UNDEFINED_ACTION;;}
sync_uid(int32_t sourceUid,int32_t targetUid)266 virtual int32_t sync_uid(int32_t sourceUid, int32_t targetUid) {return ::UNDEFINED_ACTION;}
password_uid(const String16 & password,int32_t uid)267 virtual int32_t password_uid(const String16& password, int32_t uid) {return ::UNDEFINED_ACTION;}
268 #elif ANDROID_VERSION == 18
generate(const String16 & name,int uid,int32_t flags)269 virtual int32_t generate(const String16& name, int uid, int32_t flags) {return ::UNDEFINED_ACTION;}
is_hardware_backed()270 virtual int32_t is_hardware_backed() {return ::UNDEFINED_ACTION;}
271 #else
generate(const String16 & name,int32_t uid,int32_t keyType,int32_t keySize,int32_t flags,Vector<sp<KeystoreArg>> * args)272 virtual int32_t generate(const String16& name, int32_t uid, int32_t keyType, int32_t keySize, int32_t flags, Vector<sp<KeystoreArg> >* args) {return ::UNDEFINED_ACTION;}
is_hardware_backed(const String16 & keyType)273 virtual int32_t is_hardware_backed(const String16& keyType) {return ::UNDEFINED_ACTION;}
274 #endif
275
276 protected:
virtualDestroyNSSReference()277 virtual void virtualDestroyNSSReference() {}
278
279 private:
~KeyStoreService()280 ~KeyStoreService() {
281 nsNSSShutDownPreventionLock locker;
282 if (isAlreadyShutDown()) {
283 return;
284 }
285 shutdown(ShutdownCalledFrom::Object);
286 }
287 };
288
289 } // namespace android
290
startKeyStoreService()291 void startKeyStoreService()
292 {
293 android::sp<android::IServiceManager> sm = android::defaultServiceManager();
294 android::sp<android::KeyStoreService> keyStoreService = new android::KeyStoreService();
295 sm->addService(String16("android.security.keystore"), keyStoreService);
296 }
297 #else
startKeyStoreService()298 void startKeyStoreService() { return; }
299 #endif
300
301 static const char *CA_BEGIN = "-----BEGIN ",
302 *CA_END = "-----END ",
303 *CA_TAILER = "-----\n";
304
305 namespace mozilla {
306 namespace ipc {
307
308 static const char* KEYSTORE_ALLOWED_USERS[] = {
309 "root",
310 "wifi",
311 NULL
312 };
313 static const char* KEYSTORE_ALLOWED_PREFIXES[] = {
314 "WIFI_SERVERCERT_",
315 "WIFI_USERCERT_",
316 "WIFI_USERKEY_",
317 NULL
318 };
319
320 // Transform base64 certification data into DER format
321 void
FormatCaData(const char * aCaData,int aCaDataLength,const char * aName,const uint8_t ** aFormatData,size_t * aFormatDataLength)322 FormatCaData(const char *aCaData, int aCaDataLength,
323 const char *aName, const uint8_t **aFormatData,
324 size_t *aFormatDataLength)
325 {
326 size_t bufSize = strlen(CA_BEGIN) + strlen(CA_END) + strlen(CA_TAILER) * 2 +
327 strlen(aName) * 2 + aCaDataLength + aCaDataLength/CA_LINE_SIZE
328 + 2;
329 char *buf = (char *)malloc(bufSize);
330 if (!buf) {
331 *aFormatData = nullptr;
332 return;
333 }
334
335 *aFormatDataLength = bufSize;
336 *aFormatData = (const uint8_t *)buf;
337
338 char *ptr = buf;
339 size_t len;
340
341 // Create DER header.
342 len = snprintf(ptr, bufSize, "%s%s%s", CA_BEGIN, aName, CA_TAILER);
343 ptr += len;
344 bufSize -= len;
345
346 // Split base64 data in lines.
347 int copySize;
348 while (aCaDataLength > 0) {
349 copySize = (aCaDataLength > CA_LINE_SIZE) ? CA_LINE_SIZE : aCaDataLength;
350
351 memcpy(ptr, aCaData, copySize);
352 ptr += copySize;
353 aCaData += copySize;
354 aCaDataLength -= copySize;
355 bufSize -= copySize;
356
357 *ptr = '\n';
358 ptr++;
359 bufSize--;
360 }
361
362 // Create DEA tailer.
363 snprintf(ptr, bufSize, "%s%s%s", CA_END, aName, CA_TAILER);
364 }
365
366 ResponseCode
getCertificate(const char * aCertName,const uint8_t ** aCertData,size_t * aCertDataLength)367 getCertificate(const char *aCertName, const uint8_t **aCertData,
368 size_t *aCertDataLength)
369 {
370 // certificate name prefix check.
371 if (!aCertName) {
372 return KEY_NOT_FOUND;
373 }
374
375 const char **prefix = KEYSTORE_ALLOWED_PREFIXES;
376 for (; *prefix; prefix++ ) {
377 if (!strncmp(*prefix, aCertName, strlen(*prefix))) {
378 break;
379 }
380 }
381 if (!(*prefix)) {
382 return KEY_NOT_FOUND;
383 }
384
385 // Get cert from NSS by name
386 ScopedCERTCertificate cert(CERT_FindCertByNickname(CERT_GetDefaultCertDB(),
387 aCertName));
388
389 if (!cert) {
390 return KEY_NOT_FOUND;
391 }
392
393 char *certDER = PL_Base64Encode((const char *)cert->derCert.data,
394 cert->derCert.len, nullptr);
395 if (!certDER) {
396 return SYSTEM_ERROR;
397 }
398
399 FormatCaData(certDER, strlen(certDER), "CERTIFICATE", aCertData,
400 aCertDataLength);
401 PL_strfree(certDER);
402
403 if (!(*aCertData)) {
404 return SYSTEM_ERROR;
405 }
406
407 return SUCCESS;
408 }
409
getPrivateKey(const char * aKeyName,const uint8_t ** aKeyData,size_t * aKeyDataLength)410 ResponseCode getPrivateKey(const char *aKeyName, const uint8_t **aKeyData,
411 size_t *aKeyDataLength)
412 {
413 *aKeyData = nullptr;
414 // Get corresponding user certificate nickname
415 char userCertName[128] = {0};
416 snprintf(userCertName, sizeof(userCertName) - 1, "WIFI_USERCERT_%s", aKeyName + 13);
417
418 // Get private key from user certificate.
419 ScopedCERTCertificate userCert(
420 CERT_FindCertByNickname(CERT_GetDefaultCertDB(), userCertName));
421 if (!userCert) {
422 return KEY_NOT_FOUND;
423 }
424
425 ScopedSECKEYPrivateKey privateKey(
426 PK11_FindKeyByAnyCert(userCert.get(), nullptr));
427 if (!privateKey) {
428 return KEY_NOT_FOUND;
429 }
430
431 // Export private key in PKCS#12 encrypted format, no password.
432 unsigned char pwstr[] = {0, 0};
433 SECItem password = {siBuffer, pwstr, sizeof(pwstr)};
434 ScopedSECKEYEncryptedPrivateKeyInfo encryptedPrivateKey(
435 PK11_ExportEncryptedPrivKeyInfo(privateKey->pkcs11Slot,
436 SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4, &password, privateKey, 1,
437 privateKey->wincx));
438
439 if (!encryptedPrivateKey) {
440 return KEY_NOT_FOUND;
441 }
442
443 // Decrypt into RSA private key.
444 //
445 // Generate key for PKCS#12 encryption, we use SHA1 with 1 iteration, as the
446 // parameters used in PK11_ExportEncryptedPrivKeyInfo() above.
447 // see: PKCS#12 v1.0, B.2.
448 //
449 uint8_t DSP[192] = {0};
450 memset(DSP, 0x01, 64); // Diversifier part, ID = 1 for decryption.
451 memset(DSP + 128, 0x00, 64); // Password part, no password.
452
453 uint8_t *S = &DSP[64]; // Salt part.
454 uint8_t *salt = encryptedPrivateKey->algorithm.parameters.data + 4;
455 int saltLength = (int)encryptedPrivateKey->algorithm.parameters.data[3];
456 if (saltLength <= 0) {
457 return SYSTEM_ERROR;
458 }
459 for (int i = 0; i < 64; i++) {
460 S[i] = salt[i % saltLength];
461 }
462
463 // Generate key by SHA-1
464 nsresult rv;
465 nsCOMPtr<nsICryptoHash> hash =
466 do_CreateInstance("@mozilla.org/security/hash;1", &rv);
467 if (NS_FAILED(rv)) {
468 return SYSTEM_ERROR;
469 }
470
471 rv = hash->Init(nsICryptoHash::SHA1);
472 if (NS_FAILED(rv)) {
473 return SYSTEM_ERROR;
474 }
475
476 rv = hash->Update(DSP, sizeof(DSP));
477 if (NS_FAILED(rv)) {
478 return SYSTEM_ERROR;
479 }
480
481 nsCString hashResult;
482 rv = hash->Finish(false, hashResult);
483 if (NS_FAILED(rv)) {
484 return SYSTEM_ERROR;
485 }
486
487 // First 40-bit as key for RC4.
488 uint8_t key[5];
489 memcpy(key, hashResult.get(), sizeof(key));
490
491 ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
492 if (!slot) {
493 return SYSTEM_ERROR;
494 }
495
496 SECItem keyItem = {siBuffer, key, sizeof(key)};
497 ScopedPK11SymKey symKey(PK11_ImportSymKey(slot, CKM_RC4, PK11_OriginUnwrap,
498 CKA_DECRYPT, &keyItem, nullptr));
499 if (!symKey) {
500 return SYSTEM_ERROR;
501 }
502
503 // Get expected decrypted data size then allocate memory.
504 uint8_t *encryptedData = (uint8_t *)encryptedPrivateKey->encryptedData.data;
505 unsigned int encryptedDataLen = encryptedPrivateKey->encryptedData.len;
506 unsigned int decryptedDataLen = encryptedDataLen;
507 SECStatus srv = PK11_Decrypt(symKey, CKM_RC4, &keyItem, nullptr,
508 &decryptedDataLen, encryptedDataLen,
509 encryptedData, encryptedDataLen);
510 if (srv != SECSuccess) {
511 return SYSTEM_ERROR;
512 }
513
514 ScopedSECItem decryptedData(::SECITEM_AllocItem(nullptr, nullptr,
515 decryptedDataLen));
516 if (!decryptedData) {
517 return SYSTEM_ERROR;
518 }
519
520 // Decrypt by RC4.
521 srv = PK11_Decrypt(symKey, CKM_RC4, &keyItem, decryptedData->data,
522 &decryptedDataLen, decryptedData->len, encryptedData,
523 encryptedDataLen);
524 if (srv != SECSuccess) {
525 return SYSTEM_ERROR;
526 }
527
528 // Export key in PEM format.
529 char *keyPEM = PL_Base64Encode((const char *)decryptedData->data,
530 decryptedDataLen, nullptr);
531
532 if (!keyPEM) {
533 return SYSTEM_ERROR;
534 }
535
536 FormatCaData(keyPEM, strlen(keyPEM), "PRIVATE KEY", aKeyData, aKeyDataLength);
537 PL_strfree(keyPEM);
538
539 if (!(*aKeyData)) {
540 return SYSTEM_ERROR;
541 }
542
543 return SUCCESS;
544 }
545
getPublicKey(const char * aKeyName,const uint8_t ** aKeyData,size_t * aKeyDataLength)546 ResponseCode getPublicKey(const char *aKeyName, const uint8_t **aKeyData,
547 size_t *aKeyDataLength)
548 {
549 *aKeyData = nullptr;
550
551 // Get corresponding user certificate nickname
552 char userCertName[128] = {0};
553 snprintf(userCertName, sizeof(userCertName) - 1, "WIFI_USERCERT_%s", aKeyName + 13);
554
555 // Get public key from user certificate.
556 ScopedCERTCertificate userCert(
557 CERT_FindCertByNickname(CERT_GetDefaultCertDB(), userCertName));
558 if (!userCert) {
559 return KEY_NOT_FOUND;
560 }
561
562 // Get public key.
563 ScopedSECKEYPublicKey publicKey(CERT_ExtractPublicKey(userCert));
564 if (!publicKey) {
565 return KEY_NOT_FOUND;
566 }
567
568 ScopedSECItem keyItem(PK11_DEREncodePublicKey(publicKey));
569 if (!keyItem) {
570 return KEY_NOT_FOUND;
571 }
572
573 size_t bufSize = keyItem->len;
574 char *buf = (char *)malloc(bufSize);
575 if (!buf) {
576 return SYSTEM_ERROR;
577 }
578
579 memcpy(buf, keyItem->data, bufSize);
580 *aKeyData = (const uint8_t *)buf;
581 *aKeyDataLength = bufSize;
582
583 return SUCCESS;
584 }
585
signData(const char * aKeyName,const uint8_t * data,size_t length,uint8_t ** out,size_t * outLength)586 ResponseCode signData(const char *aKeyName, const uint8_t *data, size_t length,
587 uint8_t **out, size_t *outLength)
588 {
589 *out = nullptr;
590 // Get corresponding user certificate nickname
591 char userCertName[128] = {0};
592 snprintf(userCertName, sizeof(userCertName) - 1, "WIFI_USERCERT_%s", aKeyName + 13);
593
594 // Get private key from user certificate.
595 ScopedCERTCertificate userCert(
596 CERT_FindCertByNickname(CERT_GetDefaultCertDB(), userCertName));
597 if (!userCert) {
598 return KEY_NOT_FOUND;
599 }
600
601 ScopedSECKEYPrivateKey privateKey(
602 PK11_FindKeyByAnyCert(userCert.get(), nullptr));
603 if (!privateKey) {
604 return KEY_NOT_FOUND;
605 }
606
607 //
608 // Find hash data from incoming data.
609 //
610 // Incoming data might be padded by PKCS-1 format:
611 // 00 01 FF FF ... FF 00 || Hash of length 36
612 // If the padding part exists, we have to ignore them.
613 //
614 uint8_t *hash = (uint8_t *)data;
615 const size_t HASH_LENGTH = 36;
616 if (length < HASH_LENGTH) {
617 return VALUE_CORRUPTED;
618 }
619 if (hash[0] == 0x00 && hash[1] == 0x01 && hash[2] == 0xFF && hash[3] == 0xFF) {
620 hash += 4;
621 while (*hash == 0xFF) {
622 if (hash + HASH_LENGTH > data + length) {
623 return VALUE_CORRUPTED;
624 }
625 hash++;
626 }
627 if (*hash != 0x00) {
628 return VALUE_CORRUPTED;
629 }
630 hash++;
631 }
632 if (hash + HASH_LENGTH != data + length) {
633 return VALUE_CORRUPTED;
634 }
635 SECItem hashItem = {siBuffer, hash, HASH_LENGTH};
636
637 // Sign hash.
638 ScopedSECItem signItem(::SECITEM_AllocItem(nullptr, nullptr,
639 PK11_SignatureLen(privateKey)));
640 if (!signItem) {
641 return SYSTEM_ERROR;
642 }
643
644 SECStatus srv;
645 srv = PK11_Sign(privateKey, signItem.get(), &hashItem);
646 if (srv != SECSuccess) {
647 return SYSTEM_ERROR;
648 }
649
650 uint8_t *buf = (uint8_t *)malloc(signItem->len);
651 if (!buf) {
652 return SYSTEM_ERROR;
653 }
654
655 memcpy(buf, signItem->data, signItem->len);
656 *out = buf;
657 *outLength = signItem->len;
658
659 return SUCCESS;
660 }
661
662 bool
checkPermission(uid_t uid)663 checkPermission(uid_t uid)
664 {
665 struct passwd *userInfo = getpwuid(uid);
666 for (const char **user = KEYSTORE_ALLOWED_USERS; *user; user++ ) {
667 if (!strcmp(*user, userInfo->pw_name)) {
668 return true;
669 }
670 }
671
672 return false;
673 }
674
675 //
676 // KeyStore
677 //
678
KeyStore()679 KeyStore::KeyStore()
680 : mShutdown(false)
681 {
682 MOZ_COUNT_CTOR(KeyStore);
683 ::startKeyStoreService();
684 Listen();
685 }
686
~KeyStore()687 KeyStore::~KeyStore()
688 {
689 nsNSSShutDownPreventionLock locker;
690 MOZ_COUNT_DTOR(KeyStore);
691
692 if (isAlreadyShutDown()) {
693 return;
694 }
695
696 shutdown(ShutdownCalledFrom::Object);
697
698 MOZ_ASSERT(!mListenSocket);
699 MOZ_ASSERT(!mStreamSocket);
700 }
701
702 void
Shutdown()703 KeyStore::Shutdown()
704 {
705 // We set mShutdown first, so that |OnDisconnect| won't try to reconnect.
706 mShutdown = true;
707
708 if (mStreamSocket) {
709 mStreamSocket->Close();
710 mStreamSocket = nullptr;
711 }
712 if (mListenSocket) {
713 mListenSocket->Close();
714 mListenSocket = nullptr;
715 }
716 }
717
718 void
Listen()719 KeyStore::Listen()
720 {
721 // We only allocate one |StreamSocket|, but re-use it for every connection.
722 if (mStreamSocket) {
723 mStreamSocket->Close();
724 } else {
725 mStreamSocket = new StreamSocket(this, STREAM_SOCKET);
726 }
727
728 if (!mListenSocket) {
729 // We only ever allocate one |ListenSocket|...
730 mListenSocket = new ListenSocket(this, LISTEN_SOCKET);
731 mListenSocket->Listen(new KeyStoreConnector(KEYSTORE_ALLOWED_USERS),
732 mStreamSocket);
733 } else {
734 // ... but keep it open.
735 mListenSocket->Listen(mStreamSocket);
736 }
737
738 ResetHandlerInfo();
739 }
740
741 void
ResetHandlerInfo()742 KeyStore::ResetHandlerInfo()
743 {
744 mHandlerInfo.state = STATE_IDLE;
745 mHandlerInfo.command = 0;
746 mHandlerInfo.paramCount = 0;
747 mHandlerInfo.commandPattern = nullptr;
748 for (int i = 0; i < MAX_PARAM; i++) {
749 mHandlerInfo.param[i].length = 0;
750 memset(mHandlerInfo.param[i].data, 0, VALUE_SIZE);
751 }
752 }
753
754 bool
CheckSize(UnixSocketBuffer * aMessage,size_t aExpectSize)755 KeyStore::CheckSize(UnixSocketBuffer *aMessage, size_t aExpectSize)
756 {
757 return (aMessage->GetSize() >= aExpectSize);
758 }
759
760 ResponseCode
ReadCommand(UnixSocketBuffer * aMessage)761 KeyStore::ReadCommand(UnixSocketBuffer *aMessage)
762 {
763 if (mHandlerInfo.state != STATE_IDLE) {
764 NS_WARNING("Wrong state in ReadCommand()!");
765 return SYSTEM_ERROR;
766 }
767
768 if (!CheckSize(aMessage, 1)) {
769 NS_WARNING("Data size error in ReadCommand()!");
770 return PROTOCOL_ERROR;
771 }
772
773 mHandlerInfo.command = *aMessage->GetData();
774 aMessage->Consume(1);
775
776 // Find corrsponding command pattern
777 const struct ProtocolCommand *command = commands;
778 while (command->command && command->command != mHandlerInfo.command) {
779 command++;
780 }
781
782 if (!command->command) {
783 NS_WARNING("Unsupported command!");
784 return PROTOCOL_ERROR;
785 }
786
787 // Get command pattern.
788 mHandlerInfo.commandPattern = command;
789 if (command->paramNum) {
790 // Read command parameter if needed.
791 mHandlerInfo.state = STATE_READ_PARAM_LEN;
792 } else {
793 mHandlerInfo.state = STATE_PROCESSING;
794 }
795
796 return SUCCESS;
797 }
798
799 ResponseCode
ReadLength(UnixSocketBuffer * aMessage)800 KeyStore::ReadLength(UnixSocketBuffer *aMessage)
801 {
802 if (mHandlerInfo.state != STATE_READ_PARAM_LEN) {
803 NS_WARNING("Wrong state in ReadLength()!");
804 return SYSTEM_ERROR;
805 }
806
807 if (!CheckSize(aMessage, 2)) {
808 NS_WARNING("Data size error in ReadLength()!");
809 return PROTOCOL_ERROR;
810 }
811
812 // Read length of command parameter.
813 // FIXME: Depends on endianess and (sizeof(unsigned short) == 2)
814 unsigned short dataLength;
815 memcpy(&dataLength, aMessage->GetData(), 2);
816 aMessage->Consume(2);
817 mHandlerInfo.param[mHandlerInfo.paramCount].length = ntohs(dataLength);
818
819 mHandlerInfo.state = STATE_READ_PARAM_DATA;
820
821 return SUCCESS;
822 }
823
824 ResponseCode
ReadData(UnixSocketBuffer * aMessage)825 KeyStore::ReadData(UnixSocketBuffer *aMessage)
826 {
827 if (mHandlerInfo.state != STATE_READ_PARAM_DATA) {
828 NS_WARNING("Wrong state in ReadData()!");
829 return SYSTEM_ERROR;
830 }
831
832 if (!CheckSize(aMessage, mHandlerInfo.param[mHandlerInfo.paramCount].length)) {
833 NS_WARNING("Data size error in ReadData()!");
834 return PROTOCOL_ERROR;
835 }
836
837 // Read command parameter.
838 memcpy(mHandlerInfo.param[mHandlerInfo.paramCount].data,
839 aMessage->GetData(),
840 mHandlerInfo.param[mHandlerInfo.paramCount].length);
841 aMessage->Consume(mHandlerInfo.param[mHandlerInfo.paramCount].length);
842 mHandlerInfo.paramCount++;
843
844 if (mHandlerInfo.paramCount == mHandlerInfo.commandPattern->paramNum) {
845 mHandlerInfo.state = STATE_PROCESSING;
846 } else {
847 mHandlerInfo.state = STATE_READ_PARAM_LEN;
848 }
849
850 return SUCCESS;
851 }
852
853 // Status response
854 void
SendResponse(ResponseCode aResponse)855 KeyStore::SendResponse(ResponseCode aResponse)
856 {
857 MOZ_ASSERT(mStreamSocket);
858
859 if (aResponse == NO_RESPONSE)
860 return;
861
862 uint8_t response = (uint8_t)aResponse;
863 UnixSocketRawData* data = new UnixSocketRawData((const void *)&response, 1);
864 mStreamSocket->SendSocketData(data);
865 }
866
867 // Data response
868 void
SendData(const uint8_t * aData,int aLength)869 KeyStore::SendData(const uint8_t *aData, int aLength)
870 {
871 MOZ_ASSERT(mStreamSocket);
872
873 unsigned short dataLength = htons(aLength);
874
875 UnixSocketRawData* length = new UnixSocketRawData((const void *)&dataLength, 2);
876 mStreamSocket->SendSocketData(length);
877
878 UnixSocketRawData* data = new UnixSocketRawData((const void *)aData, aLength);
879 mStreamSocket->SendSocketData(data);
880 }
881
882 // |StreamSocketConsumer|, |ListenSocketConsumer|
883
884 void
ReceiveSocketData(int aIndex,UniquePtr<UnixSocketBuffer> & aMessage)885 KeyStore::ReceiveSocketData(int aIndex, UniquePtr<UnixSocketBuffer>& aMessage)
886 {
887 MOZ_ASSERT(NS_IsMainThread());
888
889 // Handle request.
890 ResponseCode result = SUCCESS;
891 while (aMessage->GetSize() ||
892 mHandlerInfo.state == STATE_PROCESSING) {
893 switch (mHandlerInfo.state) {
894 case STATE_IDLE:
895 result = ReadCommand(aMessage.get());
896 break;
897 case STATE_READ_PARAM_LEN:
898 result = ReadLength(aMessage.get());
899 break;
900 case STATE_READ_PARAM_DATA:
901 result = ReadData(aMessage.get());
902 break;
903 case STATE_PROCESSING:
904 if (mHandlerInfo.command == 'g') {
905 result = SYSTEM_ERROR;
906
907 nsNSSShutDownPreventionLock locker;
908 if (isAlreadyShutDown()) {
909 break;
910 }
911
912 // Get CA
913 const uint8_t *data;
914 size_t dataLength;
915 const char *name = (const char *)mHandlerInfo.param[0].data;
916
917 if (!strncmp(name, "WIFI_USERKEY_", 13)) {
918 result = getPrivateKey(name, &data, &dataLength);
919 } else {
920 result = getCertificate(name, &data, &dataLength);
921 }
922 if (result != SUCCESS) {
923 break;
924 }
925
926 SendResponse(SUCCESS);
927 SendData(data, (int)dataLength);
928
929 free((void *)data);
930 }
931
932 ResetHandlerInfo();
933 break;
934 }
935
936 if (result != SUCCESS) {
937 SendResponse(result);
938 ResetHandlerInfo();
939 return;
940 }
941 }
942 }
943
944 void
OnConnectSuccess(int aIndex)945 KeyStore::OnConnectSuccess(int aIndex)
946 {
947 if (aIndex == STREAM_SOCKET) {
948 mShutdown = false;
949 }
950 }
951
952 void
OnConnectError(int aIndex)953 KeyStore::OnConnectError(int aIndex)
954 {
955 if (mShutdown) {
956 return;
957 }
958
959 if (aIndex == STREAM_SOCKET) {
960 // Stream socket error; start listening again
961 Listen();
962 }
963 }
964
965 void
OnDisconnect(int aIndex)966 KeyStore::OnDisconnect(int aIndex)
967 {
968 if (mShutdown) {
969 return;
970 }
971
972 switch (aIndex) {
973 case LISTEN_SOCKET:
974 // Listen socket disconnected; start anew.
975 mListenSocket = nullptr;
976 Listen();
977 break;
978 case STREAM_SOCKET:
979 // Stream socket disconnected; start listening again.
980 Listen();
981 break;
982 }
983 }
984
985 } // namespace ipc
986 } // namespace mozilla
987