예제 #1
0
//JSONToDoxmBin Tests
TEST(JSONToDoxmBinTest, JSONToDoxmBinValidJSON)
{
    OicSecDoxm_t * doxm1 =  getBinDoxm();
    char * json = BinToDoxmJSON(doxm1);
    EXPECT_TRUE(json != NULL);

    OicSecDoxm_t *doxm2 = JSONToDoxmBin(json);
    EXPECT_TRUE(doxm2 != NULL);

    DeleteDoxmBinData(doxm1);
    DeleteDoxmBinData(doxm2);
    OICFree(json);
}
예제 #2
0
TEST(BinToDoxmJSONTest, BinToDoxmJSONValidDoxm)
{
    OicSecDoxm_t * doxm =  getBinDoxm();

    char * json = BinToDoxmJSON(doxm);
    EXPECT_TRUE(json != NULL);

    DeleteDoxmBinData(doxm);
    OICFree(json);
}
예제 #3
0
//HandleDoxmPostRequest Test
TEST(HandleDoxmPostRequestTest, HandleDoxmPostRequestValidInput)
{
    OCEntityHandlerRequest ehRequest = {};
    OCServerRequest svRequest = {};

    OicSecDoxm_t * doxm =  getBinDoxm();

    strcpy(svRequest.addressInfo.IP.ipAddress, "10.10.10.10");
    svRequest.addressInfo.IP.port = 2345;
    svRequest.connectivityType = CA_ETHERNET;

    ehRequest.reqJSONPayload = (unsigned char *) BinToDoxmJSON(doxm);
    ehRequest.requestHandle = (OCRequestHandle) &svRequest;

    EXPECT_EQ(OC_EH_ERROR, HandleDoxmPostRequest(&ehRequest));
    DeleteDoxmBinData(doxm);
    OICFree(ehRequest.reqJSONPayload);
}
예제 #4
0
/**
 * Perform cleanup for DOXM resources.
 *
 * @return
 * OC_STACK_OK    - no error
 * OC_STACK_ERROR - stack process error
 *
 */
