AMACL payload conversion from JSON to CBOR
authorHabib Virji <habib.virji@samsung.com>
Fri, 19 Feb 2016 00:42:03 +0000 (00:42 +0000)
committerHabib Virji <habib.virji@samsung.com>
Sat, 12 Mar 2016 19:38:55 +0000 (19:38 +0000)
Converts AMACL payload conversion from JSON to CBOR directly using tinycbor library.

- Amacl unit test is updated to match new changes.
- Data file are updated to handle new format.

Change-Id: I80e56f182f3f516025977e26fa5d719058832fd8
Signed-off-by: Habib Virji <habib.virji@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/5053
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-on: https://gerrit.iotivity.org/gerrit/5777

resource/csdk/security/include/internal/amaclresource.h
resource/csdk/security/include/internal/security_internals.h
resource/csdk/security/src/amaclresource.c
resource/csdk/security/unittest/SConscript
resource/csdk/security/unittest/amaclresourcetest.cpp [new file with mode: 0644]

index 9c37a0e..f724402 100755 (executable)
@@ -63,19 +63,22 @@ void DeInitAmaclResource();
 OCStackResult AmaclGetAmsDeviceId(const char *resource, OicUuid_t *amsId);
 
 /**
- * This function converts Amacl data into JSON format.
- * Caller needs to invoke 'free' when done using
- * returned string.
- * @param Amacl  instance of OicSecAmacl_t structure.
+ * This function converts Amacl data into CBOR format.
+ * Caller needs to invoke 'free' when done using returned string.
  *
- * @retval  pointer to Amacl in json format.
+ * @param amacl instance of @ref OicSecAmacl_t structure.
+ * @param cborPayload is the converted cbor value of @ref OicSecAmacl_t structure.
+ * @param cborSize is the size of the cbor payload. This value is the size of the
+ * cborPayload. It should not be NON-NULL value.
+ *
+ * @return ::OC_STACK_OK for Success. ::OC_STACK_INVALID in case of invalid parameters.
+ * ::OC_STACK_ERROR in case of error in converting to cbor.
  */
-char* BinToAmaclJSON(const OicSecAmacl_t * amacl);
+OCStackResult AmaclToCBORPayload(const OicSecAmacl_t *amacl, uint8_t **cborPayload,
+                                 size_t *cborSize);
 
 #ifdef __cplusplus
 }
 #endif
 
 #endif //IOTVT_SRM_AMACLR_H
-
-
index de1e4fc..70ba7e6 100644 (file)
@@ -57,6 +57,17 @@ OCStackResult CreatePstatResource();
 OCEntityHandlerResult PstatEntityHandler(OCEntityHandlerFlag flag,
                                          OCEntityHandlerRequest * ehRequest);
 
+/**
+ * Converts CBOR payload to AMACL.
+ *
+ * @param cborPayload is the amacl payload cbor value that neds to be converted.
+ * @param cborSize of the cborPayload. In case size is not known, it is 0.
+ * It should be NON-NULL.
+ * @param amacl is the value that is initialized. It is NULL in case of error.
+ */
+OCStackResult CBORPayloadToAmacl(const uint8_t *cborPayload, size_t cborSize,
+                                 OicSecAmacl_t **amacl);
+
 #ifdef __cplusplus
 }
 #endif
index 63aef6a..033ad47 100644 (file)
 
 #include <stdlib.h>
 #include <string.h>
-#include "ocstack.h"
-#include "logger.h"
 #include "oic_malloc.h"
-#include "oic_string.h"
-#include "cJSON.h"
-#include "base64.h"
-#include "resourcemanager.h"
+#include "ocpayload.h"
+#include "payload_logging.h"
 #include "psinterface.h"
+#include "resourcemanager.h"
 #include "utlist.h"
 #include "srmresourcestrings.h"
-#include "amaclresource.h"
 #include "srmutility.h"
-#include <stdlib.h>
-#include <string.h>
+#include "amaclresource.h"
 
 #define TAG  "SRM-AMACL"
 
-OicSecAmacl_t *gAmacl = NULL;
+/** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
+ * The value of payload size is increased until reaching belox max cbor size. */
+static const uint8_t CBOR_SIZE = 255;
+
+/* Max cbor size payload. */
+static const uint16_t CBOR_MAX_SIZE = 4400;
+
+/** AMACL Map size - Number of mandatory items. */
+static const uint8_t AMACL_MAP_SIZE = 3;
+
+static OicSecAmacl_t *gAmacl = NULL;
 static OCResourceHandle gAmaclHandle = NULL;
 
 void DeleteAmaclList(OicSecAmacl_t* amacl)
@@ -69,193 +74,318 @@ void DeleteAmaclList(OicSecAmacl_t* amacl)
     }
 }
 
