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