#include "base64.h"
#include "srmutility.h"
#include "cainterface.h"
+#include "pbkdf2.h"
#include <stdlib.h>
+#include "iotvticalendar.h"
+#ifdef WITH_ARDUINO
#include <string.h>
+#else
+#include <strings.h>
+#endif
#include <stdint.h>
+#define TAG "SRM-CREDL"
-#define TAG PCF("SRM-CREDL")
static OicSecCred_t *gCred = NULL;
static OCResourceHandle gCredHandle = NULL;
-void DeleteCredList(OicSecCred_t* cred)
+/**
+ * This function frees OicSecCred_t object's fields and object itself.
+ */
+static void FreeCred(OicSecCred_t *cred)
{
- if (cred)
+ if(NULL == cred)
{
- OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
- LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
- {
- LL_DELETE(cred, credTmp1);
-
- //Note: Need further clarification on roleID data type
+ OC_LOG (ERROR, TAG, "Invalid Parameter");
+ return;
+ }
+ //Note: Need further clarification on roleID data type
#if 0
- //Clean roleIds
- OICFree(credTmp1->roleIds);
+ //Clean roleIds
+ OICFree(cred->roleIds);
#endif
- //Clean PublicData
- OICFree(credTmp1->publicData.data);
+ //Clean PublicData
+ OICFree(cred->publicData.data);
+
+ //Clean PrivateData
+ OICFree(cred->privateData.data);
- //Clean PrivateData
- OICFree(credTmp1->privateData.data);
+ //Clean Period
+ OICFree(cred->period);
- //Clean Period
- OICFree(credTmp1->period);
+ //Clean Owners
+ OICFree(cred->owners);
- //Clean Owners
- OICFree(credTmp1->owners);
+ //Clean Cred node itself
+ OICFree(cred);
+}
- //Clean Cred node itself
- OICFree(credTmp1);
+void DeleteCredList(OicSecCred_t* cred)
+{
+ if (cred)
+ {
+ OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
+ LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
+ {
+ LL_DELETE(cred, credTmp1);
+ FreeCred(credTmp1);
}
}
}
//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
jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_CREDTYPE_NAME);
VERIFY_NON_NULL(TAG, jsonObj, ERROR);
VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
- cred->credType = jsonObj->valueint;
+ cred->credType = (OicSecCredType_t)jsonObj->valueint;
//PrivateData is mandatory for some of the credential types listed below.
jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PRIVATEDATA_NAME);
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
//Owners -- Mandatory
jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_OWNERS_NAME);
VERIFY_NON_NULL(TAG, jsonObj, ERROR);
- VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR)
+ VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
cred->ownersLen = cJSON_GetArraySize(jsonObj);
VERIFY_SUCCESS(TAG, cred->ownersLen > 0, ERROR);
cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
const char * publicData, const char * privateData,
size_t ownersLen, const OicUuid_t * owners)
{
+ (void)publicData;
OCStackResult ret = OC_STACK_ERROR;
OicSecCred_t *cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
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)
{
return cred;
}
-/*
+static bool UpdatePersistentStorage(const OicSecCred_t *cred)
+{
+ bool ret = false;
+
+ // Convert Cred data into JSON for update to persistent storage
+ char *jsonStr = BinToCredJSON(cred);
+ if (jsonStr)
+ {
+ cJSON *jsonCred = cJSON_Parse(jsonStr);
+ OICFree(jsonStr);
+
+ if ((jsonCred) &&
+ (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, jsonCred)))
+ {
+ ret = true;
+ }
+ cJSON_Delete(jsonCred );
+ }
+ else //Empty cred list
+ {
+ if (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, NULL))
+ {
+ ret = true;
+ }
+ }
+ return ret;
+}
+
+/**
* Compare function used LL_SORT for sorting credentials
*
* @param first pointer to OicSecCred_t struct
exit:
return 0;
}
+
+
/**
* This function adds the new cred to the credential list.
*
OCStackResult AddCredential(OicSecCred_t * newCred)
{
OCStackResult ret = OC_STACK_ERROR;
- char * jsonStr = NULL;
VERIFY_SUCCESS(TAG, NULL != newCred, ERROR);
//Append the new Cred to existing list
LL_APPEND(gCred, newCred);
- //Convert CredList to JSON and update the persistent Storage
- jsonStr = BinToCredJSON(gCred);
-
- if(jsonStr)
+ if(UpdatePersistentStorage(gCred))
{
- cJSON *jsonCred = cJSON_Parse(jsonStr);
- OICFree(jsonStr);
+ ret = OC_STACK_OK;
+ }
+
+exit:
+ return ret;
+}
- if((jsonCred) && (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, jsonCred)))
+OCStackResult RemoveCredential(const OicUuid_t *subject)
+{
+ OCStackResult ret = OC_STACK_ERROR;
+ OicSecCred_t *cred = NULL;
+ OicSecCred_t *tempCred = NULL;
+ bool deleteFlag = false;
+
+ LL_FOREACH_SAFE(gCred, cred, tempCred)
+ {
+ if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
{
- ret = OC_STACK_OK;
+ LL_DELETE(gCred, cred);
+ FreeCred(cred);
+ deleteFlag = 1;
}
- cJSON_Delete(jsonCred);
}
-exit:
+ if(deleteFlag)
+ {
+ if(UpdatePersistentStorage(gCred))
+ {
+ ret = OC_STACK_RESOURCE_DELETED;
+ }
+ }
return ret;
+
}
static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
//list and updating svr database.
ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
}
-
return ret;
}
+static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
+{
+ OC_LOG(DEBUG, TAG, "Processing CredDeleteRequest");
+
+ OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+ if(NULL == ehRequest->query)
+ {
+ return ehRet;
+ }
+
+ OicParseQueryIter_t parseIter = {.attrPos=NULL};
+ OicUuid_t subject = {.id={0}};
+
+ //Parsing REST query to get the subject
+ ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
+ while(GetNextQuery(&parseIter))
+ {
+ if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME,
+ parseIter.attrLen) == 0)
+ {
+ unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
+ uint32_t outLen = 0;
+ B64Result b64Ret = B64_OK;
+
+ b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen,
+ base64Buff, sizeof(base64Buff), &outLen);
+
+ VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(subject.id)), ERROR);
+ memcpy(subject.id, base64Buff, outLen);
+ }
+ }
+
+ if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
+ {
+ ehRet = OC_EH_RESOURCE_DELETED;
+ }
+
+exit:
+ return ehRet;
+}
+
/*
* This internal method is the entity handler for Cred resources
* to handle REST request (PUT/POST/DEL)
OCEntityHandlerRequest * ehRequest,
void* callbackParameter)
{
+ (void)callbackParameter;
OCEntityHandlerResult ret = OC_EH_ERROR;
if(!ehRequest)
}
if (flag & OC_REQUEST_FLAG)
{
- OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+ OC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
//TODO : Handle PUT/DEL methods
switch(ehRequest->method)
{
case OC_REST_POST:
ret = HandlePostRequest(ehRequest);
break;
+ case OC_REST_DELETE:
+ ret = HandleDeleteRequest(ehRequest);
+ break;
default:
ret = OC_EH_ERROR;
break;
if (OC_STACK_OK != ret)
{
- OC_LOG (FATAL, TAG, PCF("Unable to instantiate Cred resource"));
+ OC_LOG (FATAL, TAG, "Unable to instantiate Cred resource");
DeInitCredResource();
}
return ret;
{
OicSecCred_t *cred = NULL;
- if ( NULL == subject)
+ if ( NULL == subject)
{
- return NULL;
+ return NULL;
}
LL_FOREACH(gCred, cred)
{
if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
{
- return cred;
+ return cred;
}
}
return NULL;
* This internal callback is used by lower stack (i.e. CA layer) to
* retrieve PSK credentials from RI security layer.
*
- * Note: When finished, caller should initialize memory to zeros and
- * invoke OICFree to delete @p credInfo.
- *
- * @param credInfo
- * binary blob containing PSK credentials
+ * @param[in] type type of PSK data required by tinyDTLS layer during DTLS handshake.
+ * @param[in] desc Additional request information.
+ * @param[in] desc_len The actual length of desc.
+ * @param[out] result Must be filled with the requested information.
+ * @param[in] result_length Maximum size of @p result.
*
- * @retval none
+ * @return The number of bytes written to @p result or a value
+ * less than zero on error.
*/
-void GetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo)
+int32_t GetDtlsPskCredentials( CADtlsPskCredType_t type,
+ const unsigned char *desc, size_t desc_len,
+ unsigned char *result, size_t result_length)
{
- CADtlsPskCredsBlob_t * caBlob = NULL;
- if(credInfo)
- {
- caBlob = (CADtlsPskCredsBlob_t *)OICCalloc(sizeof(CADtlsPskCredsBlob_t), 1);
- if (caBlob)
- {
- OicUuid_t deviceID = {};
+ int32_t ret = -1;
- // Retrieve Device ID from doxm resource and copy in PSK creds blob
- VERIFY_SUCCESS(TAG, GetDoxmDeviceID(&deviceID) == OC_STACK_OK, ERROR);
- memcpy(caBlob->identity, deviceID.id, sizeof(caBlob->identity));
+ if (NULL == result)
+ {
+ return ret;
+ }
- OicSecCred_t *cred = NULL;
- size_t count = 0;
- LL_FOREACH(gCred, cred)
+ switch (type)
+ {
+ case CA_DTLS_PSK_HINT:
+ case CA_DTLS_PSK_IDENTITY:
{
- // Currently, Iotivity supports only symmetric pair wise key credentials
- if (cred->credType == SYMMETRIC_PAIR_WISE_KEY)
+ OicUuid_t deviceID = {.id={}};
+ // Retrieve Device ID from doxm resource
+ if ( OC_STACK_OK != GetDoxmDeviceID(&deviceID) )
+ {
+ OC_LOG (ERROR, TAG, "Unable to retrieve doxm Device ID");
+ return ret;
+ }
+
+ if (result_length < sizeof(deviceID.id))
{
- ++count;
+ OC_LOG (ERROR, TAG, "Wrong value for result_length");
+ return ret;
}
+ memcpy(result, deviceID.id, sizeof(deviceID.id));
+ return (sizeof(deviceID.id));
}
- caBlob->num = count;
- if (caBlob->num)
- {
- caBlob->creds =
- (OCDtlsPskCreds*) OICMalloc(caBlob->num * sizeof(OCDtlsPskCreds));
- VERIFY_NON_NULL(TAG, caBlob->creds, ERROR);
+ break;
- unsigned int i = 0;
+ case CA_DTLS_PSK_KEY:
+ {
+ OicSecCred_t *cred = NULL;
LL_FOREACH(gCred, cred)
{
- if ((cred->credType == SYMMETRIC_PAIR_WISE_KEY) &&
- (i < count))
-
+ if (cred->credType != SYMMETRIC_PAIR_WISE_KEY)
{
- // Copy subject ID
- memcpy(caBlob->creds[i].id, cred->subject.id,
- sizeof(caBlob->creds[i].id));
+ continue;
+ }
- // Convert PSK from JSON to binary before copying
+ if ((desc_len == sizeof(cred->subject.id)) &&
+ (memcmp(desc, cred->subject.id, sizeof(cred->subject.id)) == 0))
+ {
+ /*
+ * If the credentials are valid for limited time,
+ * check their expiry.
+ */
+ if (cred->period)
+ {
+ if(IOTVTICAL_VALID_ACCESS != IsRequestWithinValidTime(cred->period, NULL))
+ {
+ OC_LOG (INFO, TAG, "Credentials are expired.");
+ ret = -1;
+ return ret;
+ }
+ }
+
+ // Convert PSK from Base64 encoding to binary before copying
uint32_t outLen = 0;
B64Result b64Ret = b64Decode(cred->privateData.data,
- strlen(cred->privateData.data), caBlob->creds[i].psk,
- sizeof(caBlob->creds[i].psk), &outLen);
- VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
- i++;
+ strlen(cred->privateData.data), result,
+ result_length, &outLen);
+ if (B64_OK != b64Ret)
+ {
+ OC_LOG (ERROR, TAG, "Base64 decoding failed.");
+ ret = -1;
+ return ret;
+ }
+ return outLen;
}
}
}
+ break;
+
+ default:
+ {
+ OC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
+ ret = -1;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * Add temporal PSK to PIN based OxM
+ *
+ * @param[in] tmpSubject UUID of target device
+ * @param[in] credType Type of credential to be added
+ * @param[in] pin numeric characters
+ * @param[in] pinSize length of 'pin'
+ * @param[in] ownersLen Number of owners
+ * @param[in] owners Array of owners
+ * @param[out] tmpCredSubject Generated credential's subject.
+ *
+ * @return OC_STACK_OK for success and errorcode otherwise.
+ */
+OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
+ const char * pin, size_t pinSize,
+ size_t ownersLen, const OicUuid_t * owners, OicUuid_t* tmpCredSubject)
+{
+ OCStackResult ret = OC_STACK_ERROR;
+
+ if(tmpSubject == NULL || pin == NULL || pinSize == 0 || tmpCredSubject == NULL)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
+ int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, owners->id,
+ UUID_LENGTH, PBKDF_ITERATIONS,
+ OWNER_PSK_LENGTH_128, privData);
+ VERIFY_SUCCESS(TAG, (dtlsRes == 0) , ERROR);
+
+ uint32_t outLen = 0;
+ char base64Buff[B64ENCODE_OUT_SAFESIZE(OWNER_PSK_LENGTH_128) + 1] = {};
+ B64Result b64Ret = b64Encode(privData, OWNER_PSK_LENGTH_128, base64Buff,
+ sizeof(base64Buff), &outLen);
+ VERIFY_SUCCESS(TAG, (B64_OK == b64Ret), ERROR);
+
+ OicSecCred_t* cred = GenerateCredential(tmpSubject, credType, NULL,
+ base64Buff, ownersLen, owners);
+ if(NULL == cred)
+ {
+ OC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
+ return OC_STACK_ERROR;
+ }
+
+ memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
+
+ ret = AddCredential(cred);
+ if( OC_STACK_OK != ret)
+ {
+ OC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
+ }
+
+exit:
+ return ret;
+}
+
+#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));
}
- *credInfo = caBlob;
- // Return from here after making the credential list
- return;
}
+ 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:
- if (caBlob)
+ return ret;
+}
+
+static OCStackResult GetCAPublicKeyData(CADtlsX509Creds_t *credInfo){
+ OCStackResult ret = OC_STACK_ERROR;
+ uint8_t *ccPtr = credInfo->certificateChain;
+ for(uint32_t i =0; i < credInfo->chainLen - 1; ++i)
{
- memset(caBlob->creds, 0, caBlob->num * sizeof(OCDtlsPskCreds));
- OICFree(caBlob->creds);
+ ccPtr += CERT_LEN_PREFIX + ParseCertPrefix(ccPtr);
}
- OICFree(caBlob);
+
+ 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;
}
-#endif /* __WITH_DTLS__ */
+
+static OCStackResult GetCertCredPublicData(CADtlsX509Creds_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_CERT_MESSAGE_LEN - 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(CADtlsX509Creds_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;
+}
+
+int GetDtlsX509Credentials(CADtlsX509Creds_t *credInfo)
+{
+ int ret = 1;
+ 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 = 0;
+exit:
+
+ return ret;
+}
+#undef CERT_LEN_PREFIX
+#endif /* __WITH_X509__ */