Add PKIX resources
authorDmitrii Zhuravlev <d.zhuravlev@samsung.com>
Tue, 15 Sep 2015 20:00:38 +0000 (23:00 +0300)
committerSachin Agrawal <sachin.agrawal@intel.com>
Wed, 16 Sep 2015 00:17:59 +0000 (00:17 +0000)
It allows to manage certificate, crl through the CoAP resources

Change-Id: Iee019fb872a6cce07e35c3b01cb25800e480fa25
Signed-off-by: Dmytro Zhuravlev <d.zhuravlev@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/2450
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: sangsu choi <sangsu.choi@samsung.com>
Reviewed-by: Sachin Agrawal <sachin.agrawal@intel.com>
resource/csdk/security/include/internal/credresource.h
resource/csdk/security/include/internal/crlresource.h [new file with mode: 0644]
resource/csdk/security/include/internal/srmresourcestrings.h
resource/csdk/security/include/securevirtualresourcetypes.h
resource/csdk/security/src/credresource.c
resource/csdk/security/src/crlresource.c [new file with mode: 0644]
resource/csdk/security/src/doxmresource.c
resource/csdk/security/src/psinterface.c
resource/csdk/security/src/resourcemanager.c
resource/csdk/security/src/srmresourcestrings.c

index 2170521..7ee74a1 100644 (file)
@@ -23,6 +23,8 @@
 
 #include "ocsecurityconfig.h"
 #include "cainterface.h"
+#include "securevirtualresourcetypes.h"
+#include "octypes.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -143,6 +145,18 @@ OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t cre
 
 #endif /* __WITH_DTLS__ */
 
+#ifdef __WITH_X509__
+/**
+ * This function is used toretrieve certificate credentials from RI security layer.
+ *
+ * @param credInfo
+ *     binary structure containing certificate credentials
+ *
+ * @retval OC_STACK_OK  on scuccess
+ */
+OCStackResult GetDtlsCertCredentials(CADtlsCertCreds_t *credInfo);
+#endif /*__WITH_X509__*/
+
 /**
  * Function to deallocate allocated memory to OicSecCred_t
  *
diff --git a/resource/csdk/security/include/internal/crlresource.h b/resource/csdk/security/include/internal/crlresource.h
new file mode 100644 (file)
index 0000000..2e69523
--- /dev/null
@@ -0,0 +1,82 @@
+//******************************************************************
+//
+// 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.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef IOTVT_SRM_CRLR_H
+#define IOTVT_SRM_CRLR_H
+
+#include "octypes.h"
+#include "securevirtualresourcetypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This function stores CRL in SRM
+ * @param crl - CRL
+ *
+ * @returns OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult UpdateCRLResource(const OicSecCrl_t *crl);
+
+/**
+ * This function get encoded with base64 CRL from SRM
+ *
+ * @returns encoded CRL with base64 format. NULL if error occured (e.g. CRL did not set)
+ * @note Caller responsible for resulting string memory (use OICFree to remove it)
+ */
+char* GetBase64CRL();
+
+/**
+ * This function get CRL from SRM
+ *
+ * @param crl [out] - pointer to buffer that contains crl. Shoul be not NULL. Buffer
+ * will be allocated by the function and content of *crl will be ignored.
+ * @param outlen [out] - pointer to length of the CRL buffer. Shoul be not NULL.
+ *
+ * @returns OC_STACK_OK if success and errorcode otherwise.
+ * @note Caller responsible for crl buffer memory (use OICFree to free it)
+ */
+OicSecCrl_t * JSONToCrlBin(const char * jsonStr);
+
+/**
+ * Initialize CLR resource by loading data from persistent storage.
+ *
+ * @returns OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitCRLResource();
+
+/**
+ * Perform cleanup for CRL resources.
+ */
+void DeInitCRLResource();
+
+OicSecCrl_t *GetCRLResource();
+
+OCEntityHandlerResult CRLEntityHandler(OCEntityHandlerFlag flag,
+                                        OCEntityHandlerRequest * ehRequest,
+                                        void* callbackParameter);
+#ifdef __cplusplus
+}
+#endif
+
+#endif //IOTVT_SRM_CRLR_H
+
+
index 9974717..fe7ba93 100644 (file)
@@ -52,6 +52,11 @@ extern const char * OIC_RSRC_TYPE_SEC_CRED;
 extern const char * OIC_RSRC_CRED_URI;
 extern const char * OIC_JSON_CRED_NAME;
 
+//CRL
+extern const char * OIC_RSRC_TYPE_SEC_CRL;
+extern const char * OIC_RSRC_CRL_URI;
+extern const char * OIC_JSON_CRL_NAME;
+
 //SVC
 extern const char * OIC_RSRC_TYPE_SEC_SVC;
 extern const char * OIC_RSRC_SVC_URI;
index 2f69026..a9edade 100644 (file)
@@ -43,6 +43,9 @@
 
 #include <stdint.h> // for uint8_t typedef
 #include <stdbool.h>
