#define DTLS_PSK_ID_LEN 16
#define DTLS_PSK_PSK_LEN 16
-#define DtlsPskCredsBlobVer_1 1 /**< Credentials stored in plaintext */
-#define DtlsPskCredsBlobVer_CurrentVersion DtlsPskCredsBlobVer_1
+#define OCSecConfigVer_1 1 /**< Initial version supporting PSK Credentials */
+#define OCSecConfigVer_CurrentVersion OCSecConfigVer_1
+
+typedef enum{
+ OC_BLOB_TYPE_PSK = 1, /**< Security blob holding PSK data */
+} OCBlobType;
+
/**
- * Credentials for a device. Includes identity and the associated PSK.
+ * Credentials of a peer device. Includes identity and the associated PSK.
*/
typedef struct
{
- unsigned char id[DTLS_PSK_ID_LEN];
- unsigned char psk[DTLS_PSK_PSK_LEN];
+ unsigned char id[DTLS_PSK_ID_LEN]; /**< identity of the peer device */
+ unsigned char psk[DTLS_PSK_PSK_LEN]; /**< psk of the peer device */
} OCDtlsPskCreds;
*/
typedef struct
{
- uint16_t blobVer; /**< version of the blob */
- uint16_t reserved; /**< reserved for future use */
- unsigned char identity[DTLS_PSK_ID_LEN]; /**< identity of self */
- uint32_t num; /**< number of credentials in this blob */
- OCDtlsPskCreds creds[1]; /**< list of credentials. Size of this
+ unsigned char identity[DTLS_PSK_ID_LEN]; /**< identity of self */
+ uint32_t num; /**< number of credentials in this blob */
+ OCDtlsPskCreds creds[1]; /**< list of credentials. Size of this
array is determined by 'num' variable. */
} OCDtlsPskCredsBlob;
+/**
+ * Generic definition of a security blob. A security blob can contain
+ * info of various types, such as : PSK info, certificates,
+ * access control lists(ACL) etc.
+ */
+typedef struct
+{
+ uint16_t type; /**< Type of blob */
+ uint16_t len; /**< length of blob data */
+ uint8_t val[1]; /**< A variable size array holding blob data */
+} OCSecBlob;
+
+
+/**
+ * This structure defines the security related configuration data for
+ * Iotivity applications.
+ */
+typedef struct
+{
+ uint16_t version; /**< version of the config data */
+ uint16_t numBlob; /**< number of security blobs in this config data */
+ uint8_t blob[1]; /**< A variable size array holding a blob */
+} OCSecConfigData;
+
+/**
+ * Interprets @p blob as pointer to a OCSecBlob and advances to
+ * the next blob in the OCSecConfigData
+ */
+#define config_data_next_blob(blob) \
+ ((OCSecBlob*)((blob)->val + (blob)->len));
+
+/**
+ * Configuration data for security will be stored in below fashion in a
+ * flat file on persistent storage.
+ *
+ * --------------------------------------------------------------
+ * | OCSecConfigData| OCSecBlob #1 | OCSecBlob #2 | OCSecBlob #3|
+ * --------------------------------------------------------------
+ */
+
#endif //OC_SECURITY_CONFIG_H
#include "ocsecurityconfig.h"
#include <string.h>
-static OCDtlsPskCredsBlob* pskCredsBlob;
-static int pskCredsBlobLen;
+static OCSecConfigData* secConfigData;
+static int secConfigDataLen;
-// Internal API. Invoked by OC stack to cleanup memory
+/**
+ * This internal API removes/clears the global variable holding the security
+ * config data. This needs to be invoked when OIC stack is shutting down.
+ *
+ * @retval none
+ */
void DeinitOCSecurityInfo()
{
- if (pskCredsBlob)
+ if (secConfigData)
{
// Initialize sensitive data to zeroes before freeing.
- memset(pskCredsBlob, 0, pskCredsBlobLen);
+ memset(secConfigData, 0, secConfigDataLen);
- OCFree(pskCredsBlob);
- pskCredsBlob = NULL;
+ OCFree(secConfigData);
+ secConfigData = NULL;
}
}
-// Internal API. Invoked by OC stack to retrieve credentials from this module
+/**
+ * This internal callback is used by lower stack (i.e. CA layer) to
+ * retrieve PSK credentials from RI security layer.
+ *
+ * Note: When finished, caller should initialize memory to zeroes and
+ * invoke OCFree to delete @p credInfo.
+ *
+ * @param credInfo
+ * binary blob containing PSK credentials
+ *
+ * @retval none
+ */
void GetDtlsPskCredentials(OCDtlsPskCredsBlob **credInfo)
{
- *credInfo = pskCredsBlob;
+ if(secConfigData && credInfo)
+ {
+ unsigned int i = 0;
+ OCSecBlob * osb = (OCSecBlob*)secConfigData->blob;
+ for ( ;(i<secConfigData->numBlob) && osb; i++)
+ {
+ if (osb->type == OC_BLOB_TYPE_PSK)
+ {
+ OCDtlsPskCredsBlob * blob;
+ blob = (OCDtlsPskCredsBlob *)OCMalloc(osb->len);
+ if (blob)
+ {
+ memcpy(blob, osb->val, osb->len);
+ *credInfo = blob;
+ break;
+ }
+ }
+ osb = config_data_next_blob(osb);
+ }
+ }
}
+
/**
- * Provides the DTLS PSK credetials blob to OC stack.
+ * This method validates the sanctity of OCDtlsPskCredsBlob.
*
- * @param credInfo
- * binary blob containing credentials
+ * @param secBlob
+ * binary blob containing PSK credentials
+ *
+ * @retval OC_STACK_OK for Success, otherwise some error value
+ */
+static
+OCStackResult ValidateBlobTypePSK(const OCSecBlob *secBlob)
+{
+ OCDtlsPskCredsBlob *pskCredsBlob;
+ uint16_t validLen;
+
+ if(secBlob->len == 0)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ pskCredsBlob = (OCDtlsPskCredsBlob *)secBlob->val;
+
+ //calculate the expected length of PSKCredsBlob
+ if(pskCredsBlob->num >= 1)
+ {
+ validLen = sizeof(OCDtlsPskCredsBlob) +
+ (pskCredsBlob->num - 1) * sizeof(OCDtlsPskCredsBlob);
+ }
+ else
+ {
+ validLen = sizeof(OCDtlsPskCredsBlob);
+ }
+
+ if(secBlob->len != validLen)
+ return OC_STACK_INVALID_PARAM;
+
+ return OC_STACK_OK;
+}
+
+
+/**
+ * This method validates the sanctity of configuration data provided
+ * by application to OC stack.
+ *
+ * @param cfgdata
+ * binary blob containing credentials and other config data
* @param len
* length of binary blob
*
* @retval OC_STACK_OK for Success, otherwise some error value
*/
-OCStackResult OCSetDtlsPskCredentials(const OCDtlsPskCredsBlob *credInfo,
+static
+OCStackResult ValidateSecConfigData(const OCSecConfigData *cfgData,
size_t len)
{
- if(credInfo && len > 0)
+ OCStackResult ret = OC_STACK_OK;
+ unsigned int i = 0;
+ OCSecBlob * osb = NULL;
+
+ if (!cfgData || (len == 0))
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ if (cfgData->version != OCSecConfigVer_CurrentVersion)
{
- if (credInfo->blobVer != DtlsPskCredsBlobVer_CurrentVersion)
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ osb = (OCSecBlob*)cfgData->blob;
+ for ( ;(i<cfgData->numBlob) && osb; i++)
+ {
+ if (osb->type == OC_BLOB_TYPE_PSK)
+ {
+ ret = ValidateBlobTypePSK(osb);
+ }
+ else
{
return OC_STACK_INVALID_PARAM;
}
+ if (ret != OC_STACK_OK)
+ {
+ return ret;
+ }
+ osb = config_data_next_blob(osb);
+ }
+
+ return ret;
+}
+
+
+
+/**
+ * Provides the Security configuration data to OC stack.
+ *
+ * @param cfgdata
+ * binary blob containing credentials and other config data
+ * @param len
+ * length of binary blob
+ *
+ * @retval OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult OCSecSetConfigData(const OCSecConfigData *cfgData,
+ size_t len)
+{
+ // Validate the data inside blob before consuming
+ if (cfgData && ValidateSecConfigData(cfgData, len) == OC_STACK_OK)
+ {
// Remove existing blob
DeinitOCSecurityInfo();
// Allocate storage for new blob
- pskCredsBlob = (OCDtlsPskCredsBlob*)OCMalloc(len);
- if (pskCredsBlob)
+ secConfigData = (OCSecConfigData*)OCMalloc(len);
+ if (secConfigData)
{
- memcpy(pskCredsBlob, credInfo, len);
- pskCredsBlobLen = len;
+ memcpy(secConfigData, cfgData, len);
+ secConfigDataLen = len;
return OC_STACK_OK;
}
#include <time.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
#define TAG "gen_sec_bin"
-void printStruct(const char * device, OCDtlsPskCredsBlob* s)
+//scratch buffer
+const int WORK_BUF_LEN = 512;
+
+const char SERVER_CRED_FILE[] = "server_cred.bin";
+const char CLIENT_CRED_FILE[] = "client_cred.bin";
+
+static void printStruct(const char * device, OCSecConfigData* s)
{
- OC_LOG(INFO, TAG, device);
- OC_LOG_V(INFO, TAG, "Version - %d", s->blobVer);
- OC_LOG(INFO, TAG, "My Identity :");
- OC_LOG_BUFFER(INFO, TAG, s->identity, DTLS_PSK_ID_LEN);
-
- OC_LOG_V(INFO, TAG, "Number of trusted Peers - %d", s->num);
- OC_LOG(INFO, TAG, "Peer Identity :");
- OC_LOG_BUFFER(INFO, TAG, s->creds[0].id, DTLS_PSK_ID_LEN);
- OC_LOG(INFO, TAG, "Peer Psk :");
- OC_LOG_BUFFER(INFO, TAG, s->creds[0].psk, DTLS_PSK_PSK_LEN);
+ if (device && s)
+ {
+ OC_LOG(INFO, TAG, device);
+ OC_LOG_V(INFO, TAG, "Version - %d", s->version);
+ OC_LOG_V(INFO, TAG, "Number of blobs - %d", s->numBlob);
+
+ OCSecBlob* osb = (OCSecBlob*)(s->blob);
+ OC_LOG_V(INFO, TAG, "Blob Type - %d", osb->type);
+ OC_LOG_V(INFO, TAG, "Blob Data Length - %d", osb->len);
+
+ OCDtlsPskCredsBlob* odpcb = (OCDtlsPskCredsBlob*)(osb->val);
+ OC_LOG(INFO, TAG, "My Identity :");
+ OC_LOG_BUFFER(INFO, TAG, odpcb->identity, DTLS_PSK_ID_LEN);
+
+ OC_LOG_V(INFO, TAG, "Number of trusted Peers - %d", odpcb->num);
+ OC_LOG(INFO, TAG, "Peer Identity :");
+ OC_LOG_BUFFER(INFO, TAG, odpcb->creds[0].id, DTLS_PSK_ID_LEN);
+ OC_LOG(INFO, TAG, "Peer Psk :");
+ OC_LOG_BUFFER(INFO, TAG, odpcb->creds[0].psk, DTLS_PSK_PSK_LEN);
+ }
}
-int main()
+static int SizeOfOCConfigData (OCSecConfigData *oscd)
{
- OCDtlsPskCredsBlob * s = NULL;
- OCDtlsPskCredsBlob * c = NULL;
- FILE* fps, *fpc;
+ int len = 0;
+ if(oscd)
+ {
+ int i = 0;
+ OCSecBlob * osb;
+ len = len + sizeof(OCSecConfigData) - sizeof(uint8_t);
+
+ //go to first blob
+ osb = (OCSecBlob*)(oscd->blob);
+ for( i =0; i < oscd->numBlob; i++)
+ {
+ len += (sizeof(OCSecBlob) - sizeof(uint8_t) + osb->len);
+ osb = config_data_next_blob(osb);
+ }
+ }
+ return len;
+}
- int i;
+int main()
+{
+ unsigned char buf_s[WORK_BUF_LEN];
+ unsigned char buf_c[WORK_BUF_LEN];
srand(time(NULL));
- s = (OCDtlsPskCredsBlob*) malloc(sizeof(OCDtlsPskCredsBlob));
- c = (OCDtlsPskCredsBlob*) malloc(sizeof(OCDtlsPskCredsBlob));
+ OCSecConfigData * oscd_s = (OCSecConfigData*)buf_s;
+ OCSecConfigData * oscd_c = (OCSecConfigData*)buf_c;
+ oscd_s->version = oscd_c->version = OCSecConfigVer_CurrentVersion;
- memset(s, 0, sizeof(OCDtlsPskCredsBlob));
- memset(c, 0, sizeof(OCDtlsPskCredsBlob));
+ //Only storing 1 blob of type 'OC_BLOB_TYPE_PSK'
+ oscd_s->numBlob = oscd_c->numBlob = 1;
- s->blobVer = DtlsPskCredsBlobVer_CurrentVersion;
- c->blobVer = DtlsPskCredsBlobVer_CurrentVersion;
+ OCSecBlob * osb_s = (OCSecBlob*)oscd_s->blob;
+ OCSecBlob * osb_c = (OCSecBlob*)oscd_c->blob;
+ osb_s->type = osb_c->type = OC_BLOB_TYPE_PSK;
+ //length of this blob will be the length to contain PSK credentials
+ // for '1' peer device
+ osb_s->len = osb_c->len = sizeof(OCDtlsPskCredsBlob);
- s->num = c->num = 1;
+ OCDtlsPskCredsBlob * odpcb_s = (OCDtlsPskCredsBlob*)(osb_s->val);
+ OCDtlsPskCredsBlob * odpcb_c = (OCDtlsPskCredsBlob*)(osb_c->val);
- for(i = 0; i < DTLS_PSK_ID_LEN; i++)
+ odpcb_s->num = odpcb_c->num = 1;
+
+ for(int i = 0; i < DTLS_PSK_ID_LEN; i++)
{
- c->creds[0].id[i] = s->identity[i] = rand() % (2^8);
+ odpcb_c->creds[0].id[i] = odpcb_s->identity[i] = rand() % (2^8);
- s->creds[0].id[i] = c->identity[i] = rand() % (2^8);
+ odpcb_s->creds[0].id[i] = odpcb_c->identity[i] = rand() % (2^8);
- c->creds[0].psk[i] = s->creds[0].psk[i] = rand() % (2^8);
+ odpcb_c->creds[0].psk[i] = odpcb_s->creds[0].psk[i] = rand() % (2^8);
}
// Print Credentials
- printStruct("Server", s);
- printStruct("Client", c);
+ printStruct("Server", oscd_s);
+ printStruct("Client", oscd_c);
// Write to files
+ FILE* fps, *fpc;
if ((fps = (FILE*) fopen("server_cred.bin", "wb")) != NULL)
{
- fwrite(s, sizeof(OCDtlsPskCredsBlob), 1, fps);
+ fwrite(oscd_s, SizeOfOCConfigData(oscd_s), 1, fps);
fclose(fps);
}
if ((fpc = (FILE*) fopen("client_cred.bin", "wb")) != NULL)
{
- fwrite(c, sizeof(OCDtlsPskCredsBlob), 1, fpc);
+ fwrite(oscd_c, SizeOfOCConfigData(oscd_c), 1, fps);
fclose(fpc);
}
- memset(s, 0, sizeof(OCDtlsPskCredsBlob));
- memset(c, 0, sizeof(OCDtlsPskCredsBlob));
+ struct stat st;
+ memset(buf_s, 0, sizeof(buf_s));
+ memset(buf_c, 0, sizeof(buf_c));
// Read from files; print and verify manually
- if ((fps = (FILE*) fopen("server_cred.bin", "rb")) != NULL)
+ if ((fps = (FILE*) fopen(SERVER_CRED_FILE, "rb")) != NULL)
{
- if (sizeof(OCDtlsPskCredsBlob) != fread(s, 1, sizeof(OCDtlsPskCredsBlob), fps))
+ stat(SERVER_CRED_FILE, &st);
+ if ((sizeof(buf_s) < (unsigned int)st.st_size) ||
+ (fread(buf_s, 1, st.st_size, fps) != (unsigned int)st.st_size))
{
OC_LOG(INFO, TAG, PCF("Reading from the file failed."));
}
}
- if ((fpc = (FILE*) fopen("client_cred.bin", "rb")) != NULL)
+ if ((fpc = (FILE*) fopen(CLIENT_CRED_FILE, "rb")) != NULL)
{
- if (sizeof(OCDtlsPskCredsBlob) != fread(c, 1, sizeof(OCDtlsPskCredsBlob), fpc))
+ stat(CLIENT_CRED_FILE, &st);
+ if ((sizeof(buf_c) < (unsigned int)st.st_size) ||
+ (fread(buf_c, 1, st.st_size, fpc) != (unsigned int)st.st_size))
{
OC_LOG(INFO, TAG, PCF("Reading from the file failed."));
}
printf("\n\n");
OC_LOG(INFO, TAG, PCF("Reading from file and printing again to verify manually"));
- printStruct("Server", s);
- printStruct("Client", c);
+ printStruct("Server", (OCSecConfigData*)buf_s);
+ printStruct("Client", (OCSecConfigData*)buf_c);
- free(s);
- free(c);
}