[IOT-2561] provision a certificate
authorOleksandr Dmytrenko <o.dmytrenko@samsung.com>
Mon, 14 Aug 2017 12:41:24 +0000 (15:41 +0300)
committerRandeep Singh <randeep.s@samsung.com>
Fri, 18 Aug 2017 11:03:25 +0000 (11:03 +0000)
child from [IOT-2263]: 'dos' feature enabling
4) CERT

Change-Id: I0006b0dd357023a3892a0fb6385157cd66274ab1
Signed-off-by: Oleksandr Dmytrenko <o.dmytrenko@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/21901
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Alex Kelley <alexke@microsoft.com>
Reviewed-by: Oleh Vasyliev <o.vasyliev@samsung.com>
Reviewed-by: Randeep Singh <randeep.s@samsung.com>
resource/csdk/security/include/internal/credresource.h
resource/csdk/security/provisioning/include/internal/secureresourceprovider.h
resource/csdk/security/provisioning/sample/provisioningclient.c
resource/csdk/security/provisioning/src/ocprovisioningmanager.c
resource/csdk/security/provisioning/src/secureresourceprovider.c
resource/csdk/security/src/credresource.c

index 1bee048..35f9450 100644 (file)
@@ -265,6 +265,12 @@ CborError DeserializeEncodingFromCbor(CborValue *rootMap, OicSecKey_t *value);
 CborError DeserializeSecOptFromCbor(CborValue *rootMap, OicSecOpt_t *value);
 bool IsSameSecOpt(const OicSecOpt_t* sk1, const OicSecOpt_t* sk2);
 bool IsSameSecKey(const OicSecKey_t* sk1, const OicSecKey_t* sk2);
+/**
+ * Delete OicSecCred_t
+ *
+ * @param[in] cred the pointer to credential usage.
+ */
+void FreeCred(OicSecCred_t *cred);
 
 #ifdef __cplusplus
 }
index ff6e95e..03b657a 100644 (file)
@@ -348,6 +348,18 @@ OCStackResult SRPResetDevice(const OCProvisionDev_t* pTargetDev,
  */
 OCStackResult SRPReadTrustCertChain(uint16_t credId, uint8_t **trustCertChain,
                                      size_t *chainSize);
+/**
+ * Function for certificate provisioning.
+ * @param[in] ctx Application context to be returned in result callback.
+ * @param[in] pDev Selected target device.
+ * @param[in] pemCert the certificate in PEM.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ *            provisioning request receives a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult SRPProvisionCertificate(void *ctx, const OCProvisionDev_t *pDev,
+        const char* pemCert, OCProvisionResultCB resultCallback);
+
 #ifdef __cplusplus
 }
 #endif
index d69c308..457bdba 100644 (file)
@@ -1085,20 +1085,27 @@ static int provisionCert(void)
 
     // select device for provisioning certificate
     int dev_num = 0;
-    for (; ; )
+    if (g_own_cnt == 1)
     {
-        printf("   > Enter Device Number, for certificate provisioning: ");
-        for (int ret = 0; 1 != ret; )
+        dev_num = 1;
+    }
+    else
+    {
+        for (; ; )
         {
-            ret = scanf("%d", &dev_num);
-            for (; 0x20 <= getchar(); );  // for removing overflow garbages
+            printf("   > Enter Device Number, for certificate provisioning: ");
+            for (int ret = 0; 1 != ret; )
+            {
+                ret = scanf("%d", &dev_num);
+                for (; 0x20 <= getchar(); );  // for removing overflow garbages
                                           // '0x20<=code' is character region
+            }
+            if (0<dev_num && g_own_cnt >= dev_num)
+            {
+                break;
+            }
+            printf("     Entered Wrong Number. Please Enter Again\n");
         }
-        if (0<dev_num && g_own_cnt >= dev_num)
-        {
-            break;
-        }
-        printf("     Entered Wrong Number. Please Enter Again\n");
     }
 
     OCProvisionDev_t* targetDevice = getDevInst((const OCProvisionDev_t*)g_own_list, dev_num);
index 6c9ab00..ea9dd84 100644 (file)
@@ -529,8 +529,7 @@ OCStackResult OC_CALL OCProvisionCertificate(void *ctx,
     const char* pemCert,
     OCProvisionResultCB resultCallback)
 {
-    return SRPProvisionCredentials(ctx, SIGNED_ASYMMETRIC_KEY, 0,
-        pDev, NULL, pemCert, NULL, NULL, resultCallback);
+    return SRPProvisionCertificate(ctx, pDev, pemCert, resultCallback);
 }
 #endif
 
index a86a34f..f2c4232 100644 (file)
@@ -55,6 +55,8 @@
 #include "crlresource.h"
 #endif
 
+#define DEFAULT_URI_LENGTH (MAX_URI_LENGTH + MAX_QUERY_LENGTH)
+
 #define TAG "OIC_SRPAPI"
 
 trustCertChainContext_t g_trustCertChainNotifier;
@@ -123,6 +125,19 @@ typedef struct TrustChainData
     int numOfResults;                           /**< Number of results in result array.**/
 } TrustChainData_t;
 
