diff --git a/dom/wifi/WifiCertService.cpp b/dom/wifi/WifiCertService.cpp index cb90ef419975..82dacd1aab27 100644 --- a/dom/wifi/WifiCertService.cpp +++ b/dom/wifi/WifiCertService.cpp @@ -471,6 +471,36 @@ WifiCertService::DeleteCert(int32_t aId, const nsAString& aCertNickname) return task->Dispatch("WifiDeleteCert"); } +NS_IMETHODIMP +WifiCertService::HasPrivateKey(const nsAString& aCertNickname, bool *aHasKey) +{ + *aHasKey = false; + + nsNSSShutDownPreventionLock locker; + if (isAlreadyShutDown()) { + return NS_ERROR_NOT_AVAILABLE; + } + + nsCString certNickname; + CopyUTF16toUTF8(aCertNickname, certNickname); + + ScopedCERTCertificate cert( + CERT_FindCertByNickname(CERT_GetDefaultCertDB(), certNickname.get()) + ); + if (!cert) { + return NS_OK; + } + + ScopedPK11SlotInfo slot( + PK11_KeyForCertExists(cert, nullptr, nullptr) + ); + if (slot) { + *aHasKey = true; + } + + return NS_OK; +} + NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(WifiCertService, WifiCertService::FactoryCreate) diff --git a/dom/wifi/WifiCertService.h b/dom/wifi/WifiCertService.h index 7f7bff5c8812..b3efcf4e991c 100644 --- a/dom/wifi/WifiCertService.h +++ b/dom/wifi/WifiCertService.h @@ -8,13 +8,15 @@ #include "nsIWifiCertService.h" #include "nsCOMPtr.h" +#include "nsNSSShutDown.h" #include "nsThread.h" #include "mozilla/dom/WifiOptionsBinding.h" namespace mozilla { namespace dom { -class WifiCertService MOZ_FINAL : public nsIWifiCertService +class WifiCertService MOZ_FINAL : public nsIWifiCertService, + public nsNSSShutDownObject { public: NS_DECL_ISUPPORTS @@ -27,6 +29,7 @@ public: private: WifiCertService(); ~WifiCertService(); + virtual void virtualDestroyNSSReference() {}; nsCOMPtr mListener; }; diff --git a/dom/wifi/WifiWorker.js b/dom/wifi/WifiWorker.js index 2fe79d5da879..c05a7b3cd776 100755 --- a/dom/wifi/WifiWorker.js +++ b/dom/wifi/WifiWorker.js @@ -1211,6 +1211,11 @@ var WifiManager = (function() { {name: "pcsc", type: "string"}, {name: "ca_cert", type: "string"}, {name: "subject_match", type: "string"}, + {name: "client_cert", type: "string"}, + {name: "private_key", type: "stirng"}, + {name: "engine", type: "integer"}, + {name: "engine_id", type: "string"}, + {name: "key_id", type: "string"}, {name: "frequency", type: "integer"}, {name: "mode", type: "integer"} ]; @@ -1535,6 +1540,10 @@ var WifiManager = (function() { wifiCertService.deleteCert(id, caInfo.certNickname); } + manager.sdkVersion = function() { + return sdkVersion; + } + return manager; })(); @@ -1691,7 +1700,8 @@ Network.api = { pin: "rw", phase1: "rw", phase2: "rw", - serverCertificate: "rw" + serverCertificate: "rw", + userCertificate: "rw" }; // Note: We never use ScanResult.prototype, so the fact that it's unrelated to @@ -1936,6 +1946,10 @@ function WifiWorker() { if(net.subject_match) { pub.subjectMatch = net.subject_match; } + if ("client_cert" in net && net.client_cert && + net.client_cert.indexOf("keystore://WIFI_USERCERT_" === 0)) { + pub.userCertificate = net.client_cert.substr(25); + } return pub; }; @@ -2025,6 +2039,24 @@ function WifiWorker() { if (hasValidProperty("subjectMatch")) net.subject_match = quote(net.subjectMatch); + + if (hasValidProperty("userCertificate")) { + let userCertName = "WIFI_USERCERT_" + net.userCertificate; + net.client_cert = quote("keystore://" + userCertName); + + let wifiCertService = Cc["@mozilla.org/wifi/certservice;1"]. + getService(Ci.nsIWifiCertService); + if (wifiCertService.hasPrivateKey(userCertName)) { + if (WifiManager.sdkVersion() >= 19) { + // Use openssol engine instead of keystore protocol after Kitkat. + net.engine = 1; + net.engine_id = quote("keystore"); + net.key_id = quote("WIFI_USERKEY_" + net.userCertificate); + } else { + net.private_key = quote("keystore://WIFI_USERKEY_" + net.userCertificate); + } + } + } } return net; diff --git a/dom/wifi/nsIWifiCertService.idl b/dom/wifi/nsIWifiCertService.idl index 93fe7299017a..fce2dd7199c9 100644 --- a/dom/wifi/nsIWifiCertService.idl +++ b/dom/wifi/nsIWifiCertService.idl @@ -7,7 +7,7 @@ interface nsIDOMBlob; interface nsIWifiEventListener; -[scriptable, uuid(2712a791-f720-484d-8820-c4085629f657)] +[scriptable, uuid(5d0edcd3-c2f1-4946-aae5-06adcbdf0992)] interface nsIWifiCertService : nsISupports { const unsigned short WIFI_CERT_USAGE_FLAG_SERVER = 0x01; @@ -43,4 +43,12 @@ interface nsIWifiCertService : nsISupports */ void deleteCert(in long id, in DOMString certNickname); + + /** + * Check if certificate has private key. + * + * @param certNickname + * Certificate nickname to check for private key. + */ + boolean hasPrivateKey(in DOMString certNickname); };