-/*
- * This internal method converts AMACL data into JSON format.
- *
- * Note: Caller needs to invoke 'free' when finished using the return string.
- */
-char * BinToAmaclJSON(const OicSecAmacl_t * amacl)
+static size_t OicSecAmaclCount(const OicSecAmacl_t *secAmacl)
 {
-    cJSON *jsonRoot = NULL;
-    char *jsonStr = NULL;
-
-    if (amacl)
+    size_t size = 0;
+    for (const OicSecAmacl_t *amacl = secAmacl; amacl; amacl = amacl->next)
     {
-        jsonRoot = cJSON_CreateObject();
-        VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+        size++;
+    }
+    return size;
+}
 
-        cJSON *jsonAmaclArray = NULL;
-        cJSON_AddItemToObject (jsonRoot, OIC_JSON_AMACL_NAME, jsonAmaclArray = cJSON_CreateArray());
-        VERIFY_NON_NULL(TAG, jsonAmaclArray, ERROR);
+OCStackResult AmaclToCBORPayload(const OicSecAmacl_t *amaclS, uint8_t **cborPayload,
+                                 size_t *cborSize)
+{
+    if (NULL == amaclS || NULL == cborPayload || NULL != *cborPayload || NULL == cborSize)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
 
-        while(amacl)
-        {
-            char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
-            uint32_t outLen = 0;
-            B64Result b64Ret = B64_OK;
+    OCStackResult ret = OC_STACK_ERROR;
+    size_t cborLen = *cborSize;
+    if (0 == cborLen)
+    {
+        cborLen = CBOR_SIZE;
+    }
 
-            cJSON *jsonAmacl = cJSON_CreateObject();
+    *cborSize = 0;
+    *cborPayload = NULL;
 
-            // Resources -- Mandatory
-            cJSON *jsonRsrcArray = NULL;
-            cJSON_AddItemToObject(jsonAmacl, OIC_JSON_RESOURCES_NAME, jsonRsrcArray =
-                    cJSON_CreateArray());
-            VERIFY_NON_NULL(TAG, jsonRsrcArray, ERROR);
-            for (unsigned int i = 0; i < amacl->resourcesLen; i++)
-            {
-                cJSON_AddItemToArray(jsonRsrcArray, cJSON_CreateString(amacl->resources[i]));
-            }
+    CborEncoder encoder = { {.ptr = NULL }, .end = 0 };
+    CborEncoder amaclArray = { {.ptr = NULL }, .end = 0 };
+    CborError cborEncoderResult = CborNoError;
 
-            // Amss -- Mandatory
-            cJSON *jsonAmsArray = NULL;
-            cJSON_AddItemToObject(jsonAmacl, OIC_JSON_AMSS_NAME, jsonAmsArray =
-                    cJSON_CreateArray());
-            VERIFY_NON_NULL(TAG, jsonAmsArray, ERROR);
-            for (unsigned int i = 0; i < amacl->amssLen; i++)
-            {
-                outLen = 0;
+    const OicSecAmacl_t *amacl = amaclS;
+    uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
+    VERIFY_NON_NULL(TAG, outPayload, ERROR);
+    cbor_encoder_init(&encoder, outPayload, cborLen, 0);
 
-                b64Ret = b64Encode(amacl->amss[i].id, sizeof(((OicUuid_t*) 0)->id), base64Buff,
-                        sizeof(base64Buff), &outLen);
-                VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+    // Create AMACL Array
+    cborEncoderResult = cbor_encoder_create_array(&encoder, &amaclArray, OicSecAmaclCount(amacl));
+    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMACL Array.");
 
-                cJSON_AddItemToArray(jsonAmsArray, cJSON_CreateString(base64Buff));
-            }
+    while (amacl)
+    {
+        CborEncoder amaclMap = { {.ptr = NULL }, .end = 0 };
+        cborEncoderResult = cbor_encoder_create_map(&amaclArray, &amaclMap, AMACL_MAP_SIZE);
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMACL MAP.");
 
-            // Owners -- Mandatory
-            cJSON *jsonOwnrArray = NULL;
-            cJSON_AddItemToObject(jsonAmacl, OIC_JSON_OWNERS_NAME, jsonOwnrArray =
-                    cJSON_CreateArray());
-            VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
-            for (unsigned int i = 0; i < amacl->ownersLen; i++)
+        // Resources -- Mandatory
+        {
+            CborEncoder resources = { {.ptr = NULL }, .end = 0};
+            cborEncoderResult = cbor_encode_text_string(&amaclMap, OIC_JSON_RESOURCES_NAME,
+                strlen(OIC_JSON_RESOURCES_NAME));
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Name Tag.");
+            cborEncoderResult = cbor_encoder_create_array(&amaclMap, &resources, amacl->resourcesLen);
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Name Array.");
+            for (size_t i = 0; i < amacl->resourcesLen; i++)
             {
-                outLen = 0;
-
-                b64Ret = b64Encode(amacl->owners[i].id, sizeof(((OicUuid_t*) 0)->id), base64Buff,
-                        sizeof(base64Buff), &outLen);
-                VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+                cborEncoderResult = cbor_encode_text_string(&resources, amacl->resources[i],
+                    strlen(amacl->resources[i]));
+                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Resource Name Value in Array.");
 
-                cJSON_AddItemToArray(jsonOwnrArray, cJSON_CreateString(base64Buff));
             }
-
-            // Attach current amacl node to Amacl Array
-            cJSON_AddItemToArray(jsonAmaclArray, jsonAmacl);
-            amacl = amacl->next;
+            cborEncoderResult = cbor_encoder_close_container(&amaclMap, &resources);
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Resource Name ");
+        }
+        // Amss -- Mandatory
+        {
+            CborEncoder amss = { {.ptr = NULL }, .end = 0 };
+            cborEncoderResult = cbor_encode_text_string(&amaclMap, OIC_JSON_AMSS_NAME,
+                strlen(OIC_JSON_AMSS_NAME));
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMSS Name Tag.");
+            cborEncoderResult = cbor_encoder_create_array(&amaclMap, &amss, amacl->amssLen);
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMSS Name Array.");
+            for (size_t i = 0; i < amacl->amssLen; i++)
+            {
+                cborEncoderResult = cbor_encode_byte_string(&amss, amacl->amss[i].id,
+                    sizeof(amacl->amss[i].id));
+                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding AMSS Name Value.");
+            }
+            cborEncoderResult = cbor_encoder_close_container(&amaclMap, &amss);
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing AMSS Array.");
+        }
+        // Owners -- Mandatory
+        {
+            cborEncoderResult = cbor_encode_text_string(&amaclMap, OIC_JSON_OWNERS_NAME,
+                strlen(OIC_JSON_OWNERS_NAME));
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Owners Array Tag.");
+            CborEncoder owners = { {.ptr = NULL }, .end = 0};
+            cborEncoderResult = cbor_encoder_create_array(&amaclMap, &owners, amacl->ownersLen);
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Owners Array.");
+            for (size_t i = 0; i < amacl->ownersLen; i++)
+            {
+                cborEncoderResult = cbor_encode_byte_string(&owners, (uint8_t *)amacl->owners[i].id,
+                    sizeof(amacl->owners[i].id));
+                VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Owners Array Value.");
+            }
+            cborEncoderResult = cbor_encoder_close_container(&amaclMap, &owners);
+            VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Owners Array.");
         }
+        cborEncoderResult = cbor_encoder_close_container(&amaclArray, &amaclMap);
+        VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing AMACL Map.");
 
-        jsonStr = cJSON_PrintUnformatted(jsonRoot);
+        amacl = amacl->next;
     }
+    cborEncoderResult = cbor_encoder_close_container(&encoder, &amaclArray);
+    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Amacl Array.");
 
-exit:
-    if (jsonRoot)
+    if (CborNoError == cborEncoderResult)
     {
-        cJSON_Delete(jsonRoot);
+        *cborPayload = outPayload;
+        *cborSize = encoder.ptr - outPayload;
+        ret = OC_STACK_OK;
     }
-    return jsonStr;
-}
 
+exit:
+    if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
+    {
+       // reallocate and try again!
+       OICFree(outPayload);
+       outPayload = NULL;
+       // Since the allocated initial memory failed, double the memory.
+       cborLen += encoder.ptr - encoder.end;
+       cborEncoderResult = CborNoError;
+       ret = AmaclToCBORPayload(amaclS, cborPayload, &cborLen);
+       if (OC_STACK_OK == ret)
+       {
+           *cborSize = cborLen;
+           ret = OC_STACK_OK;
+       }
+    }
 
+    if (CborNoError != cborEncoderResult)
+    {
+       OICFree(outPayload);
+       outPayload = NULL;
+       *cborSize = 0;
+       *cborPayload = NULL;
+       ret = OC_STACK_ERROR;
+    }
 
+    return ret;
+}
 