OCStackResult DeInitDoxmResource()
{
    OCStackResult ret = OCDeleteResource(gDoxmHandle);
    if(gDoxm  != &gDefaultDoxm)
    {
        DeleteDoxmBinData(gDoxm);
    }
    gDoxm = NULL;

    if(OC_STACK_OK == ret)
    {
        return OC_STACK_OK;
    }
    else
    {
        return OC_STACK_ERROR;
    }
}
예제 #5
0
static void ConvertJsonToCBOR(const char *jsonFileName, const char *cborFileName)
{
    char *jsonStr = NULL;
    FILE *fp = NULL;
    FILE *fp1 = NULL;
    uint8_t *aclCbor = NULL;
    uint8_t *pstatCbor = NULL;
    uint8_t *doxmCbor = NULL;
    uint8_t *amaclCbor = NULL;
    uint8_t *svcCbor = NULL;
    uint8_t *credCbor = NULL;
    cJSON *jsonRoot = NULL;
    OCStackResult ret = OC_STACK_ERROR;
    size_t size = GetJSONFileSize(jsonFileName);
    if (0 == size)
    {
        OIC_LOG (ERROR, TAG, "Failed converting to JSON");
        return;
    }

    jsonStr = (char *)OICMalloc(size + 1);
    VERIFY_NON_NULL(TAG, jsonStr, FATAL);

    fp = fopen(jsonFileName, "r");
    if (fp)
    {
        size_t bytesRead = fread(jsonStr, 1, size, fp);
        jsonStr[bytesRead] = '\0';

        OIC_LOG_V(DEBUG, TAG, "Read %zu bytes", bytesRead);
        fclose(fp);
        fp = NULL;
    }
    else
    {
        OIC_LOG (ERROR, TAG, "Unable to open JSON file!!");
        goto exit;
    }

    jsonRoot = cJSON_Parse(jsonStr);

    cJSON *value = cJSON_GetObjectItem(jsonRoot, OIC_JSON_ACL_NAME);
    //printf("ACL json : \n%s\n", cJSON_PrintUnformatted(value));
    size_t aclCborSize = 0;
    if (NULL != value)
    {
        OicSecAcl_t *acl = JSONToAclBin(jsonStr);
        VERIFY_NON_NULL(TAG, acl, FATAL);
        ret = AclToCBORPayload(acl, &aclCbor, &aclCborSize);
        if(OC_STACK_OK != ret)
        {
            OIC_LOG (ERROR, TAG, "Failed converting Acl to Cbor Payload");
            DeleteACLList(acl);
            goto exit;
        }
        printf("ACL Cbor Size: %zd\n", aclCborSize);
        DeleteACLList(acl);
    }

    value = cJSON_GetObjectItem(jsonRoot, OIC_JSON_PSTAT_NAME);
    size_t pstatCborSize = 0;
    if (NULL != value)
    {
        OicSecPstat_t *pstat = JSONToPstatBin(jsonStr);
        VERIFY_NON_NULL(TAG, pstat, FATAL);
        ret = PstatToCBORPayload(pstat, &pstatCbor, &pstatCborSize);
        if(OC_STACK_OK != ret)
        {
            OIC_LOG (ERROR, TAG, "Failed converting Pstat to Cbor Payload");
            DeletePstatBinData(pstat);
            goto exit;
        }
        printf("PSTAT Cbor Size: %zd\n", pstatCborSize);
        DeletePstatBinData(pstat);
    }
    value = cJSON_GetObjectItem(jsonRoot, OIC_JSON_DOXM_NAME);
    size_t doxmCborSize = 0;
    if (NULL != value)
    {
        OicSecDoxm_t *doxm = JSONToDoxmBin(jsonStr);
        VERIFY_NON_NULL(TAG, doxm, FATAL);
        ret = DoxmToCBORPayload(doxm, &doxmCbor, &doxmCborSize);
        if(OC_STACK_OK != ret)
        {
            OIC_LOG (ERROR, TAG, "Failed converting Doxm to Cbor Payload");
            DeleteDoxmBinData(doxm);
            goto exit;
        }
        printf("DOXM Cbor Size: %zd\n", doxmCborSize);
        DeleteDoxmBinData(doxm);
    }
    value = cJSON_GetObjectItem(jsonRoot, OIC_JSON_AMACL_NAME);
    size_t amaclCborSize = 0;
    if (NULL != value)
    {
        OicSecAmacl_t *amacl = JSONToAmaclBin(jsonStr);
        VERIFY_NON_NULL(TAG, amacl, FATAL);
        ret = AmaclToCBORPayload(amacl, &amaclCbor, &amaclCborSize);
        if(OC_STACK_OK != ret)
        {
            OIC_LOG (ERROR, TAG, "Failed converting Amacl to Cbor Payload");
            DeleteAmaclList(amacl);
            goto exit;
        }
        printf("AMACL Cbor Size: %zd\n", amaclCborSize);
        DeleteAmaclList(amacl);
    }
    value = cJSON_GetObjectItem(jsonRoot, OIC_JSON_SVC_NAME);
    size_t svcCborSize = 0;
    if (NULL != value)
    {
        OicSecSvc_t *svc = JSONToSvcBin(jsonStr);
        VERIFY_NON_NULL(TAG, svc, FATAL);
        ret = SVCToCBORPayload(svc, &svcCbor, &svcCborSize);
        if(OC_STACK_OK != ret)
        {
            OIC_LOG (ERROR, TAG, "Failed converting Svc to Cbor Payload");
            DeleteSVCList(svc);
            goto exit;
        }
        printf("SVC Cbor Size: %zd\n", svcCborSize);
        DeleteSVCList(svc);
    }
    value = cJSON_GetObjectItem(jsonRoot, OIC_JSON_CRED_NAME);
    //printf("CRED json : \n%s\n", cJSON_PrintUnformatted(value));
    size_t credCborSize = 0;
    int secureFlag = 0;
    if (NULL != value)
    {
        OicSecCred_t *cred = JSONToCredBin(jsonStr);
        VERIFY_NON_NULL(TAG, cred, FATAL);
        ret = CredToCBORPayload(cred, &credCbor, &credCborSize, secureFlag);
        if(OC_STACK_OK != ret)
        {
            OIC_LOG (ERROR, TAG, "Failed converting Cred to Cbor Payload");
            DeleteCredList(cred);
            goto exit;
        }
        printf("CRED Cbor Size: %zd\n", credCborSize);
        DeleteCredList(cred);
    }

    CborEncoder encoder;
    size_t cborSize = aclCborSize + pstatCborSize + doxmCborSize + svcCborSize + credCborSize + amaclCborSize;

    printf("Total Cbor Size : %zd\n", cborSize);
    cborSize += 255; // buffer margin for adding map and byte string
    uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborSize);
    VERIFY_NON_NULL(TAG, outPayload, ERROR);
    cbor_encoder_init(&encoder, outPayload, cborSize, 0);
    CborEncoder map;
    CborError cborEncoderResult = cbor_encoder_create_map(&encoder, &map, CborIndefiniteLength);
    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating Main Map.");
    if (aclCborSize > 0)
    {
        cborEncoderResult = cbor_encode_text_string(&map, OIC_JSON_ACL_NAME, strlen(OIC_JSON_ACL_NAME));
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Name.");
        cborEncoderResult = cbor_encode_byte_string(&map, aclCbor, aclCborSize);
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding ACL Value.");
    }

    if (pstatCborSize > 0)
    {
        cborEncoderResult = cbor_encode_text_string(&map, OIC_JSON_PSTAT_NAME, strlen(OIC_JSON_PSTAT_NAME));
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Name.");
        cborEncoderResult = cbor_encode_byte_string(&map, pstatCbor, pstatCborSize);
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PSTAT Value.");
    }
    if (doxmCborSize > 0)
    {
        cborEncoderResult = cbor_encode_text_string(&map, OIC_JSON_DOXM_NAME, strlen(OIC_JSON_DOXM_NAME));
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DOXM Name.");
        cborEncoderResult = cbor_encode_byte_string(&map, doxmCbor, doxmCborSize);
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding DOXM Value.");
    }
    if (amaclCborSize > 0)
    {
        cborEncoderResult = cbor_encode_text_string(&map, OIC_JSON_AMACL_NAME, strlen(OIC_JSON_AMACL_NAME));
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding AMACL Name.");
        cborEncoderResult = cbor_encode_byte_string(&map, amaclCbor, amaclCborSize);
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding AMACL Value.");
    }
    if (svcCborSize > 0)
    {
        cborEncoderResult = cbor_encode_text_string(&map, OIC_JSON_SVC_NAME, strlen(OIC_JSON_SVC_NAME));
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SVC Name.");
        cborEncoderResult = cbor_encode_byte_string(&map, svcCbor, svcCborSize);
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SVC Value.");
    }
    if (credCborSize > 0)
    {
        cborEncoderResult = cbor_encode_text_string(&map, OIC_JSON_CRED_NAME, strlen(OIC_JSON_CRED_NAME));
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CRED Name.");
        cborEncoderResult = cbor_encode_byte_string(&map, credCbor, credCborSize);
        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding CRED Value.");
    }

    cborEncoderResult = cbor_encoder_close_container(&encoder, &map);
    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Container.");

    size_t s = encoder.ptr - outPayload;
    OIC_LOG_V(DEBUG, TAG, "Payload size %zu", s);

    fp1 = fopen(cborFileName, "w");
    if (fp1)
    {
        size_t bytesWritten = fwrite(outPayload, 1, s, fp1);
        if (bytesWritten == s)
        {
            OIC_LOG_V(DEBUG, TAG, "Written %zu bytes", bytesWritten);
        }
        else
        {
            OIC_LOG_V(ERROR, TAG, "Failed writing %zu bytes", s);
        }
        fclose(fp1);
        fp1 = NULL;
    }
