Commit 1d5a1ff9 authored by Oleksandr Dmytrenko's avatar Oleksandr Dmytrenko Committed by Randeep

[IOT-2561] provision a certificate

child from [IOT-2263]: 'dos' feature enabling
4) CERT 

Change-Id: I0006b0dd357023a3892a0fb6385157cd66274ab1
Signed-off-by: default avatarOleksandr Dmytrenko <o.dmytrenko@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/21901Tested-by: default avatarjenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: default avatarAlex Kelley <alexke@microsoft.com>
Reviewed-by: default avatarOleh Vasyliev <o.vasyliev@samsung.com>
Reviewed-by: Randeep's avatarRandeep Singh <randeep.s@samsung.com>
parent ba31f88e
......@@ -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
}
......
......@@ -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
......
......@@ -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);
......
......@@ -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
......
......@@ -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__
......
......@@ -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().
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment