#include "credresource.h"
#include "ocserverrequest.h"
#include "srmutility.h"
+#include "pinoxmcommon.h"
+
+#ifdef __WITH_DTLS__
+#include "global.h"
+#endif
+
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#endif
-#define TAG PCF("SRM-DOXM")
+#define TAG "SRM-DOXM"
static OicSecDoxm_t *gDoxm = NULL;
static OCResourceHandle gDoxmHandle = NULL;
&gOicSecDoxmJustWorks, /* uint16_t *oxm */
1, /* size_t oxmLen */
OIC_JUST_WORKS, /* uint16_t oxmSel */
+ SYMMETRIC_PAIR_WISE_KEY,/* OicSecCredType_t sct */
false, /* bool owned */
- {}, /* OicUuid_t deviceID */
- {}, /* OicUuid_t owner */
+ {.id = {0}}, /* OicUuid_t deviceID */
+ {.id = {0}}, /* OicUuid_t owner */
};
void DeleteDoxmBinData(OicSecDoxm_t* doxm)
if (doxm)
{
//Clean oxmType
- for(int i = 0; i < doxm->oxmTypeLen; i++)
+ for (size_t i = 0; i < doxm->oxmTypeLen; i++)
{
OICFree(doxm->oxmType[i]);
}
//OxmSel -- Mandatory
cJSON_AddNumberToObject(jsonDoxm, OIC_JSON_OXM_SEL_NAME, (int)doxm->oxmSel);
+ //sct -- Mandatory
+ cJSON_AddNumberToObject(jsonDoxm, OIC_JSON_SUPPORTED_CRED_TYPE_NAME, (int)doxm->sct);
+
//Owned -- Mandatory
cJSON_AddBoolToObject(jsonDoxm, OIC_JSON_OWNED_NAME, doxm->owned);
doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(char *));
VERIFY_NON_NULL(TAG, (doxm->oxmType), ERROR);
- for(int i = 0; i < doxm->oxmTypeLen ; i++)
+ for (size_t i = 0; i < doxm->oxmTypeLen ; i++)
{
cJSON *jsonOxmTy = cJSON_GetArrayItem(jsonObj, i);
VERIFY_NON_NULL(TAG, jsonOxmTy, ERROR);
doxm->oxm = (OicSecOxm_t*)OICCalloc(doxm->oxmLen, sizeof(OicSecOxm_t));
VERIFY_NON_NULL(TAG, doxm->oxm, ERROR);
- for(int i = 0; i < doxm->oxmLen ; i++)
+ for (size_t i = 0; i < doxm->oxmLen ; i++)
{
cJSON *jsonOxm = cJSON_GetArrayItem(jsonObj, i);
VERIFY_NON_NULL(TAG, jsonOxm, ERROR);
jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_SEL_NAME);
if(jsonObj)
{
- VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR)
+ VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
doxm->oxmSel = (OicSecOxm_t)jsonObj->valueint;
}
else // PUT/POST JSON may not have oxmsel so set it to the gDoxm->oxmSel
doxm->oxmSel = gDoxm->oxmSel;
}
+ //sct -- Mandatory
+ jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_SUPPORTED_CRED_TYPE_NAME);
+ if(jsonObj)
+ {
+ VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
+ doxm->sct = (OicSecCredType_t)jsonObj->valueint;
+ }
+ else // PUT/POST JSON may not have sct so set it to the gDoxm->sct
+ {
+ VERIFY_NON_NULL(TAG, gDoxm, ERROR);
+ doxm->sct = gDoxm->sct;
+ }
+
//Owned -- Mandatory
jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNED_NAME);
if(jsonObj)
{
- VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type), ERROR)
+ VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type), ERROR);
doxm->owned = jsonObj->valueint;
}
else // PUT/POST JSON may not have owned so set it to the gDomx->owned
else // PUT/POST JSON will not have deviceID so set it to the gDoxm->deviceID.id
{
VERIFY_NON_NULL(TAG, gDoxm, ERROR);
- VERIFY_SUCCESS(TAG, strcmp((char *)gDoxm->deviceID.id, "") != 0, ERROR);
- strncpy((char *)doxm->deviceID.id, (char *)gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
+ memcpy((char *)doxm->deviceID.id, (char *)gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
}
- // Owner -- will be empty when device state is unowned.
- if (true == doxm->owned)
+ //Owner -- will be empty when device status is unowned.
+ jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNER_NAME);
+ if(true == doxm->owned)
{
- jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNER_NAME);
VERIFY_NON_NULL(TAG, jsonObj, ERROR);
- VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR)
- outLen = 0;
+ }
+ if(jsonObj)
+ {
+ VERIFY_SUCCESS(TAG, (cJSON_String == jsonObj->type), ERROR);
+ outLen = 0;
b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
sizeof(base64Buff), &outLen);
- VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(doxm->owner.id)), ERROR);
+ VERIFY_SUCCESS(TAG, ((b64Ret == B64_OK) && (outLen <= sizeof(doxm->owner.id))), ERROR);
memcpy(doxm->owner.id, base64Buff, outLen);
}
return bRet;
}
-static bool ValidateQuery(unsigned char * query)
+static bool ValidateQuery(const char * query)
{
// Send doxm resource data if the state of doxm resource
// matches with the query parameters.
// access rules. Eventually, the PE and PM code will
// not send a request to the /doxm Entity Handler at all
// if it should not respond.
- OC_LOG (INFO, TAG, PCF("In ValidateQuery"));
+ OC_LOG (DEBUG, TAG, "In ValidateQuery");
if(NULL == gDoxm)
{
return false;
}
- OicParseQueryIter_t parseIter = {};
+ bool bOwnedQry = false; // does querystring contains 'owned' query ?
+ bool bOwnedMatch = false; // does 'owned' query value matches with doxm.owned status?
+ bool bDeviceIDQry = false; // does querystring contains 'deviceid' query ?
+ bool bDeviceIDMatch = false; // does 'deviceid' query matches with doxm.deviceid ?
+
+ OicParseQueryIter_t parseIter = {.attrPos = NULL};
- ParseQueryIterInit(query, &parseIter);
+ ParseQueryIterInit((unsigned char*)query, &parseIter);
while(GetNextQuery(&parseIter))
{
if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
{
+ bOwnedQry = true;
if((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
(gDoxm->owned))
{
- return true;
+ bOwnedMatch = true;
}
else if((strncasecmp((char *)parseIter.valPos, OIC_SEC_FALSE, parseIter.valLen) == 0)
&& (!gDoxm->owned))
{
- return true;
+ bOwnedMatch = true;
+ }
+ }
+
+ if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_DEVICE_ID_NAME, parseIter.attrLen) == 0)
+ {
+ bDeviceIDQry = true;
+ OicUuid_t subject = {.id={0}};
+ unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
+ uint32_t outLen = 0;
+ B64Result b64Ret = B64_OK;
+
+ b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen, base64Buff,
+ sizeof(base64Buff), &outLen);
+
+ VERIFY_SUCCESS(TAG, (B64_OK == b64Ret && outLen <= sizeof(subject.id)), ERROR);
+ memcpy(subject.id, base64Buff, outLen);
+ if(0 == memcmp(&gDoxm->deviceID.id, &subject.id, sizeof(gDoxm->deviceID.id)))
+ {
+ bDeviceIDMatch = true;
}
}
}
- return false;
+
+exit:
+ return ((bOwnedQry ? bOwnedMatch : true) && (bDeviceIDQry ? bDeviceIDMatch : true));
}
static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehRequest)
char* jsonStr = NULL;
OCEntityHandlerResult ehRet = OC_EH_OK;
- OC_LOG (INFO, TAG, PCF("Doxm EntityHandle processing GET request"));
+ OC_LOG (DEBUG, TAG, "Doxm EntityHandle processing GET request");
//Checking if Get request is a query.
if(ehRequest->query)
{
- OC_LOG (INFO, TAG, PCF("HandleDoxmGetRequest processing query"));
- if(!ValidateQuery((unsigned char *)ehRequest->query))
+ OC_LOG (DEBUG, TAG, "HandleDoxmGetRequest processing query");
+ if(!ValidateQuery(ehRequest->query))
{
ehRet = OC_EH_ERROR;
}
// Send response payload to request originator
if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, jsonStr))
{
- OC_LOG (ERROR, TAG, PCF("SendSRMResponse failed in HandleDoxmGetRequest"));
+ OC_LOG (ERROR, TAG, "SendSRMResponse failed in HandleDoxmGetRequest");
}
OICFree(jsonStr);
return ehRet;
}
+#ifdef __WITH_DTLS__
+/*
+ * Generating new credential for provisioning tool
+ *
+ * PSK generated by
+ */
+static OCEntityHandlerResult AddOwnerPSK(const CAEndpoint_t* endpoint,
+ OicSecDoxm_t* ptDoxm,
+ const uint8_t* label, const size_t labelLen)
+{
+ size_t ownLen = 1;
+ uint32_t outLen = 0;
+ OicSecCred_t *cred = NULL;
+ uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {};
+
+ CAResult_t pskRet = CAGenerateOwnerPSK(endpoint,
+ label, labelLen,
+ ptDoxm->owner.id, sizeof(ptDoxm->owner.id),
+ gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
+ ownerPSK, OWNER_PSK_LENGTH_128);
+
+ VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
+
+ char base64Buff[B64ENCODE_OUT_SAFESIZE(OWNER_PSK_LENGTH_128) + 1] = {};
+ B64Result b64Ret = b64Encode(ownerPSK, OWNER_PSK_LENGTH_128, base64Buff,
+ sizeof(base64Buff), &outLen);
+ VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+
+ OC_LOG (DEBUG, TAG, "Doxm EntityHandle generating Credential");
+ cred = GenerateCredential(&ptDoxm->owner, SYMMETRIC_PAIR_WISE_KEY,
+ NULL, base64Buff, ownLen, &ptDoxm->owner);
+ VERIFY_NON_NULL(TAG, cred, ERROR);
+
+ //Adding provisioning tool credential to cred Resource.
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == AddCredential(cred), ERROR);
+
+ gDoxm->owned = true;
+ gDoxm->oxmSel = ptDoxm->oxmSel;
+ memcpy(&(gDoxm->owner), &(ptDoxm->owner), sizeof(OicUuid_t));
+
+ return OC_EH_OK;
+
+exit:
+ return OC_EH_ERROR;
+}
+#endif //__WITH_DTLS__
static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest * ehRequest)
{
- OC_LOG (INFO, TAG, PCF("Doxm EntityHandle processing PUT request"));
+ OC_LOG (DEBUG, TAG, "Doxm EntityHandle processing PUT request");
OCEntityHandlerResult ehRet = OC_EH_ERROR;
- OicUuid_t emptyOwner = {};
+ OicUuid_t emptyOwner = {.id = {0}};
/*
* Convert JSON Doxm data into binary. This will also validate
*/
if ((false == gDoxm->owned) && (false == newDoxm->owned))
{
- OC_LOG (INFO, TAG, PCF("Doxm EntityHandle enabling AnonECDHCipherSuite"));
+ OC_LOG (INFO, TAG, "Doxm EntityHandle enabling AnonECDHCipherSuite");
#ifdef __WITH_DTLS__
ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
#endif //__WITH_DTLS__
*
*/
#ifdef __WITH_DTLS__
- CAResult_t pskRet;
-
OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
- uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {};
//Generating OwnerPSK
- OC_LOG (INFO, TAG, PCF("Doxm EntityHandle generating OwnerPSK"));
- pskRet = CAGenerateOwnerPSK((CAEndpoint_t *)&request->devAddr,
- (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS),
- newDoxm->owner.id, sizeof(newDoxm->owner.id),
- gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
- ownerPSK, OWNER_PSK_LENGTH_128);
+ OC_LOG (INFO, TAG, "Doxm EntityHandle generating OwnerPSK");
- VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
+ //Generate new credential for provisioning tool
+ ehRet = AddOwnerPSK((CAEndpoint_t *)&request->devAddr, newDoxm,
+ (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS));
- //Generating new credential for provisioning tool
- size_t ownLen = 1;
- uint32_t outLen = 0;
-
- char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
- B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff,
- sizeof(base64Buff), &outLen);
- VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
-
- OC_LOG (INFO, TAG, PCF("Doxm EntityHandle generating Credential"));
- OicSecCred_t *cred = GenerateCredential(&newDoxm->owner, SYMMETRIC_PAIR_WISE_KEY,
- NULL, base64Buff, ownLen, &newDoxm->owner);
- VERIFY_NON_NULL(TAG, cred, ERROR);
-
- //Adding provisioning tool credential to cred Resource.
- VERIFY_SUCCESS(TAG, OC_STACK_OK == AddCredential(cred), ERROR);
-
- gDoxm->owned = true;
- memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
+ VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);
// Update new state in persistent storage
if (true == UpdatePersistentStorage(gDoxm))
* for global variable.
*/
gDoxm->owned = false;
+ gDoxm->oxmSel = 0;
memset(&(gDoxm->owner), 0, sizeof(OicUuid_t));
}
* in owned state.
*/
CAEnableAnonECDHCipherSuite(false);
+#ifdef __WITH_X509__
+#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE
+ CASelectCipherSuite(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
+#endif //__WITH_X509__
+#endif //__WITH_DTLS__
+ }
+ }
+ else if(OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
+ {
+ //this temp Credential ID is used to track temporal Cred Id
+ static OicUuid_t tmpCredId = {.id={0}};
+ static bool tmpCredGenFlag = false;
+
+ if ((false == gDoxm->owned) && (false == newDoxm->owned))
+ {
+#ifdef __WITH_DTLS__
+ CAEnableAnonECDHCipherSuite(false);
+ OC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
+ CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);
+
+ char ranPin[OXM_RANDOM_PIN_SIZE + 1] = {0,};
+ if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
+ {
+ if(tmpCredGenFlag)
+ {
+ OC_LOG(INFO, TAG, "Corrupted PSK is detected!!!");
+ VERIFY_SUCCESS(TAG,
+ OC_STACK_RESOURCE_DELETED == RemoveCredential(&tmpCredId),
+ ERROR);
+ }
+
+ OCStackResult res = AddTmpPskWithPIN( &(newDoxm->owner), SYMMETRIC_PAIR_WISE_KEY,
+ ranPin, OXM_RANDOM_PIN_SIZE, 1, &(newDoxm->owner), &tmpCredId);
+ VERIFY_SUCCESS(TAG, res == OC_STACK_OK, ERROR);
+ tmpCredGenFlag = true;
+ ehRet = OC_EH_OK;
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Failed to generate random PIN");
+ ehRet = OC_EH_ERROR;
+ }
+
#endif //__WITH_DTLS__
}
+
+ /*
+ * When current state of the device is un-owned and Provisioning
+ * Tool is attempting to change the state to 'Owned' with a
+ * qualified value for the field 'Owner'
+ */
+ if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
+ (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0))
+ {
+#ifdef __WITH_DTLS__
+ OCServerRequest * request = (OCServerRequest *)ehRequest->requestHandle;
+
+ //Remove Temporal Credential resource
+ if(tmpCredGenFlag)
+ {
+ VERIFY_SUCCESS(TAG,
+ OC_STACK_RESOURCE_DELETED == RemoveCredential(&tmpCredId),
+ ERROR);
+ tmpCredGenFlag = false;
+ }
+
+ //Generate new credential for provisioning tool
+ ehRet = AddOwnerPSK((CAEndpoint_t*)(&request->devAddr), newDoxm,
+ (uint8_t*)OXM_RANDOM_DEVICE_PIN, strlen(OXM_RANDOM_DEVICE_PIN));
+ VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);
+
+ //Update new state in persistent storage
+ if((UpdatePersistentStorage(gDoxm) == true))
+ {
+ ehRet = OC_EH_OK;
+ }
+ else
+ {
+ /*
+ * If persistent storage update failed, revert back the state
+ * for global variable.
+ */
+ gDoxm->owned = false;
+ gDoxm->oxmSel = 0;
+ memset(&(gDoxm->owner), 0, sizeof(OicUuid_t));
+ ehRet = OC_EH_ERROR;
+
+ }
+#endif
+ }
}
}
//Send payload to request originator
if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL))
{
- OC_LOG (ERROR, TAG, PCF("SendSRMResponse failed in HandlePstatPostRequest"));
+ OC_LOG (ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest");
}
DeleteDoxmBinData(newDoxm);
OCEntityHandlerRequest * ehRequest,
void* callbackParam)
{
+ (void)callbackParam;
OCEntityHandlerResult ehRet = OC_EH_ERROR;
if(NULL == ehRequest)
if (flag & OC_REQUEST_FLAG)
{
- OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+ OC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
switch (ehRequest->method)
{
case OC_REST_GET:
if (OC_STACK_OK != ret)
{
- OC_LOG (FATAL, TAG, PCF("Unable to instantiate Doxm resource"));
+ OC_LOG (FATAL, TAG, "Unable to instantiate Doxm resource");
DeInitDoxmResource();
}
return ret;
* Once DeviceID is assigned to the device it does not change for the lifetime of the device.
*
*/
-void CheckDeviceID()
+static OCStackResult CheckDeviceID()
{
- if(strcmp((char *)gDoxm->deviceID.id, "") == 0 )
+ OCStackResult ret = OC_STACK_ERROR;
+ bool validId = false;
+ for (uint8_t i = 0; i < UUID_LENGTH; i++)
{
- OCFillRandomMem(gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id));
- UpdatePersistentStorage(gDoxm);
+ if (gDoxm->deviceID.id[i] != 0)
+ {
+ validId = true;
+ break;
+ }
}
+
+ if (!validId)
+ {
+ if (OCGenerateUuid(gDoxm->deviceID.id) != RAND_UUID_OK)
+ {
+ OC_LOG(FATAL, TAG, "Generate UUID for Server Instance failed!");
+ return ret;
+ }
+ ret = OC_STACK_OK;
+
+ if (UpdatePersistentStorage(gDoxm))
+ {
+ //TODO: After registering PSI handler in all samples, do ret = OC_STACK_OK here.
+ OC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
+ }
+ }
+ else
+ {
+ ret = OC_STACK_OK;
+ }
+ return ret;
}
/**
*/
static OicSecDoxm_t* GetDoxmDefault()
{
- OC_LOG (INFO, TAG, PCF("GetDoxmToDefault"));
+ OC_LOG (DEBUG, TAG, "GetDoxmToDefault");
return &gDefaultDoxm;
}
{
gDoxm = GetDoxmDefault();
}
- CheckDeviceID();
- //Instantiate 'oic.sec.doxm'
- ret = CreateDoxmResource();
+ ret = CheckDeviceID();
+ if (ret == OC_STACK_OK)
+ {
+ //Instantiate 'oic.sec.doxm'
+ ret = CreateDoxmResource();
+ }
+ else
+ {
+ OC_LOG (ERROR, TAG, "CheckDeviceID failed");
+ }
OICFree(jsonSVRDatabase);
return ret;
}