+#ifdef __WITH_X509__
+#include "byte_array.h"
+#endif /* __WITH_X509__ */
 
 #ifdef __cplusplus
 extern "C" {
@@ -252,6 +255,10 @@ typedef char *OicUrn_t; //TODO is URN type defined elsewhere?
 typedef struct OicUuid OicUuid_t; //TODO is UUID type defined elsewhere?
 
 
+#ifdef __WITH_X509__
+typedef struct OicSecCrl OicSecCrl_t;
+#endif /* __WITH_X509__ */
+
 /**
  * @brief   /oic/uuid (Universal Unique Identifier) data type.
  */
@@ -428,6 +435,15 @@ struct OicSecSvc
     OicSecSvc_t             *next;
 };
 
+#ifdef __WITH_X509__
+struct OicSecCrl
+{
+    uint16_t CrlId;
+    ByteArray ThisUpdate;   
+    ByteArray CrlData;      
+};
+#endif /* __WITH_X509__ */
+
 #ifdef __cplusplus
 }
 #endif
index 901e5d5..748126a 100644 (file)
@@ -158,17 +158,37 @@ char * BinToCredJSON(const OicSecCred_t * cred)
             //CredType -- Mandatory
             cJSON_AddNumberToObject(jsonCred, OIC_JSON_CREDTYPE_NAME,(int)cred->credType);
 
-#if 0
+#ifdef __WITH_X509__
             //PublicData -- Not Mandatory
             if(cred->publicData.data)
             {
+                if (SIGNED_ASYMMETRIC_KEY == cred->credType)
+                {
+                    cJSON_AddItemToObject(jsonCred, OIC_JSON_PUBLICDATA_NAME,
+                                          cJSON_Parse(cred->publicData.data));
+                }
+                else
+                {
                 cJSON_AddStringToObject(jsonCred, OIC_JSON_PUBLICDATA_NAME, cred->publicData.data);
+                }
             }
-#endif
+#endif /*__WITH_X509__*/
             //PrivateData -- Not Mandatory
             if(cred->privateData.data)
             {
+#ifdef __WITH_X509__
+                if (SIGNED_ASYMMETRIC_KEY == cred->credType)
+                {
+                    cJSON_AddItemToObject(jsonCred, OIC_JSON_PRIVATEDATA_NAME,
+                                          cJSON_Parse(cred->privateData.data));
+                }
+                else
+                {
+                    cJSON_AddStringToObject(jsonCred, OIC_JSON_PRIVATEDATA_NAME, cred->privateData.data);
+                }
+#else
                 cJSON_AddStringToObject(jsonCred, OIC_JSON_PRIVATEDATA_NAME, cred->privateData.data);
+#endif
             }
 
             //Period -- Not Mandatory
@@ -286,12 +306,56 @@ OicSecCred_t * JSONToCredBin(const char * jsonStr)
                 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
                 VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
             }
-            if(jsonObj && cJSON_String == jsonObj->type)
+#ifdef __WITH_X509__
+            else if (cred->credType & SIGNED_ASYMMETRIC_KEY)
             {
-                jsonObjLen = strlen(jsonObj->valuestring) + 1;
-                cred->privateData.data = (char *)OICMalloc(jsonObjLen);
-                VERIFY_NON_NULL(TAG, (cred->privateData.data), ERROR);
-                strncpy((char *)cred->privateData.data, (char *)jsonObj->valuestring, jsonObjLen);
+                VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+                VERIFY_SUCCESS(TAG, cJSON_Object == jsonObj->type, ERROR);
+            }
+#endif //  __WITH_X509__
+            if (NULL != jsonObj)
+            {
+                if (cJSON_String == jsonObj->type)
+                {
+                    jsonObjLen = strlen(jsonObj->valuestring) + 1;
+                    cred->privateData.data = (char *)OICMalloc(jsonObjLen);
+                    VERIFY_NON_NULL(TAG, (cred->privateData.data), ERROR);
+                    strncpy((char *)cred->privateData.data, (char *)jsonObj->valuestring, jsonObjLen);
+                }
+#ifdef __WITH_X509__
+                else if (SIGNED_ASYMMETRIC_KEY == cred->credType && cJSON_Object == jsonObj->type)
+                {
+                    cred->privateData.data = cJSON_PrintUnformatted(jsonObj);
+                    VERIFY_NON_NULL(TAG, (cred->privateData.data), ERROR);
+                }
+#endif // __WITH_X509__
+            }
+
+            //PublicData is mandatory only for SIGNED_ASYMMETRIC_KEY credentials type.
+            jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PUBLICDATA_NAME);
+#ifdef __WITH_X509__
+            if (cred->credType & SIGNED_ASYMMETRIC_KEY)
+            {
+                VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+                VERIFY_SUCCESS(TAG, cJSON_Object == jsonObj->type, ERROR);
+            }
+#endif //  __WITH_X509__
+            if (NULL != jsonObj)
+            {
+                if (cJSON_String == jsonObj->type)
+                {
+                    jsonObjLen = strlen(jsonObj->valuestring) + 1;
+                    cred->publicData.data = (char *)OICMalloc(jsonObjLen);
+                    VERIFY_NON_NULL(TAG, (cred->publicData.data), ERROR);
+                    strncpy((char *)cred->publicData.data, (char *)jsonObj->valuestring, jsonObjLen);
+                }
+#ifdef __WITH_X509__
+                else if (SIGNED_ASYMMETRIC_KEY == cred->credType && cJSON_Object == jsonObj->type)
+                {
+                    cred->publicData.data = cJSON_PrintUnformatted(jsonObj);
+                    VERIFY_NON_NULL(TAG, (cred->publicData.data), ERROR);
+                }
+#endif //  __WITH_X509__
             }
 
             //Period -- Not Mandatory