-/*
- * This internal method converts JSON AMACL into binary AMACL.
- */
-OicSecAmacl_t * JSONToAmaclBin(const char * jsonStr)
+OCStackResult CBORPayloadToAmacl(const uint8_t *cborPayload, size_t size,
+                                 OicSecAmacl_t **secAmacl)
 {
-    OCStackResult ret = OC_STACK_ERROR;
-    OicSecAmacl_t * headAmacl = NULL;
-    OicSecAmacl_t * prevAmacl = NULL;
-    cJSON *jsonRoot = NULL;
-    cJSON *jsonAmaclArray = NULL;
-
-    VERIFY_NON_NULL(TAG, jsonStr, ERROR);
+    if (NULL == cborPayload || NULL == secAmacl || NULL != *secAmacl)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
 
-    jsonRoot = cJSON_Parse(jsonStr);
-    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+    *secAmacl = NULL;
 
-    jsonAmaclArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_AMACL_NAME);
-    VERIFY_NON_NULL(TAG, jsonAmaclArray, INFO);
+    OCStackResult ret = OC_STACK_ERROR;
 
-    if (cJSON_Array == jsonAmaclArray->type)
+    CborValue amaclCbor = { .parser = NULL };
+    CborParser parser = { .end = NULL };
+    CborError cborFindResult = CborNoError;
+    int cborLen = size;
+    if (0 == size)
     {
-        int numAmacl = cJSON_GetArraySize(jsonAmaclArray);
-        int idx = 0;
+        cborLen = CBOR_SIZE;
+    }
+    cbor_parser_init(cborPayload, cborLen, 0, &parser, &amaclCbor);
 
