1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/keystore/KeyStore.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,388 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* vim: set sw=4 ts=8 et ft=cpp: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include <fcntl.h> 1.11 +#include <sys/stat.h> 1.12 + 1.13 +#undef CHROMIUM_LOG 1.14 +#if defined(MOZ_WIDGET_GONK) 1.15 +#include <android/log.h> 1.16 +#define CHROMIUM_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk", args) 1.17 +#else 1.18 +#define CHROMIUM_LOG(args...) printf(args); 1.19 +#endif 1.20 + 1.21 +#include "KeyStore.h" 1.22 +#include "jsfriendapi.h" 1.23 +#include "MainThreadUtils.h" // For NS_IsMainThread. 1.24 + 1.25 +#include "plbase64.h" 1.26 +#include "certdb.h" 1.27 +#include "ScopedNSSTypes.h" 1.28 + 1.29 +using namespace mozilla::ipc; 1.30 + 1.31 +namespace mozilla { 1.32 +namespace ipc { 1.33 + 1.34 +static const char* KEYSTORE_SOCKET_NAME = "keystore"; 1.35 +static const char* KEYSTORE_SOCKET_PATH = "/dev/socket/keystore"; 1.36 + 1.37 +int 1.38 +KeyStoreConnector::Create() 1.39 +{ 1.40 + MOZ_ASSERT(!NS_IsMainThread()); 1.41 + 1.42 + int fd; 1.43 + 1.44 + unlink(KEYSTORE_SOCKET_PATH); 1.45 + 1.46 + fd = socket(AF_LOCAL, SOCK_STREAM, 0); 1.47 + 1.48 + if (fd < 0) { 1.49 + NS_WARNING("Could not open keystore socket!"); 1.50 + return -1; 1.51 + } 1.52 + 1.53 + return fd; 1.54 +} 1.55 + 1.56 +bool 1.57 +KeyStoreConnector::CreateAddr(bool aIsServer, 1.58 + socklen_t& aAddrSize, 1.59 + sockaddr_any& aAddr, 1.60 + const char* aAddress) 1.61 +{ 1.62 + // Keystore socket must be server 1.63 + MOZ_ASSERT(aIsServer); 1.64 + 1.65 + aAddr.un.sun_family = AF_LOCAL; 1.66 + if(strlen(KEYSTORE_SOCKET_PATH) > sizeof(aAddr.un.sun_path)) { 1.67 + NS_WARNING("Address too long for socket struct!"); 1.68 + return false; 1.69 + } 1.70 + strcpy((char*)&aAddr.un.sun_path, KEYSTORE_SOCKET_PATH); 1.71 + aAddrSize = strlen(KEYSTORE_SOCKET_PATH) + offsetof(struct sockaddr_un, sun_path) + 1; 1.72 + 1.73 + return true; 1.74 +} 1.75 + 1.76 +bool 1.77 +KeyStoreConnector::SetUp(int aFd) 1.78 +{ 1.79 + return true; 1.80 +} 1.81 + 1.82 +bool 1.83 +KeyStoreConnector::SetUpListenSocket(int aFd) 1.84 +{ 1.85 + // Allow access of wpa_supplicant(different user, differnt group) 1.86 + chmod(KEYSTORE_SOCKET_PATH, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); 1.87 + 1.88 + return true; 1.89 +} 1.90 + 1.91 +void 1.92 +KeyStoreConnector::GetSocketAddr(const sockaddr_any& aAddr, 1.93 + nsAString& aAddrStr) 1.94 +{ 1.95 + // Unused. 1.96 + MOZ_CRASH("This should never be called!"); 1.97 +} 1.98 + 1.99 +static char * 1.100 +get_cert_db_filename(void *arg, int vers) 1.101 +{ 1.102 + static char keystoreDbPath[] = "/data/misc/wifi/keystore"; 1.103 + return keystoreDbPath; 1.104 +} 1.105 + 1.106 +KeyStore::KeyStore() 1.107 +{ 1.108 + // Initial NSS 1.109 + certdb = CERT_GetDefaultCertDB(); 1.110 + 1.111 + Listen(); 1.112 +} 1.113 + 1.114 +void 1.115 +KeyStore::Shutdown() 1.116 +{ 1.117 + mShutdown = true; 1.118 + CloseSocket(); 1.119 +} 1.120 + 1.121 +void 1.122 +KeyStore::Listen() 1.123 +{ 1.124 + ListenSocket(new KeyStoreConnector()); 1.125 + 1.126 + ResetHandlerInfo(); 1.127 +} 1.128 + 1.129 +void 1.130 +KeyStore::ResetHandlerInfo() 1.131 +{ 1.132 + mHandlerInfo.state = STATE_IDLE; 1.133 + mHandlerInfo.command = 0; 1.134 + mHandlerInfo.paramCount = 0; 1.135 + mHandlerInfo.commandPattern = nullptr; 1.136 + for (int i = 0; i < MAX_PARAM; i++) { 1.137 + mHandlerInfo.param[i].length = 0; 1.138 + memset(mHandlerInfo.param[i].data, 0, VALUE_SIZE); 1.139 + } 1.140 +} 1.141 + 1.142 +bool 1.143 +KeyStore::CheckSize(UnixSocketRawData *aMessage, size_t aExpectSize) 1.144 +{ 1.145 + return (aMessage->mSize - aMessage->mCurrentWriteOffset >= aExpectSize) ? 1.146 + true : false; 1.147 +} 1.148 + 1.149 +bool 1.150 +KeyStore::ReadCommand(UnixSocketRawData *aMessage) 1.151 +{ 1.152 + if (mHandlerInfo.state != STATE_IDLE) { 1.153 + NS_WARNING("Wrong state in ReadCommand()!"); 1.154 + return false; 1.155 + } 1.156 + 1.157 + if (!CheckSize(aMessage, 1)) { 1.158 + NS_WARNING("Data size error in ReadCommand()!"); 1.159 + return false; 1.160 + } 1.161 + 1.162 + mHandlerInfo.command = aMessage->mData[aMessage->mCurrentWriteOffset]; 1.163 + aMessage->mCurrentWriteOffset++; 1.164 + 1.165 + // Find corrsponding command pattern 1.166 + const struct ProtocolCommand *command = commands; 1.167 + while (command->command && command->command != mHandlerInfo.command) { 1.168 + command++; 1.169 + } 1.170 + 1.171 + if (!command->command) { 1.172 + NS_WARNING("Unsupported command!"); 1.173 + return false; 1.174 + } 1.175 + 1.176 + // Get command pattern. 1.177 + mHandlerInfo.commandPattern = command; 1.178 + if (command->paramNum) { 1.179 + // Read command parameter if needed. 1.180 + mHandlerInfo.state = STATE_READ_PARAM_LEN; 1.181 + } else { 1.182 + mHandlerInfo.state = STATE_PROCESSING; 1.183 + } 1.184 + 1.185 + return true; 1.186 +} 1.187 + 1.188 +bool 1.189 +KeyStore::ReadLength(UnixSocketRawData *aMessage) 1.190 +{ 1.191 + if (mHandlerInfo.state != STATE_READ_PARAM_LEN) { 1.192 + NS_WARNING("Wrong state in ReadLength()!"); 1.193 + return false; 1.194 + } 1.195 + 1.196 + if (!CheckSize(aMessage, 2)) { 1.197 + NS_WARNING("Data size error in ReadLength()!"); 1.198 + return false; 1.199 + } 1.200 + 1.201 + // Read length of command parameter. 1.202 + unsigned short dataLength; 1.203 + memcpy(&dataLength, &aMessage->mData[aMessage->mCurrentWriteOffset], 2); 1.204 + aMessage->mCurrentWriteOffset += 2; 1.205 + mHandlerInfo.param[mHandlerInfo.paramCount].length = ntohs(dataLength); 1.206 + 1.207 + mHandlerInfo.state = STATE_READ_PARAM_DATA; 1.208 + 1.209 + return true; 1.210 +} 1.211 + 1.212 +bool 1.213 +KeyStore::ReadData(UnixSocketRawData *aMessage) 1.214 +{ 1.215 + if (mHandlerInfo.state != STATE_READ_PARAM_DATA) { 1.216 + NS_WARNING("Wrong state in ReadData()!"); 1.217 + return false; 1.218 + } 1.219 + 1.220 + if (!CheckSize(aMessage, mHandlerInfo.param[mHandlerInfo.paramCount].length)) { 1.221 + NS_WARNING("Data size error in ReadData()!"); 1.222 + return false; 1.223 + } 1.224 + 1.225 + // Read command parameter. 1.226 + memcpy(mHandlerInfo.param[mHandlerInfo.paramCount].data, 1.227 + &aMessage->mData[aMessage->mCurrentWriteOffset], 1.228 + mHandlerInfo.param[mHandlerInfo.paramCount].length); 1.229 + aMessage->mCurrentWriteOffset += mHandlerInfo.param[mHandlerInfo.paramCount].length; 1.230 + mHandlerInfo.paramCount++; 1.231 + 1.232 + if (mHandlerInfo.paramCount == mHandlerInfo.commandPattern->paramNum) { 1.233 + mHandlerInfo.state = STATE_PROCESSING; 1.234 + } else { 1.235 + mHandlerInfo.state = STATE_READ_PARAM_LEN; 1.236 + } 1.237 + 1.238 + return true; 1.239 +} 1.240 + 1.241 +// Transform base64 certification data into DER format 1.242 +void 1.243 +KeyStore::FormatCaData(const uint8_t *aCaData, int aCaDataLength, 1.244 + const char *aName, const uint8_t **aFormatData, 1.245 + int &aFormatDataLength) 1.246 +{ 1.247 + int bufSize = strlen(CA_BEGIN) + strlen(CA_END) + strlen(CA_TAILER) * 2 + 1.248 + strlen(aName) * 2 + aCaDataLength + aCaDataLength/CA_LINE_SIZE + 2; 1.249 + char *buf = (char *)malloc(bufSize); 1.250 + 1.251 + aFormatDataLength = bufSize; 1.252 + *aFormatData = (const uint8_t *)buf; 1.253 + 1.254 + char *ptr = buf; 1.255 + int len; 1.256 + 1.257 + // Create DER header. 1.258 + len = snprintf(ptr, bufSize, "%s%s%s", CA_BEGIN, aName, CA_TAILER); 1.259 + ptr += len; 1.260 + bufSize -= len; 1.261 + 1.262 + // Split base64 data in lines. 1.263 + int copySize; 1.264 + while (aCaDataLength > 0) { 1.265 + copySize = (aCaDataLength > CA_LINE_SIZE) ? CA_LINE_SIZE : aCaDataLength; 1.266 + 1.267 + memcpy(ptr, aCaData, copySize); 1.268 + ptr += copySize; 1.269 + aCaData += copySize; 1.270 + aCaDataLength -= copySize; 1.271 + bufSize -= copySize; 1.272 + 1.273 + *ptr = '\n'; 1.274 + ptr++; 1.275 + bufSize--; 1.276 + } 1.277 + 1.278 + // Create DEA tailer. 1.279 + snprintf(ptr, bufSize, "%s%s%s", CA_END, aName, CA_TAILER); 1.280 +} 1.281 + 1.282 +// Status response 1.283 +void 1.284 +KeyStore::SendResponse(ResponseCode aResponse) 1.285 +{ 1.286 + if (aResponse == NO_RESPONSE) 1.287 + return; 1.288 + 1.289 + uint8_t response = (uint8_t)aResponse; 1.290 + UnixSocketRawData* data = new UnixSocketRawData((const void *)&response, 1); 1.291 + SendSocketData(data); 1.292 +} 1.293 + 1.294 +// Data response 1.295 +void 1.296 +KeyStore::SendData(const uint8_t *aData, int aLength) 1.297 +{ 1.298 + unsigned short dataLength = htons(aLength); 1.299 + 1.300 + UnixSocketRawData* length = new UnixSocketRawData((const void *)&dataLength, 2); 1.301 + SendSocketData(length); 1.302 + 1.303 + UnixSocketRawData* data = new UnixSocketRawData((const void *)aData, aLength); 1.304 + SendSocketData(data); 1.305 +} 1.306 + 1.307 +void 1.308 +KeyStore::ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage) 1.309 +{ 1.310 + MOZ_ASSERT(NS_IsMainThread()); 1.311 + 1.312 + bool success = true; 1.313 + while (aMessage->mCurrentWriteOffset < aMessage->mSize || 1.314 + mHandlerInfo.state == STATE_PROCESSING) { 1.315 + switch (mHandlerInfo.state) { 1.316 + case STATE_IDLE: 1.317 + success = ReadCommand(aMessage); 1.318 + break; 1.319 + case STATE_READ_PARAM_LEN: 1.320 + success = ReadLength(aMessage); 1.321 + break; 1.322 + case STATE_READ_PARAM_DATA: 1.323 + success = ReadData(aMessage); 1.324 + break; 1.325 + case STATE_PROCESSING: 1.326 + success = false; 1.327 + if (mHandlerInfo.command == 'g') { 1.328 + // Get CA 1.329 + const uint8_t *certData; 1.330 + int certDataLength; 1.331 + const char *certName = (const char *)mHandlerInfo.param[0].data; 1.332 + 1.333 + // Get cert from NSS by name 1.334 + ScopedCERTCertificate cert(CERT_FindCertByNickname(certdb, certName)); 1.335 + if (!cert) { 1.336 + break; 1.337 + } 1.338 + 1.339 + char *certDER = PL_Base64Encode((const char *)cert->derCert.data, 1.340 + cert->derCert.len, nullptr); 1.341 + if (!certDER) { 1.342 + break; 1.343 + } 1.344 + 1.345 + FormatCaData((const uint8_t *)certDER, strlen(certDER), "CERTIFICATE", 1.346 + &certData, certDataLength); 1.347 + PL_strfree(certDER); 1.348 + 1.349 + SendResponse(SUCCESS); 1.350 + SendData(certData, certDataLength); 1.351 + success = true; 1.352 + 1.353 + free((void *)certData); 1.354 + } 1.355 + 1.356 + ResetHandlerInfo(); 1.357 + break; 1.358 + } 1.359 + 1.360 + if (!success) { 1.361 + SendResponse(PROTOCOL_ERROR); 1.362 + ResetHandlerInfo(); 1.363 + return; 1.364 + } 1.365 + } 1.366 +} 1.367 + 1.368 +void 1.369 +KeyStore::OnConnectSuccess() 1.370 +{ 1.371 + mShutdown = false; 1.372 +} 1.373 + 1.374 +void 1.375 +KeyStore::OnConnectError() 1.376 +{ 1.377 + if (!mShutdown) { 1.378 + Listen(); 1.379 + } 1.380 +} 1.381 + 1.382 +void 1.383 +KeyStore::OnDisconnect() 1.384 +{ 1.385 + if (!mShutdown) { 1.386 + Listen(); 1.387 + } 1.388 +} 1.389 + 1.390 +} // namespace ipc 1.391 +} // namespace mozilla