exit:

    cJSON_Delete(jsonRoot);
    OICFree(aclCbor);
    OICFree(doxmCbor);
    OICFree(pstatCbor);
    OICFree(amaclCbor);
    OICFree(svcCbor);
    OICFree(credCbor);
    OICFree(jsonStr);
    return ;
}
예제 #6
0
OicSecDoxm_t* JSONToDoxmBin(const char * jsonStr)
{
    printf("IN JSONToDoxmBin\n");
    if (NULL == jsonStr)
    {
        return NULL;
    }

    OCStackResult ret = OC_STACK_ERROR;
    OicSecDoxm_t *doxm =  NULL;
    cJSON *jsonDoxm = NULL;
    cJSON *jsonObj = NULL;

    size_t jsonObjLen = 0;

    cJSON *jsonRoot = cJSON_Parse(jsonStr);
    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);

    jsonDoxm = cJSON_GetObjectItem(jsonRoot, OIC_JSON_DOXM_NAME);
    VERIFY_NON_NULL(TAG, jsonDoxm, ERROR);

    doxm = (OicSecDoxm_t *)OICCalloc(1, sizeof(OicSecDoxm_t));
    VERIFY_NON_NULL(TAG, doxm, ERROR);

    //OxmType -- not Mandatory
    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_TYPE_NAME);
    if ((jsonObj) && (cJSON_Array == jsonObj->type))
    {
        doxm->oxmTypeLen = (size_t)cJSON_GetArraySize(jsonObj);
        VERIFY_SUCCESS(TAG, doxm->oxmTypeLen > 0, ERROR);

        doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(char *));
        VERIFY_NON_NULL(TAG, (doxm->oxmType), ERROR);

        for (size_t i  = 0; i < doxm->oxmTypeLen ; i++)
        {
            cJSON *jsonOxmTy = cJSON_GetArrayItem(jsonObj, i);
            VERIFY_NON_NULL(TAG, jsonOxmTy, ERROR);

            jsonObjLen = strlen(jsonOxmTy->valuestring) + 1;
            doxm->oxmType[i] = (char*)OICMalloc(jsonObjLen);
            VERIFY_NON_NULL(TAG, doxm->oxmType[i], ERROR);
            strncpy((char *)doxm->oxmType[i], (char *)jsonOxmTy->valuestring, jsonObjLen);
        }
    }

    //Oxm -- not Mandatory
    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXMS_NAME);
    if (jsonObj && cJSON_Array == jsonObj->type)
    {
        doxm->oxmLen = (size_t)cJSON_GetArraySize(jsonObj);
        VERIFY_SUCCESS(TAG, doxm->oxmLen > 0, ERROR);

        doxm->oxm = (OicSecOxm_t*)OICCalloc(doxm->oxmLen, sizeof(OicSecOxm_t));
        VERIFY_NON_NULL(TAG, doxm->oxm, ERROR);

        for (size_t i  = 0; i < doxm->oxmLen ; i++)
        {
            cJSON *jsonOxm = cJSON_GetArrayItem(jsonObj, i);
            VERIFY_NON_NULL(TAG, jsonOxm, ERROR);
            doxm->oxm[i] = (OicSecOxm_t)jsonOxm->valueint;
        }
    }

    //OxmSel -- Mandatory
    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_SEL_NAME);
    if (jsonObj)
    {
        VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
        doxm->oxmSel = (OicSecOxm_t)jsonObj->valueint;
    }

    //sct -- Mandatory
    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_SUPPORTED_CRED_TYPE_NAME);
    if (jsonObj)
    {
        VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
        doxm->sct = (OicSecCredType_t)jsonObj->valueint;
    }

    //Owned -- Mandatory
    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNED_NAME);
    if (jsonObj)
    {
        VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type), ERROR);
        doxm->owned = jsonObj->valueint;
    }

    //DPC -- Mandatory
    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_DPC_NAME);
    if (jsonObj)
    {
        VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type), ERROR);
        doxm->dpc = jsonObj->valueint;
    }

    //DeviceId -- Mandatory
    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_DEVICE_ID_NAME);
    if (jsonObj)
    {
        VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
        if (cJSON_String == jsonObj->type)
        {
            //Check for empty string, in case DeviceId field has not been set yet
            if (jsonObj->valuestring[0])
            {
                ret = ConvertStrToUuid(jsonObj->valuestring, &doxm->deviceID);
                VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
            }
        }
    }

    //rowner -- Mandatory
    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_ROWNERID_NAME);
    if (true == doxm->owned)
    {
        VERIFY_NON_NULL(TAG, jsonObj, ERROR);
    }
    if (jsonObj)
    {
        ret = ConvertStrToUuid(jsonObj->valuestring, &doxm->rownerID);
        VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
    }

    //Owner -- will be empty when device status is unowned.
    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_DEVOWNERID_NAME);
    if (true == doxm->owned)
    {
        VERIFY_NON_NULL(TAG, jsonObj, ERROR);
    }
    if (jsonObj)
    {
        ret = ConvertStrToUuid(jsonObj->valuestring, &doxm->owner);
                VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
    }

    ret = OC_STACK_OK;