-        VERIFY_SUCCESS(TAG, numAmacl > 0, INFO);
-        do
-        {
-            cJSON *jsonAmacl = cJSON_GetArrayItem(jsonAmaclArray, idx);
-            VERIFY_NON_NULL(TAG, jsonAmacl, ERROR);
+    OicSecAmacl_t *headAmacl = NULL;
 
-            OicSecAmacl_t *amacl = (OicSecAmacl_t*)OICCalloc(1, sizeof(OicSecAmacl_t));
-            VERIFY_NON_NULL(TAG, amacl, ERROR);
+    CborValue amaclArray = { .parser = NULL };
+    cborFindResult = cbor_value_enter_container(&amaclCbor, &amaclArray);
+    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
 
-            headAmacl = (headAmacl) ? headAmacl : amacl;
-            if (prevAmacl)
-            {
-                prevAmacl->next = amacl;
-            }
+    while (cbor_value_is_valid(&amaclArray))
+    {
+        CborValue amaclMap = { .parser = NULL };
+        cborFindResult = cbor_value_enter_container(&amaclArray, &amaclMap);
+        VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
 
-            size_t jsonObjLen = 0;
-            cJSON *jsonObj = NULL;
+        OicSecAmacl_t *amacl = (OicSecAmacl_t *) OICCalloc(1, sizeof(*amacl));
+        VERIFY_NON_NULL(TAG, amacl, ERROR);
 
-            // Resources -- Mandatory
-            jsonObj = cJSON_GetObjectItem(jsonAmacl, OIC_JSON_RESOURCES_NAME);
-            VERIFY_NON_NULL(TAG, jsonObj, ERROR);
-            VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
+        while (cbor_value_is_valid(&amaclMap))
+        {
+            char *name = NULL;
+            size_t len = 0;
+            cborFindResult = cbor_value_dup_text_string(&amaclMap, &name, &len, NULL);
+            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
+            cborFindResult = cbor_value_advance(&amaclMap);
+            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
 
-            amacl->resourcesLen = (size_t)cJSON_GetArraySize(jsonObj);
-            VERIFY_SUCCESS(TAG, amacl->resourcesLen > 0, ERROR);
-            amacl->resources = (char**)OICCalloc(amacl->resourcesLen, sizeof(char*));
-            VERIFY_NON_NULL(TAG, (amacl->resources), ERROR);
+            CborType type = cbor_value_get_type(&amaclMap);
 
-            size_t idxx = 0;
-            do
+            // Resources -- Mandatory
+            if (0 == strcmp(OIC_JSON_RESOURCES_NAME, name))
             {
-                cJSON *jsonRsrc = cJSON_GetArrayItem(jsonObj, idxx);
-                VERIFY_NON_NULL(TAG, jsonRsrc, ERROR);
-
-                jsonObjLen = strlen(jsonRsrc->valuestring) + 1;
-                amacl->resources[idxx] = (char*)OICMalloc(jsonObjLen);
-                VERIFY_NON_NULL(TAG, (amacl->resources[idxx]), ERROR);
-                OICStrcpy(amacl->resources[idxx], jsonObjLen, jsonRsrc->valuestring);
-            } while ( ++idxx < amacl->resourcesLen);
+                CborValue resources = { .parser = NULL  };
+                cborFindResult = cbor_value_get_array_length(&amaclMap, &amacl->resourcesLen);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
+
+                cborFindResult = cbor_value_enter_container(&amaclMap, &resources);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
+
+                amacl->resources = (char **) OICMalloc(amacl->resourcesLen * sizeof(*amacl->resources));
+                VERIFY_NON_NULL(TAG, amacl->resources, ERROR);
+                int i = 0;
+                while (cbor_value_is_text_string(&resources))
+                {
+                    cborFindResult = cbor_value_dup_text_string(&resources, &amacl->resources[i++],
+                        &len, NULL);
+                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
+                    cborFindResult = cbor_value_advance(&resources);
+                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
+                }
+            }
 
             // Amss -- Mandatory
-            VERIFY_SUCCESS( TAG, OC_STACK_OK == AddUuidArray(jsonAmacl, OIC_JSON_AMSS_NAME,
-                               &(amacl->amssLen), &(amacl->amss)), ERROR);
+            if (0 == strcmp(OIC_JSON_AMSS_NAME, name))
+            {
+                CborValue amss = { .parser = NULL };
+                cborFindResult = cbor_value_get_array_length(&amaclMap, &amacl->amssLen);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
+                cborFindResult = cbor_value_enter_container(&amaclMap, &amss);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
+                int i = 0;
+                amacl->amss = (OicUuid_t *)OICCalloc(amacl->amssLen, sizeof(*amacl->amss));
+                VERIFY_NON_NULL(TAG, amacl->amss, ERROR);
+                while (cbor_value_is_valid(&amss))
+                {
+                    uint8_t *amssId = NULL;
+                    cborFindResult = cbor_value_dup_byte_string(&amss, &amssId, &len, NULL);
+                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
+                    cborFindResult = cbor_value_advance(&amss);
+                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
+                    memcpy(amacl->amss[i].id, amssId, len);
+                    OICFree(amssId);
+                }
+            }
 
             // Owners -- Mandatory
-            VERIFY_SUCCESS( TAG, OC_STACK_OK == AddUuidArray(jsonAmacl, OIC_JSON_OWNERS_NAME,
-                               &(amacl->ownersLen), &(amacl->owners)), ERROR);
+            if (0 == strcmp(OIC_JSON_OWNERS_NAME, name))
+            {
+                CborValue owners = { .parser = NULL };
+                cborFindResult = cbor_value_get_array_length(&amaclMap, &amacl->ownersLen);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
+                cborFindResult = cbor_value_enter_container(&amaclMap, &owners);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
+                int i = 0;
+                amacl->owners = (OicUuid_t *)OICCalloc(amacl->ownersLen, sizeof(*amacl->owners));
+                VERIFY_NON_NULL(TAG, amacl->owners, ERROR);
+                while (cbor_value_is_valid(&owners))
+                {
+                    uint8_t *owner = NULL;
+                    cborFindResult = cbor_value_dup_byte_string(&owners, &owner, &len, NULL);
+                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
+                    cborFindResult = cbor_value_advance(&owners);
+                    VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
+                    memcpy(amacl->owners[i].id, owner, len);
+                    OICFree(owner);
+                }
+            }
+            if (CborMapType != type && cbor_value_is_valid(&amaclMap))
+            {
+                cborFindResult = cbor_value_advance(&amaclMap);
+                VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
+            }
+            OICFree(name);
+        }
 
-            prevAmacl = amacl;
-        } while( ++idx < numAmacl);
+        amacl->next = NULL;
+        if (NULL == headAmacl)
+        {
+            headAmacl = amacl;
+        }
+        else
+        {
+            OicSecAmacl_t *temp = headAmacl;
+            while (temp->next)
+            {
+                temp = temp->next;
+            }
+            temp->next = amacl;
+        }
+        if (cbor_value_is_valid(&amaclArray))
+        {
+            cborFindResult = cbor_value_advance(&amaclArray);
+            VERIFY_CBOR_SUCCESS(TAG, cborFindResult, ERROR);
+        }
     }
