// Write a base64 encoded opaque value to the buffer provided static int JsonEncodeOpaque(char * buffer, int bufferLen, char * id, char * value, int len, bool last) { char * buf; int outLength; if ((buffer == NULL) || (value == NULL)) { Lwm2m_Error("ERROR: input or output buffers cannot be NULL\n"); return -1; } outLength = (((len + 2) * 4) / 3); buf = (char * )malloc(outLength); if (buf == NULL) { return 0; } b64Encode(buf, outLength, value, len); sprintf(buffer, "{\"n\":\"%s\",\"sv\":\"%s\"}", id, buf); if (!last) { strcat(buffer,",\n"); } else { strcat(buffer,"]\n"); } free(buf); return strlen(buffer); }
char * BinToPstatJSON(const OicSecPstat_t * pstat, const bool isIncResName) { if(NULL == pstat) { return NULL; } cJSON *jsonPstat = NULL; char *jsonStr = NULL; cJSON *jsonSmArray = NULL; char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*) 0)->id)) + 1] = {}; uint32_t outLen = 0; B64Result b64Ret = B64_OK; cJSON *jsonRoot = NULL; if(isIncResName) { jsonRoot = cJSON_CreateObject(); VERIFY_NON_NULL(TAG, jsonRoot, INFO); cJSON_AddItemToObject(jsonRoot, OIC_JSON_PSTAT_NAME, jsonPstat = cJSON_CreateObject()); } else { jsonPstat = cJSON_CreateObject(); jsonRoot = jsonPstat; } VERIFY_NON_NULL(TAG, jsonPstat, INFO); cJSON_AddBoolToObject(jsonPstat, OIC_JSON_ISOP_NAME, pstat->isOp); b64Ret = b64Encode(pstat->deviceID.id, sizeof(pstat->deviceID.id), base64Buff, sizeof(base64Buff), &outLen); VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR); cJSON_AddStringToObject(jsonPstat, OIC_JSON_DEVICE_ID_NAME, base64Buff); cJSON_AddNumberToObject(jsonPstat, OIC_JSON_COMMIT_HASH_NAME, pstat->commitHash); cJSON_AddNumberToObject(jsonPstat, OIC_JSON_CM_NAME, (int)pstat->cm); cJSON_AddNumberToObject(jsonPstat, OIC_JSON_TM_NAME, (int)pstat->tm); cJSON_AddNumberToObject(jsonPstat, OIC_JSON_OM_NAME, (int)pstat->om); cJSON_AddItemToObject(jsonPstat, OIC_JSON_SM_NAME, jsonSmArray = cJSON_CreateArray()); VERIFY_NON_NULL(TAG, jsonSmArray, INFO); for (size_t i = 0; i < pstat->smLen; i++) { cJSON_AddItemToArray(jsonSmArray, cJSON_CreateNumber((int )pstat->sm[i])); } jsonStr = cJSON_Print(jsonRoot); exit: if (jsonRoot) { cJSON_Delete(jsonRoot); } return jsonStr; }
std::string OCSecureResource::getDeviceID() { char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {0,}; uint32_t outLen = 0; B64Result b64Ret = B64_OK; std::ostringstream deviceId(""); validateSecureResource(); b64Ret = b64Encode(devPtr->doxm->deviceID.id, sizeof(devPtr->doxm->deviceID.id), base64Buff, sizeof(base64Buff), &outLen); if (B64_OK == b64Ret) { deviceId << base64Buff; } return deviceId.str(); }
OCStackResult SendAclReq(PEContext_t *context, OCDevAddr *devAddr, OCConnectivityType connType, uint16_t securedPort) { OCStackResult ret = OC_STACK_ERROR; const char GET_ACE_QUERY_FMT[] = "%s?%s=%s;%s=%s"; char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {}; uint32_t outLen = 0; char uri[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {}; OCCallbackData cbData = {.context=NULL}; OCDevAddr destAddr = {.adapter = OC_ADAPTER_IP}; B64Result b64Ret; VERIFY_NON_NULL(TAG, context, ERROR); VERIFY_NON_NULL(TAG, devAddr, ERROR); b64Ret = b64Encode(context->subject.id, sizeof(context->subject.id), base64Buff, sizeof(base64Buff), &outLen); VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR); snprintf(uri, sizeof(uri), GET_ACE_QUERY_FMT, OIC_RSRC_ACL_URI, OIC_JSON_SUBJECT_NAME, base64Buff, OIC_JSON_RESOURCES_NAME, context->resource); cbData.cb = &AmsMgrAclReqCallback; cbData.context = context; destAddr = *devAddr; //update port info destAddr.flags = (OCTransportFlags)(destAddr.flags | OC_FLAG_SECURE); destAddr.port = securedPort; OC_LOG_V(INFO, TAG, "AMS Manager Sending Unicast ACL request with URI = %s", uri); ret = OCDoResource(NULL, OC_REST_GET, uri, &destAddr, NULL, connType, OC_LOW_QOS, &cbData, NULL, 0); exit: OC_LOG_V(INFO, TAG, "%s returns %d ", __func__, ret); return ret; }
/* * 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); OIC_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; }
OCStackResult DiscoverAmsService(PEContext_t *context) { OC_LOG(INFO, TAG, "IN DiscoverAmsService"); OCStackResult ret = OC_STACK_ERROR; const char DOXM_DEVICEID_QUERY_FMT[] = "%s?%s=%s"; char uri[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {}; OCCallbackData cbData = {.context=NULL}; char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {}; uint32_t outLen = 0; B64Result b64Ret; VERIFY_NON_NULL(TAG, context, ERROR); b64Ret = b64Encode(context->amsMgrContext->amsDeviceId.id, sizeof(context->amsMgrContext->amsDeviceId.id), base64Buff, sizeof(base64Buff), &outLen); VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR); snprintf(uri, sizeof(uri), DOXM_DEVICEID_QUERY_FMT, OIC_RSRC_DOXM_URI, OIC_JSON_DEVICE_ID_NAME, base64Buff); cbData.cb = &AmsMgrDiscoveryCallback; cbData.context = (void*)context; /* TODO * If no good response was received for this discovery request, * PE would be blocked forever waiting for AMS service to respond with the ACE. * Need logic to reset the PE state and send ACCESS_DENIED response, * when discovery response from AMS service is not received within certain time. */ OC_LOG_V(INFO, TAG,"AMS Manager Sending Multicast Discovery with URI = %s", uri); ret = OCDoResource(NULL, OC_REST_DISCOVER, uri, NULL, NULL, CT_DEFAULT, OC_LOW_QOS, &cbData, NULL, 0); exit: OC_LOG(INFO, TAG, "Leaving DiscoverAmsService"); return ret; }
char * xmlif_EncodeValue(AwaResourceType dataType, const char * buffer, int bufferLength) { int outLength = 0; char * dataValue = NULL; if (buffer == NULL) { return NULL; } switch(dataType) { case AwaResourceType_String: { // adjust string length because object store expects Pascal strings if (bufferLength > 0 && buffer[bufferLength - 1] == 0) { int lengthAsString = strlen(buffer); bufferLength = lengthAsString < bufferLength ? lengthAsString : bufferLength; } } // no break - intentional fall-through case AwaResourceType_Opaque: outLength = (((bufferLength + 2) * 4) / 3); dataValue = malloc(outLength + 1); if (dataValue == NULL) { AwaLwm2mResult_SetResult(AwaLwm2mResult_OutOfMemory); goto error; } dataValue[outLength] = '\0'; outLength = b64Encode(dataValue, outLength, (char*)buffer, bufferLength); break; case AwaResourceType_Float: if (bufferLength == sizeof(double)) { // IEEE 754 supports up to 17 significant digits double temp; memcpy(&temp, buffer, sizeof(temp)); outLength = asprintf(&dataValue, "%.17g", temp); } else if (bufferLength == sizeof(float)) { // IEEE 754 supports up to 9 significant digits float temp; memcpy(&temp, buffer, sizeof(temp)); outLength = asprintf(&dataValue, "%.9g", temp); } if ((outLength <= 0) || (dataValue == NULL)) { AwaLwm2mResult_SetResult(AwaLwm2mResult_InternalError); goto error; } break; case AwaResourceType_Integer: // no break case AwaResourceType_Time: switch (bufferLength) { case sizeof(int8_t): outLength = asprintf(&dataValue, "%"PRId8, *(int8_t*)&buffer[0]); break; case sizeof(int16_t): outLength = asprintf(&dataValue, "%"PRId16, *(int16_t*)&buffer[0]); break; case sizeof(int32_t): outLength = asprintf(&dataValue, "%"PRId32, *(int32_t*)&buffer[0]); break; case sizeof(int64_t): outLength = asprintf(&dataValue, "%"PRId64, *(int64_t*)&buffer[0]); break; default: outLength = -1; break; } if ((outLength <= 0) || (dataValue == NULL)) { AwaLwm2mResult_SetResult(AwaLwm2mResult_OutOfMemory); goto error; } break; case AwaResourceType_Boolean: outLength = asprintf(&dataValue, "%s", (*(bool*)&buffer[0]) ? "True" : "False"); if ((outLength <= 0) || (dataValue == NULL)) { AwaLwm2mResult_SetResult(AwaLwm2mResult_OutOfMemory); goto error; } break; case AwaResourceType_ObjectLink:; AwaObjectLink * objectLink = (AwaObjectLink *) buffer; outLength = asprintf(&dataValue, "%d:%d", objectLink->ObjectID, objectLink->ObjectInstanceID); if ((outLength <= 0) || (dataValue == NULL)) { AwaLwm2mResult_SetResult(AwaLwm2mResult_OutOfMemory); goto error; } break; case AwaResourceType_None: default: AwaLwm2mResult_SetResult(AwaLwm2mResult_BadRequest); goto error; } AwaLwm2mResult_SetResult(AwaLwm2mResult_Success); error: return dataValue; }
/** * Function to save ownerPSK at provisioning tool end. * * @param[in] selectedDeviceInfo selected device information to performing provisioning. * @return OC_STACK_OK on success */ static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo) { OC_LOG(DEBUG, TAG, "IN SaveOwnerPSK"); OCStackResult res = OC_STACK_ERROR; CAEndpoint_t endpoint; memset(&endpoint, 0x00, sizeof(CAEndpoint_t)); OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr); endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0'; endpoint.port = selectedDeviceInfo->securePort; OicUuid_t ptDeviceID = {.id={0}}; if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID)) { OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID"); return res; } uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0}; //Generating OwnerPSK CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint, (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel), strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)), ptDeviceID.id, sizeof(ptDeviceID.id), selectedDeviceInfo->doxm->deviceID.id, sizeof(selectedDeviceInfo->doxm->deviceID.id), ownerPSK, OWNER_PSK_LENGTH_128); if (CA_STATUS_OK == pskRet) { OC_LOG(INFO, TAG,"ownerPSK dump:\n"); OC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128); //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, B64_OK == b64Ret, ERROR); OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID, SYMMETRIC_PAIR_WISE_KEY, NULL, base64Buff, ownLen, &ptDeviceID); VERIFY_NON_NULL(TAG, cred, ERROR); res = AddCredential(cred); if(res != OC_STACK_OK) { DeleteCredList(cred); return res; } } else { OC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed"); } OC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK"); exit: return res; }
char * BinToDoxmJSON(const OicSecDoxm_t * doxm) { if (NULL == doxm) { return NULL; } char *jsonStr = NULL; cJSON *jsonDoxm = NULL; char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {}; uint32_t outLen = 0; B64Result b64Ret = B64_OK; cJSON *jsonRoot = cJSON_CreateObject(); VERIFY_NON_NULL(TAG, jsonRoot, ERROR); jsonDoxm = cJSON_CreateObject(); VERIFY_NON_NULL(TAG, jsonDoxm, ERROR); cJSON_AddItemToObject(jsonRoot, OIC_JSON_DOXM_NAME, jsonDoxm ); //OxmType -- Not Mandatory if(doxm->oxmTypeLen > 0) { cJSON *jsonOxmTyArray = cJSON_CreateArray(); VERIFY_NON_NULL(TAG, jsonOxmTyArray, ERROR); cJSON_AddItemToObject (jsonDoxm, OIC_JSON_OXM_TYPE_NAME, jsonOxmTyArray ); for (size_t i = 0; i < doxm->oxmTypeLen; i++) { cJSON_AddItemToArray (jsonOxmTyArray, cJSON_CreateString(doxm->oxmType[i])); } } //Oxm -- Not Mandatory if(doxm->oxmLen > 0) { cJSON *jsonOxmArray = cJSON_CreateArray(); VERIFY_NON_NULL(TAG, jsonOxmArray, ERROR); cJSON_AddItemToObject (jsonDoxm, OIC_JSON_OXM_NAME,jsonOxmArray ); for (size_t i = 0; i < doxm->oxmLen; i++) { cJSON_AddItemToArray (jsonOxmArray, cJSON_CreateNumber(doxm->oxm[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); //TODO: Need more clarification on deviceIDFormat field type. #if 0 //DeviceIdFormat -- Mandatory cJSON_AddNumberToObject(jsonDoxm, OIC_JSON_DEVICE_ID_FORMAT_NAME, doxm->deviceIDFormat); #endif //DeviceId -- Mandatory outLen = 0; b64Ret = b64Encode(doxm->deviceID.id, sizeof(doxm->deviceID.id), base64Buff, sizeof(base64Buff), &outLen); VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR); cJSON_AddStringToObject(jsonDoxm, OIC_JSON_DEVICE_ID_NAME, base64Buff); //DPC -- Mandatory cJSON_AddBoolToObject(jsonDoxm, OIC_JSON_DPC_NAME, doxm->dpc); //Owner -- Mandatory outLen = 0; b64Ret = b64Encode(doxm->owner.id, sizeof(doxm->owner.id), base64Buff, sizeof(base64Buff), &outLen); VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR); cJSON_AddStringToObject(jsonDoxm, OIC_JSON_OWNER_NAME, base64Buff); jsonStr = cJSON_PrintUnformatted(jsonRoot); exit: if (jsonRoot) { cJSON_Delete(jsonRoot); } return jsonStr; }
// Tests for base64 encode function TEST(B64EncodeTest, ValidInputForEncoding) { char buf[128]; uint32_t outputLength; uint32_t expectedLength; uint32_t i=0; B64Result res = B64_OK; const char* input = "IoTivity base64~!@#$%^&*()-=0123456789<>?;:'[]{},.\"\\|"; /**< expected output is generated from "http://www.convertstring.com/EncodeDecode/Base64Encode" */ const char* expectedOutput[53] = { "SQ==", "SW8=", "SW9U", "SW9UaQ==", "SW9UaXY=", "SW9UaXZp", "SW9UaXZpdA==", "SW9UaXZpdHk=", "SW9UaXZpdHkg", "SW9UaXZpdHkgYg==", "SW9UaXZpdHkgYmE=", "SW9UaXZpdHkgYmFz", "SW9UaXZpdHkgYmFzZQ==", "SW9UaXZpdHkgYmFzZTY=", "SW9UaXZpdHkgYmFzZTY0", "SW9UaXZpdHkgYmFzZTY0fg==", "SW9UaXZpdHkgYmFzZTY0fiE=", "SW9UaXZpdHkgYmFzZTY0fiFA", "SW9UaXZpdHkgYmFzZTY0fiFAIw==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQ=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQl", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXg==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiY=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYq", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKA==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCk=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCkt", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPQ==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTA=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAx", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMg==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NQ==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3OA==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pg==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj8=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87Og==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87Oic=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87Oidb", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXQ==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXs=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LA==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LC4=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LC4i", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LC4iXA==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LC4iXHw=" }; for(i=0; i< strlen(input); i++) { memset(buf, 0, sizeof(buf)); expectedLength = strlen(expectedOutput[i]); res = b64Encode((uint8_t*)input, i + 1, buf, 128, &outputLength); EXPECT_EQ(B64_OK, res); EXPECT_EQ(expectedLength, outputLength); EXPECT_EQ(0, strcmp(expectedOutput[i], buf)); } }
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; }