#include "ocmalloc.h"
#include "ocsecurity.h"
#include "ocsecurityconfig.h"
+#ifdef CA_SEC_MERGE_WORKAROUND
+#include "ocsecurityinternal.h"
+#endif //CA_SEC_MERGE_WORKAROUND
#include <string.h>
-static OCDtlsPskCredsBlob* pskCredsBlob;
-static int pskCredsBlobLen;
+static OCSecConfigData* secConfigData;
+static int secConfigDataLen;
-// Internal API. Invoked by OC stack to cleanup memory
+/**
+ * Currently, there is a disconnect in the data structure used between RI layer
+ * and CA layer to convey DTLS PSK credentials. We cannot update this data
+ * structure until all reviews of CA layer is completed. To enable security
+ * feature in CA branch this workaround is added as a temporary stop-gap.
+ *
+ */
+#ifdef CA_SEC_MERGE_WORKAROUND
+static CADtlsPskCredsBlob *caBlob;
+#endif //CA_SEC_MERGE_WORKAROUND
+
+/**
+ * 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(secConfigData);
+ secConfigData = NULL;
+ }
- OCFree(pskCredsBlob);
- pskCredsBlob = NULL;
+#ifdef CA_SEC_MERGE_WORKAROUND
+ if (caBlob)
+ {
+ OCFree(caBlob->creds);
}
+ OCFree(caBlob);
+#endif
+
}
-// 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)
+ {
+#ifdef CA_SEC_MERGE_WORKAROUND
+ OCDtlsPskCredsBlob * ocBlob = (OCDtlsPskCredsBlob *)osb->val;
+ if (!caBlob)
+ {
+ caBlob = (CADtlsPskCredsBlob *)OCCalloc(sizeof(CADtlsPskCredsBlob), 1);
+ if (caBlob)
+ {
+ memcpy(caBlob->identity, ocBlob->identity, sizeof(caBlob->identity));
+ caBlob->num = ocBlob->num;
+ caBlob->creds =
+ (OCDtlsPskCreds*) OCMalloc(caBlob->num * sizeof(OCDtlsPskCreds));
+ if (caBlob->creds)
+ {
+ memcpy(caBlob->creds, ocBlob->creds,
+ caBlob->num * sizeof(OCDtlsPskCreds));
+ }
+ }
+ }
+ *credInfo = (OCDtlsPskCredsBlob *) caBlob;
+ break;
+#else
+ OCDtlsPskCredsBlob * blob;
+ blob = (OCDtlsPskCredsBlob *)OCMalloc(osb->len);
+ if (blob)
+ {
+ memcpy(blob, osb->val, osb->len);
+ *credInfo = blob;
+ break;
+ }
+#endif //CA_SEC_MERGE_WORKAROUND
+ }
+ 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))
{
- if (credInfo->blobVer != DtlsPskCredsBlobVer_CurrentVersion)
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ if (cfgData->version != OCSecConfigVer_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;
}