1 //******************************************************************
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #define __STDC_LIMIT_MACROS
24 #include "oic_malloc.h"
26 #include "resourcemanager.h"
27 #include "psinterface.h"
29 #include "srmresourcestrings.h"
30 #include "credresource.h"
32 #include "doxmresource.h"
34 #include "srmutility.h"
35 #include "cainterface.h"
38 #include "iotvticalendar.h"
46 #define TAG "SRM-CREDL"
49 static OicSecCred_t *gCred = NULL;
50 static OCResourceHandle gCredHandle = NULL;
53 * This function frees OicSecCred_t object's fields and object itself.
55 static void FreeCred(OicSecCred_t *cred)
59 OC_LOG (ERROR, TAG, "Invalid Parameter");
62 //Note: Need further clarification on roleID data type
65 OICFree(cred->roleIds);
69 OICFree(cred->publicData.data);
72 OICFree(cred->privateData.data);
75 OICFree(cred->period);
78 OICFree(cred->owners);
80 //Clean Cred node itself
84 void DeleteCredList(OicSecCred_t* cred)
88 OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
89 LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
91 LL_DELETE(cred, credTmp1);
98 * This function converts credential data into JSON format.
99 * Caller needs to invoke 'free' when done using
101 * @param cred pointer to instance of OicSecCred_t structure.
102 * @param isIncResName Decide whether or not to include the resource name in output.
105 * pointer to JSON credential representation - if credential for subjectId found
106 * NULL - if credential for subjectId not found
108 char * BinToCredJSON(const OicSecCred_t * cred, const bool isIncResName)
110 cJSON *jsonRoot = NULL;
111 char *jsonStr = NULL;
115 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
117 B64Result b64Ret = B64_OK;
118 cJSON *jsonCredArray = NULL;
122 jsonRoot = cJSON_CreateObject();
123 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
124 cJSON_AddItemToObject(jsonRoot, OIC_JSON_CRED_NAME,
125 jsonCredArray = cJSON_CreateArray());
129 jsonCredArray = cJSON_CreateArray();
130 jsonRoot = jsonCredArray;
132 VERIFY_NON_NULL(TAG, jsonCredArray, ERROR);
136 cJSON *jsonCred = cJSON_CreateObject();
137 VERIFY_NON_NULL(TAG, jsonCred, ERROR);
139 //CredID -- Mandatory
140 cJSON_AddNumberToObject(jsonCred, OIC_JSON_CREDID_NAME, (int)cred->credId);
142 //Subject -- Mandatory
144 memset(base64Buff, 0, sizeof(base64Buff));
145 b64Ret = b64Encode(cred->subject.id, sizeof(cred->subject.id), base64Buff,
146 sizeof(base64Buff), &outLen);
147 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
148 cJSON_AddStringToObject(jsonCred, OIC_JSON_SUBJECTID_NAME, base64Buff);
150 //Note: Need further clarification on roleID data type
152 //RoleId -- Not Mandatory
153 if(cred->roleIdsLen > 0)
155 cJSON *jsonRoleIdsArray = NULL;
156 cJSON_AddItemToObject (jsonCred, OIC_JSON_ROLEIDS_NAME,
157 jsonRoleIdsArray = cJSON_CreateArray());
158 VERIFY_NON_NULL(TAG, jsonRoleIdsArray, ERROR);
159 for (size_t i = 0; i < cred->roleIdsLen; i++)
161 cJSON_AddItemToArray (jsonRoleIdsArray,
162 cJSON_CreateString((char *)cred->roleIds[i].id));
167 //CredType -- Mandatory
168 cJSON_AddNumberToObject(jsonCred, OIC_JSON_CREDTYPE_NAME,(int)cred->credType);
171 //PublicData -- Not Mandatory
172 if(cred->publicData.data)
174 if (SIGNED_ASYMMETRIC_KEY == cred->credType)
176 cJSON_AddItemToObject(jsonCred, OIC_JSON_PUBLICDATA_NAME,
177 cJSON_Parse(cred->publicData.data));
181 cJSON_AddStringToObject(jsonCred, OIC_JSON_PUBLICDATA_NAME, cred->publicData.data);
184 #endif /*__WITH_X509__*/
185 //PrivateData -- Not Mandatory
186 if(cred->privateData.data)
189 if (SIGNED_ASYMMETRIC_KEY == cred->credType)
191 cJSON_AddItemToObject(jsonCred, OIC_JSON_PRIVATEDATA_NAME,
192 cJSON_Parse(cred->privateData.data));
196 cJSON_AddStringToObject(jsonCred, OIC_JSON_PRIVATEDATA_NAME, cred->privateData.data);
199 cJSON_AddStringToObject(jsonCred, OIC_JSON_PRIVATEDATA_NAME, cred->privateData.data);
203 //Period -- Not Mandatory
206 cJSON_AddStringToObject(jsonCred, OIC_JSON_PERIOD_NAME,
210 //Owners -- Mandatory
211 cJSON *jsonOwnrArray = NULL;
212 cJSON_AddItemToObject (jsonCred, OIC_JSON_OWNERS_NAME,
213 jsonOwnrArray = cJSON_CreateArray());
214 VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
215 for (size_t i = 0; i < cred->ownersLen; i++)
218 memset(base64Buff, 0, sizeof(base64Buff));
219 b64Ret = b64Encode(cred->owners[i].id, sizeof(cred->owners[i].id),
220 base64Buff, sizeof(base64Buff), &outLen);
221 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
222 cJSON_AddItemToArray (jsonOwnrArray,
223 cJSON_CreateString((char *)(base64Buff)));
226 /* Attach current cred node to cred Array */
227 cJSON_AddItemToArray(jsonCredArray, jsonCred);
231 jsonStr = cJSON_PrintUnformatted(jsonRoot);
237 cJSON_Delete(jsonRoot);
243 * This internal method converts JSON cred into binary cred.
245 OicSecCred_t * JSONToCredBin(const char * jsonStr, const bool isIncResName)
247 OCStackResult ret = OC_STACK_ERROR;
248 OicSecCred_t * headCred = NULL;
249 OicSecCred_t * prevCred = NULL;
250 cJSON *jsonCredArray = NULL;
252 cJSON *jsonRoot = cJSON_Parse(jsonStr);
253 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
257 jsonCredArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_CRED_NAME);
261 jsonCredArray = jsonRoot;
263 VERIFY_NON_NULL(TAG, jsonCredArray, ERROR);
265 if (cJSON_Array == jsonCredArray->type)
267 int numCred = cJSON_GetArraySize(jsonCredArray);
270 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
272 B64Result b64Ret = B64_OK;
274 VERIFY_SUCCESS(TAG, numCred > 0, ERROR);
277 cJSON *jsonCred = cJSON_GetArrayItem(jsonCredArray, idx);
278 VERIFY_NON_NULL(TAG, jsonCred, ERROR);
280 OicSecCred_t *cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
281 VERIFY_NON_NULL(TAG, cred, ERROR);
283 headCred = (headCred) ? headCred : cred;
286 prevCred->next = cred;
288 size_t jsonObjLen = 0;
289 cJSON *jsonObj = NULL;
291 //CredId -- Mandatory
292 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_CREDID_NAME);
295 VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
296 cred->credId = jsonObj->valueint;
299 //subject -- Mandatory
300 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_SUBJECTID_NAME);
301 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
302 VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
304 memset(base64Buff, 0, sizeof(base64Buff));
305 b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring),
306 base64Buff, sizeof(base64Buff), &outLen);
307 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(cred->subject.id)),
309 memcpy(cred->subject.id, base64Buff, outLen);
311 //CredType -- Mandatory
312 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_CREDTYPE_NAME);
313 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
314 VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
315 cred->credType = (OicSecCredType_t)jsonObj->valueint;
317 //PrivateData is mandatory for some of the credential types listed below.
318 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PRIVATEDATA_NAME);
319 if ((cred->credType & SYMMETRIC_PAIR_WISE_KEY) ||
320 (cred->credType & SYMMETRIC_GROUP_KEY) ||
321 (cred->credType & PIN_PASSWORD))
323 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
324 VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
327 else if (cred->credType & SIGNED_ASYMMETRIC_KEY)
329 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
330 VERIFY_SUCCESS(TAG, cJSON_Object == jsonObj->type, ERROR);
332 #endif // __WITH_X509__
335 if (cJSON_String == jsonObj->type)
337 jsonObjLen = strlen(jsonObj->valuestring) + 1;
338 cred->privateData.data = (char *)OICMalloc(jsonObjLen);
339 VERIFY_NON_NULL(TAG, (cred->privateData.data), ERROR);
340 strncpy((char *)cred->privateData.data, (char *)jsonObj->valuestring, jsonObjLen);
343 else if (SIGNED_ASYMMETRIC_KEY == cred->credType && cJSON_Object == jsonObj->type)
345 cred->privateData.data = cJSON_PrintUnformatted(jsonObj);
346 VERIFY_NON_NULL(TAG, (cred->privateData.data), ERROR);
348 #endif // __WITH_X509__
351 //PublicData is mandatory only for SIGNED_ASYMMETRIC_KEY credentials type.
352 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PUBLICDATA_NAME);
354 if (cred->credType & SIGNED_ASYMMETRIC_KEY)
356 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
357 VERIFY_SUCCESS(TAG, cJSON_Object == jsonObj->type, ERROR);
359 #endif // __WITH_X509__
362 if (cJSON_String == jsonObj->type)
364 jsonObjLen = strlen(jsonObj->valuestring) + 1;
365 cred->publicData.data = (char *)OICMalloc(jsonObjLen);
366 VERIFY_NON_NULL(TAG, (cred->publicData.data), ERROR);
367 strncpy((char *)cred->publicData.data, (char *)jsonObj->valuestring, jsonObjLen);
370 else if (SIGNED_ASYMMETRIC_KEY == cred->credType && cJSON_Object == jsonObj->type)
372 cred->publicData.data = cJSON_PrintUnformatted(jsonObj);
373 VERIFY_NON_NULL(TAG, (cred->publicData.data), ERROR);
375 #endif // __WITH_X509__
378 //Period -- Not Mandatory
379 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PERIOD_NAME);
380 if(jsonObj && cJSON_String == jsonObj->type)
382 jsonObjLen = strlen(jsonObj->valuestring) + 1;
383 cred->period = (char *)OICMalloc(jsonObjLen);
384 VERIFY_NON_NULL(TAG, cred->period, ERROR);
385 strncpy(cred->period, jsonObj->valuestring, jsonObjLen);
388 //Owners -- Mandatory
389 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_OWNERS_NAME);
390 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
391 VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
392 cred->ownersLen = cJSON_GetArraySize(jsonObj);
393 VERIFY_SUCCESS(TAG, cred->ownersLen > 0, ERROR);
394 cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
395 VERIFY_NON_NULL(TAG, (cred->owners), ERROR);
396 for(size_t i = 0; i < cred->ownersLen; i++)
398 cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, i);
399 VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
400 VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
402 memset(base64Buff, 0, sizeof(base64Buff));
403 b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring),
404 base64Buff, sizeof(base64Buff), &outLen);
405 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK &&
406 outLen <= sizeof(cred->owners[i].id)), ERROR);
407 memcpy(cred->owners[i].id, base64Buff, outLen);
410 } while( ++idx < numCred);
416 cJSON_Delete(jsonRoot);
417 if (OC_STACK_OK != ret)
419 DeleteCredList(headCred);
426 * This function generates the bin credential data.
428 * @param subject pointer to subject of this credential.
429 * @param credType credential type.
430 * @param publicData public data such as public key.
431 * @param privateData private data such as private key.
432 * The privateData is expected in base64 encoded format.
433 * @param ownersLen length of owners array
434 * @param owners array of owners.
437 * pointer to instance of OicSecCred_t - success
440 OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t credType,
441 const char * publicData, const char * privateData,
442 size_t ownersLen, const OicUuid_t * owners)
445 OCStackResult ret = OC_STACK_ERROR;
447 OicSecCred_t *cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
448 VERIFY_NON_NULL(TAG, cred, ERROR);
450 //CredId is assigned before appending new cred to the existing
451 //credential list and updating svr database in AddCredential().
454 VERIFY_NON_NULL(TAG, subject, ERROR);
455 memcpy(cred->subject.id, subject->id , sizeof(cred->subject.id));
457 VERIFY_SUCCESS(TAG, credType < (NO_SECURITY_MODE | SYMMETRIC_PAIR_WISE_KEY |
458 SYMMETRIC_GROUP_KEY | ASYMMETRIC_KEY | SIGNED_ASYMMETRIC_KEY | PIN_PASSWORD), ERROR);
459 cred->credType = credType;
464 cred->publicData.data = (char *)OICMalloc(strlen(publicData)+1);
465 VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
466 strncpy((char *)cred->publicData.data, publicData, strlen(publicData)+1);
468 #endif // __WITH_X509__
472 cred->privateData.data = (char *)OICMalloc(strlen(privateData)+1);
473 VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
474 strncpy((char *)cred->privateData.data, privateData, strlen(privateData)+1);
477 VERIFY_SUCCESS(TAG, ownersLen > 0, ERROR);
478 cred->ownersLen = ownersLen;
480 cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
481 VERIFY_NON_NULL(TAG, cred->owners, ERROR);
482 for(size_t i = 0; i < cred->ownersLen; i++)
484 memcpy(cred->owners[i].id, owners[i].id, sizeof(cred->owners[i].id));
489 if (OC_STACK_OK != ret)
491 DeleteCredList(cred);
497 static bool UpdatePersistentStorage(const OicSecCred_t *cred)
501 // Convert Cred data into JSON for update to persistent storage
502 char *jsonStr = BinToCredJSON(cred, true);
505 cJSON *jsonCred = cJSON_Parse(jsonStr);
509 (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, jsonCred)))
513 cJSON_Delete(jsonCred );
515 else //Empty cred list
517 if (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, NULL))
526 * Compare function used LL_SORT for sorting credentials
528 * @param first pointer to OicSecCred_t struct
529 * @param second pointer to OicSecCred_t struct
532 * -1 if credId of first is less than credId of second
533 * 0 if credId of first is equal to credId of second
534 * 1 if credId of first is greater than credId of second
536 static int CmpCredId(const OicSecCred_t * first, const OicSecCred_t *second)
538 if(first->credId < second->credId)
542 else if(first->credId > second->credId)
551 * GetCredId goes through the cred list and returns the next
552 * available credId. The next credId could be the credId that is
553 * available due deletion of OicSecCred_t object or one more than
554 * credId of last credential in the list.
557 * next available credId - success
561 static uint16_t GetCredId()
563 //Sorts credential list in incremental order of credId
564 LL_SORT(gCred, CmpCredId);
567 OicSecCred_t *currentCred = NULL, *credTmp = NULL;
568 uint16_t nextCredId = 1;
570 LL_FOREACH_SAFE(gCred, currentCred, credTmp)
572 if(currentCred->credId == nextCredId)
582 VERIFY_SUCCESS(TAG, nextCredId < UINT16_MAX, ERROR);
590 * Get the default value
591 * @retval NULL for now. Update it when we finalize the default info.
593 static OicSecCred_t* GetCredDefault()
599 * This function adds the new cred to the credential list.
601 * @param cred pointer to new credential.
604 * OC_STACK_OK - cred not NULL and persistent storage gets updated
605 * OC_STACK_ERROR - cred is NULL or fails to update persistent storage
607 OCStackResult AddCredential(OicSecCred_t * newCred)
609 OCStackResult ret = OC_STACK_ERROR;
611 VERIFY_SUCCESS(TAG, NULL != newCred, ERROR);
613 //Assigning credId to the newCred
614 newCred->credId = GetCredId();
616 VERIFY_SUCCESS(TAG, newCred->credId != 0, ERROR);
618 //Append the new Cred to existing list
619 LL_APPEND(gCred, newCred);
621 if(UpdatePersistentStorage(gCred))
630 OCStackResult RemoveCredential(const OicUuid_t *subject)
632 OCStackResult ret = OC_STACK_ERROR;
633 OicSecCred_t *cred = NULL;
634 OicSecCred_t *tempCred = NULL;
635 bool deleteFlag = false;
637 LL_FOREACH_SAFE(gCred, cred, tempCred)
639 if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
641 LL_DELETE(gCred, cred);
649 if(UpdatePersistentStorage(gCred))
651 ret = OC_STACK_RESOURCE_DELETED;
659 * Remove all credential data on credential resource and persistent storage
662 * OC_STACK_OK - no errors
663 * OC_STACK_ERROR - stack process error
665 OCStackResult RemoveAllCredentials(void)
667 DeleteCredList(gCred);
668 gCred = GetCredDefault();
670 if(!UpdatePersistentStorage(gCred))
672 return OC_STACK_ERROR;
677 static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
679 OCEntityHandlerResult ret = OC_EH_ERROR;
681 //Get binary representation of json
682 OicSecCred_t * cred = JSONToCredBin(((OCSecurityPayload*)ehRequest->payload)->securityData, false);
686 //If the Post request credential has credId, it will be
687 //discarded and the next available credId will be assigned
688 //to it before getting appended to the existing credential
689 //list and updating svr database.
690 ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
695 static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
697 OC_LOG(DEBUG, TAG, "Processing CredDeleteRequest");
699 OCEntityHandlerResult ehRet = OC_EH_ERROR;
701 if(NULL == ehRequest->query)
706 OicParseQueryIter_t parseIter = {.attrPos=NULL};
707 OicUuid_t subject = {.id={0}};
709 //Parsing REST query to get the subject
710 ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
711 while(GetNextQuery(&parseIter))
713 if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECTID_NAME,
714 parseIter.attrLen) == 0)
716 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
718 B64Result b64Ret = B64_OK;
720 b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen,
721 base64Buff, sizeof(base64Buff), &outLen);
723 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(subject.id)), ERROR);
724 memcpy(subject.id, base64Buff, outLen);
728 if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
730 ehRet = OC_EH_RESOURCE_DELETED;
738 * This internal method is the entity handler for Cred resources
739 * to handle REST request (PUT/POST/DEL)
741 OCEntityHandlerResult CredEntityHandler (OCEntityHandlerFlag flag,
742 OCEntityHandlerRequest * ehRequest,
743 void* callbackParameter)
745 (void)callbackParameter;
746 OCEntityHandlerResult ret = OC_EH_ERROR;
752 if (flag & OC_REQUEST_FLAG)
754 OC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
755 //TODO : Handle PUT/DEL methods
756 switch(ehRequest->method)
759 ret = OC_EH_FORBIDDEN;
762 ret = HandlePostRequest(ehRequest);
765 ret = HandleDeleteRequest(ehRequest);
773 //Send payload to request originator
774 ret = (SendSRMResponse(ehRequest, ret, NULL) == OC_STACK_OK ?
781 * This internal method is used to create '/oic/sec/Cred' resource.
783 OCStackResult CreateCredResource()
787 ret = OCCreateResource(&gCredHandle,
788 OIC_RSRC_TYPE_SEC_CRED,
795 if (OC_STACK_OK != ret)
797 OC_LOG (FATAL, TAG, "Unable to instantiate Cred resource");
798 DeInitCredResource();
804 * Initialize Cred resource by loading data from persistent storage.
807 * OC_STACK_OK - no errors
808 * OC_STACK_ERROR - stack process error
810 OCStackResult InitCredResource()
812 OCStackResult ret = OC_STACK_ERROR;
814 //Read Cred resource from PS
815 char* jsonSVRDatabase = GetSVRDatabase();
819 //Convert JSON Cred into binary format
820 gCred = JSONToCredBin(jsonSVRDatabase, true);
823 * If SVR database in persistent storage got corrupted or
824 * is not available for some reason, a default Cred is created
825 * which allows user to initiate Cred provisioning again.
827 if (!jsonSVRDatabase || !gCred)
829 gCred = GetCredDefault();
831 //Instantiate 'oic.sec.cred'
832 ret = CreateCredResource();
833 OICFree(jsonSVRDatabase);
838 * Perform cleanup for Cred resources.
841 * OC_STACK_OK - no errors
842 * OC_STACK_ERROR - stack process error
843 * OC_STACK_NO_RESOURCE - resource not found
844 * OC_STACK_INVALID_PARAM - invalid param
846 OCStackResult DeInitCredResource()
848 OCStackResult result = OCDeleteResource(gCredHandle);
849 DeleteCredList(gCred);
855 * This method is used by tinydtls/SRM to retrieve credential for given Subject.
857 * @param subject - subject for which credential is required.
860 * reference to OicSecCred_t - if credential is found
861 * NULL - if credential not found
863 const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
865 OicSecCred_t *cred = NULL;
867 if ( NULL == subject)
872 LL_FOREACH(gCred, cred)
874 if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
883 #if defined(__WITH_DTLS__)
885 * This internal callback is used by lower stack (i.e. CA layer) to
886 * retrieve PSK credentials from RI security layer.
888 * @param[in] type type of PSK data required by tinyDTLS layer during DTLS handshake.
889 * @param[in] desc Additional request information.
890 * @param[in] desc_len The actual length of desc.
891 * @param[out] result Must be filled with the requested information.
892 * @param[in] result_length Maximum size of @p result.
894 * @return The number of bytes written to @p result or a value
895 * less than zero on error.
897 int32_t GetDtlsPskCredentials( CADtlsPskCredType_t type,
898 const unsigned char *desc, size_t desc_len,
899 unsigned char *result, size_t result_length)
910 case CA_DTLS_PSK_HINT:
911 case CA_DTLS_PSK_IDENTITY:
913 OicUuid_t deviceID = {.id={}};
914 // Retrieve Device ID from doxm resource
915 if ( OC_STACK_OK != GetDoxmDeviceID(&deviceID) )
917 OC_LOG (ERROR, TAG, "Unable to retrieve doxm Device ID");
921 if (result_length < sizeof(deviceID.id))
923 OC_LOG (ERROR, TAG, "Wrong value for result_length");
926 memcpy(result, deviceID.id, sizeof(deviceID.id));
927 return (sizeof(deviceID.id));
931 case CA_DTLS_PSK_KEY:
933 OicSecCred_t *cred = NULL;
934 LL_FOREACH(gCred, cred)
936 if (cred->credType != SYMMETRIC_PAIR_WISE_KEY)
941 if ((desc_len == sizeof(cred->subject.id)) &&
942 (memcmp(desc, cred->subject.id, sizeof(cred->subject.id)) == 0))
945 * If the credentials are valid for limited time,
946 * check their expiry.
950 if(IOTVTICAL_VALID_ACCESS != IsRequestWithinValidTime(cred->period, NULL))
952 OC_LOG (INFO, TAG, "Credentials are expired.");
958 // Convert PSK from Base64 encoding to binary before copying
960 B64Result b64Ret = b64Decode(cred->privateData.data,
961 strlen(cred->privateData.data), result,
962 result_length, &outLen);
963 if (B64_OK != b64Ret)
965 OC_LOG (ERROR, TAG, "Base64 decoding failed.");
977 OC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
987 * Add temporal PSK to PIN based OxM
989 * @param[in] tmpSubject UUID of target device
990 * @param[in] credType Type of credential to be added
991 * @param[in] pin numeric characters
992 * @param[in] pinSize length of 'pin'
993 * @param[in] ownersLen Number of owners
994 * @param[in] owners Array of owners
995 * @param[out] tmpCredSubject Generated credential's subject.
997 * @return OC_STACK_OK for success and errorcode otherwise.
999 OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
1000 const char * pin, size_t pinSize,
1001 size_t ownersLen, const OicUuid_t * owners, OicUuid_t* tmpCredSubject)
1003 OCStackResult ret = OC_STACK_ERROR;
1005 if(tmpSubject == NULL || pin == NULL || pinSize == 0 || tmpCredSubject == NULL)
1007 return OC_STACK_INVALID_PARAM;
1010 uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
1011 int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, owners->id,
1012 UUID_LENGTH, PBKDF_ITERATIONS,
1013 OWNER_PSK_LENGTH_128, privData);
1014 VERIFY_SUCCESS(TAG, (dtlsRes == 0) , ERROR);
1016 uint32_t outLen = 0;
1017 char base64Buff[B64ENCODE_OUT_SAFESIZE(OWNER_PSK_LENGTH_128) + 1] = {};
1018 B64Result b64Ret = b64Encode(privData, OWNER_PSK_LENGTH_128, base64Buff,
1019 sizeof(base64Buff), &outLen);
1020 VERIFY_SUCCESS(TAG, (B64_OK == b64Ret), ERROR);
1022 OicSecCred_t* cred = GenerateCredential(tmpSubject, credType, NULL,
1023 base64Buff, ownersLen, owners);
1026 OC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
1027 return OC_STACK_ERROR;
1030 memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
1032 ret = AddCredential(cred);
1033 if( OC_STACK_OK != ret)
1035 OC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
1042 #endif /* __WITH_DTLS__ */
1043 #ifdef __WITH_X509__
1044 #define CERT_LEN_PREFIX (3)
1045 #define BYTE_SIZE (8) //bits
1046 #define PUB_KEY_X_COORD ("x")
1047 #define PUB_KEY_Y_COORD ("y")
1048 #define CERTIFICATE ("x5c")
1049 #define PRIVATE_KEY ("d")
1052 static void WriteCertPrefix(uint8_t *prefix, uint32_t certLen)
1054 for (size_t i = 0; i < CERT_LEN_PREFIX; ++i)
1056 prefix[i] = (certLen >> (BYTE_SIZE * (CERT_LEN_PREFIX - 1 - i))) & 0xFF;
1060 static uint32_t ParseCertPrefix(uint8_t *prefix)
1065 for(int i=0; i < CERT_LEN_PREFIX; ++i)
1067 res |= (((uint32_t) prefix[i]) << ((CERT_LEN_PREFIX - 1 -i) * BYTE_SIZE));
1073 static uint32_t appendCert2Chain(uint8_t *appendPoint, char *cert, uint32_t max_len)
1076 VERIFY_NON_NULL(TAG, appendPoint, ERROR);
1077 VERIFY_NON_NULL(TAG, cert, ERROR);
1080 VERIFY_SUCCESS(TAG, B64_OK == b64Decode(cert, strlen(cert), appendPoint + CERT_LEN_PREFIX,
1081 max_len - CERT_LEN_PREFIX, &certLen), ERROR);
1082 WriteCertPrefix(appendPoint, certLen);
1084 ret = certLen + CERT_LEN_PREFIX;
1089 static OCStackResult GetCAPublicKeyData(CADtlsX509Creds_t *credInfo){
1090 OCStackResult ret = OC_STACK_ERROR;
1091 uint8_t *ccPtr = credInfo->certificateChain;
1092 for(uint32_t i =0; i < credInfo->chainLen - 1; ++i)
1094 ccPtr += CERT_LEN_PREFIX + ParseCertPrefix(ccPtr);
1098 .data = ccPtr + CERT_LEN_PREFIX,
1099 .len = ParseCertPrefix(ccPtr)
1101 CertificateX509 certStruct;
1103 VERIFY_SUCCESS(TAG, PKI_SUCCESS == DecodeCertificate(cert, &certStruct), ERROR);
1105 INC_BYTE_ARRAY(certStruct.pubKey, 2);
1107 memcpy(credInfo->rootPublicKeyX, certStruct.pubKey.data, PUBLIC_KEY_SIZE / 2);
1108 memcpy(credInfo->rootPublicKeyY, certStruct.pubKey.data + PUBLIC_KEY_SIZE / 2, PUBLIC_KEY_SIZE / 2);
1115 static OCStackResult GetCertCredPublicData(CADtlsX509Creds_t *credInfo, OicSecCred_t *cred)
1117 OCStackResult ret = OC_STACK_ERROR;
1118 VERIFY_NON_NULL(TAG, credInfo, ERROR);
1119 VERIFY_NON_NULL(TAG, cred, ERROR);
1120 VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
1121 //VERIFY_SUCCESS(TAG, NULL == credInfo->certificateChain.data, ERROR);
1122 cJSON *jsonRoot = cJSON_Parse(cred->publicData.data);
1123 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
1125 //Get certificate chain
1126 cJSON *jsonObj = cJSON_GetObjectItem(jsonRoot, CERTIFICATE);//TODO define field names constants
1127 VERIFY_SUCCESS(TAG, NULL != jsonObj && cJSON_Array == jsonObj->type, ERROR);
1129 size_t certChainLen = cJSON_GetArraySize(jsonObj);
1130 credInfo->chainLen = certChainLen;
1131 VERIFY_SUCCESS(TAG, MAX_CHAIN_LEN >= certChainLen, ERROR);
1134 for (size_t i = 0; i < certChainLen; ++i)
1136 cJSON *item = cJSON_GetArrayItem(jsonObj, i);
1137 VERIFY_SUCCESS(TAG, cJSON_String == item->type, ERROR);
1138 uint32_t appendedLen = appendCert2Chain(credInfo->certificateChain + len, item->valuestring,
1139 MAX_CERT_MESSAGE_LEN - len);
1140 VERIFY_SUCCESS(TAG, 0 != appendedLen, ERROR);
1143 credInfo->certificateChainLen = len;
1144 VERIFY_SUCCESS(TAG, OC_STACK_OK == GetCAPublicKeyData(credInfo), ERROR);
1147 cJSON_Delete(jsonRoot);
1151 static OCStackResult GetCertCredPrivateData(CADtlsX509Creds_t *credInfo, OicSecCred_t *cred)
1153 OCStackResult ret = OC_STACK_ERROR;
1154 VERIFY_NON_NULL(TAG, credInfo, ERROR);
1155 VERIFY_NON_NULL(TAG, cred, ERROR);
1156 VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
1157 cJSON *jsonRoot = cJSON_Parse(cred->privateData.data);
1158 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
1160 cJSON *jsonObj = cJSON_GetObjectItem(jsonRoot, PRIVATE_KEY);//TODO define field names constants
1161 VERIFY_SUCCESS(TAG, NULL != jsonObj && cJSON_String == jsonObj->type, ERROR);
1164 VERIFY_SUCCESS(TAG, B64_OK == b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring),
1165 credInfo->devicePrivateKey, PRIVATE_KEY_SIZE, &read)
1166 && PRIVATE_KEY_SIZE == read, ERROR);
1171 cJSON_Delete(jsonRoot);
1175 int GetDtlsX509Credentials(CADtlsX509Creds_t *credInfo)
1178 VERIFY_NON_NULL(TAG, credInfo, ERROR);
1181 VERIFY_SUCCESS(TAG, OC_STACK_OK == InitCredResource(), ERROR);
1184 OicSecCred_t *cred = NULL;
1185 LL_SEARCH_SCALAR(gCred, cred, credType, SIGNED_ASYMMETRIC_KEY);
1186 VERIFY_NON_NULL(TAG, cred, ERROR);
1188 VERIFY_SUCCESS(TAG, OC_STACK_OK == GetCertCredPrivateData(credInfo, cred), ERROR);
1189 VERIFY_SUCCESS(TAG, OC_STACK_OK == GetCertCredPublicData(credInfo, cred), ERROR);
1196 #undef CERT_LEN_PREFIX
1197 #endif /* __WITH_X509__ */