/**
* @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;
}
Exemple #2
0
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);
}
Exemple #3
0
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;
}
Exemple #5
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;

}
Exemple #6
0
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;
}
Exemple #8
0
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;
            }
        }
    }
Exemple #9
0
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));
    }
}
Exemple #12
0
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;
}