X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=resource%2Fcsdk%2Fsecurity%2Fsrc%2Fcredresource.c;h=e7235b5eeee6d268a601409253ed303c9d843e12;hb=17c68b2fd1e74586f85e552eeab4e32dc121f8a0;hp=af21b26156ce6da4d96c01d30335de7a8bb5afba;hpb=8c01dff2c5bc5496f7dc1632c498943ec6ecb015;p=platform%2Fupstream%2Fiotivity.git diff --git a/resource/csdk/security/src/credresource.c b/resource/csdk/security/src/credresource.c old mode 100755 new mode 100644 index af21b26..e7235b5 --- a/resource/csdk/security/src/credresource.c +++ b/resource/csdk/security/src/credresource.c @@ -33,45 +33,63 @@ #include "base64.h" #include "srmutility.h" #include "cainterface.h" +#include "pbkdf2.h" #include +#include "iotvticalendar.h" +#ifdef WITH_ARDUINO #include +#else +#include +#endif #include +#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); } } } @@ -141,17 +159,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 @@ -258,7 +296,7 @@ OicSecCred_t * JSONToCredBin(const char * jsonStr) 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); @@ -269,12 +307,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 @@ -290,7 +372,7 @@ OicSecCred_t * JSONToCredBin(const char * jsonStr) //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)); @@ -343,6 +425,7 @@ OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t cr 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)); @@ -359,14 +442,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) { @@ -395,7 +478,35 @@ exit: 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 @@ -458,6 +569,8 @@ static uint16_t GetCredId() exit: return 0; } + + /** * This function adds the new cred to the credential list. * @@ -470,7 +583,6 @@ exit: OCStackResult AddCredential(OicSecCred_t * newCred) { OCStackResult ret = OC_STACK_ERROR; - char * jsonStr = NULL; VERIFY_SUCCESS(TAG, NULL != newCred, ERROR); @@ -482,23 +594,41 @@ OCStackResult AddCredential(OicSecCred_t * newCred) //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) @@ -516,10 +646,51 @@ 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; } +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) @@ -528,6 +699,7 @@ OCEntityHandlerResult CredEntityHandler (OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest, void* callbackParameter) { + (void)callbackParameter; OCEntityHandlerResult ret = OC_EH_ERROR; if(!ehRequest) @@ -536,7 +708,7 @@ OCEntityHandlerResult CredEntityHandler (OCEntityHandlerFlag flag, } 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) { @@ -546,6 +718,9 @@ OCEntityHandlerResult CredEntityHandler (OCEntityHandlerFlag flag, case OC_REST_POST: ret = HandlePostRequest(ehRequest); break; + case OC_REST_DELETE: + ret = HandleDeleteRequest(ehRequest); + break; default: ret = OC_EH_ERROR; break; @@ -576,7 +751,7 @@ OCStackResult CreateCredResource() 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; @@ -655,16 +830,16 @@ const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject) { 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; @@ -676,78 +851,313 @@ const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject) * 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__ */