/** * @brief Calculate the Licensee Hash based-on challenge. * @param[out] hash Hash of licensee data calculated from challenge and hash iterations. * @param[in] challenge Licensee challenge. * @param[in] challengeLength length of challenge. * @param[in] iterations Hash iterations. * @param[in] licenseeSecret Licensee Secret. * @return true for success otherwise false. */ static bool CalculateLicenseeHash(uint8_t hash[SHA256_HASH_LENGTH], const char *challenge, int challengeLength, int iterations, const char *licenseeSecret) { unsigned int i; uint8_t key[MAX_STR_SIZE]; int keyLength; if (challenge == NULL || licenseeSecret == NULL) { LOG(LOG_ERR, "Null params passed to %s()", __func__); return false; } LOG(LOG_DBG, "Calculating licensee hash"); keyLength = b64Decode((char *)key, sizeof(key), licenseeSecret, strlen(licenseeSecret)); if (keyLength == -1) { LOG(LOG_ERR, "Failed to decode a base64 encoded value"); return false; } HmacSha256_ComputeHash(hash, (const uint8_t *) challenge, challengeLength, key, keyLength); for (i = 1; i < iterations; i++) { HmacSha256_ComputeHash(hash, hash, SHA256_HASH_LENGTH, key, keyLength); } return true; }
TEST(MarshalingAndUnMarshalingTest, BinToPstatJSONAndJSONToPstatBin) { const char* id = "ZGV2aWNlaWQAAAAAABhanw=="; OicSecPstat_t pstat; pstat.cm = NORMAL; pstat.commitHash = 0; uint32_t outLen = 0; unsigned char base64Buff[sizeof(((OicUuid_t*) 0)->id)] = {}; EXPECT_EQ(B64_OK, b64Decode(id, strlen(id), base64Buff, sizeof(base64Buff), &outLen)); memcpy(pstat.deviceID.id, base64Buff, outLen); pstat.isOp = true; pstat.tm = NORMAL; pstat.om = SINGLE_SERVICE_CLIENT_DRIVEN; pstat.smLen = 2; pstat.sm = (OicSecDpom_t*)OICCalloc(pstat.smLen, sizeof(OicSecDpom_t)); pstat.sm[0] = SINGLE_SERVICE_CLIENT_DRIVEN; pstat.sm[1] = SINGLE_SERVICE_SERVER_DRIVEN; char* jsonPstat = BinToPstatJSON(&pstat); printf("BinToJSON Dump:\n%s\n\n", jsonPstat); EXPECT_TRUE(jsonPstat != NULL); OicSecPstat_t *pstat1 = JSONToPstatBin(jsonPstat); EXPECT_TRUE(pstat1 != NULL); OICFree(pstat1->sm); OICFree(pstat1); OICFree(jsonPstat); OICFree(pstat.sm); }
char* b64Decode(char *source, char *dest) { size_t srcsize = strlen(source); char* dst = dest?dest:source; size_t dstsize = b64Decode(source,(unsigned char*)dst,srcsize+1); dst[dstsize] = 0; return dst; }
int main(void) { int pid; char ch; /* set buf for socket */ setbuf(stdin,0); setbuf(stdout,0); setbuf(stderr,0); printf("I am a simple program\n"); printf("So what should I do?\n"); while(1) { printf("\nMay be I can know if you give me some data[Y/N]\n"); if(getchar()=='Y') { ch = getchar(); while(ch != '\n' && ch != 0); //throw char } else { break; } /* fork a new thread to do decode */ pid = fork(); if(pid == 0) { b64Decode(); printf("\nback\n"); exit(0); } else if(pid > 0) { wait(NULL); } else if(pid == -1) { puts("Something Wrong"); exit(0); } } printf("At last I did some thing (:\n"); return 0; }
// TODO This functionality is replicated in all SVR's and therefore we need // to encapsulate it in a common method. However, this may not be the right // file for this method. OCStackResult AddUuidArray(const cJSON* jsonRoot, const char* arrayItem, size_t *numUuids, OicUuid_t** uuids) { size_t idxx = 0; cJSON* jsonObj = cJSON_GetObjectItem((cJSON *)jsonRoot, arrayItem); VERIFY_NON_NULL(TAG, jsonObj, ERROR); VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR); *numUuids = (size_t)cJSON_GetArraySize(jsonObj); VERIFY_SUCCESS(TAG, *numUuids > 0, ERROR); *uuids = (OicUuid_t*)OICCalloc(*numUuids, sizeof(OicUuid_t)); VERIFY_NON_NULL(TAG, *uuids, ERROR); do { unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {}; uint32_t outLen = 0; B64Result b64Ret = B64_OK; cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, idxx); VERIFY_NON_NULL(TAG, jsonOwnr, ERROR); VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR); outLen = 0; b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring), base64Buff, sizeof(base64Buff), &outLen); VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof((*uuids)[idxx].id)), ERROR); memcpy((*uuids)[idxx].id, base64Buff, outLen); } while ( ++idxx < *numUuids); return OC_STACK_OK; exit: return OC_STACK_ERROR; }
static OicSecSvc_t* JSONToSvcBin(const char * jsonStr) { OCStackResult ret = OC_STACK_ERROR; OicSecSvc_t * headSvc = NULL; OicSecSvc_t * prevSvc = NULL; cJSON *jsonRoot = NULL; cJSON *jsonSvcArray = NULL; VERIFY_NON_NULL(TAG, jsonStr, ERROR); jsonRoot = cJSON_Parse(jsonStr); VERIFY_NON_NULL(TAG, jsonRoot, ERROR); jsonSvcArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_SVC_NAME); VERIFY_NON_NULL(TAG, jsonSvcArray, INFO); if (cJSON_Array == jsonSvcArray->type) { int numSvc = cJSON_GetArraySize(jsonSvcArray); int idx = 0; VERIFY_SUCCESS(TAG, numSvc > 0, INFO); do { cJSON *jsonSvc = cJSON_GetArrayItem(jsonSvcArray, idx); VERIFY_NON_NULL(TAG, jsonSvc, ERROR); OicSecSvc_t *svc = (OicSecSvc_t*)OICCalloc(1, sizeof(OicSecSvc_t)); VERIFY_NON_NULL(TAG, svc, ERROR); headSvc = (headSvc) ? headSvc : svc; if (prevSvc) { prevSvc->next = svc; } cJSON *jsonObj = NULL; unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {}; uint32_t outLen = 0; B64Result b64Ret = B64_OK; // Service Device Identity jsonObj = cJSON_GetObjectItem(jsonSvc, OIC_JSON_SERVICE_DEVICE_ID); VERIFY_NON_NULL(TAG, jsonObj, ERROR); 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(svc->svcdid.id)), ERROR); memcpy(svc->svcdid.id, base64Buff, outLen); // Service Type jsonObj = cJSON_GetObjectItem(jsonSvc, OIC_JSON_SERVICE_TYPE); VERIFY_NON_NULL(TAG, jsonObj, ERROR); VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR); svc->svct = (OicSecSvcType_t)jsonObj->valueint; // Resource Owners jsonObj = cJSON_GetObjectItem(jsonSvc, OIC_JSON_OWNERS_NAME); VERIFY_NON_NULL(TAG, jsonObj, ERROR); VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR); svc->ownersLen = (size_t)cJSON_GetArraySize(jsonObj); VERIFY_SUCCESS(TAG, svc->ownersLen > 0, ERROR); svc->owners = (OicUuid_t*)OICCalloc(svc->ownersLen, sizeof(OicUuid_t)); VERIFY_NON_NULL(TAG, (svc->owners), ERROR); size_t idxx = 0; do { cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, idxx); VERIFY_NON_NULL(TAG, jsonOwnr, ERROR); VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR); outLen = 0; b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring), base64Buff, sizeof(base64Buff), &outLen); VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(svc->owners[idxx].id)), ERROR); memcpy(svc->owners[idxx].id, base64Buff, outLen); } while ( ++idxx < svc->ownersLen); prevSvc = svc; } while( ++idx < numSvc); } ret = OC_STACK_OK; exit: cJSON_Delete(jsonRoot); if (OC_STACK_OK != ret) { DeleteSVCList(headSvc); headSvc = NULL; } return headSvc; }
int xmlif_DecodeValue(char ** dataValue, AwaResourceType dataType, const char * buffer, int bufferLength) { int dataLength = -1; int outLength; switch(dataType) { case AwaResourceType_String: // outLength = ((bufferLength * 3) / 4); // every 4 base encoded bytes are decoded to 3 bytes, *dataValue = malloc(outLength); if (*dataValue == NULL) { AwaLwm2mResult_SetResult(AwaLwm2mResult_OutOfMemory); goto error; } dataLength = b64Decode(*dataValue, outLength, (char*)buffer, bufferLength); if (dataLength == -1) { AwaLwm2mResult_SetResult(AwaLwm2mResult_BadRequest); goto error; } else { dataLength++; // add space for null terminator char * nullTerminated = malloc(dataLength); memcpy(nullTerminated, *dataValue, dataLength - 1); free(*dataValue); nullTerminated[dataLength-1] = '\0'; *dataValue = nullTerminated; } break; case AwaResourceType_Opaque: case AwaResourceType_None: // TypeNone for Executable payload which is an Opaque outLength = ((bufferLength * 3) / 4); // every 4 base encoded bytes are decoded to 3 bytes *dataValue = malloc(outLength); if (*dataValue == NULL) { AwaLwm2mResult_SetResult(AwaLwm2mResult_OutOfMemory); goto error; } dataLength = b64Decode(*dataValue, outLength, (char*)buffer, bufferLength); if (dataLength == -1) { AwaLwm2mResult_SetResult(AwaLwm2mResult_BadRequest); goto error; } break; case AwaResourceType_Float: { double d; *dataValue = malloc(sizeof(double)); if (*dataValue == NULL) { AwaLwm2mResult_SetResult(AwaLwm2mResult_OutOfMemory); goto error; } sscanf(buffer, "%20lf", &d); dataLength = sizeof(double); memcpy(*dataValue, &d, dataLength); break; } case AwaResourceType_Integer: // no break case AwaResourceType_Time: { uint64_t u; *dataValue = malloc(sizeof(uint64_t)); if (*dataValue == NULL) { AwaLwm2mResult_SetResult(AwaLwm2mResult_OutOfMemory); goto error; } sscanf(buffer, "%"SCNd64, &u); dataLength = sizeof(uint64_t); memcpy(*dataValue, &u, dataLength); break; } case AwaResourceType_Boolean: *dataValue = malloc(sizeof(bool)); if (*dataValue == NULL) { AwaLwm2mResult_SetResult(AwaLwm2mResult_OutOfMemory); goto error; } (*dataValue)[0] = (strcmp(buffer, "True") == 0); dataLength = sizeof(bool); break; case AwaResourceType_ObjectLink: { dataLength = sizeof(AwaObjectLink); *dataValue = malloc(dataLength); if (*dataValue == NULL) { AwaLwm2mResult_SetResult(AwaLwm2mResult_OutOfMemory); goto error; } AwaObjectLink * objectLink = (AwaObjectLink *)*dataValue; sscanf(buffer, "%10d:%10d", &objectLink->ObjectID, &objectLink->ObjectInstanceID); break; } //case AwaResourceType_None: default: AwaLwm2mResult_SetResult(AwaLwm2mResult_BadRequest); goto error; } AwaLwm2mResult_SetResult(AwaLwm2mResult_Success); error: return dataLength; }
static bool ValidateQuery(const char * query) { // Send doxm resource data if the state of doxm resource // matches with the query parameters. // else send doxm resource data as NULL // TODO Remove this check and rely on Policy Engine // and Provisioning Mode to enforce provisioning-state // 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. OIC_LOG (DEBUG, TAG, "In ValidateQuery"); if(NULL == gDoxm) { return false; } 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((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)) { bOwnedMatch = true; } else if((strncasecmp((char *)parseIter.valPos, OIC_SEC_FALSE, parseIter.valLen) == 0) && (!gDoxm->owned)) { 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; } } }
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; }
// Tests for base64 decode function TEST(B64DeodeTest, InvalidInputForDecoding) { uint8_t buf[128]; uint32_t outputLength; uint32_t i=0; const char* input[53] = { "SQ=", "Sw8=", "SW1U", "SW9Uaq==", "SW9uaXY=", "SW91UaXZp", "SW9UaXZpdA.==", "Sw9UAXZpdHk=", "SW9UAXZpdHkg", "SW9UaXZpdhkgYg==", "SW9UaXZpd5kgYmE=", "SW9UaXZ1dHkgYmFz", "SW9UaXZpdHkgymFzZQ==", "SW9UaXZpdHkgYmFzZTY==", "SW9UaXZpdHkgYmFzZTY0=", "SW9UaXZpdHkgYmFzZTY0fg=", "SW9UaXZpdHkgYmFzZTY0fiE==", "SW8UaXZpdHkgYmFzZTY0fiFA", "SW9UaxzPDHkgYmFzZTY0fiFAIw==", "SW9UaXZpdHKGYmFzZTY0fiFAIyQ=", "SW9UaXZpdHkgYmFZztY0fiFAIyQl=", "SW8UaXZpdHkgYmFzZTY0fiFAIyQlXg=", "#SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiY=", "SSW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYq", "SW9UaXZpdHkgYmFzZTY0fiFAiyQlXiYqKA==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCk===", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKckt", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKcktpQ==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQiXiYqKCktPTA=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAx=", "SW9UaXZpdHkgYmFzZTY0fifAIyQlXiYqKCktPTAxmg=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM#1=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM1", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0Nq==", "sw9uaxzpdhkgymfzzty0fifaiyqlxiyqKcktptaxmjm0nty=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0nTY3", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3Ok==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3OA==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pg", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pg=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjm0NTY3ODk8Pj9=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXqKCktPTAxMjM0NTY3ODk8Pj87=", "SW9UaXZpdHkgYmFzZTY0fiFaIyiYqKCktPTAxMjM0NTY3ODk8Pj87Og==", "W9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87Oic1=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCkTAxMjM0NTY3ODk8Pj87Oidb==", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYCktPTAxMjM0NTY3ODk8Pj87Oidbxq==", "SW9UaXZpdHkgYmzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87Oidbxxs=", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCkPTAxMjM0NTY3ODk8Pj87OidbXXT9", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9la==", "SW9UaXZpdHkgYzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9Lc4=", "SW9UaXZpdHkgYmFzZ0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9lC4i", "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9lc4iXA==", "SW9UaXZpdHkgYmFzZTY0fiFqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LC4ixHw=" }; const char* expectedOutput = "IoTivity base64~!@#$%^&*()-=0123456789<>?;:'[]{},.\"\\|"; for(i=0; i< (sizeof(input)/sizeof(char*)); i++) { memset(buf, 0, sizeof(buf)); if( B64_OK == b64Decode(input[i], strlen(input[i]), buf, 128, &outputLength) ) { EXPECT_NE(0, memcmp(expectedOutput, buf, i + 1)); } } }
// Tests for base64 decode function TEST(B64DeodeTest, ValidInputForDecoding) { uint8_t buf[128]; uint32_t outputLength; uint32_t i=0; B64Result res = B64_OK; const char* input[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=" }; const char* expectedOutput = "IoTivity base64~!@#$%^&*()-=0123456789<>?;:'[]{},.\"\\|"; for(i=0; i< (sizeof(input)/sizeof(char*)); i++) { memset(buf, 0, sizeof(buf)); res = b64Decode(input[i], strlen(input[i]), buf, 128, &outputLength); EXPECT_EQ(B64_OK, res); EXPECT_EQ(i + 1, outputLength); EXPECT_EQ(0, memcmp(expectedOutput, buf, i + 1)); } }
OicSecPstat_t * JSONToPstatBin(const char * jsonStr, const bool isIncResName) { if(NULL == jsonStr) { return NULL; } OCStackResult ret = OC_STACK_ERROR; OicSecPstat_t *pstat = NULL; cJSON *jsonPstat = NULL; cJSON *jsonObj = NULL; 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, INFO); if(isIncResName) { jsonPstat = cJSON_GetObjectItem(jsonRoot, OIC_JSON_PSTAT_NAME); } else { jsonPstat = jsonRoot; } VERIFY_NON_NULL(TAG, jsonPstat, INFO); pstat = (OicSecPstat_t*)OICCalloc(1, sizeof(OicSecPstat_t)); VERIFY_NON_NULL(TAG, pstat, INFO); jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_ISOP_NAME); VERIFY_NON_NULL(TAG, jsonObj, ERROR); VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type) , ERROR); pstat->isOp = jsonObj->valueint; jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_DEVICE_ID_NAME); VERIFY_NON_NULL(TAG, jsonObj, ERROR); VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR); b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff, sizeof(base64Buff), &outLen); VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(pstat->deviceID.id)), ERROR); memcpy(pstat->deviceID.id, base64Buff, outLen); jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_COMMIT_HASH_NAME); VERIFY_NON_NULL(TAG, jsonObj, ERROR); VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR); pstat->commitHash = jsonObj->valueint; jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_CM_NAME); VERIFY_NON_NULL(TAG, jsonObj, ERROR); VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR); pstat->cm = (OicSecDpm_t)jsonObj->valueint; jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_OM_NAME); VERIFY_NON_NULL(TAG, jsonObj, ERROR); VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR); pstat->om = (OicSecDpom_t)jsonObj->valueint; jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_SM_NAME); VERIFY_NON_NULL(TAG, jsonObj, ERROR); if (cJSON_Array == jsonObj->type) { pstat->smLen = cJSON_GetArraySize(jsonObj); size_t idxx = 0; VERIFY_SUCCESS(TAG, pstat->smLen != 0, ERROR); pstat->sm = (OicSecDpom_t*)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t)); VERIFY_NON_NULL(TAG, pstat->sm, ERROR); do { cJSON *jsonSm = cJSON_GetArrayItem(jsonObj, idxx); VERIFY_NON_NULL(TAG, jsonSm, ERROR); pstat->sm[idxx] = (OicSecDpom_t)jsonSm->valueint; }while ( ++idxx < pstat->smLen); } ret = OC_STACK_OK; exit: cJSON_Delete(jsonRoot); if (OC_STACK_OK != ret) { OC_LOG (ERROR, TAG, "JSONToPstatBin failed"); DeletePstatBinData(pstat); pstat = NULL; } return pstat; }
static int JsonDeserialise(Lwm2mTreeNode ** dest, const DefinitionRegistry * registry, ObjectIDType objectID, ObjectInstanceIDType instanceID, ResourceIDType resourceID, const uint8_t * buf, int bufferLen) { int result; int index; jsmn_parser p; jsmntok_t tokens[MAX_JSON_TOKENS]; enum { BASENAME_SIZE = 128 }; char basename[BASENAME_SIZE]; uint64_t basetime = 0; const char * buffer = (const char *)buf; jsmn_init(&p); result = jsmn_parse(&p, buffer, bufferLen, tokens, (sizeof(tokens) / sizeof(*tokens))); if (result < 0) { Lwm2m_Error("ERROR: deserialising JSON, malformed!\n"); return -1; } jsmntok_t *root = &tokens[0]; // { if (root->type != JSMN_OBJECT) { return -1; } jsmntok_t * t; // First lookup the basename if ((index = JsonTokenFind(tokens, buffer, root, "bn")) != -1) { t = &tokens[tokens[index].first_child]; if (t->type != JSMN_STRING) { return -1; } strncpy(basename, JsonTokenToString(buffer, t), BASENAME_SIZE); basename[BASENAME_SIZE - 1] = '\0'; // Defensive *dest = Lwm2mTreeNode_Create(); Lwm2mTreeNode_SetType(*dest, Lwm2mTreeNodeType_Root); } else { if (resourceID != -1) { sprintf(basename, "/%d/%d/%d/", objectID, instanceID, resourceID); *dest = AddResourceNode(NULL, registry, objectID, resourceID); } else { if (instanceID != -1) { sprintf(basename, "/%d/%d/", objectID, instanceID); *dest = AddObjectInstanceNode(NULL, registry, objectID); } else { sprintf(basename, "/%d/", objectID); *dest = AddObjectNode(NULL, registry, objectID); } } } // Lookup base time if ((index = JsonTokenFind(tokens, buffer, root, "bt")) != -1) { t = &tokens[tokens[index].first_child]; if (t->type != JSMN_PRIMITIVE) { return -1; } char * string = JsonTokenToString(buffer, t); sscanf(string, "%24" SCNu64, &basetime); } // Lookup resource array if ((index = JsonTokenFind(tokens, buffer, root, "e")) != -1) { jsmntok_t * resourceArray = &tokens[tokens[index].first_child]; if (resourceArray->type != JSMN_ARRAY) { return -1; } // Add Resource nodes if (resourceArray->size <= 0) { return -1; } index = resourceArray->first_child; do { // {"n":"<name>","<type>":"<data>"}, t = &tokens[index]; if (t->type != JSMN_OBJECT) { return -1; } // "n" t = &tokens[t->first_child]; if (t->type != JSMN_STRING) { return -1; } if (!JsonTokenStrcmp(buffer, t, "n")) { return -1; } // resource name jsmntok_t * key = &tokens[t->first_child]; if (key->type != JSMN_STRING) { return -1; } char * name = JsonTokenToString(buffer, key); // append the basename and then parse the O/I/R/Ri int resourceInstanceID = 0; char base[256]; snprintf(base, 256, "%s%s", basename, name); sscanf(base, "/%5d/%5d/%5d/%5d", &objectID, &instanceID, &resourceID, &resourceInstanceID); Lwm2mTreeNode * resourceNode; Lwm2mTreeNode * resourceValueNode; if (Lwm2mTreeNode_GetType(*dest) == Lwm2mTreeNodeType_Root) { Lwm2mTreeNode * objectNode = AddObjectNode(*dest, registry, objectID); Lwm2mTreeNode * instanceNode = AddObjectInstanceNode(objectNode, registry, instanceID); resourceNode = AddResourceNode(instanceNode, registry, objectID, resourceID); } else if (Lwm2mTreeNode_GetType(*dest) == Lwm2mTreeNodeType_Object) { Lwm2mTreeNode * instanceNode = AddObjectInstanceNode(*dest, registry, instanceID); resourceNode = AddResourceNode(instanceNode, registry, objectID, resourceID); } else if (Lwm2mTreeNode_GetType(*dest) == Lwm2mTreeNodeType_ObjectInstance) { // lookup resource node, create if doesn't exist. resourceNode = AddResourceNode(*dest, registry, objectID, resourceID); } else { // Deserialise a single resource. resourceNode = *dest; } // Data type, "sv", "v", "bv" etc JsonDataType jsonDataType; t = &tokens[t->next_sibling]; if (t->type != JSMN_STRING) { return -1; } if (JsonTokenStrcmp(buffer, t, "sv")) { jsonDataType = JSON_TYPE_STRING; } else if (JsonTokenStrcmp(buffer, t, "v")) { jsonDataType = JSON_TYPE_FLOAT; } else if (JsonTokenStrcmp(buffer, t, "bv")) { jsonDataType = JSON_TYPE_BOOLEAN; } else if (JsonTokenStrcmp(buffer, t, "ov")) { jsonDataType = JSON_TYPE_OBJECT_LINK; } else { return -1; } // Process value t = &tokens[t->first_child]; if ((t->type != JSMN_STRING) && (t->type != JSMN_PRIMITIVE)) { return -1; } char * value = JsonTokenToString(buffer, t); resourceValueNode = Lwm2mTreeNode_Create(); Lwm2mTreeNode_SetID(resourceValueNode, resourceInstanceID); Lwm2mTreeNode_SetType(resourceValueNode, Lwm2mTreeNodeType_ResourceInstance); int resourceType = Definition_GetResourceType(registry, objectID, resourceID); switch (resourceType) { case AwaResourceType_Time: if (jsonDataType == JSON_TYPE_FLOAT) { int64_t temp = 0; result = sscanf((char *)value, "%24" SCNu64, &temp); if (result > 0) { // adjust time based on the basetime. temp -= basetime; result = Lwm2mTreeNode_SetValue(resourceValueNode, (const uint8_t *)&temp, sizeof(temp)); } } else { Lwm2mTreeNode_DeleteRecursive(resourceValueNode); return -1; } break; case AwaResourceType_Float: // no break case AwaResourceType_Integer: if (jsonDataType != JSON_TYPE_FLOAT) { Lwm2mTreeNode_DeleteRecursive(resourceValueNode); return -1; } if (resourceType == AwaResourceType_Float) { double temp = 0; result = sscanf((char *)value, "%24lf", &temp); if (result > 0) { result = Lwm2mTreeNode_SetValue(resourceValueNode, (const uint8_t *)&temp, sizeof(temp)); } } else { int64_t temp = 0; result = sscanf((char *)value, "%24" SCNu64, &temp); if (result > 0) { result = Lwm2mTreeNode_SetValue(resourceValueNode, (const uint8_t *)&temp, sizeof(temp)); } } break; case AwaResourceType_Boolean: if (jsonDataType == JSON_TYPE_BOOLEAN) { int64_t temp = (strcmp(value, "true")) ? 1: 0; result = Lwm2mTreeNode_SetValue(resourceValueNode, (const uint8_t *)&temp, sizeof(temp)); } else { Lwm2mTreeNode_DeleteRecursive(resourceValueNode); return -1; } break; case AwaResourceType_Opaque: { if (jsonDataType != JSON_TYPE_STRING) { Lwm2mTreeNode_DeleteRecursive(resourceValueNode); return -1; } int outLength = ((strlen(value) * 3) / 4); // every 4 base encoded bytes are decoded to 3 bytes, char * decodedValue = (char *)malloc(outLength); if (decodedValue == NULL) { Lwm2mTreeNode_DeleteRecursive(resourceValueNode); return -1; } int decodedLength = b64Decode(decodedValue, outLength, value, strlen(value)); if (decodedLength >= 0) { result = Lwm2mTreeNode_SetValue(resourceValueNode, (const uint8_t *)decodedValue, decodedLength); } else { result = -1; } free(decodedValue); } break; case AwaResourceType_String: if (jsonDataType != JSON_TYPE_STRING) { Lwm2mTreeNode_DeleteRecursive(resourceValueNode); return -1; } result = Lwm2mTreeNode_SetValue(resourceValueNode, (const uint8_t *)&value[0], strlen(value) + 1); break; case AwaResourceType_ObjectLink: { if (jsonDataType != JSON_TYPE_OBJECT_LINK) { Lwm2mTreeNode_DeleteRecursive(resourceValueNode); return -1; } AwaObjectLink objectLink; result = sscanf(value, "%10d:%10d", &objectLink.ObjectID, &objectLink.ObjectInstanceID); if (result > 0) { result = Lwm2mTreeNode_SetValue(resourceValueNode, (const uint8_t *)&objectLink, sizeof(objectLink)); } } break; default: break; } if (result >= 0) { Lwm2mTreeNode_AddChild(resourceNode, resourceValueNode); } else { Lwm2mTreeNode_DeleteRecursive(resourceValueNode); } } while((index = tokens[index].next_sibling) != -1); } // "e" return result; }