-
+    *secAmacl = headAmacl;
     ret = OC_STACK_OK;
-
 exit:
-    cJSON_Delete(jsonRoot);
-    if (OC_STACK_OK != ret)
+    if (CborNoError != cborFindResult)
     {
         DeleteAmaclList(headAmacl);
         headAmacl = NULL;
+        ret = OC_STACK_ERROR;
     }
-    return headAmacl;
+    return ret;
 }
 
 static OCEntityHandlerResult HandleAmaclGetRequest (const OCEntityHandlerRequest * ehRequest)
 {
     // Convert Amacl data into JSON for transmission
-    char* jsonStr = BinToAmaclJSON(gAmacl);
+    size_t size = 0;
+    uint8_t *cborPayload = NULL;
+    OCStackResult res = AmaclToCBORPayload(gAmacl, &cborPayload, &size);
 
-    OCEntityHandlerResult ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
+    OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
 
     // Send response payload to request originator
-    SendSRMResponse(ehRequest, ehRet, jsonStr);
+    SendSRMCBORResponse(ehRequest, ehRet, cborPayload);
 
-    OICFree(jsonStr);
+    OICFree(cborPayload);
 
     OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
     return ehRet;
@@ -265,34 +395,34 @@ static OCEntityHandlerResult HandleAmaclPostRequest (const OCEntityHandlerReques
 {
     OCEntityHandlerResult ehRet = OC_EH_ERROR;
 
-    // Convert JSON Amacl data into binary. This will also validate the Amacl data received.
-    OicSecAmacl_t* newAmacl = JSONToAmaclBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
-
-    if (newAmacl)
+    // Convert CBOR Amacl data into binary. This will also validate the Amacl data received.
+    uint8_t *payload = ((OCSecurityPayload *) ehRequest->payload)->securityData1;;
+    if (payload)
     {
-        // Append the new Amacl to existing Amacl
-        LL_APPEND(gAmacl, newAmacl);
-
-        // Convert Amacl data into JSON for update to persistent storage
-        char *jsonStr = BinToAmaclJSON(gAmacl);
-        if (jsonStr)
+        OicSecAmacl_t *newAmacl = NULL;
+        OCStackResult res = CBORPayloadToAmacl(payload, CBOR_SIZE, &newAmacl);
+        if (newAmacl && OC_STACK_OK == res)
         {
-            cJSON *jsonAmacl = cJSON_Parse(jsonStr);
-            OICFree(jsonStr);
-
-            if ((jsonAmacl) &&
-                (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_AMACL_NAME, jsonAmacl)))
+            // Append the new Amacl to existing Amacl
+            LL_APPEND(gAmacl, newAmacl);
+            size_t size = 0;
+            // Convert Amacl data into JSON for update to persistent storage.
+            uint8_t *cborPayload = NULL;
+            res = AmaclToCBORPayload(gAmacl, &cborPayload, &size);
+            if (cborPayload && (OC_STACK_OK == res) &&
+                (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_AMACL_NAME, cborPayload, size)))
             {
                 ehRet = OC_EH_RESOURCE_CREATED;
             }
-            cJSON_Delete(jsonAmacl);
+            OICFree(cborPayload);
         }
+        OICFree(payload);
     }
 
     // Send payload to request originator
-    SendSRMResponse(ehRequest, ehRet, NULL);
+    SendSRMCBORResponse(ehRequest, ehRet, NULL);
 
-    OIC_LOG_V (DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
+    OIC_LOG_V(DEBUG, TAG, "%s RetVal %d", __func__ , ehRet);
     return ehRet;
 }
 
@@ -339,15 +469,13 @@ OCEntityHandlerResult AmaclEntityHandler (OCEntityHandlerFlag flag,
  */
 OCStackResult CreateAmaclResource()
 {
-    OCStackResult ret;
-
-    ret = OCCreateResource(&gAmaclHandle,
-                           OIC_RSRC_TYPE_SEC_AMACL,
-                           OIC_MI_DEF,
-                           OIC_RSRC_AMACL_URI,
-                           AmaclEntityHandler,
-                           NULL,
-                           OC_OBSERVABLE);
+    OCStackResult ret = OCCreateResource(&gAmaclHandle,
+                                         OIC_RSRC_TYPE_SEC_AMACL,
+                                         OIC_MI_DEF,
+                                         OIC_RSRC_AMACL_URI,
+                                         AmaclEntityHandler,
+                                         NULL,
+                                         OC_OBSERVABLE);
 
     if (OC_STACK_OK != ret)
     {
@@ -366,14 +494,20 @@ OCStackResult InitAmaclResource()
 {
     OCStackResult ret = OC_STACK_ERROR;
 
-    // Read Amacl resource from PS
-    char* jsonSVRDatabase = GetSVRDatabase();
+    uint8_t *data = NULL;
+    size_t size = 0;
+    ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_AMACL_NAME, &data, &size);
 
-    if (jsonSVRDatabase)
+    // If database read failed
+    if (OC_STACK_OK != ret)
+    {
+        OIC_LOG(DEBUG, TAG, "ReadSVDataFromPS failed");
+    }
+    if (data)
     {
-        // Convert JSON Amacl into binary format
-        gAmacl = JSONToAmaclBin(jsonSVRDatabase);
-        OICFree(jsonSVRDatabase);
+        // Read AMACL resource from PS
+        ret = CBORPayloadToAmacl(data, size, &gAmacl);
+        OICFree(data);
     }
 
     // Instantiate 'oic/sec/amacl' resource
@@ -412,7 +546,7 @@ OCStackResult AmaclGetAmsDeviceId(const char *resource, OicUuid_t *amsDeviceId)
     {
         for(size_t i = 0; i < amacl->resourcesLen; i++)
         {
-            if (strncmp((amacl->resources[i]), resource, strlen(amacl->resources[i])) == 0)
+            if (0 == strncmp((amacl->resources[i]), resource, strlen(amacl->resources[i])))
             {
                 //Returning the ID of the first AMS service for the resource
                 memcpy(amsDeviceId, &amacl->amss[0], sizeof(*amsDeviceId));
index 55a767a..884ffe5 100644 (file)
@@ -70,6 +70,7 @@ if not env.get('RELEASE'):
 # Source files and Targets
 ######################################################################
 unittest = srmtest_env.Program('unittest', ['aclresourcetest.cpp',
+                                            'amaclresourcetest.cpp',
                                             'pstatresource.cpp',
                                             'doxmresource.cpp',
                                             'policyengine.cpp',
diff --git a/resource/csdk/security/unittest/amaclresourcetest.cpp b/resource/csdk/security/unittest/amaclresourcetest.cpp
new file mode 100644 (file)
index 0000000..e819f38
--- /dev/null
@@ -0,0 +1,204 @@
+//******************************************************************
+//
+// Copyright 2015 Samsung Electronics All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "gtest/gtest.h"
+#include "cainterface.h"
+#include "ocstack.h"
+#include "ocpayload.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "payload_logging.h"
+#include "psinterface.h"
+#include "secureresourcemanager.h"
+#include "securevirtualresourcetypes.h"
+#include "srmresourcestrings.h"
+#include "srmutility.h"
+#include "amaclresource.h"
+#include "security_internals.h"
+
+using namespace std;
+
+#define TAG  "SRM-AMACL-UT"
+
+TEST(AMACLResourceTest, CBORAMACLConversion)
+{
+    OicSecAmacl_t *secAmacl = (OicSecAmacl_t *) OICCalloc(1, sizeof(*secAmacl));
+    ASSERT_TRUE(NULL != secAmacl);
+    uint8_t amss[] = {0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
+        0x35, 0x35, 0x35, 0x35, 0x35, 0x35};
+    uint8_t amss1[] = {0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+        0x36, 0x36, 0x36, 0x36, 0x36, 0x36};
+    secAmacl->amssLen = 2;
+    secAmacl->amss = (OicUuid_t *)OICCalloc(secAmacl->amssLen, sizeof(*secAmacl->amss));
+    if (!secAmacl->amss)
+    {
+        OICFree(secAmacl);
+    }
+    ASSERT_TRUE(NULL != secAmacl->amss);
+    memcpy(secAmacl->amss[0].id, amss, sizeof(amss));
+    memcpy(secAmacl->amss[1].id, amss1, sizeof(amss1));
+
+    const char *rsrc[] = { "/a/led", "/a/fan"};
+    secAmacl->resourcesLen = 2;
+    secAmacl->resources = (char **)OICCalloc(secAmacl->resourcesLen,
+                          sizeof(*secAmacl->resources));
+    if (!secAmacl->resources)
+    {
+        OICFree(secAmacl->amss);
+        OICFree(secAmacl);
+    }
+    ASSERT_TRUE(NULL != secAmacl->resources);
+    for (size_t i = 0 ; i < secAmacl->resourcesLen; i++)
+    {
+        secAmacl->resources[i] = OICStrdup(rsrc[i]);
+        ASSERT_TRUE(NULL != secAmacl->resources[i]);
+    }
+    secAmacl->ownersLen = 1;
+    uint8_t ownrs[] = {0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
+        0x32, 0x32, 0x32, 0x32, 0x32, 0x32};
+    secAmacl->owners = (OicUuid_t *)OICCalloc(1, sizeof(*secAmacl->owners));
+    if (!secAmacl->owners)
+    {
+        OICFree(secAmacl->resources);
+        OICFree(secAmacl->amss);
+        OICFree(secAmacl);
+    }
+    ASSERT_TRUE(NULL != secAmacl->owners);
+    memcpy(secAmacl->owners[0].id, ownrs, sizeof(ownrs));
+
+    OicSecAmacl_t *secAmacl1 = (OicSecAmacl_t *) OICCalloc(1, sizeof(*secAmacl1));
+    if (!secAmacl1)
+    {
+        OICFree(secAmacl->owners);
+        OICFree(secAmacl->resources);
+        OICFree(secAmacl->amss);
+        OICFree(secAmacl);
+    }
+    ASSERT_TRUE(NULL != secAmacl1);
+    secAmacl1->amssLen = 2;
+    secAmacl1->amss = (OicUuid_t *)OICCalloc(2, sizeof(*secAmacl1->amss));
+    if (!secAmacl1->amss)
+    {
+        OICFree(secAmacl->owners);
+        OICFree(secAmacl->resources);
+        OICFree(secAmacl->amss);
+        OICFree(secAmacl);
+        OICFree(secAmacl1);
+    }
+    ASSERT_TRUE(NULL != secAmacl1->amss);
+    memcpy(secAmacl1->amss[0].id, amss, sizeof(amss));
+    memcpy(secAmacl1->amss[1].id, amss1, sizeof(amss1));
+
+    const char *rsrc1[] = { "/b/led", "/b/fan"};
+    secAmacl1->resourcesLen = 2;
+    secAmacl1->resources = (char **)OICCalloc(secAmacl1->resourcesLen,
+                            sizeof(*secAmacl1->resources));
+    if (!secAmacl1->resources)
+    {
+        OICFree(secAmacl->owners);
+        OICFree(secAmacl->resources);
+        OICFree(secAmacl->amss);
+        OICFree(secAmacl);
+        OICFree(secAmacl1->amss);
+        OICFree(secAmacl1);
+    }
+    ASSERT_TRUE(NULL != secAmacl1->resources);
+    for (size_t i = 0 ; i < secAmacl1->resourcesLen; i++)
+    {
+        secAmacl1->resources[i] = OICStrdup(rsrc1[i]);
+        ASSERT_TRUE(NULL != secAmacl1->resources[i]);
+    }
+    secAmacl1->ownersLen = 1;
+    secAmacl1->owners = (OicUuid_t *)OICCalloc(1, sizeof(*secAmacl1->owners));
+    if (!secAmacl1->owners)
+    {
+        OICFree(secAmacl->owners);
+        OICFree(secAmacl->resources);
+        OICFree(secAmacl->amss);
+        OICFree(secAmacl);
+        OICFree(secAmacl1->resources);
+        OICFree(secAmacl1->amss);
+        OICFree(secAmacl1);
+    }
+    ASSERT_TRUE(NULL != secAmacl1->owners);
+    memcpy(secAmacl1->owners[0].id, ownrs, sizeof(ownrs));
+    secAmacl1->next = NULL;
+    secAmacl->next = secAmacl1;
+
+    size_t size = 0;
+    uint8_t *psStorage = NULL;
+    EXPECT_EQ(OC_STACK_OK, AmaclToCBORPayload(secAmacl, &psStorage, &size));
+    if (!psStorage)
+    {
+        OICFree(secAmacl->owners);
+        OICFree(secAmacl->resources);
+        OICFree(secAmacl->amss);
+        OICFree(secAmacl);
+        OICFree(secAmacl1->owners);
+        OICFree(secAmacl1->resources);
+        OICFree(secAmacl1->amss);
+        OICFree(secAmacl1);
+    }
+    ASSERT_TRUE(NULL != psStorage);
+
+    OicSecAmacl_t *amacl = NULL;
+    EXPECT_EQ(OC_STACK_OK, CBORPayloadToAmacl(psStorage, size, &amacl));
+    if (!amacl)
+    {
+        OICFree(secAmacl->owners);
+        OICFree(secAmacl->resources);
+        OICFree(secAmacl->amss);
+        OICFree(secAmacl);
+        OICFree(secAmacl1->owners);
+        OICFree(secAmacl1->resources);
+        OICFree(secAmacl1->amss);
+        OICFree(secAmacl1);
+        OICFree(psStorage);
+    }
+    ASSERT_TRUE(NULL != amacl);
+
+    EXPECT_EQ(secAmacl->amssLen, amacl->amssLen);
+    EXPECT_EQ(sizeof(secAmacl->amss[0].id), sizeof(amacl->amss[0].id));
+    EXPECT_EQ(sizeof(secAmacl->amss[1].id), sizeof(amacl->amss[1].id));
+    EXPECT_STREQ(secAmacl->resources[0], amacl->resources[0]);
+    EXPECT_STREQ(secAmacl->resources[1], amacl->resources[1]);
+    EXPECT_EQ(secAmacl->resourcesLen, amacl->resourcesLen);
+    EXPECT_EQ(secAmacl->ownersLen, amacl->ownersLen);
+    EXPECT_EQ(*secAmacl->owners[0].id, *amacl->owners[0].id);
+
+    EXPECT_EQ(secAmacl->next->amssLen, amacl->next->amssLen);
+    EXPECT_EQ(sizeof(secAmacl->next->amss[0].id), sizeof(amacl->next->amss[0].id));
+    EXPECT_STREQ(secAmacl->next->resources[0], amacl->next->resources[0]);
+    EXPECT_STREQ(secAmacl->next->resources[1], amacl->next->resources[1]);
+    EXPECT_EQ(secAmacl->next->resourcesLen, amacl->next->resourcesLen);
+    EXPECT_EQ(secAmacl->next->ownersLen, amacl->next->ownersLen);
+    EXPECT_EQ(*secAmacl->next->owners[0].id, *amacl->next->owners[0].id);
+
+    OICFree(secAmacl->owners);
+    OICFree(secAmacl->resources);
+    OICFree(secAmacl->amss);
+    OICFree(secAmacl);
+    OICFree(secAmacl1->owners);
+    OICFree(secAmacl1->resources);
+    OICFree(secAmacl1->amss);
+    OICFree(secAmacl1);
+    OICFree(psStorage);
+    OICFree(amacl);
+}