exit:
    cJSON_Delete(jsonRoot);
    if (OC_STACK_OK != ret)
    {
        DeleteDoxmBinData(doxm);
        doxm = NULL;
    }
    printf("OUT JSONToDoxmBin\n");
    return doxm;
}
예제 #7
0
static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest * ehRequest)
{
    OIC_LOG (DEBUG, TAG, "Doxm EntityHandle  processing PUT request");
    OCEntityHandlerResult ehRet = OC_EH_ERROR;
    OicUuid_t emptyOwner = {.id = {0}};

    /*
     * Convert JSON Doxm data into binary. This will also validate
     * the Doxm data received.
     */
    OicSecDoxm_t* newDoxm = JSONToDoxmBin(((OCSecurityPayload*)ehRequest->payload)->securityData);

    if (newDoxm)
    {
        // Iotivity SRM ONLY supports OIC_JUST_WORKS now
        if (OIC_JUST_WORKS == newDoxm->oxmSel)
        {
            if ((false == gDoxm->owned) && (false == newDoxm->owned))
            {
                /*
                 * If current state of the device is un-owned, enable
                 * anonymous ECDH cipher in tinyDTLS so that Provisioning
                 * tool can initiate JUST_WORKS ownership transfer process.
                 */
                if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
                {
                    OIC_LOG (INFO, TAG, "Doxm EntityHandle  enabling AnonECDHCipherSuite");
#ifdef __WITH_DTLS__
                    ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
#endif //__WITH_DTLS__
                    goto exit;
                }
                else
                {
#ifdef __WITH_DTLS__
                    //Save the owner's UUID to derive owner credential
                    memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));

//                    OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
//                    //Generating OwnerPSK
//                    OIC_LOG (INFO, TAG, "Doxm EntityHandle  generating OwnerPSK");
//                    //Generate new credential for provisioning tool
//                    ehRet = AddOwnerPSK((CAEndpoint_t *)&request->devAddr, newDoxm,
//                            (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS));
//                    VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);

                    // Update new state in persistent storage
                    if (true == UpdatePersistentStorage(gDoxm))
                    {
                        ehRet = OC_EH_OK;
                    }
                    else
                    {
                        OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
                        ehRet = OC_EH_ERROR;
                    }

                    /*
                     * Disable anonymous ECDH cipher in tinyDTLS since device is now
                     * in owned state.
                     */
                    CAResult_t caRes = CA_STATUS_OK;
                    caRes = CAEnableAnonECDHCipherSuite(false);
                    VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
                    OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");

#ifdef __WITH_X509__
#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE
                    CASelectCipherSuite(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
#endif //__WITH_X509__
#endif //__WITH_DTLS__
                }
            }
        }
        else if(OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
        {
            if ((false == gDoxm->owned) && (false == newDoxm->owned))
            {
                /*
                 * If current state of the device is un-owned, enable
                 * anonymous ECDH cipher in tinyDTLS so that Provisioning
                 * tool can initiate JUST_WORKS ownership transfer process.
                 */
                if(memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) == 0)
                {
                    gDoxm->oxmSel = newDoxm->oxmSel;
                    //Update new state in persistent storage
                    if((UpdatePersistentStorage(gDoxm) == true))
                    {
                        ehRet = OC_EH_OK;
                    }
                    else
                    {
                        OIC_LOG(WARNING, TAG, "Failed to update DOXM in persistent storage");
                        ehRet = OC_EH_ERROR;
                    }

#ifdef __WITH_DTLS__
                    CAResult_t caRes = CA_STATUS_OK;

                    caRes = CAEnableAnonECDHCipherSuite(false);
                    VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
                    OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");

                    caRes = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);
                    VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);

                    char ranPin[OXM_RANDOM_PIN_SIZE + 1] = {0,};
                    if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
                    {
                        //Set the device id to derive temporal PSK
                        SetUuidForRandomPinOxm(&gDoxm->deviceID);

                        /**
                         * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
                         * Credential should not be saved into SVR.
                         * For this reason, use a temporary get_psk_info callback to random PIN OxM.
                         */
                        caRes = CARegisterDTLSCredentialsHandler(GetDtlsPskForRandomPinOxm);
                        VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
                        ehRet = OC_EH_OK;
                    }
                    else
                    {
                        OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
                        ehRet = OC_EH_ERROR;
                    }
#endif //__WITH_DTLS__
                }
                else
                {
#ifdef __WITH_DTLS__
                    //Save the owner's UUID to derive owner credential
                    memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));

                    //Update new state in persistent storage
                    if((UpdatePersistentStorage(gDoxm) == true))
                    {
                        ehRet = OC_EH_OK;
                    }
                    else
                    {
                        OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
                        ehRet = OC_EH_ERROR;
                    }