@@ -377,14 +441,14 @@ OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t cr
             SYMMETRIC_GROUP_KEY | ASYMMETRIC_KEY | SIGNED_ASYMMETRIC_KEY | PIN_PASSWORD), ERROR);
     cred->credType = credType;
 
-#if 0
+#ifdef __WITH_X509__
     if(publicData)
     {
         cred->publicData.data = (char *)OICMalloc(strlen(publicData)+1);
         VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
         strncpy((char *)cred->publicData.data, publicData, strlen(publicData)+1);
     }
-#endif
+#endif // __WITH_X509__
 
     if(privateData)
     {
@@ -581,7 +645,6 @@ static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * eh
         //list and updating svr database.
         ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
     }
-
     return ret;
 }
 
@@ -627,7 +690,6 @@ exit:
     return ehRet;
 }
 
-
 /*
  * This internal method is the entity handler for Cred resources
  * to handle REST request (PUT/POST/DEL)
@@ -920,3 +982,158 @@ exit:
 }
 
 #endif /* __WITH_DTLS__ */
+#ifdef __WITH_X509__
+#define CERT_LEN_PREFIX (3)
+#define BYTE_SIZE (8) //bits
+#define PUB_KEY_X_COORD ("x")
+#define PUB_KEY_Y_COORD ("y")
+#define CERTIFICATE ("x5c")
+#define PRIVATE_KEY ("d")
+
+
+static void WriteCertPrefix(uint8_t *prefix, uint32_t certLen)
+{
+    for (size_t i = 0; i < CERT_LEN_PREFIX; ++i)
+    {
+        prefix[i] = (certLen >> (BYTE_SIZE * (CERT_LEN_PREFIX - 1 - i))) & 0xFF;
+    }
+}
+
+static uint32_t ParseCertPrefix(uint8_t *prefix)
+{
+    uint32_t res = 0;
+    if(NULL != prefix)
+    {
+        for(int i=0; i < CERT_LEN_PREFIX; ++i)
+        {
+            res |= (((uint32_t) prefix[i]) << ((CERT_LEN_PREFIX - 1 -i) * BYTE_SIZE));
+        }
+    }
+    return res;
+}
+
+static uint32_t appendCert2Chain(uint8_t *appendPoint, char *cert, uint32_t max_len)
+{
+    uint32_t ret = 0;
+    VERIFY_NON_NULL(TAG, appendPoint, ERROR);
+    VERIFY_NON_NULL(TAG, cert, ERROR);
+
+    uint32_t certLen;
+    VERIFY_SUCCESS(TAG, B64_OK == b64Decode(cert, strlen(cert), appendPoint + CERT_LEN_PREFIX,
+                                            max_len - CERT_LEN_PREFIX, &certLen), ERROR);
+    WriteCertPrefix(appendPoint, certLen);
+
+    ret = certLen + CERT_LEN_PREFIX;
+exit:
+    return ret;
+}
+
+static OCStackResult GetCAPublicKeyData(CADtlsCertCreds_t *credInfo){
+    OCStackResult ret = OC_STACK_ERROR;
+    uint8_t *ccPtr = credInfo->certificateChain;
+    for(uint32_t i =0; i < credInfo->chainLen - 1; ++i)
+    {
+        ccPtr += CERT_LEN_PREFIX + ParseCertPrefix(ccPtr);
+    }
+
+    ByteArray cert = {
+        .data = ccPtr + CERT_LEN_PREFIX,
+        .len = ParseCertPrefix(ccPtr)
+         };
+    CertificateX509 certStruct;
+
+    VERIFY_SUCCESS(TAG, PKI_SUCCESS == DecodeCertificate(cert, &certStruct), ERROR);
+
+    INC_BYTE_ARRAY(certStruct.pubKey, 2);
+
+    memcpy(credInfo->rootPublicKeyX, certStruct.pubKey.data, PUBLIC_KEY_SIZE / 2);
+    memcpy(credInfo->rootPublicKeyY, certStruct.pubKey.data + PUBLIC_KEY_SIZE / 2, PUBLIC_KEY_SIZE / 2);
+
+    ret = OC_STACK_OK;
+    exit:
+    return ret;
+}
+
+static OCStackResult GetCertCredPublicData(CADtlsCertCreds_t *credInfo, OicSecCred_t *cred)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    VERIFY_NON_NULL(TAG, credInfo, ERROR);
+    VERIFY_NON_NULL(TAG, cred, ERROR);
+    VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
+    //VERIFY_SUCCESS(TAG, NULL == credInfo->certificateChain.data, ERROR);
+    cJSON *jsonRoot = cJSON_Parse(cred->publicData.data);
+    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+    //Get certificate chain
+    cJSON *jsonObj = cJSON_GetObjectItem(jsonRoot, CERTIFICATE);//TODO define field names constants
+    VERIFY_SUCCESS(TAG, NULL != jsonObj && cJSON_Array == jsonObj->type, ERROR);
+
+    size_t certChainLen = cJSON_GetArraySize(jsonObj);
+    credInfo->chainLen = certChainLen;
+    VERIFY_SUCCESS(TAG, MAX_CHAIN_LEN >= certChainLen, ERROR);
+
+    uint32_t len = 0;
+    for (size_t i = 0; i < certChainLen; ++i)
+    {
+        cJSON *item = cJSON_GetArrayItem(jsonObj, i);
+        VERIFY_SUCCESS(TAG, cJSON_String == item->type, ERROR);
+        uint32_t appendedLen = appendCert2Chain(credInfo->certificateChain + len, item->valuestring,
+                                              MAX_REQUEST_LENGTH - len);
+        VERIFY_SUCCESS(TAG, 0 != appendedLen, ERROR);
+        len += appendedLen;
+    }
+    credInfo->certificateChainLen = len;
+    VERIFY_SUCCESS(TAG, OC_STACK_OK == GetCAPublicKeyData(credInfo), ERROR);
+    ret = OC_STACK_OK;
+exit:
+    cJSON_Delete(jsonRoot);
+    return ret;
+}
+
+static OCStackResult GetCertCredPrivateData(CADtlsCertCreds_t *credInfo, OicSecCred_t *cred)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    VERIFY_NON_NULL(TAG, credInfo, ERROR);
+    VERIFY_NON_NULL(TAG, cred, ERROR);
+    VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
+    cJSON *jsonRoot = cJSON_Parse(cred->privateData.data);
+    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+    cJSON *jsonObj = cJSON_GetObjectItem(jsonRoot, PRIVATE_KEY);//TODO define field names constants
+    VERIFY_SUCCESS(TAG, NULL != jsonObj && cJSON_String == jsonObj->type, ERROR);
+
+    uint32_t read = 0u;
+    VERIFY_SUCCESS(TAG, B64_OK == b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring),
+                                            credInfo->devicePrivateKey, PRIVATE_KEY_SIZE, &read)
+                   && PRIVATE_KEY_SIZE == read, ERROR);
+
+    ret = OC_STACK_OK;
+
+exit:
+    cJSON_Delete(jsonRoot);
+    return ret;
+}
+
+OCStackResult GetDtlsCertCredentials(CADtlsCertCreds_t *credInfo)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    VERIFY_NON_NULL(TAG, credInfo, ERROR);
+    if (NULL == gCred)
+    {
+        VERIFY_SUCCESS(TAG, OC_STACK_OK == InitCredResource(), ERROR);
+    }
+
+    OicSecCred_t *cred = NULL;
+    LL_SEARCH_SCALAR(gCred, cred, credType, SIGNED_ASYMMETRIC_KEY);
+    VERIFY_NON_NULL(TAG, cred, ERROR);
+
+    VERIFY_SUCCESS(TAG, OC_STACK_OK == GetCertCredPrivateData(credInfo, cred), ERROR);
+    VERIFY_SUCCESS(TAG, OC_STACK_OK == GetCertCredPublicData(credInfo, cred), ERROR);
+
+    ret = OC_STACK_OK;
+exit:
+
+    return ret;
+}
+#undef CERT_LEN_PREFIX
+#endif /* __WITH_X509__ */
diff --git a/resource/csdk/security/src/crlresource.c b/resource/csdk/security/src/crlresource.c
new file mode 100644 (file)
index 0000000..36d005f
--- /dev/null
@@ -0,0 +1,509 @@
+//******************************************************************
+//
+// 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 <stdlib.h>
+#include <string.h>
+#include "ocstack.h"
+#include "logger.h"
+#include "oic_malloc.h"
+#include "cJSON.h"
+#include "base64.h"
+#include "resourcemanager.h"
+#include "psinterface.h"
+#include "utlist.h"
+#include "srmresourcestrings.h"
+#include "doxmresource.h"
+#include "srmutility.h"
+#ifdef __WITH_X509__
+#include "crlresource.h"
+#include "crl.h"
+#include "ckm_info.h"
+#endif /* __WITH_X509__ */
+
+#define TAG  PCF("SRM-CRL")
+
+#define SEPARATOR                   ":"
+#define SEPARATOR_LEN               (1)
+#define JSON_CRL_NAME               "\"CRL\""
+#define JSON_CRL_NAME_LEN           (5)
+#define OIC_JSON_CRL_NAME           "crl"
+#define OIC_JSON_CRL_ID             "CRLId"
+#define OIC_JSON_CRL_THIS_UPDATE    "ThisUpdate"
+#define OIC_JSON_CRL_DATA           "CRLData"
+#define CRL_DEFAULT_CRL_ID           1
+#define CRL_DEFAULT_THIS_UPDATE     "150101000000Z"
+#define CRL_DEFAULT_CRL_DATA        "-"
+
+static OCResourceHandle     gCrlHandle  = NULL;
+static OicSecCrl_t         *gCrl        = NULL;
+
+
+void DeleteCrlBinData(OicSecCrl_t *crl)
+{
+    if (crl)
+    {
+        //Clean ThisUpdate
+        OICFree(crl->ThisUpdate.data);
+
+        //clean CrlData
+        OICFree(crl->CrlData.data);
+
+        //Clean crl itself
+        OICFree(crl);
+    }
+}
+
+char *BinToCrlJSON(const OicSecCrl_t *crl)
+{
+    if (NULL == crl)
+    {
+        return NULL;
+    }
+
+    char *base64Buff = NULL;
+    uint32_t outLen = 0;
+    uint32_t base64CRLLen = 0;
+    B64Result b64Ret = B64_OK;
+    char *jsonStr = NULL;
+    cJSON *jsonRoot = cJSON_CreateObject();
+    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+    cJSON *jsonCrl = cJSON_CreateObject();
+    VERIFY_NON_NULL(TAG, jsonCrl, ERROR);
+
+    cJSON_AddItemToObject(jsonRoot, OIC_JSON_CRL_NAME, jsonCrl);
+
+    //CRLId -- Mandatory
+    cJSON_AddNumberToObject(jsonCrl, OIC_JSON_CRL_ID, (int)crl->CrlId);
+
+    //ThisUpdate -- Mandatory
+    outLen = 0;
+    base64CRLLen = B64ENCODE_OUT_SAFESIZE(crl->ThisUpdate.len);
+    base64Buff = OICMalloc(base64CRLLen);
+    b64Ret = b64Encode(crl->ThisUpdate.data, crl->ThisUpdate.len, base64Buff,
+             base64CRLLen, &outLen);
+    VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+    cJSON_AddStringToObject(jsonCrl, OIC_JSON_CRL_THIS_UPDATE, base64Buff);
+    OICFree(base64Buff);
+
+    //CRLData -- Mandatory
+    outLen = 0;
+    base64CRLLen = B64ENCODE_OUT_SAFESIZE(crl->CrlData.len);
+    base64Buff = OICMalloc(base64CRLLen);
+    b64Ret = b64Encode(crl->CrlData.data, crl->CrlData.len, base64Buff,
+             base64CRLLen, &outLen);
+    VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+    cJSON_AddStringToObject(jsonCrl, OIC_JSON_CRL_DATA, base64Buff);
+
+    jsonStr = cJSON_PrintUnformatted(jsonRoot);
+
+exit:
+    OICFree(base64Buff);
+    if (jsonRoot)
+    {
+        cJSON_Delete(jsonRoot);
+    }
+    return jsonStr;
+}
+
+OicSecCrl_t *JSONToCrlBin(const char * jsonStr)
+{
+    if (NULL == jsonStr)
+    {
+        return NULL;
+    }
+
+    OCStackResult ret = OC_STACK_ERROR;
+    OicSecCrl_t *crl =  NULL;
+    cJSON *jsonCrl = NULL;
+    cJSON *jsonObj = NULL;
+
+    unsigned char *base64Buff = NULL;
+    uint32_t base64CRLLen = 0;
+    uint32_t outLen = 0;
+    B64Result b64Ret = B64_OK;
+
+    cJSON *jsonRoot = cJSON_Parse(jsonStr);
+    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+    jsonCrl = cJSON_GetObjectItem(jsonRoot, OIC_JSON_CRL_NAME);
+    VERIFY_NON_NULL(TAG, jsonCrl, ERROR);
+    crl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
+    VERIFY_NON_NULL(TAG, crl, ERROR);
+
+    //CRLId -- Mandatory
+    jsonObj = cJSON_GetObjectItem(jsonCrl, OIC_JSON_CRL_ID);
+    if(jsonObj)
+    {
+        VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
+        crl->CrlId = (uint16_t)jsonObj->valueint;
+    }
+    else // PUT/POST JSON may not have CRLId so set it to the gCRList->CRLId
+    {
+        VERIFY_NON_NULL(TAG, gCrl, ERROR);
+        crl->CrlId = gCrl->CrlId;
+    }
+
+    //ThisUpdate -- Mandatory
+    jsonObj = cJSON_GetObjectItem(jsonCrl, OIC_JSON_CRL_THIS_UPDATE);
+    if(jsonObj)
+    {
+        VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
+        if(cJSON_String == jsonObj->type)
+        {
+            //Check for empty string, in case ThisUpdate field has not been set yet
+            if (jsonObj->valuestring[0])
+            {
+                base64CRLLen = B64ENCODE_OUT_SAFESIZE(strlen(jsonObj->valuestring));
+                base64Buff = OICMalloc(base64CRLLen);
+                b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
+                        base64CRLLen, &outLen);
+                VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= base64CRLLen),
+                                ERROR);
+                crl->ThisUpdate.data = OICMalloc(outLen + 1);
+                memcpy(crl->ThisUpdate.data, base64Buff, outLen);
+                crl->ThisUpdate.len = outLen;
+                OICFree(base64Buff);
+                base64Buff = NULL;
+            }
+        }
+    }
+    else // PUT/POST JSON will not have ThisUpdate so set it to the gCRList->ThisUpdate
+    {
+        VERIFY_NON_NULL(TAG, gCrl, ERROR);
+        outLen = gCrl->ThisUpdate.len;
+        crl->ThisUpdate.data = OICMalloc(outLen + 1);
+        memcpy(crl->ThisUpdate.data, gCrl->ThisUpdate.data, outLen);
+        crl->ThisUpdate.len = outLen;
+    }
+
+    //CRLData -- Mandatory
+    jsonObj = cJSON_GetObjectItem(jsonCrl, OIC_JSON_CRL_DATA);
+    if(jsonObj)
+    {
+        VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
+        if(cJSON_String == jsonObj->type)
+        {
+            //Check for empty string, in case CRLData field has not been set yet
+            if (jsonObj->valuestring[0])
+            {
+                outLen = 0;
+                base64CRLLen = B64ENCODE_OUT_SAFESIZE(strlen(jsonObj->valuestring));
+                base64Buff = OICMalloc(base64CRLLen);
+                b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
+                        base64CRLLen, &outLen);
+                VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= base64CRLLen),
+                                ERROR);
+                crl->CrlData.data = OICMalloc(outLen + 1);
+                memcpy(crl->CrlData.data, base64Buff, outLen);
+                crl->CrlData.len = outLen;
+                OICFree(base64Buff);
+                base64Buff = NULL;
+            }
+        }
+    }
+    else // PUT/POST JSON will not have CRLData so set it to the gCRList->CRLData
+    {
+        VERIFY_NON_NULL(TAG, gCrl, ERROR);
+        outLen = gCrl->CrlData.len;
+        crl->CrlData.data = OICMalloc(outLen + 1);
+        memcpy(crl->CrlData.data, gCrl->CrlData.data, outLen);
+        crl->CrlData.len = outLen;
+    }
+
+    ret = OC_STACK_OK;
+exit:
+    cJSON_Delete(jsonRoot);
+    OICFree(base64Buff);
+    base64Buff = NULL;
+    if (OC_STACK_OK != ret)
+    {
+        DeleteCrlBinData(crl);
+        crl = NULL;
+    }
+    return crl;
+}
+
+OCStackResult UpdateCRLResource(const OicSecCrl_t *crl)
+{
+    char *jsonStr = NULL;
+    OCStackResult res = OC_STACK_ERROR;
+
+    jsonStr = BinToCrlJSON((OicSecCrl_t *) crl);
+    if (!jsonStr)
+    {
+        return OC_STACK_ERROR;
+    }
+
+    cJSON *jsonObj = cJSON_Parse(jsonStr);
+    OICFree(jsonStr);
+
+    if (jsonObj == NULL)
+    {
+        return OC_STACK_ERROR;
+    }
+
+    res = UpdateSVRDatabase(OIC_JSON_CRL_NAME, jsonObj);
+    cJSON_Delete(jsonObj);
+
+    return res;
+}
+
+static OCEntityHandlerResult HandleCRLPostRequest(const OCEntityHandlerRequest *ehRequest)
+{
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+    char *jsonCRL = (char *)(((OCSecurityPayload *)ehRequest->payload)->securityData);
+
+    if (jsonCRL)
+    {
+        OC_LOG(INFO, TAG, PCF("UpdateSVRDB..."));
+        OC_LOG_V(INFO, TAG, PCF("crl: \"%s\""), jsonCRL);
+
+        cJSON *jsonObj = cJSON_Parse(jsonCRL);
+        OicSecCrl_t *crl = NULL;
+        crl = JSONToCrlBin(jsonCRL);
+        if (!crl)
+        {
+            OC_LOG(ERROR, TAG, PCF("Error JSONToCrlBin"));
+        }
+
+        gCrl->CrlId = crl->CrlId;
+
+        OICFree(gCrl->ThisUpdate.data);
+        gCrl->ThisUpdate.data = NULL;
+        gCrl->ThisUpdate.data = OICMalloc(crl->ThisUpdate.len);
+        memcpy(gCrl->ThisUpdate.data, crl->ThisUpdate.data, crl->ThisUpdate.len);
+        gCrl->ThisUpdate.len = crl->ThisUpdate.len;
+
+        OICFree(gCrl->CrlData.data);
+        gCrl->CrlData.data = NULL;
+        gCrl->CrlData.data = OICMalloc(crl->CrlData.len);
+        memcpy(gCrl->CrlData.data, crl->CrlData.data, crl->CrlData.len);
+        gCrl->CrlData.len = crl->CrlData.len;
+
+        if (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRL_NAME, jsonObj))
+        {
+            OC_LOG(INFO, TAG, PCF("UpdateSVRDB == OK"));
+            ehRet = OC_EH_RESOURCE_CREATED;
+        }
+
+        DeleteCrlBinData(crl);
+        cJSON_Delete(jsonObj);
+
+    }
+
+    // Send payload to request originator
+    SendSRMResponse(ehRequest, ehRet, NULL);
+
+    OC_LOG_V(INFO, TAG, PCF("%s RetVal %d"), __func__, ehRet);
+    return ehRet;
+}
+
+
+/*
+ * This internal method is the entity handler for CRL resource and
+ * will handle REST request (GET/PUT/POST/DEL) for them.
+ */
+OCEntityHandlerResult CRLEntityHandler(OCEntityHandlerFlag flag,
+                                       OCEntityHandlerRequest *ehRequest,
+                                       void *callbackParameter)
+{
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+    (void)callbackParameter;
+
+    if (!ehRequest)
+    {
+        return ehRet;
+    }
+
+    OC_LOG(INFO, TAG, PCF("Handle CRL resource"));
+
+    if (flag & OC_REQUEST_FLAG)
+    {
+        // TODO :  Handle PUT and DEL methods
+        OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+        switch (ehRequest->method)
+        {
+            case OC_REST_GET:
+                OC_LOG (INFO, TAG, PCF("Not implemented request method."));
+                //ehRet = HandleCRLGetRequest(ehRequest);
+                break;
+
+            case OC_REST_POST:
+                ehRet = HandleCRLPostRequest(ehRequest);
+                break;
+
+            default:
+                ehRet = OC_EH_ERROR;
+                SendSRMResponse(ehRequest, ehRet, NULL);
+        }
+    }
+
+    return ehRet;
+}
+
+/*
+ * This internal method is used to create '/oic/sec/crl' resource.
+ */
+OCStackResult CreateCRLResource()
+{
+    OCStackResult ret;
+    ret = OCCreateResource(&gCrlHandle,
+                           OIC_RSRC_TYPE_SEC_CRL,
+                           OIC_MI_DEF,
+                           OIC_RSRC_CRL_URI,
+                           CRLEntityHandler,
+                           NULL,
+                           OC_OBSERVABLE);
+
+    if (OC_STACK_OK != ret)
+    {
+        OC_LOG(FATAL, TAG, PCF("Unable to instantiate CRL resource"));
+        DeInitCRLResource();
+    }
+    return ret;
+}
+
+/**
+ * Get the default value
+ * @retval  NULL for now. Update it when we finalize the default info.
+ */
+static OicSecCrl_t *GetCrlDefault()
+{
+    OicSecCrl_t *defaultCrl = NULL;
+    defaultCrl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
+
+    defaultCrl->CrlId = CRL_DEFAULT_CRL_ID;
+
+    defaultCrl->CrlData.len = strlen(CRL_DEFAULT_CRL_DATA);
+    defaultCrl->CrlData.data = OICMalloc(defaultCrl->CrlData.len);
+    memcpy(defaultCrl->CrlData.data, CRL_DEFAULT_CRL_DATA, defaultCrl->CrlData.len);
+
+    defaultCrl->ThisUpdate.len = strlen(CRL_DEFAULT_THIS_UPDATE);
+    defaultCrl->ThisUpdate.data = OICMalloc(defaultCrl->ThisUpdate.len);
+    memcpy(defaultCrl->ThisUpdate.data, CRL_DEFAULT_THIS_UPDATE, defaultCrl->ThisUpdate.len);
+
+    return defaultCrl;
+}
+
+/**
+ * Initialize CRL resource by loading data from persistent storage.
+ *
+ * @retval
+ *     OC_STACK_OK    - no errors
+ *     OC_STACK_ERROR - stack process error
+ */
+OCStackResult InitCRLResource()
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    char* jsonSVRDatabase;
+
+    //Read CRL resource from PS
+    jsonSVRDatabase = GetSVRDatabase();
+
+    if (jsonSVRDatabase)
+    {
+        //Convert JSON CRL into binary format
+        gCrl = JSONToCrlBin(jsonSVRDatabase);
+    }
+    /*
+     * If SVR database in persistent storage got corrupted or
+     * is not available for some reason, a default CrlResource is created
+     * which allows user to initiate CrlResource provisioning again.
+     */
+    if (!jsonSVRDatabase || !gCrl)
+    {
+        gCrl = GetCrlDefault();
+    }
+
+    ret = CreateCRLResource();
+    OICFree(jsonSVRDatabase);
+    return ret;
+}
+
+/**
+ * Perform cleanup for ACL resources.
+ */
+void DeInitCRLResource()
+{
+    OCDeleteResource(gCrlHandle);
+    gCrlHandle = NULL;
+    DeleteCrlBinData(gCrl);
+    gCrl = NULL;
+}
+
+OicSecCrl_t *GetCRLResource()
+{
+    OicSecCrl_t *crl =  NULL;
+
+    //Read CRL resource from PS
+    char* jsonSVRDatabase = GetSVRDatabase();
+
+    if (jsonSVRDatabase)
+    {
+        //Convert JSON CRL into binary format
+        crl = JSONToCrlBin(jsonSVRDatabase);
+    }
+    /*
+     * If SVR database in persistent storage got corrupted or
+     * is not available for some reason, a default CrlResource is created
+     * which allows user to initiate CrlResource provisioning again.
+     */
+    if (!jsonSVRDatabase || !crl)
+    {
+        crl = GetCrlDefault();
+    }
+    OICFree(jsonSVRDatabase);
+
+    return crl;
+}
+
+char *GetBase64CRL()
+{
+    cJSON *jsonCrl = NULL;
+    cJSON *jsonObj = NULL;
+    char *jsonSVRDatabase = GetSVRDatabase();
+    char* ret = NULL;
+
+    cJSON *jsonRoot = cJSON_Parse(jsonSVRDatabase);
+    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+    jsonCrl = cJSON_GetObjectItem(jsonRoot, OIC_JSON_CRL_NAME);
+    VERIFY_NON_NULL(TAG, jsonCrl, ERROR);
+
+    //CRLData -- Mandatory
+    jsonObj = cJSON_GetObjectItem(jsonCrl, OIC_JSON_CRL_DATA);
+    if(jsonObj)
+    {
+        VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
+        if(cJSON_String == jsonObj->type)
+        {
+            //Check for empty string, in case CRLData field has not been set yet
+            if (jsonObj->valuestring[0])
+            {
+                ret = jsonObj->valuestring;
+            }
+        }
+    }
+exit:
+    OICFree(jsonSVRDatabase);
+    cJSON_Delete(jsonRoot);
+    return ret;
+}
index 0ed223f..5657901 100644 (file)
@@ -518,7 +518,7 @@ static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest
                 ehRet = AddOwnerPSK((CAEndpoint_t *)&request->devAddr, newDoxm,
                         (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS));
 
