X-Git-Url: http://plrg.eecs.uci.edu/git/?p=iotcloud.git;a=blobdiff_plain;f=version2%2Fsrc%2FC%2FCloudComm.cc;h=3b5fb970199962959a18895dc03824a3b923ebf4;hp=c6c0e750dd060e0ad35d24aad61c587c0d42675c;hb=d60b25736c12e51307a9c32cacf39671e42b9fbd;hpb=34ca5d4113dbbd0b5342abd280e2f9e11e7cd3b7 diff --git a/version2/src/C/CloudComm.cc b/version2/src/C/CloudComm.cc index c6c0e75..3b5fb97 100644 --- a/version2/src/C/CloudComm.cc +++ b/version2/src/C/CloudComm.cc @@ -5,6 +5,13 @@ #include "Error.h" #include "URL.h" #include "Mac.h" +#include "Table.h" +#include "Slot.h" +#include "Crypto.h" +#include "ByteBuffer.h" +#include "aes.h" +#include +#include /** * Empty Constructor needed for child class. @@ -20,10 +27,18 @@ CloudComm::CloudComm() : listeningPort(-1), localServerThread(NULL), doEnd(false), - timer(TimingSingleton_getInstance()) + timer(TimingSingleton_getInstance()), + getslot(new Array("getslot", 7)), + putslot(new Array("putslot", 7)) { } +void *threadWrapper(void *cloud) { + CloudComm *c = (CloudComm *) cloud; + c->localServerWorkerFunction(); + return NULL; +} + /** * Constructor for actual use. Takes in the url and password. */ @@ -40,26 +55,20 @@ CloudComm::CloudComm(Table *_table, IoTString *_baseurl, IoTString *_password, doEnd(false), timer(TimingSingleton_getInstance()) { if (listeningPort > 0) { - localServerThread = new Thread(new Runnable() { - void run() { - localServerWorkerFunction(); - } - }); - localServerThread->start(); + pthread_create(&localServerThread, NULL, threadWrapper, this); } } /** * Generates Key from password. */ -SecretKeySpec *CloudComm::initKey() { +AESKey *CloudComm::initKey() { try { - PBEKeySpec *keyspec = new PBEKeySpec(password->internalBytes(), - salt, - 65536, - 128); - SecretKey *tmpkey = SecretKeyFactory_getInstance("PBKDF2WithHmacSHA256")->generateSecret(keyspec); - return new SecretKeySpec(tmpkey->getEncoded(), "AES"); + AESKey *key = new AESKey(password->internalBytes(), + salt, + 65536, + 128); + return key; } catch (Exception *e) { throw new Error("Failed generating key."); } @@ -89,7 +98,7 @@ void CloudComm::initCrypt() { try { key = initKey(); password = NULL;// drop password - mac = Mac_getInstance("HmacSHA256"); + mac = new Mac(); mac->init(key); } catch (Exception *e) { throw new Error("Failed To Initialize Ciphers"); @@ -99,7 +108,7 @@ void CloudComm::initCrypt() { /* * Builds the URL for the given request. */ -URL *CloudComm::buildRequest(bool isput, int64_t sequencenumber, int64_t maxentries) { +IoTString *CloudComm::buildRequest(bool isput, int64_t sequencenumber, int64_t maxentries) { const char *reqstring = isput ? "req=putslot" : "req=getslot"; char *buffer = (char *) malloc(baseurl->length() + 200); memcpy(buffer, baseurl->internalBytes(), baseurl->length()); @@ -108,8 +117,45 @@ URL *CloudComm::buildRequest(bool isput, int64_t sequencenumber, int64_t maxentr if (maxentries != 0) sprintf(&buffer[offset], "&max=%" PRId64, maxentries); IoTString *urlstr = new IoTString(buffer); - free(buffer); - return new URL(urlstr); + return urlstr; +} + +int openURL(IoTString *url, bool isPost) { + return 0; +} + +int createSocket(IoTString *host, int port) { + return 0; +} + +int createSocket(int port) { + return 0; +} + +int acceptSocket(int socket) { + return 0; +} + +void writeSocketData(int fd, Array *data) {} + +void writeSocketInt(int fd, int value) {} + +int readSocketInt(int fd) {return 0;} + +void readSocketData(int fd, Array *data) {} + +void writeURLData(int fd, Array *data) { +} + +void readURLData(int fd, Array *output) { +} + +int readURLInt(int fd) { + return 0; +} + +int getResponseCode(int fd) { + return 0; } void CloudComm::setSalt() { @@ -118,6 +164,7 @@ void CloudComm::setSalt() { return; } + int fd = -1; try { Array *saltTmp = new Array(CloudComm_SALT_SIZE); random->nextBytes(saltTmp); @@ -129,22 +176,11 @@ void CloudComm::setSalt() { IoTString *urlstr = new IoTString(buffer); free(buffer); - URL *url = new URL(urlstr); timer->startTime(); - URLConnection *con = url->openConnection(); - HttpURLConnection *http = (HttpURLConnection *) con; - - http->setRequestMethod("POST"); - http->setFixedLengthStreamingMode(saltTmp->length()); - http->setDoOutput(true); - http->setConnectTimeout(CloudComm_TIMEOUT_MILLIS); - http->connect(); + fd = openURL(urlstr, true); + writeURLData(fd, saltTmp); - OutputStream *os = http->getOutputStream(); - os->write(saltTmp); - os->flush(); - - int responsecode = http->getResponseCode(); + int responsecode = getResponseCode(fd); if (responsecode != HttpURLConnection_HTTP_OK) { throw new Error("Invalid response"); } @@ -158,30 +194,22 @@ void CloudComm::setSalt() { } bool CloudComm::getSalt() { - URL *url = NULL; - URLConnection *con = NULL; - HttpURLConnection *http = NULL; + int fd = -1; + IoTString *urlstr = NULL; try { char *buffer = (char *) malloc(baseurl->length() + 100); memcpy(buffer, baseurl->internalBytes(), baseurl->length()); int offset = baseurl->length(); offset += sprintf(&buffer[offset], "?req=getsalt"); - IoTString *urlstr = new IoTString(buffer); + urlstr = new IoTString(buffer); free(buffer); - - url = new URL(urlstr); } catch (Exception *e) { throw new Error("getSlot failed"); } try { timer->startTime(); - con = url->openConnection(); - http = (HttpURLConnection *) con; - http->setRequestMethod("POST"); - http->setConnectTimeout(CloudComm_TIMEOUT_MILLIS); - http->setReadTimeout(CloudComm_TIMEOUT_MILLIS); - http->connect(); + fd = openURL(urlstr, true); timer->endTime(); } catch (SocketTimeoutException *e) { timer->endTime(); @@ -192,23 +220,16 @@ bool CloudComm::getSalt() { try { timer->startTime(); - int responsecode = http->getResponseCode(); + int responsecode = getResponseCode(fd); if (responsecode != HttpURLConnection_HTTP_OK) { throw new Error("Invalid response"); } - InputStream *is = http->getInputStream(); - if (is->available() > 0) { - DataInputStream *dis = new DataInputStream(is); - int salt_length = dis->readInt(); - Array *tmp = new Array(salt_length); - dis->readFully(tmp); - salt = tmp; - timer->endTime(); - return true; - } else { - timer->endTime(); - return false; - } + int salt_length = readURLInt(fd); + Array *tmp = new Array(salt_length); + readURLData(fd, tmp); + salt = tmp; + timer->endTime(); + return true; } catch (SocketTimeoutException *e) { timer->endTime(); throw new ServerException("getSalt failed", ServerException_TypeInputTimeout); @@ -225,12 +246,21 @@ Array *CloudComm::createIV(int64_t machineId, int64_t localSequenceNumber) return buffer->array(); } +Array *AESEncrypt(Array *ivBytes, AESKey *key, Array *data) { + Array * output=new Array(data->length()); + aes_encrypt_ctr((BYTE *)data->internalArray(), data->length(), (BYTE *) output->internalArray(), (WORD *)key->getKey()->internalArray(), key->getKey()->length()/(sizeof(WORD)/sizeof(BYTE)), (BYTE *)ivBytes->internalArray()); + return output; +} + +Array *AESDecrypt(Array *ivBytes, AESKey *key, Array *data) { + Array * output=new Array(data->length()); + aes_decrypt_ctr((BYTE *)data->internalArray(), data->length(), (BYTE *)output->internalArray(), (WORD *)key->getKey()->internalArray(), key->getKey()->length()/(sizeof(WORD)/sizeof(BYTE)), (BYTE *)ivBytes->internalArray()); + return output; +} + Array *CloudComm::encryptSlotAndPrependIV(Array *rawData, Array *ivBytes) { try { - IvParameterSpec *ivSpec = new IvParameterSpec(ivBytes); - Cipher *cipher = Cipher_getInstance("AES/CTR/NoPadding"); - cipher->init(Cipher_ENCRYPT_MODE, key, ivSpec); - Array *encryptedBytes = cipher->doFinal(rawData); + Array *encryptedBytes = AESEncrypt(ivBytes, key, rawData); Array *chars = new Array(encryptedBytes->length() + CloudComm_IV_SIZE); System_arraycopy(ivBytes, 0, chars, 0, ivBytes->length()); System_arraycopy(encryptedBytes, 0, chars, CloudComm_IV_SIZE, encryptedBytes->length()); @@ -246,11 +276,8 @@ Array *CloudComm::stripIVAndDecryptSlot(Array *rawData) { Array *ivBytes = new Array(CloudComm_IV_SIZE); Array *encryptedBytes = new Array(rawData->length() - CloudComm_IV_SIZE); System_arraycopy(rawData, 0, ivBytes, 0, CloudComm_IV_SIZE); - System_arraycopy(rawData, CloudComm_IV_SIZE, encryptedBytes, 0, encryptedBytes->length); - IvParameterSpec *ivSpec = new IvParameterSpec(ivBytes); - Cipher *cipher = Cipher_getInstance("AES/CTR/NoPadding"); - cipher->init(Cipher_DECRYPT_MODE, key, ivSpec); - return cipher->doFinal(encryptedBytes); + System_arraycopy(rawData, CloudComm_IV_SIZE, encryptedBytes, 0, encryptedBytes->length()); + return AESDecrypt(ivBytes, key, encryptedBytes); } catch (Exception *e) { throw new Error("Failed To Decrypt"); } @@ -262,6 +289,7 @@ Array *CloudComm::stripIVAndDecryptSlot(Array *rawData) { * numbers. */ Array *CloudComm::putSlot(Slot *slot, int max) { + int fd = -1; try { if (salt == NULL) { if (!getSalt()) { @@ -273,19 +301,10 @@ Array *CloudComm::putSlot(Slot *slot, int max) { int64_t sequencenumber = slot->getSequenceNumber(); Array *slotBytes = slot->encode(mac); Array *chars = encryptSlotAndPrependIV(slotBytes, slot->getSlotCryptIV()); - URL *url = buildRequest(true, sequencenumber, max); + IoTString *url = buildRequest(true, sequencenumber, max); timer->startTime(); - URLConnection *con = url->openConnection(); - HttpURLConnection *http = (HttpURLConnection *) con; - http->setRequestMethod("POST"); - http->setFixedLengthStreamingMode(chars->length); - http->setDoOutput(true); - http->setConnectTimeout(CloudComm_TIMEOUT_MILLIS); - http->setReadTimeout(CloudComm_TIMEOUT_MILLIS); - http->connect(); - OutputStream *os = http->getOutputStream(); - os->write(chars); - os->flush(); + fd = openURL(url, true); + writeURLData(fd, chars); timer->endTime(); } catch (ServerException *e) { timer->endTime(); @@ -299,21 +318,19 @@ Array *CloudComm::putSlot(Slot *slot, int max) { try { timer->startTime(); - InputStream *is = http->getInputStream(); - DataInputStream *dis = new DataInputStream(is); Array *resptype = new Array(7); - dis->readFully(resptype); + readURLData(fd, resptype); timer->endTime(); - if (Arrays->equals(resptype, "getslot"->getBytes())) { - return processSlots(dis); - } else if (Arrays->equals(resptype, "putslot"->getBytes())) { + if (resptype->equals(getslot)) { + return processSlots(fd); + } else if (resptype->equals(putslot)) { return NULL; } else throw new Error("Bad response to putslot"); } catch (SocketTimeoutException *e) { timer->endTime(); - throw new ServerException("putSlot failed", ServerException->TypeInputTimeout); + throw new ServerException("putSlot failed", ServerException_TypeInputTimeout); } catch (Exception *e) { throw new Error("putSlot failed"); } @@ -324,6 +341,7 @@ Array *CloudComm::putSlot(Slot *slot, int max) { * sequencenumber or newer-> */ Array *CloudComm::getSlots(int64_t sequencenumber) { + int fd = -1; try { if (salt == NULL) { if (!getSalt()) { @@ -332,14 +350,9 @@ Array *CloudComm::getSlots(int64_t sequencenumber) { initCrypt(); } - URL *url = buildRequest(false, sequencenumber, 0); + IoTString *url = buildRequest(false, sequencenumber, 0); timer->startTime(); - URLConnection *con = url->openConnection(); - HttpURLConnection *http = (HttpURLConnection *) con; - http->setRequestMethod("POST"); - http->setConnectTimeout(CloudComm_TIMEOUT_MILLIS); - http->setReadTimeout(CloudComm_TIMEOUT_MILLIS); - http->connect(); + fd = openURL(url, true); timer->endTime(); } catch (SocketTimeoutException *e) { timer->endTime(); @@ -354,15 +367,13 @@ Array *CloudComm::getSlots(int64_t sequencenumber) { try { timer->startTime(); - InputStream *is = http->getInputStream(); - DataInputStream *dis = new DataInputStream(is); Array *resptype = new Array(7); - dis->readFully(resptype); + readURLData(fd, resptype); timer->endTime(); - if (!resptype->equals("getslot"->getBytes())) - throw new Error("Bad Response: " + new String(resptype)); + if (!resptype->equals(getslot)) + throw new Error("Bad Response: "); - return processSlots(dis); + return processSlots(fd); } catch (SocketTimeoutException *e) { timer->endTime(); throw new ServerException("getSlots failed", ServerException_TypeInputTimeout); @@ -375,29 +386,28 @@ Array *CloudComm::getSlots(int64_t sequencenumber) { * Method that actually handles building Slot objects from the * server response. Shared by both putSlot and getSlots. */ -Array *CloudComm::processSlots(DataInputStream *dis) { - int numberofslots = dis->readInt(); +Array *CloudComm::processSlots(int fd) { + int numberofslots = readURLInt(fd); Array *sizesofslots = new Array(numberofslots); Array *slots = new Array(numberofslots); for (int i = 0; i < numberofslots; i++) - sizesofslots->set(i, dis->readInt()); + sizesofslots->set(i, readURLInt(fd)); for (int i = 0; i < numberofslots; i++) { Array *rawData = new Array(sizesofslots->get(i)); - dis->readFully(rawData); + readURLData(fd, rawData); Array *data = stripIVAndDecryptSlot(rawData); slots->set(i, Slot_decode(table, data, mac)); } - dis->close(); return slots; } -Array *sendLocalData(Array *sendData, int64_t localSequenceNumber, String host, int port) { +Array *CloudComm::sendLocalData(Array *sendData, int64_t localSequenceNumber, IoTString *host, int port) { if (salt == NULL) return NULL; try { printf("Passing Locally\n"); - mac->update(sendData); + mac->update(sendData, 0, sendData->length()); Array *genmac = mac->doFinal(); Array *totalData = new Array(sendData->length() + genmac->length()); System_arraycopy(sendData, 0, totalData, 0, sendData->length()); @@ -408,35 +418,31 @@ Array *sendLocalData(Array *sendData, int64_t localSequenceNumber, S Array *encryptedData = encryptSlotAndPrependIV(totalData, iv); // Open a TCP socket connection to a local device - Socket *socket = new Socket(host, port); - socket->setReuseAddress(true); - DataOutputStream *output = new DataOutputStream(socket->getOutputStream()); - DataInputStream *input = new DataInputStream(socket->getInputStream()); + int socket = createSocket(host, port); timer->startTime(); // Send data to output (length of data, the data) - output->writeInt(encryptedData->length); - output->write(encryptedData, 0, encryptedData->length); - output->flush(); + writeSocketInt(socket, encryptedData->length()); + writeSocketData(socket, encryptedData); - int lengthOfReturnData = input->readInt(); + int lengthOfReturnData = readSocketInt(socket); Array *returnData = new Array(lengthOfReturnData); - input->readFully(returnData); + readSocketData(socket, returnData); timer->endTime(); returnData = stripIVAndDecryptSlot(returnData); // We are done with this socket - socket->close(); - mac->update(returnData, 0, returnData->length - HMAC_SIZE); + close(socket); + mac->update(returnData, 0, returnData->length() - CloudComm_HMAC_SIZE); Array *realmac = mac->doFinal(); - Array *recmac = new Array(HMAC_SIZE); - System_arraycopy(returnData, returnData->length - realmac->length, recmac, 0, realmac->length); + Array *recmac = new Array(CloudComm_HMAC_SIZE); + System_arraycopy(returnData, returnData->length() - realmac->length(), recmac, 0, realmac->length()); if (!recmac->equals(realmac)) throw new Error("Local Error: Invalid HMAC! Potential Attack!"); Array *returnData2 = new Array(lengthOfReturnData - recmac->length()); - System_arraycopy(returnData, 0, returnData2, 0, returnData2->length); + System_arraycopy(returnData, 0, returnData2, 0, returnData2->length()); return returnData2; } catch (Exception *e) { @@ -447,13 +453,11 @@ Array *sendLocalData(Array *sendData, int64_t localSequenceNumber, S } void CloudComm::localServerWorkerFunction() { - ServerSocket *inputSocket = NULL; + int inputSocket = -1; try { // Local server socket - inputSocket = new ServerSocket(listeningPort); - inputSocket->setReuseAddress(true); - inputSocket->setSoTimeout(CloudComm_TIMEOUT_MILLIS); + inputSocket = createSocket(listeningPort); } catch (Exception *e) { throw new Error("Local server setup failure..."); } @@ -461,21 +465,19 @@ void CloudComm::localServerWorkerFunction() { while (!doEnd) { try { // Accept incoming socket - Socket *socket = inputSocket->accept(); - DataInputStream *input = new DataInputStream(socket->getInputStream()); - DataOutputStream *output = new DataOutputStream(socket->getOutputStream()); + int socket = acceptSocket(inputSocket); // Get the encrypted data from the server - int dataSize = input->readInt(); + int dataSize = readSocketInt(socket); Array *readData = new Array(dataSize); - input->readFully(readData); + readSocketData(socket, readData); timer->endTime(); // Decrypt the data readData = stripIVAndDecryptSlot(readData); - mac->update(readData, 0, readData->length - HMAC_SIZE); + mac->update(readData, 0, readData->length() - CloudComm_HMAC_SIZE); Array *genmac = mac->doFinal(); - Array *recmac = new Array(HMAC_SIZE); + Array *recmac = new Array(CloudComm_HMAC_SIZE); System_arraycopy(readData, readData->length() - recmac->length(), recmac, 0, recmac->length()); if (!recmac->equals(genmac)) @@ -486,7 +488,7 @@ void CloudComm::localServerWorkerFunction() { // Process the data Array *sendData = table->acceptDataFromLocal(returnData); - mac->update(sendData); + mac->update(sendData, 0, sendData->length()); Array *realmac = mac->doFinal(); Array *totalData = new Array(sendData->length() + realmac->length()); System_arraycopy(sendData, 0, totalData, 0, sendData->length()); @@ -498,33 +500,27 @@ void CloudComm::localServerWorkerFunction() { timer->startTime(); // Send data to output (length of data, the data) - output->writeInt(encryptedData->length()); - output->write(encryptedData, 0, encryptedData->length()); - output->flush(); - - // close the socket - socket->close(); + writeSocketInt(socket, encryptedData->length()); + writeSocketData(socket, encryptedData); + close(socket); } catch (Exception *e) { } } - if (inputSocket != NULL) { + if (inputSocket != -1) { try { - inputSocket->close(); + close(inputSocket); } catch (Exception *e) { throw new Error("Local server close failure..."); } } } -void CloudComm::close() { +void CloudComm::closeCloud() { doEnd = true; if (localServerThread != NULL) { - try { - localServerThread->join(); - } catch (Exception *e) { + if (pthread_join(localServerThread, NULL) != 0) throw new Error("Local Server thread join issue..."); - } } }