#endif
                }
            }
        }

        /*
         * When current state of the device is un-owned and Provisioning
         * Tool is attempting to change the state to 'Owned' with a
         * qualified value for the field 'Owner'
         */
        if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
            (memcmp(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t)) == 0))
        {
            gDoxm->owned = true;
            // Update new state in persistent storage
            if (UpdatePersistentStorage(gDoxm))
            {
                //Update default ACL of security resource to prevent anonymous user access.
                if(OC_STACK_OK == UpdateDefaultSecProvACL())
                {
                    ehRet = OC_EH_OK;
                }
                else
                {
                    OIC_LOG(ERROR, TAG, "Failed to remove default ACL for security provisioning");
                    ehRet = OC_EH_ERROR;
                }
            }
            else
            {
                OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
                ehRet = OC_EH_ERROR;
            }
        }
    }

exit:
    if(OC_EH_OK != ehRet)
    {
        OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request,"\
                            "DOXM will be reverted.");

        /*
         * If some error is occured while ownership transfer,
         * ownership transfer related resource should be revert back to initial status.
         */
        RestoreDoxmToInitState();
        RestorePstatToInitState();
    }

    //Send payload to request originator
    if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL))
    {
        OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest");
    }
    DeleteDoxmBinData(newDoxm);

    return ehRet;
}
예제 #8
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;
}
예제 #9
0
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;
}
예제 #10
0
static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest * ehRequest)
{
    OIC_LOG (DEBUG, TAG, "Doxm EntityHandle  processing PUT request");
    OCEntityHandlerResult ehRet = OC_EH_ERROR;
    OicUuid_t emptyOwner = {.id = {0}};

    /*
     * Convert JSON Doxm data into binary. This will also validate
     * the Doxm data received.
     */
    OicSecDoxm_t* newDoxm = JSONToDoxmBin(((OCSecurityPayload*)ehRequest->payload)->securityData);

    if (newDoxm)
    {
        // Iotivity SRM ONLY supports OIC_JUST_WORKS now
        if (OIC_JUST_WORKS == newDoxm->oxmSel)
        {
            /*
             * If current state of the device is un-owned, enable
             * anonymous ECDH cipher in tinyDTLS so that Provisioning
             * tool can initiate JUST_WORKS ownership transfer process.
             */
            if ((false == gDoxm->owned) && (false == newDoxm->owned))
            {
                OIC_LOG (INFO, TAG, "Doxm EntityHandle  enabling AnonECDHCipherSuite");
#ifdef __WITH_DTLS__
                ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
#endif //__WITH_DTLS__
                goto exit;
            }

            /*
             * When current state of the device is un-owned and Provisioning
             * Tool is attempting to change the state to 'Owned' with a
             * qualified value for the field 'Owner'
             */
            if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
                (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0))
            {
                /*
                 * Generate OwnerPSK and create credential for Provisioning
                 * tool with the generated OwnerPSK.
                 * Update persistent storage and disable anonymous ECDH cipher
                 *
                 */
#ifdef __WITH_DTLS__
                OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;

                //Generating OwnerPSK
                OIC_LOG (INFO, TAG, "Doxm EntityHandle  generating OwnerPSK");

                //Generate new credential for provisioning tool
                ehRet = AddOwnerPSK((CAEndpoint_t *)&request->devAddr, newDoxm,
                        (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS));

                VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);

                // Update new state in persistent storage
                if (true == UpdatePersistentStorage(gDoxm))
                {
                    ehRet = OC_EH_OK;
                }
                else
                {
                    ehRet = OC_EH_ERROR;

                    /*
                     * If persistent storage update failed, revert back the state
                     * for global variable.
                     */
                    gDoxm->owned = false;
                    gDoxm->oxmSel = 0;
                    memset(&(gDoxm->owner), 0, sizeof(OicUuid_t));
                }

                /*
                 * Disable anonymous ECDH cipher in tinyDTLS since device is now
                 * in owned state.
                 */
                CAEnableAnonECDHCipherSuite(false);
#ifdef __WITH_X509__
#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE
                CASelectCipherSuite(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
#endif //__WITH_X509__
#endif //__WITH_DTLS__
            }
        }
        else if(OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
        {
#ifdef __WITH_DTLS__
            //this temp Credential ID is used to track temporal Cred Id
            static OicUuid_t tmpCredId = {.id={0}};
            static bool tmpCredGenFlag = false;
#endif //__WITH_DTLS__

            if ((false == gDoxm->owned) && (false == newDoxm->owned))
            {
#ifdef __WITH_DTLS__
                CAEnableAnonECDHCipherSuite(false);
                OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
                CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);

                char ranPin[OXM_RANDOM_PIN_SIZE + 1] = {0,};
                if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
                {
                    if(tmpCredGenFlag)
                    {
                       OIC_LOG(INFO, TAG, "Corrupted PSK is detected!!!");
                       VERIFY_SUCCESS(TAG,
                                      OC_STACK_RESOURCE_DELETED == RemoveCredential(&tmpCredId),
                                      ERROR);
                    }

                    OCStackResult res = AddTmpPskWithPIN( &(newDoxm->owner), SYMMETRIC_PAIR_WISE_KEY,
                                     ranPin, OXM_RANDOM_PIN_SIZE, 1, &(newDoxm->owner), &tmpCredId);
                    VERIFY_SUCCESS(TAG, res == OC_STACK_OK, ERROR);
                    tmpCredGenFlag = true;
                    ehRet = OC_EH_OK;
                }
                else
                {
                    OIC_LOG(ERROR, TAG, "Failed to generate random PIN");
                    ehRet = OC_EH_ERROR;
                }

#endif //__WITH_DTLS__
            }

            /*
             * When current state of the device is un-owned and Provisioning
             * Tool is attempting to change the state to 'Owned' with a
             * qualified value for the field 'Owner'
             */
            if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
                (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0))
            {
#ifdef __WITH_DTLS__
                OCServerRequest * request = (OCServerRequest *)ehRequest->requestHandle;

                //Remove Temporal Credential resource
                if(tmpCredGenFlag)
                {
                    VERIFY_SUCCESS(TAG,
                                   OC_STACK_RESOURCE_DELETED == RemoveCredential(&tmpCredId),
                                   ERROR);
                    tmpCredGenFlag = false;
                }

                //Generate new credential for provisioning tool
                ehRet = AddOwnerPSK((CAEndpoint_t*)(&request->devAddr), newDoxm,
                                    (uint8_t*)OXM_RANDOM_DEVICE_PIN, strlen(OXM_RANDOM_DEVICE_PIN));
                VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);

                //Update new state in persistent storage
                if((UpdatePersistentStorage(gDoxm) == true))
                {
                    ehRet = OC_EH_OK;
                }
                else
                {
                    /*
                     * If persistent storage update failed, revert back the state
                     * for global variable.
                     */
                    gDoxm->owned = false;
                    gDoxm->oxmSel = 0;
                    memset(&(gDoxm->owner), 0, sizeof(OicUuid_t));
                    ehRet = OC_EH_ERROR;

                }
#endif
             }
        }
    }

exit:

    //Send payload to request originator
    if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL))
    {
        OIC_LOG (ERROR, TAG, "SendSRMResponse failed in HandlePstatPostRequest");
    }
    DeleteDoxmBinData(newDoxm);

    return ehRet;
}