-                VERIFY_SUCCESS(TAG, ehRet = OC_EH_OK, ERROR);
+                VERIFY_SUCCESS(TAG, ehRet == OC_EH_OK, ERROR);
 
                 // Update new state in persistent storage
                 if (true == UpdatePersistentStorage(gDoxm))
@@ -543,6 +543,10 @@ static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest
                  * 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__
             }
         }
index 746a164..f2d2106 100644 (file)
@@ -159,7 +159,8 @@ OCStackResult UpdateSVRDatabase(const char* rsrcName, cJSON* jsonObj)
          ACL, PStat & Doxm resources at least have default entries in the database but
          Cred resource may have no entries. The first cred resource entry (for provisioning tool)
          is created when the device is owned by provisioning tool and it's ownerpsk is generated.*/
-        if((strcmp(rsrcName, OIC_JSON_CRED_NAME) == 0) && (!jsonObj))
+        if((strcmp(rsrcName, OIC_JSON_CRED_NAME) == 0 || strcmp(rsrcName, OIC_JSON_CRL_NAME) == 0) 
+                                                                                    && (!jsonObj))
         {
             // Add the fist cred object in existing SVR database json
             cJSON_AddItemToObject(jsonSVRDb, rsrcName, jsonDuplicateObj->child);
index 5eefbd4..0be77a3 100644 (file)
@@ -93,6 +93,12 @@ OCStackResult InitSecureResources( )
     {
         ret = InitCredResource();
     }
+#ifdef __WITH_X509__
+    if(OC_STACK_OK == ret)
+    {
+        ret = InitCRLResource();
+    }
+#endif // __WITH_X509__
     if(OC_STACK_OK == ret)
     {
         ret = InitSVCResource();
index 4cca17b..61f7e36 100644 (file)
@@ -49,6 +49,10 @@ const char * OIC_RSRC_TYPE_SEC_CRED = "oic.sec.cred";
 const char * OIC_RSRC_CRED_URI =  "/oic/sec/cred";
 const char * OIC_JSON_CRED_NAME = "cred";
 
+//CRL
+const char * OIC_RSRC_TYPE_SEC_CRL = "oic.sec.crl";
+const char * OIC_RSRC_CRL_URI =  "/oic/sec/crl";
+const char * OIC_JSON_CRL_NAME = "crl";
 //svc
 const char * OIC_RSRC_TYPE_SEC_SVC = "oic.sec.svc";
 const char * OIC_RSRC_SVC_URI =  "/oic/sec/svc";