+/**
+ * Structure to carry Certificate provision API data to callback.
+ */
+typedef struct CertData
+{
+    void *ctx;                                  /**< Pointer to user context.**/
+    const OCProvisionDev_t *targetDev;          /**< Pointer to OCProvisionDev_t.**/
+    OicSecCred_t *credInfo;                     /**< Array of pointers to OicSecCred_t.**/
+    OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
+    OCProvisionResult_t *resArr;                /**< Result array.**/
+    int numOfResults;                           /**< Number of results in result array.**/
+    const char* cert;                           /**< The certificate.**/
+} CertData_t;
 
 // Structure to carry get security resource APIs data to callback.
 typedef struct GetSecData GetSecData_t;
@@ -225,6 +240,17 @@ typedef enum {
  */
 static void FreeData(Data_t *data)
 {
+    if(NULL == data)
+    {
+        return;
+    }
+
+    if (NULL == data->ctx)
+    {
+        OICFree(data);
+        return;
+    }
+
     switch (data->type)
     {
         case CHAIN_TYPE:
@@ -248,6 +274,18 @@ static void FreeData(Data_t *data)
                 OICFree(pskData);
                 break;
             }
+        case CERT_TYPE:
+            {
+                CertData_t *certData = (CertData_t *)data->ctx;
+                if (NULL != certData->resArr)
+                {
+                     OICFreeAndSetToNull((void**)&certData->resArr);
+                }
+                FreeCred(certData->credInfo);
+
+                OICFreeAndSetToNull((void**)&certData);
+                break;
+            }
         default:
             {
                 OIC_LOG_V(INFO, TAG, "Unknown type %d", data->type);
@@ -737,9 +775,18 @@ static OCStackApplicationResult SetReadyForNormalOperationCB(void *ctx, OCDoHand
         }
         case CERT_TYPE:
         {
-            OIC_LOG_V(ERROR, TAG, "Not implemented type %d", dataType);
-            OIC_LOG_V(ERROR, TAG, "OUT %s", __func__);
-            return OC_STACK_DELETE_TRANSACTION;
+            CertData_t *certData = (CertData_t *) ((Data_t *) ctx)->ctx;
+            if (NULL == certData)
+            {
+                OIC_LOG_V(ERROR, TAG, "%s: certData is NULL", __func__);
+                break;
+            }
+            resultCallback = certData->resultCallback;
+            targetDev = certData->targetDev;
+            resArr = certData->resArr;
+            numOfResults = &(certData->numOfResults);
+            dataCtx = certData->ctx;
+            break;
         }
         default:
         {
@@ -810,9 +857,8 @@ static OCStackResult SetDOS(const Data_t *data, OicSecDeviceOnboardingState_t do
         }
         case CERT_TYPE:
         {
-            // TODO check cert provision flow
-            OIC_LOG_V(ERROR, TAG, "Not implemented type: %d", data->type);
-            return OC_STACK_INVALID_PARAM;
+            pTargetDev = ((CertData_t *)data->ctx)->targetDev;
+            break;
         }
         default:
         {
@@ -913,12 +959,12 @@ error:
 /**
  * Restores pstat after provisioning.
  */
-static OCStackApplicationResult ProvisionCB(void *ctx, OCDoHandle UNUSED,
+static OCStackApplicationResult ProvisionCB(void *ctx, OCDoHandle handle,
         OCClientResponse *clientResponse)
 {
     OIC_LOG_V(DEBUG, TAG, "IN %s", __func__);
     VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
-    (void) UNUSED;
+    OC_UNUSED(handle);
     if (clientResponse && OC_STACK_RESOURCE_CHANGED != clientResponse->result)
     {
         OIC_LOG_V(ERROR, TAG, "Responce result: %d", clientResponse->result);
@@ -983,20 +1029,6 @@ static OCStackApplicationResult  ProvisionPskCB(void *ctx, OCDoHandle UNUSED,
 
 
 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
-/**
- * Structure to carry certificate data to callback.
- */
-typedef struct CertificateData CertData_t;
-struct CertificateData
-{
-    void *ctx;                                  /**< Pointer to user context.**/
-    const OCProvisionDev_t *deviceInfo;        /**< Pointer to OCProvisionDev_t.**/
-    OicSecCred_t *credInfo;                     /**< Pointer to OicSecCred_t.**/
-    OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
-    OCProvisionResult_t *resArr;                /**< Result array.**/
-    int numOfResults;                           /**< Number of results in result array.**/
-};
-
 OCStackResult SRPRegisterTrustCertChainNotifier(void *ctx, TrustCertChainChangeCB callback)
 {
     if (g_trustCertChainNotifier.callback)
@@ -1336,6 +1368,150 @@ OCStackResult SRPSaveOwnRoleCert(OicSecKey_t * cert, uint16_t *credId)
 {
     return saveCertChain(cert, NULL, credId, ROLE_CERT);
 }
+/**
+ * Callback for Certificate provisioning.
+ */
+static OCStackApplicationResult ProvisionCertificateCB(void *ctx, OCDoHandle handle,
+        OCClientResponse *clientResponse)
+{
+    OIC_LOG_V(INFO, TAG, "IN %s", __func__);
+
+    OC_UNUSED(handle);
+    OCStackResult ret = OC_STACK_ERROR;
+    char *query = NULL;
+    const OCProvisionDev_t *pDev = NULL;
+    OicSecCred_t *cred = NULL;
+    OCSecurityPayload *secPayload = NULL;
+
+    VERIFY_NOT_NULL_RETURN(TAG, ctx, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NOT_NULL_RETURN(TAG, clientResponse, ERROR,  OC_STACK_INVALID_PARAM);
+
+    VERIFY_SUCCESS_RETURN(TAG, (OC_STACK_RESOURCE_CHANGED == clientResponse->result), ERROR,
+        OC_STACK_INVALID_PARAM);
+
+    Data_t *data = (Data_t *) ctx;
+    VERIFY_SUCCESS_RETURN(TAG, (CERT_TYPE == data->type), ERROR, OC_STACK_INVALID_PARAM);
+
+    CertData_t *certData = (CertData_t *) (data->ctx);
+    VERIFY_NOT_NULL(TAG, certData, ERROR);
+    pDev = certData->targetDev;
+    VERIFY_NOT_NULL(TAG, pDev, ERROR);
+    cred = certData->credInfo;
+    VERIFY_NOT_NULL(TAG, cred, ERROR);
+
+    secPayload = (OCSecurityPayload *)OICCalloc(1, sizeof(OCSecurityPayload));
+    VERIFY_NOT_NULL(TAG, secPayload, ERROR);
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+
+    int secureFlag = 0;//don't send private data(key)
+    VERIFY_SUCCESS(TAG, OC_STACK_OK == CredToCBORPayload(cred, &secPayload->securityData,
+                                             &secPayload->payloadSize, secureFlag), ERROR);
+    OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
+
+    query = OICCalloc(1, DEFAULT_URI_LENGTH);
+    VERIFY_NOT_NULL(TAG, query, ERROR);
+    VERIFY_SUCCESS(TAG, PMGenerateQuery(true,
+                             pDev->endpoint.addr,
+                             pDev->securePort,
+                             pDev->connType,
+                             query, DEFAULT_URI_LENGTH, OIC_RSRC_CRED_URI), ERROR);
+
+    OCCallbackData cbData =  {.context = ctx, .cb = ProvisionCB, .cd = NULL};
+    OCDoHandle lHandle = NULL;
+
+    ret = OCDoResource(&lHandle, OC_REST_POST, query, 
+                                &pDev->endpoint, (OCPayload *)secPayload,
+                                pDev->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+    OIC_LOG_V(DEBUG, TAG, "POST:%s ret:%d", query, ret);
+exit:
+    OICFree(query);
+    if (OC_STACK_OK != ret)
+    {
+        if(NULL != secPayload)
+        {
+            OCPayloadDestroy((OCPayload *)secPayload);
+        }
+        if(NULL != cred)
+        {
+            FreeCred(cred);
+        }
+    }
+
+    OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
+
+    return ret;
+}
+
+OCStackResult SRPProvisionCertificate(void *ctx,
+    const OCProvisionDev_t *pDev,
+    const char* pemCert,
+    OCProvisionResultCB resultCallback)
+{
+    OIC_LOG_V(INFO, TAG, "IN %s", __func__);
+
+    VERIFY_NOT_NULL_RETURN(TAG, pDev, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NOT_NULL_RETURN(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
+    VERIFY_NOT_NULL_RETURN(TAG, pemCert, ERROR,  OC_STACK_INVALID_CALLBACK);
+
+    OCStackResult ret = OC_STACK_ERROR;
+    Data_t *data = NULL;
+
+    OicUuid_t provTooldeviceID =   {{0,}};
+    if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
+    {
+        OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+        return OC_STACK_ERROR;
+    }
+
+    data = (Data_t *)OICCalloc(1, sizeof(Data_t));
+    VERIFY_NOT_NULL(TAG, data, ERROR);
+    data->type = CERT_TYPE;
+
+    CertData_t *certData = (CertData_t *)OICCalloc(1, sizeof(CertData_t));
+    VERIFY_NOT_NULL(TAG, certData, ERROR);
+    data->ctx = certData;
+    certData->ctx = ctx;
+    certData->targetDev = pDev;
+    certData->resultCallback = resultCallback;
+    certData->numOfResults = 0;
+    certData->credInfo = NULL;
+
+    certData->resArr = (OCProvisionResult_t *)OICCalloc(1, sizeof(OCProvisionResult_t));
+    VERIFY_NOT_NULL(TAG, certData->resArr, ERROR);
+
+    OicSecKey_t deviceCert = { 0 };
+    deviceCert.data = (uint8_t*) pemCert;
+    deviceCert.len = strlen(pemCert) + 1;
+    deviceCert.encoding = OIC_ENCODING_PEM;
+
+    OicSecCred_t *cred = GenerateCredential(&pDev->doxm->deviceID, SIGNED_ASYMMETRIC_KEY,
+        &deviceCert, NULL, &provTooldeviceID, NULL);
+    VERIFY_NOT_NULL(TAG, cred, ERROR);
+    certData->credInfo = cred;
+
+    cred->publicData.encoding = OIC_ENCODING_PEM;
+
+    if (OC_STACK_OK == OCInternalIsValidRoleCertificate(deviceCert.data, deviceCert.len, NULL, NULL))
+    {
+        cred->credUsage = OICStrdup(ROLE_CERT);
+    }
+    else
+    {
+        cred->credUsage = OICStrdup(PRIMARY_CERT);
+    }
+
+    ret = SetDOS(data, DOS_RFPRO, ProvisionCertificateCB);
+exit:
+    if (OC_STACK_OK != ret)
+    {
+         FreeData(data);
+    }
+
+    OIC_LOG_V(INFO, TAG, "OUT %s", __func__);
+
+    return ret;
+}
+
 
 #endif // __WITH_DTLS__ || __WITH_TLS__
 
index 34b14db..cc1b5a3 100644 (file)
@@ -277,7 +277,7 @@ exit:
 /**
  * This function frees OicSecCred_t object's fields and object itself.
  */
-static void FreeCred(OicSecCred_t *cred)
+void FreeCred(OicSecCred_t *cred)
 {
     if(NULL == cred)
     {
@@ -311,6 +311,8 @@ static void FreeCred(OicSecCred_t *cred)
     OICFree(cred->eownerID);
 #endif
 
+    cred->next = NULL;
+
     //Clean Cred node itself
     OICFree(cred);
 }
@@ -1338,6 +1340,7 @@ OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t cr
 
     OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
     VERIFY_NOT_NULL(TAG, cred, ERROR);
+    cred->next = NULL;
 
     //CredId is assigned before appending new cred to the existing
     //credential list and updating svr database in AddCredential().