//JSONToDoxmBin Tests TEST(JSONToDoxmBinTest, JSONToDoxmBinValidJSON) { OicSecDoxm_t * doxm1 = getBinDoxm(); char * json = BinToDoxmJSON(doxm1); EXPECT_TRUE(json != NULL); OicSecDoxm_t *doxm2 = JSONToDoxmBin(json); EXPECT_TRUE(doxm2 != NULL); DeleteDoxmBinData(doxm1); DeleteDoxmBinData(doxm2); OICFree(json); }
TEST(BinToDoxmJSONTest, BinToDoxmJSONValidDoxm) { OicSecDoxm_t * doxm = getBinDoxm(); char * json = BinToDoxmJSON(doxm); EXPECT_TRUE(json != NULL); DeleteDoxmBinData(doxm); OICFree(json); }
//HandleDoxmPostRequest Test TEST(HandleDoxmPostRequestTest, HandleDoxmPostRequestValidInput) { OCEntityHandlerRequest ehRequest = {}; OCServerRequest svRequest = {}; OicSecDoxm_t * doxm = getBinDoxm(); strcpy(svRequest.addressInfo.IP.ipAddress, "10.10.10.10"); svRequest.addressInfo.IP.port = 2345; svRequest.connectivityType = CA_ETHERNET; ehRequest.reqJSONPayload = (unsigned char *) BinToDoxmJSON(doxm); ehRequest.requestHandle = (OCRequestHandle) &svRequest; EXPECT_EQ(OC_EH_ERROR, HandleDoxmPostRequest(&ehRequest)); DeleteDoxmBinData(doxm); OICFree(ehRequest.reqJSONPayload); }
/** * Perform cleanup for DOXM resources. * * @return * OC_STACK_OK - no error * OC_STACK_ERROR - stack process error * */ OCStackResult DeInitDoxmResource() { OCStackResult ret = OCDeleteResource(gDoxmHandle); if(gDoxm != &gDefaultDoxm) { DeleteDoxmBinData(gDoxm); } gDoxm = NULL; if(OC_STACK_OK == ret) { return OC_STACK_OK; } else { return OC_STACK_ERROR; } }
static void ConvertJsonToCBOR(const char *jsonFileName, const char *cborFileName) { char *jsonStr = NULL; FILE *fp = NULL; FILE *fp1 = NULL; uint8_t *aclCbor = NULL; uint8_t *pstatCbor = NULL; uint8_t *doxmCbor = NULL; uint8_t *amaclCbor = NULL; uint8_t *svcCbor = NULL; uint8_t *credCbor = NULL; cJSON *jsonRoot = NULL; OCStackResult ret = OC_STACK_ERROR; size_t size = GetJSONFileSize(jsonFileName); if (0 == size) { OIC_LOG (ERROR, TAG, "Failed converting to JSON"); return; } jsonStr = (char *)OICMalloc(size + 1); VERIFY_NON_NULL(TAG, jsonStr, FATAL); fp = fopen(jsonFileName, "r"); if (fp) { size_t bytesRead = fread(jsonStr, 1, size, fp); jsonStr[bytesRead] = '\0'; OIC_LOG_V(DEBUG, TAG, "Read %zu bytes", bytesRead); fclose(fp); fp = NULL; } else { OIC_LOG (ERROR, TAG, "Unable to open JSON file!!"); goto exit; } jsonRoot = cJSON_Parse(jsonStr); cJSON *value = cJSON_GetObjectItem(jsonRoot, OIC_JSON_ACL_NAME); //printf("ACL json : \n%s\n", cJSON_PrintUnformatted(value)); size_t aclCborSize = 0; if (NULL != value) { OicSecAcl_t *acl = JSONToAclBin(jsonStr); VERIFY_NON_NULL(TAG, acl, FATAL); ret = AclToCBORPayload(acl, &aclCbor, &aclCborSize); if(OC_STACK_OK != ret) { OIC_LOG (ERROR, TAG, "Failed converting Acl to Cbor Payload"); DeleteACLList(acl); goto exit; } printf("ACL Cbor Size: %zd\n", aclCborSize); DeleteACLList(acl); } value = cJSON_GetObjectItem(jsonRoot, OIC_JSON_PSTAT_NAME); size_t pstatCborSize = 0; if (NULL != value) { OicSecPstat_t *pstat = JSONToPstatBin(jsonStr); VERIFY_NON_NULL(TAG, pstat, FATAL); ret = PstatToCBORPayload(pstat, &pstatCbor, &pstatCborSize); if(OC_STACK_OK != ret) { OIC_LOG (ERROR, TAG, "Failed converting Pstat to Cbor Payload"); DeletePstatBinData(pstat); goto exit; } printf("PSTAT Cbor Size: %zd\n", pstatCborSize); DeletePstatBinData(pstat); } value = cJSON_GetObjectItem(jsonRoot, OIC_JSON_DOXM_NAME); size_t doxmCborSize = 0; if (NULL != value) { OicSecDoxm_t *doxm = JSONToDoxmBin(jsonStr); VERIFY_NON_NULL(TAG, doxm, FATAL); ret = DoxmToCBORPayload(doxm, &doxmCbor, &doxmCborSize); if(OC_STACK_OK != ret) { OIC_LOG (ERROR, TAG, "Failed converting Doxm to Cbor Payload"); DeleteDoxmBinData(doxm); goto exit; } printf("DOXM Cbor Size: %zd\n", doxmCborSize); DeleteDoxmBinData(doxm); } value = cJSON_GetObjectItem(jsonRoot, OIC_JSON_AMACL_NAME); size_t amaclCborSize = 0; if (NULL != value) { OicSecAmacl_t *amacl = JSONToAmaclBin(jsonStr); VERIFY_NON_NULL(TAG, amacl, FATAL); ret = AmaclToCBORPayload(amacl, &amaclCbor, &amaclCborSize); if(OC_STACK_OK != ret) { OIC_LOG (ERROR, TAG, "Failed converting Amacl to Cbor Payload"); DeleteAmaclList(amacl); goto exit; } printf("AMACL Cbor Size: %zd\n", amaclCborSize); DeleteAmaclList(amacl); } value = cJSON_GetObjectItem(jsonRoot, OIC_JSON_SVC_NAME); size_t svcCborSize = 0; if (NULL != value) { OicSecSvc_t *svc = JSONToSvcBin(jsonStr); VERIFY_NON_NULL(TAG, svc, FATAL); ret = SVCToCBORPayload(svc, &svcCbor, &svcCborSize); if(OC_STACK_OK != ret) { OIC_LOG (ERROR, TAG, "Failed converting Svc to Cbor Payload"); DeleteSVCList(svc); goto exit; } printf("SVC Cbor Size: %zd\n", svcCborSize); DeleteSVCList(svc); } value = cJSON_GetObjectItem(jsonRoot, OIC_JSON_CRED_NAME); //printf("CRED json : \n%s\n", cJSON_PrintUnformatted(value)); size_t credCborSize = 0; int secureFlag = 0; if (NULL != value) { OicSecCred_t *cred = JSONToCredBin(jsonStr); VERIFY_NON_NULL(TAG, cred, FATAL); ret = CredToCBORPayload(cred, &credCbor, &credCborSize, secureFlag); if(OC_STACK_OK != ret) { OIC_LOG (ERROR, TAG, "Failed converting Cred to Cbor Payload"); DeleteCredList(cred); goto exit; } printf("CRED Cbor Size: %zd\n", credCborSize); DeleteCredList(cred); } CborEncoder encoder; size_t cborSize = aclCborSize + pstatCborSize + doxmCborSize + svcCborSize + credCborSize + amaclCborSize; printf("Total Cbor Size : %zd\n", cborSize); cborSize += 255; // buffer margin for adding map and byte string uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborSize); VERIFY_NON_NULL(TAG, outPayload, ERROR); cbor_encoder_init(&encoder, outPayload, cborSize, 0); CborEncoder map; CborError cborEncoderResult = cbor_encoder_create_map(&encoder, &map, CborIndefiniteLength); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating Main Map."); if (aclCborSize > 0) { cborEncoderResult = cbor_encode_text_string(&map, OIC_JSON_ACL_NAME, strlen(OIC_JSON_ACL_NAME)); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Name."); cborEncoderResult = cbor_encode_byte_string(&map, aclCbor, aclCborSize); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Value."); } if (pstatCborSize > 0) { cborEncoderResult = cbor_encode_text_string(&map, OIC_JSON_PSTAT_NAME, strlen(OIC_JSON_PSTAT_NAME)); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Name."); cborEncoderResult = cbor_encode_byte_string(&map, pstatCbor, pstatCborSize); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Value."); } if (doxmCborSize > 0) { cborEncoderResult = cbor_encode_text_string(&map, OIC_JSON_DOXM_NAME, strlen(OIC_JSON_DOXM_NAME)); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DOXM Name."); cborEncoderResult = cbor_encode_byte_string(&map, doxmCbor, doxmCborSize); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DOXM Value."); } if (amaclCborSize > 0) { cborEncoderResult = cbor_encode_text_string(&map, OIC_JSON_AMACL_NAME, strlen(OIC_JSON_AMACL_NAME)); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding AMACL Name."); cborEncoderResult = cbor_encode_byte_string(&map, amaclCbor, amaclCborSize); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding AMACL Value."); } if (svcCborSize > 0) { cborEncoderResult = cbor_encode_text_string(&map, OIC_JSON_SVC_NAME, strlen(OIC_JSON_SVC_NAME)); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SVC Name."); cborEncoderResult = cbor_encode_byte_string(&map, svcCbor, svcCborSize); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SVC Value."); } if (credCborSize > 0) { cborEncoderResult = cbor_encode_text_string(&map, OIC_JSON_CRED_NAME, strlen(OIC_JSON_CRED_NAME)); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CRED Name."); cborEncoderResult = cbor_encode_byte_string(&map, credCbor, credCborSize); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CRED Value."); } cborEncoderResult = cbor_encoder_close_container(&encoder, &map); VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Container."); size_t s = encoder.ptr - outPayload; OIC_LOG_V(DEBUG, TAG, "Payload size %zu", s); fp1 = fopen(cborFileName, "w"); if (fp1) { size_t bytesWritten = fwrite(outPayload, 1, s, fp1); if (bytesWritten == s) { OIC_LOG_V(DEBUG, TAG, "Written %zu bytes", bytesWritten); } else { OIC_LOG_V(ERROR, TAG, "Failed writing %zu bytes", s); } fclose(fp1); fp1 = NULL; } exit: cJSON_Delete(jsonRoot); OICFree(aclCbor); OICFree(doxmCbor); OICFree(pstatCbor); OICFree(amaclCbor); OICFree(svcCbor); OICFree(credCbor); OICFree(jsonStr); return ; }
OicSecDoxm_t* JSONToDoxmBin(const char * jsonStr) { printf("IN JSONToDoxmBin\n"); if (NULL == jsonStr) { return NULL; } OCStackResult ret = OC_STACK_ERROR; OicSecDoxm_t *doxm = NULL; cJSON *jsonDoxm = NULL; cJSON *jsonObj = NULL; size_t jsonObjLen = 0; cJSON *jsonRoot = cJSON_Parse(jsonStr); VERIFY_NON_NULL(TAG, jsonRoot, ERROR); jsonDoxm = cJSON_GetObjectItem(jsonRoot, OIC_JSON_DOXM_NAME); VERIFY_NON_NULL(TAG, jsonDoxm, ERROR); doxm = (OicSecDoxm_t *)OICCalloc(1, sizeof(OicSecDoxm_t)); VERIFY_NON_NULL(TAG, doxm, ERROR); //OxmType -- not Mandatory jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_TYPE_NAME); if ((jsonObj) && (cJSON_Array == jsonObj->type)) { doxm->oxmTypeLen = (size_t)cJSON_GetArraySize(jsonObj); VERIFY_SUCCESS(TAG, doxm->oxmTypeLen > 0, ERROR); doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(char *)); VERIFY_NON_NULL(TAG, (doxm->oxmType), ERROR); for (size_t i = 0; i < doxm->oxmTypeLen ; i++) { cJSON *jsonOxmTy = cJSON_GetArrayItem(jsonObj, i); VERIFY_NON_NULL(TAG, jsonOxmTy, ERROR); jsonObjLen = strlen(jsonOxmTy->valuestring) + 1; doxm->oxmType[i] = (char*)OICMalloc(jsonObjLen); VERIFY_NON_NULL(TAG, doxm->oxmType[i], ERROR); strncpy((char *)doxm->oxmType[i], (char *)jsonOxmTy->valuestring, jsonObjLen); } } //Oxm -- not Mandatory jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXMS_NAME); if (jsonObj && cJSON_Array == jsonObj->type) { doxm->oxmLen = (size_t)cJSON_GetArraySize(jsonObj); VERIFY_SUCCESS(TAG, doxm->oxmLen > 0, ERROR); doxm->oxm = (OicSecOxm_t*)OICCalloc(doxm->oxmLen, sizeof(OicSecOxm_t)); VERIFY_NON_NULL(TAG, doxm->oxm, ERROR); for (size_t i = 0; i < doxm->oxmLen ; i++) { cJSON *jsonOxm = cJSON_GetArrayItem(jsonObj, i); VERIFY_NON_NULL(TAG, jsonOxm, ERROR); doxm->oxm[i] = (OicSecOxm_t)jsonOxm->valueint; } } //OxmSel -- Mandatory jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_SEL_NAME); if (jsonObj) { VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR); doxm->oxmSel = (OicSecOxm_t)jsonObj->valueint; } //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; } //Owned -- Mandatory jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNED_NAME); if (jsonObj) { VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type), ERROR); doxm->owned = jsonObj->valueint; } //DPC -- Mandatory jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_DPC_NAME); if (jsonObj) { VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type), ERROR); doxm->dpc = jsonObj->valueint; } //DeviceId -- Mandatory jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_DEVICE_ID_NAME); if (jsonObj) { VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR); if (cJSON_String == jsonObj->type) { //Check for empty string, in case DeviceId field has not been set yet if (jsonObj->valuestring[0]) { ret = ConvertStrToUuid(jsonObj->valuestring, &doxm->deviceID); VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR); } } } //rowner -- Mandatory jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_ROWNERID_NAME); if (true == doxm->owned) { VERIFY_NON_NULL(TAG, jsonObj, ERROR); } if (jsonObj) { ret = ConvertStrToUuid(jsonObj->valuestring, &doxm->rownerID); VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR); } //Owner -- will be empty when device status is unowned. jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_DEVOWNERID_NAME); if (true == doxm->owned) { VERIFY_NON_NULL(TAG, jsonObj, ERROR); } if (jsonObj) { ret = ConvertStrToUuid(jsonObj->valuestring, &doxm->owner); VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR); } ret = OC_STACK_OK; exit: cJSON_Delete(jsonRoot); if (OC_STACK_OK != ret) { DeleteDoxmBinData(doxm); doxm = NULL; } printf("OUT JSONToDoxmBin\n"); return doxm; }
static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest * ehRequest) { OIC_LOG (DEBUG, TAG, "Doxm EntityHandle processing PUT request"); OCEntityHandlerResult ehRet = OC_EH_ERROR; OicUuid_t emptyOwner = {.id = {0}}; /* * Convert JSON Doxm data into binary. This will also validate * the Doxm data received. */ OicSecDoxm_t* newDoxm = JSONToDoxmBin(((OCSecurityPayload*)ehRequest->payload)->securityData); if (newDoxm) { // Iotivity SRM ONLY supports OIC_JUST_WORKS now if (OIC_JUST_WORKS == newDoxm->oxmSel) { if ((false == gDoxm->owned) && (false == newDoxm->owned)) { /* * If current state of the device is un-owned, enable * anonymous ECDH cipher in tinyDTLS so that Provisioning * tool can initiate JUST_WORKS ownership transfer process. */ if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0) { OIC_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__ goto exit; } else { #ifdef __WITH_DTLS__ //Save the owner's UUID to derive owner credential memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)); // OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle; // //Generating OwnerPSK // OIC_LOG (INFO, TAG, "Doxm EntityHandle generating OwnerPSK"); // //Generate new credential for provisioning tool // ehRet = AddOwnerPSK((CAEndpoint_t *)&request->devAddr, newDoxm, // (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS)); // VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR); // Update new state in persistent storage if (true == UpdatePersistentStorage(gDoxm)) { ehRet = OC_EH_OK; } else { OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage"); ehRet = OC_EH_ERROR; } /* * Disable anonymous ECDH cipher in tinyDTLS since device is now * in owned state. */ CAResult_t caRes = CA_STATUS_OK; caRes = CAEnableAnonECDHCipherSuite(false); VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR); OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED"); #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) { if ((false == gDoxm->owned) && (false == newDoxm->owned)) { /* * If current state of the device is un-owned, enable * anonymous ECDH cipher in tinyDTLS so that Provisioning * tool can initiate JUST_WORKS ownership transfer process. */ if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0) { gDoxm->oxmSel = newDoxm->oxmSel; //Update new state in persistent storage if((UpdatePersistentStorage(gDoxm) == true)) { ehRet = OC_EH_OK; } else { OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage"); ehRet = OC_EH_ERROR; } #ifdef __WITH_DTLS__ CAResult_t caRes = CA_STATUS_OK; caRes = CAEnableAnonECDHCipherSuite(false); VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR); OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED"); caRes = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256); VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR); char ranPin[OXM_RANDOM_PIN_SIZE + 1] = {0,}; if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1)) { //Set the device id to derive temporal PSK SetUuidForRandomPinOxm(&gDoxm->deviceID); /** * Since PSK will be used directly by DTLS layer while PIN based ownership transfer, * Credential should not be saved into SVR. * For this reason, use a temporary get_psk_info callback to random PIN OxM. */ caRes = CARegisterDTLSCredentialsHandler(GetDtlsPskForRandomPinOxm); VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR); ehRet = OC_EH_OK; } else { OIC_LOG(ERROR, TAG, "Failed to generate random PIN"); ehRet = OC_EH_ERROR; } #endif //__WITH_DTLS__ } else { #ifdef __WITH_DTLS__ //Save the owner's UUID to derive owner credential memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)); //Update new state in persistent storage if((UpdatePersistentStorage(gDoxm) == true)) { ehRet = OC_EH_OK; } else { OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage"); ehRet = OC_EH_ERROR; } #endif } } } /* * 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(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0)) { gDoxm->owned = true; // Update new state in persistent storage if (UpdatePersistentStorage(gDoxm)) { //Update default ACL of security resource to prevent anonymous user access. if(OC_STACK_OK == UpdateDefaultSecProvACL()) { ehRet = OC_EH_OK; } else { OIC_LOG(ERROR, TAG, "Failed to remove default ACL for security provisioning"); ehRet = OC_EH_ERROR; } } else { OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage"); ehRet = OC_EH_ERROR; } } } exit: if(OC_EH_OK != ehRet) { OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request,"\ "DOXM will be reverted."); /* * If some error is occured while ownership transfer, * ownership transfer related resource should be revert back to initial status. */ RestoreDoxmToInitState(); RestorePstatToInitState(); } //Send payload to request originator if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL)) { OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest"); } DeleteDoxmBinData(newDoxm); return ehRet; }
OicSecDoxm_t * JSONToDoxmBin(const char * jsonStr) { if (NULL == jsonStr) { return NULL; } OCStackResult ret = OC_STACK_ERROR; OicSecDoxm_t *doxm = NULL; cJSON *jsonDoxm = NULL; cJSON *jsonObj = NULL; size_t jsonObjLen = 0; unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {}; uint32_t outLen = 0; B64Result b64Ret = B64_OK; cJSON *jsonRoot = cJSON_Parse(jsonStr); VERIFY_NON_NULL(TAG, jsonRoot, ERROR); jsonDoxm = cJSON_GetObjectItem(jsonRoot, OIC_JSON_DOXM_NAME); VERIFY_NON_NULL(TAG, jsonDoxm, ERROR); doxm = (OicSecDoxm_t*)OICCalloc(1, sizeof(OicSecDoxm_t)); VERIFY_NON_NULL(TAG, doxm, ERROR); //OxmType -- not Mandatory jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_TYPE_NAME); if ((jsonObj) && (cJSON_Array == jsonObj->type)) { doxm->oxmTypeLen = (size_t)cJSON_GetArraySize(jsonObj); VERIFY_SUCCESS(TAG, doxm->oxmTypeLen > 0, ERROR); doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(char *)); VERIFY_NON_NULL(TAG, (doxm->oxmType), ERROR); for (size_t i = 0; i < doxm->oxmTypeLen ; i++) { cJSON *jsonOxmTy = cJSON_GetArrayItem(jsonObj, i); VERIFY_NON_NULL(TAG, jsonOxmTy, ERROR); jsonObjLen = strlen(jsonOxmTy->valuestring) + 1; doxm->oxmType[i] = (char*)OICMalloc(jsonObjLen); VERIFY_NON_NULL(TAG, doxm->oxmType[i], ERROR); strncpy((char *)doxm->oxmType[i], (char *)jsonOxmTy->valuestring, jsonObjLen); } } //Oxm -- not Mandatory jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_NAME); if (jsonObj && cJSON_Array == jsonObj->type) { doxm->oxmLen = (size_t)cJSON_GetArraySize(jsonObj); VERIFY_SUCCESS(TAG, doxm->oxmLen > 0, ERROR); doxm->oxm = (OicSecOxm_t*)OICCalloc(doxm->oxmLen, sizeof(OicSecOxm_t)); VERIFY_NON_NULL(TAG, doxm->oxm, ERROR); for (size_t i = 0; i < doxm->oxmLen ; i++) { cJSON *jsonOxm = cJSON_GetArrayItem(jsonObj, i); VERIFY_NON_NULL(TAG, jsonOxm, ERROR); doxm->oxm[i] = (OicSecOxm_t)jsonOxm->valueint; } } //OxmSel -- Mandatory jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_SEL_NAME); if(jsonObj) { 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 { VERIFY_NON_NULL(TAG, gDoxm, ERROR); 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); doxm->owned = jsonObj->valueint; } else // PUT/POST JSON may not have owned so set it to the gDomx->owned { VERIFY_NON_NULL(TAG, gDoxm, ERROR); doxm->owned = gDoxm->owned; } //DeviceId -- Mandatory jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_DEVICE_ID_NAME); if(jsonObj) { VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR); if(cJSON_String == jsonObj->type) { //Check for empty string, in case DeviceId field has not been set yet if (jsonObj->valuestring[0]) { outLen = 0; b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff, sizeof(base64Buff), &outLen); VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(doxm->deviceID.id)), ERROR); memcpy(doxm->deviceID.id, base64Buff, outLen); } } } else // PUT/POST JSON will not have deviceID so set it to the gDoxm->deviceID.id { VERIFY_NON_NULL(TAG, gDoxm, ERROR); memcpy((char *)doxm->deviceID.id, (char *)gDoxm->deviceID.id, sizeof(doxm->deviceID.id)); } //DPC -- Mandatory jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_DPC_NAME); if(jsonObj) { VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type), ERROR); doxm->dpc = jsonObj->valueint; } else // PUT/POST JSON may not have owned so set it to the gDomx->dpc { if(NULL != gDoxm) { doxm->dpc = gDoxm->dpc; } else { doxm->dpc = false; // default is false } } //Owner -- will be empty when device status is unowned. jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNER_NAME); if(true == doxm->owned) { VERIFY_NON_NULL(TAG, jsonObj, ERROR); } 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); memcpy(doxm->owner.id, base64Buff, outLen); } ret = OC_STACK_OK; exit: cJSON_Delete(jsonRoot); if (OC_STACK_OK != ret) { DeleteDoxmBinData(doxm); doxm = NULL; } return doxm; }
static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest * ehRequest) { OC_LOG (INFO, TAG, PCF("Doxm EntityHandle processing PUT request")); OCEntityHandlerResult ehRet = OC_EH_ERROR; OicUuid_t emptyOwner = {.id = {0}}; /* * Convert JSON Doxm data into binary. This will also validate * the Doxm data received. */ OicSecDoxm_t* newDoxm = JSONToDoxmBin(((OCSecurityPayload*)ehRequest->payload)->securityData); if (newDoxm) { // Iotivity SRM ONLY supports OIC_JUST_WORKS now if (OIC_JUST_WORKS == newDoxm->oxmSel) { /* * If current state of the device is un-owned, enable * anonymous ECDH cipher in tinyDTLS so that Provisioning * tool can initiate JUST_WORKS ownership transfer process. */ if ((false == gDoxm->owned) && (false == newDoxm->owned)) { OC_LOG (INFO, TAG, PCF("Doxm EntityHandle enabling AnonECDHCipherSuite")); #ifdef __WITH_DTLS__ ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR; #endif //__WITH_DTLS__ goto exit; } /* * 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)) { /* * Generate OwnerPSK and create credential for Provisioning * tool with the generated OwnerPSK. * Update persistent storage and disable anonymous ECDH cipher * */ #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); VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR); //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)); // Update new state in persistent storage if (true == UpdatePersistentStorage(gDoxm)) { ehRet = OC_EH_OK; } else { ehRet = OC_EH_ERROR; /* * If persistent storage update failed, revert back the state * for global variable. */ gDoxm->owned = false; memset(&(gDoxm->owner), 0, sizeof(OicUuid_t)); } /* * Disable anonymous ECDH cipher in tinyDTLS since device is now * in owned state. */ CAEnableAnonECDHCipherSuite(false); #endif //__WITH_DTLS__ } } } exit: //Send payload to request originator if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL)) { OC_LOG (ERROR, TAG, PCF("SendSRMResponse failed in HandlePstatPostRequest")); } DeleteDoxmBinData(newDoxm); return ehRet; }
static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest * ehRequest) { OIC_LOG (DEBUG, TAG, "Doxm EntityHandle processing PUT request"); OCEntityHandlerResult ehRet = OC_EH_ERROR; OicUuid_t emptyOwner = {.id = {0}}; /* * Convert JSON Doxm data into binary. This will also validate * the Doxm data received. */ OicSecDoxm_t* newDoxm = JSONToDoxmBin(((OCSecurityPayload*)ehRequest->payload)->securityData); if (newDoxm) { // Iotivity SRM ONLY supports OIC_JUST_WORKS now if (OIC_JUST_WORKS == newDoxm->oxmSel) { /* * If current state of the device is un-owned, enable * anonymous ECDH cipher in tinyDTLS so that Provisioning * tool can initiate JUST_WORKS ownership transfer process. */ if ((false == gDoxm->owned) && (false == newDoxm->owned)) { OIC_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__ goto exit; } /* * 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)) { /* * Generate OwnerPSK and create credential for Provisioning * tool with the generated OwnerPSK. * Update persistent storage and disable anonymous ECDH cipher * */ #ifdef __WITH_DTLS__ OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle; //Generating OwnerPSK OIC_LOG (INFO, TAG, "Doxm EntityHandle generating OwnerPSK"); //Generate new credential for provisioning tool ehRet = AddOwnerPSK((CAEndpoint_t *)&request->devAddr, newDoxm, (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS)); VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR); // Update new state in persistent storage if (true == UpdatePersistentStorage(gDoxm)) { ehRet = OC_EH_OK; } else { ehRet = OC_EH_ERROR; /* * 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)); } /* * Disable anonymous ECDH cipher in tinyDTLS since device is now * 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) { #ifdef __WITH_DTLS__ //this temp Credential ID is used to track temporal Cred Id static OicUuid_t tmpCredId = {.id={0}}; static bool tmpCredGenFlag = false; #endif //__WITH_DTLS__ if ((false == gDoxm->owned) && (false == newDoxm->owned)) { #ifdef __WITH_DTLS__ CAEnableAnonECDHCipherSuite(false); OIC_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) { OIC_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 { OIC_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 } } } exit: //Send payload to request originator if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL)) { OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest"); } DeleteDoxmBinData(newDoxm); return ehRet; }