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 OIC_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.
104 * pointer to JSON credential representation - if credential for subjectId found
105 * NULL - if credential for subjectId not found
107 char * BinToCredJSON(const OicSecCred_t * cred)
109 cJSON *jsonRoot = NULL;
110 char *jsonStr = NULL;
114 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
116 B64Result b64Ret = B64_OK;
118 jsonRoot = cJSON_CreateObject();
119 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
121 cJSON *jsonCredArray = NULL;
122 cJSON_AddItemToObject(jsonRoot, OIC_JSON_CRED_NAME,
123 jsonCredArray = cJSON_CreateArray());
124 VERIFY_NON_NULL(TAG, jsonCredArray, ERROR);
128 cJSON *jsonCred = cJSON_CreateObject();
129 VERIFY_NON_NULL(TAG, jsonCred, ERROR);
131 //CredID -- Mandatory
132 cJSON_AddNumberToObject(jsonCred, OIC_JSON_CREDID_NAME, (int)cred->credId);
134 //Subject -- Mandatory
136 memset(base64Buff, 0, sizeof(base64Buff));
137 b64Ret = b64Encode(cred->subject.id, sizeof(cred->subject.id), base64Buff,
138 sizeof(base64Buff), &outLen);
139 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
140 cJSON_AddStringToObject(jsonCred, OIC_JSON_SUBJECT_NAME, base64Buff);
142 //Note: Need further clarification on roleID data type
144 //RoleId -- Not Mandatory
145 if(cred->roleIdsLen > 0)
147 cJSON *jsonRoleIdsArray = NULL;
148 cJSON_AddItemToObject (jsonCred, OIC_JSON_ROLEIDS_NAME,
149 jsonRoleIdsArray = cJSON_CreateArray());
150 VERIFY_NON_NULL(TAG, jsonRoleIdsArray, ERROR);
151 for (size_t i = 0; i < cred->roleIdsLen; i++)
153 cJSON_AddItemToArray (jsonRoleIdsArray,
154 cJSON_CreateString((char *)cred->roleIds[i].id));
159 //CredType -- Mandatory
160 cJSON_AddNumberToObject(jsonCred, OIC_JSON_CREDTYPE_NAME,(int)cred->credType);
163 //PublicData -- Not Mandatory
164 if(cred->publicData.data)
166 if (SIGNED_ASYMMETRIC_KEY == cred->credType)
168 cJSON_AddItemToObject(jsonCred, OIC_JSON_PUBLICDATA_NAME,
169 cJSON_Parse(cred->publicData.data));
173 cJSON_AddStringToObject(jsonCred, OIC_JSON_PUBLICDATA_NAME, cred->publicData.data);
176 #endif /*__WITH_X509__*/
177 //PrivateData -- Not Mandatory
178 if(cred->privateData.data)
181 if (SIGNED_ASYMMETRIC_KEY == cred->credType)
183 cJSON_AddItemToObject(jsonCred, OIC_JSON_PRIVATEDATA_NAME,
184 cJSON_Parse(cred->privateData.data));
188 cJSON_AddStringToObject(jsonCred, OIC_JSON_PRIVATEDATA_NAME, cred->privateData.data);
191 cJSON_AddStringToObject(jsonCred, OIC_JSON_PRIVATEDATA_NAME, cred->privateData.data);
195 //Period -- Not Mandatory
198 cJSON_AddStringToObject(jsonCred, OIC_JSON_PERIOD_NAME,
202 //Owners -- Mandatory
203 cJSON *jsonOwnrArray = NULL;
204 cJSON_AddItemToObject (jsonCred, OIC_JSON_OWNERS_NAME,
205 jsonOwnrArray = cJSON_CreateArray());
206 VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
207 for (size_t i = 0; i < cred->ownersLen; i++)
210 memset(base64Buff, 0, sizeof(base64Buff));
211 b64Ret = b64Encode(cred->owners[i].id, sizeof(cred->owners[i].id),
212 base64Buff, sizeof(base64Buff), &outLen);
213 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
214 cJSON_AddItemToArray (jsonOwnrArray,
215 cJSON_CreateString((char *)(base64Buff)));
218 /* Attach current cred node to cred Array */
219 cJSON_AddItemToArray(jsonCredArray, jsonCred);
223 jsonStr = cJSON_PrintUnformatted(jsonRoot);
229 cJSON_Delete(jsonRoot);
235 * This internal method converts JSON cred into binary cred.
237 OicSecCred_t * JSONToCredBin(const char * jsonStr)
239 OCStackResult ret = OC_STACK_ERROR;
240 OicSecCred_t * headCred = NULL;
241 OicSecCred_t * prevCred = NULL;
242 cJSON *jsonCredArray = NULL;
244 cJSON *jsonRoot = cJSON_Parse(jsonStr);
245 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
247 jsonCredArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_CRED_NAME);
248 VERIFY_NON_NULL(TAG, jsonCredArray, ERROR);
249 if (cJSON_Array == jsonCredArray->type)
251 int numCred = cJSON_GetArraySize(jsonCredArray);
254 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
256 B64Result b64Ret = B64_OK;
258 VERIFY_SUCCESS(TAG, numCred > 0, ERROR);
261 cJSON *jsonCred = cJSON_GetArrayItem(jsonCredArray, idx);
262 VERIFY_NON_NULL(TAG, jsonCred, ERROR);
264 OicSecCred_t *cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
265 VERIFY_NON_NULL(TAG, cred, ERROR);
267 headCred = (headCred) ? headCred : cred;
270 prevCred->next = cred;
272 size_t jsonObjLen = 0;
273 cJSON *jsonObj = NULL;
275 //CredId -- Mandatory
276 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_CREDID_NAME);
279 VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
280 cred->credId = jsonObj->valueint;
283 //subject -- Mandatory
284 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_SUBJECT_NAME);
285 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
286 VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
288 memset(base64Buff, 0, sizeof(base64Buff));
289 b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring),
290 base64Buff, sizeof(base64Buff), &outLen);
291 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(cred->subject.id)),
293 memcpy(cred->subject.id, base64Buff, outLen);
295 //CredType -- Mandatory
296 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_CREDTYPE_NAME);
297 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
298 VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
299 cred->credType = (OicSecCredType_t)jsonObj->valueint;
301 //PrivateData is mandatory for some of the credential types listed below.
302 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PRIVATEDATA_NAME);
303 if ((cred->credType & SYMMETRIC_PAIR_WISE_KEY) ||
304 (cred->credType & SYMMETRIC_GROUP_KEY) ||
305 (cred->credType & PIN_PASSWORD))
307 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
308 VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
311 else if (cred->credType & SIGNED_ASYMMETRIC_KEY)
313 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
314 VERIFY_SUCCESS(TAG, cJSON_Object == jsonObj->type, ERROR);
316 #endif // __WITH_X509__
319 if (cJSON_String == jsonObj->type)
321 jsonObjLen = strlen(jsonObj->valuestring) + 1;
322 cred->privateData.data = (char *)OICMalloc(jsonObjLen);
323 VERIFY_NON_NULL(TAG, (cred->privateData.data), ERROR);
324 strncpy((char *)cred->privateData.data, (char *)jsonObj->valuestring, jsonObjLen);
327 else if (SIGNED_ASYMMETRIC_KEY == cred->credType && cJSON_Object == jsonObj->type)
329 cred->privateData.data = cJSON_PrintUnformatted(jsonObj);
330 VERIFY_NON_NULL(TAG, (cred->privateData.data), ERROR);
332 #endif // __WITH_X509__
335 //PublicData is mandatory only for SIGNED_ASYMMETRIC_KEY credentials type.
336 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PUBLICDATA_NAME);
338 if (cred->credType & SIGNED_ASYMMETRIC_KEY)
340 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
341 VERIFY_SUCCESS(TAG, cJSON_Object == jsonObj->type, ERROR);
343 #endif // __WITH_X509__
346 if (cJSON_String == jsonObj->type)
348 jsonObjLen = strlen(jsonObj->valuestring) + 1;
349 cred->publicData.data = (char *)OICMalloc(jsonObjLen);
350 VERIFY_NON_NULL(TAG, (cred->publicData.data), ERROR);
351 strncpy((char *)cred->publicData.data, (char *)jsonObj->valuestring, jsonObjLen);
354 else if (SIGNED_ASYMMETRIC_KEY == cred->credType && cJSON_Object == jsonObj->type)
356 cred->publicData.data = cJSON_PrintUnformatted(jsonObj);
357 VERIFY_NON_NULL(TAG, (cred->publicData.data), ERROR);
359 #endif // __WITH_X509__
362 //Period -- Not Mandatory
363 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PERIOD_NAME);
364 if(jsonObj && cJSON_String == jsonObj->type)
366 jsonObjLen = strlen(jsonObj->valuestring) + 1;
367 cred->period = (char *)OICMalloc(jsonObjLen);
368 VERIFY_NON_NULL(TAG, cred->period, ERROR);
369 strncpy(cred->period, jsonObj->valuestring, jsonObjLen);
372 //Owners -- Mandatory
373 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_OWNERS_NAME);
374 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
375 VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
376 cred->ownersLen = cJSON_GetArraySize(jsonObj);
377 VERIFY_SUCCESS(TAG, cred->ownersLen > 0, ERROR);
378 cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
379 VERIFY_NON_NULL(TAG, (cred->owners), ERROR);
380 for(size_t i = 0; i < cred->ownersLen; i++)
382 cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, i);
383 VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
384 VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
386 memset(base64Buff, 0, sizeof(base64Buff));
387 b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring),
388 base64Buff, sizeof(base64Buff), &outLen);
389 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK &&
390 outLen <= sizeof(cred->owners[i].id)), ERROR);
391 memcpy(cred->owners[i].id, base64Buff, outLen);
394 } while( ++idx < numCred);
400 cJSON_Delete(jsonRoot);
401 if (OC_STACK_OK != ret)
403 DeleteCredList(headCred);
410 * This function generates the bin credential data.
412 * @param subject pointer to subject of this credential.
413 * @param credType credential type.
414 * @param publicData public data such as public key.
415 * @param privateData private data such as private key.
416 * The privateData is expected in base64 encoded format.
417 * @param ownersLen length of owners array
418 * @param owners array of owners.
421 * pointer to instance of OicSecCred_t - success
424 OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t credType,
425 const char * publicData, const char * privateData,
426 size_t ownersLen, const OicUuid_t * owners)
429 OCStackResult ret = OC_STACK_ERROR;
431 OicSecCred_t *cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
432 VERIFY_NON_NULL(TAG, cred, ERROR);
434 //CredId is assigned before appending new cred to the existing
435 //credential list and updating svr database in AddCredential().
438 VERIFY_NON_NULL(TAG, subject, ERROR);
439 memcpy(cred->subject.id, subject->id , sizeof(cred->subject.id));
441 VERIFY_SUCCESS(TAG, credType < (NO_SECURITY_MODE | SYMMETRIC_PAIR_WISE_KEY |
442 SYMMETRIC_GROUP_KEY | ASYMMETRIC_KEY | SIGNED_ASYMMETRIC_KEY | PIN_PASSWORD), ERROR);
443 cred->credType = credType;
448 cred->publicData.data = (char *)OICMalloc(strlen(publicData)+1);
449 VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
450 strncpy((char *)cred->publicData.data, publicData, strlen(publicData)+1);
452 #endif // __WITH_X509__
456 cred->privateData.data = (char *)OICMalloc(strlen(privateData)+1);
457 VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
458 strncpy((char *)cred->privateData.data, privateData, strlen(privateData)+1);
461 VERIFY_SUCCESS(TAG, ownersLen > 0, ERROR);
462 cred->ownersLen = ownersLen;
464 cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
465 VERIFY_NON_NULL(TAG, cred->owners, ERROR);
466 for(size_t i = 0; i < cred->ownersLen; i++)
468 memcpy(cred->owners[i].id, owners[i].id, sizeof(cred->owners[i].id));
473 if (OC_STACK_OK != ret)
475 DeleteCredList(cred);
481 static bool UpdatePersistentStorage(const OicSecCred_t *cred)
485 // Convert Cred data into JSON for update to persistent storage
486 char *jsonStr = BinToCredJSON(cred);
489 cJSON *jsonCred = cJSON_Parse(jsonStr);
493 (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, jsonCred)))
497 cJSON_Delete(jsonCred );
499 else //Empty cred list
501 if (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, NULL))
510 * Compare function used LL_SORT for sorting credentials
512 * @param first pointer to OicSecCred_t struct
513 * @param second pointer to OicSecCred_t struct
516 * -1 if credId of first is less than credId of second
517 * 0 if credId of first is equal to credId of second
518 * 1 if credId of first is greater than credId of second
520 static int CmpCredId(const OicSecCred_t * first, const OicSecCred_t *second)
522 if(first->credId < second->credId)
526 else if(first->credId > second->credId)
535 * GetCredId goes through the cred list and returns the next
536 * available credId. The next credId could be the credId that is
537 * available due deletion of OicSecCred_t object or one more than
538 * credId of last credential in the list.
541 * next available credId - success
545 static uint16_t GetCredId()
547 //Sorts credential list in incremental order of credId
548 LL_SORT(gCred, CmpCredId);
551 OicSecCred_t *currentCred = NULL, *credTmp = NULL;
552 uint16_t nextCredId = 1;
554 LL_FOREACH_SAFE(gCred, currentCred, credTmp)
556 if(currentCred->credId == nextCredId)
566 VERIFY_SUCCESS(TAG, nextCredId < UINT16_MAX, ERROR);
574 * Get the default value
575 * @retval NULL for now. Update it when we finalize the default info.
577 static OicSecCred_t* GetCredDefault()
583 * This function adds the new cred to the credential list.
585 * @param cred pointer to new credential.
588 * OC_STACK_OK - cred not NULL and persistent storage gets updated
589 * OC_STACK_ERROR - cred is NULL or fails to update persistent storage
591 OCStackResult AddCredential(OicSecCred_t * newCred)
593 OCStackResult ret = OC_STACK_ERROR;
595 VERIFY_SUCCESS(TAG, NULL != newCred, ERROR);
597 //Assigning credId to the newCred
598 newCred->credId = GetCredId();
600 VERIFY_SUCCESS(TAG, newCred->credId != 0, ERROR);
602 //Append the new Cred to existing list
603 LL_APPEND(gCred, newCred);
605 if(UpdatePersistentStorage(gCred))
614 OCStackResult RemoveCredential(const OicUuid_t *subject)
616 OCStackResult ret = OC_STACK_ERROR;
617 OicSecCred_t *cred = NULL;
618 OicSecCred_t *tempCred = NULL;
619 bool deleteFlag = false;
621 LL_FOREACH_SAFE(gCred, cred, tempCred)
623 if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
625 LL_DELETE(gCred, cred);
633 if(UpdatePersistentStorage(gCred))
635 ret = OC_STACK_RESOURCE_DELETED;
643 * Remove all credential data on credential resource and persistent storage
646 * OC_STACK_OK - no errors
647 * OC_STACK_ERROR - stack process error
649 OCStackResult RemoveAllCredentials(void)
651 DeleteCredList(gCred);
652 gCred = GetCredDefault();
654 if(!UpdatePersistentStorage(gCred))
656 return OC_STACK_ERROR;
661 static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
663 OCEntityHandlerResult ret = OC_EH_ERROR;
665 //Get binary representation of json
666 OicSecCred_t * cred = JSONToCredBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
670 //If the Post request credential has credId, it will be
671 //discarded and the next available credId will be assigned
672 //to it before getting appended to the existing credential
673 //list and updating svr database.
674 ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
679 static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
681 OIC_LOG(DEBUG, TAG, "Processing CredDeleteRequest");
683 OCEntityHandlerResult ehRet = OC_EH_ERROR;
685 if(NULL == ehRequest->query)
690 OicParseQueryIter_t parseIter = {.attrPos=NULL};
691 OicUuid_t subject = {.id={0}};
693 //Parsing REST query to get the subject
694 ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
695 while(GetNextQuery(&parseIter))
697 if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME,
698 parseIter.attrLen) == 0)
700 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
702 B64Result b64Ret = B64_OK;
704 b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen,
705 base64Buff, sizeof(base64Buff), &outLen);
707 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(subject.id)), ERROR);
708 memcpy(subject.id, base64Buff, outLen);
712 if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
714 ehRet = OC_EH_RESOURCE_DELETED;
722 * This internal method is the entity handler for Cred resources
723 * to handle REST request (PUT/POST/DEL)
725 OCEntityHandlerResult CredEntityHandler (OCEntityHandlerFlag flag,
726 OCEntityHandlerRequest * ehRequest,
727 void* callbackParameter)
729 (void)callbackParameter;
730 OCEntityHandlerResult ret = OC_EH_ERROR;
736 if (flag & OC_REQUEST_FLAG)
738 OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
739 //TODO : Handle PUT/DEL methods
740 switch(ehRequest->method)
743 ret = OC_EH_FORBIDDEN;
746 ret = HandlePostRequest(ehRequest);
749 ret = HandleDeleteRequest(ehRequest);
757 //Send payload to request originator
758 ret = (SendSRMResponse(ehRequest, ret, NULL) == OC_STACK_OK ?
765 * This internal method is used to create '/oic/sec/Cred' resource.
767 OCStackResult CreateCredResource()
771 ret = OCCreateResource(&gCredHandle,
772 OIC_RSRC_TYPE_SEC_CRED,
779 if (OC_STACK_OK != ret)
781 OIC_LOG (FATAL, TAG, "Unable to instantiate Cred resource");
782 DeInitCredResource();
788 * Initialize Cred resource by loading data from persistent storage.
791 * OC_STACK_OK - no errors
792 * OC_STACK_ERROR - stack process error
794 OCStackResult InitCredResource()
796 OCStackResult ret = OC_STACK_ERROR;
798 //Read Cred resource from PS
799 char* jsonSVRDatabase = GetSVRDatabase();
803 //Convert JSON Cred into binary format
804 gCred = JSONToCredBin(jsonSVRDatabase);
807 * If SVR database in persistent storage got corrupted or
808 * is not available for some reason, a default Cred is created
809 * which allows user to initiate Cred provisioning again.
811 if (!jsonSVRDatabase || !gCred)
813 gCred = GetCredDefault();
815 //Instantiate 'oic.sec.cred'
816 ret = CreateCredResource();
817 OICFree(jsonSVRDatabase);
822 * Perform cleanup for Cred resources.
825 * OC_STACK_OK - no errors
826 * OC_STACK_ERROR - stack process error
827 * OC_STACK_NO_RESOURCE - resource not found
828 * OC_STACK_INVALID_PARAM - invalid param
830 OCStackResult DeInitCredResource()
832 OCStackResult result = OCDeleteResource(gCredHandle);
833 DeleteCredList(gCred);
839 * This method is used by tinydtls/SRM to retrieve credential for given Subject.
841 * @param subject - subject for which credential is required.
844 * reference to OicSecCred_t - if credential is found
845 * NULL - if credential not found
847 const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
849 OicSecCred_t *cred = NULL;
851 if ( NULL == subject)
856 LL_FOREACH(gCred, cred)
858 if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
867 #if defined(__WITH_DTLS__)
869 * This internal callback is used by lower stack (i.e. CA layer) to
870 * retrieve PSK credentials from RI security layer.
872 * @param[in] type type of PSK data required by tinyDTLS layer during DTLS handshake.
873 * @param[in] desc Additional request information.
874 * @param[in] desc_len The actual length of desc.
875 * @param[out] result Must be filled with the requested information.
876 * @param[in] result_length Maximum size of @p result.
878 * @return The number of bytes written to @p result or a value
879 * less than zero on error.
881 int32_t GetDtlsPskCredentials( CADtlsPskCredType_t type,
882 const unsigned char *desc, size_t desc_len,
883 unsigned char *result, size_t result_length)
894 case CA_DTLS_PSK_HINT:
895 case CA_DTLS_PSK_IDENTITY:
897 OicUuid_t deviceID = {.id={}};
898 // Retrieve Device ID from doxm resource
899 if ( OC_STACK_OK != GetDoxmDeviceID(&deviceID) )
901 OIC_LOG (ERROR, TAG, "Unable to retrieve doxm Device ID");
905 if (result_length < sizeof(deviceID.id))
907 OIC_LOG (ERROR, TAG, "Wrong value for result_length");
910 memcpy(result, deviceID.id, sizeof(deviceID.id));
911 return (sizeof(deviceID.id));
915 case CA_DTLS_PSK_KEY:
917 OicSecCred_t *cred = NULL;
918 LL_FOREACH(gCred, cred)
920 if (cred->credType != SYMMETRIC_PAIR_WISE_KEY)
925 if ((desc_len == sizeof(cred->subject.id)) &&
926 (memcmp(desc, cred->subject.id, sizeof(cred->subject.id)) == 0))
929 * If the credentials are valid for limited time,
930 * check their expiry.
934 if(IOTVTICAL_VALID_ACCESS != IsRequestWithinValidTime(cred->period, NULL))
936 OIC_LOG (INFO, TAG, "Credentials are expired.");
942 // Convert PSK from Base64 encoding to binary before copying
944 B64Result b64Ret = b64Decode(cred->privateData.data,
945 strlen(cred->privateData.data), result,
946 result_length, &outLen);
947 if (B64_OK != b64Ret)
949 OIC_LOG (ERROR, TAG, "Base64 decoding failed.");
961 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
971 * Add temporal PSK to PIN based OxM
973 * @param[in] tmpSubject UUID of target device
974 * @param[in] credType Type of credential to be added
975 * @param[in] pin numeric characters
976 * @param[in] pinSize length of 'pin'
977 * @param[in] ownersLen Number of owners
978 * @param[in] owners Array of owners
979 * @param[out] tmpCredSubject Generated credential's subject.
981 * @return OC_STACK_OK for success and errorcode otherwise.
983 OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
984 const char * pin, size_t pinSize,
985 size_t ownersLen, const OicUuid_t * owners, OicUuid_t* tmpCredSubject)
987 OCStackResult ret = OC_STACK_ERROR;
989 if(tmpSubject == NULL || pin == NULL || pinSize == 0 || tmpCredSubject == NULL)
991 return OC_STACK_INVALID_PARAM;
994 uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
995 int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, owners->id,
996 UUID_LENGTH, PBKDF_ITERATIONS,
997 OWNER_PSK_LENGTH_128, privData);
998 VERIFY_SUCCESS(TAG, (dtlsRes == 0) , ERROR);
1000 uint32_t outLen = 0;
1001 char base64Buff[B64ENCODE_OUT_SAFESIZE(OWNER_PSK_LENGTH_128) + 1] = {};
1002 B64Result b64Ret = b64Encode(privData, OWNER_PSK_LENGTH_128, base64Buff,
1003 sizeof(base64Buff), &outLen);
1004 VERIFY_SUCCESS(TAG, (B64_OK == b64Ret), ERROR);
1006 OicSecCred_t* cred = GenerateCredential(tmpSubject, credType, NULL,
1007 base64Buff, ownersLen, owners);
1010 OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
1011 return OC_STACK_ERROR;
1014 memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
1016 ret = AddCredential(cred);
1017 if( OC_STACK_OK != ret)
1019 OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
1026 #endif /* __WITH_DTLS__ */
1027 #ifdef __WITH_X509__
1028 #define CERT_LEN_PREFIX (3)
1029 #define BYTE_SIZE (8) //bits
1030 #define PUB_KEY_X_COORD ("x")
1031 #define PUB_KEY_Y_COORD ("y")
1032 #define CERTIFICATE ("x5c")
1033 #define PRIVATE_KEY ("d")
1036 static void WriteCertPrefix(uint8_t *prefix, uint32_t certLen)
1038 for (size_t i = 0; i < CERT_LEN_PREFIX; ++i)
1040 prefix[i] = (certLen >> (BYTE_SIZE * (CERT_LEN_PREFIX - 1 - i))) & 0xFF;
1044 static uint32_t ParseCertPrefix(uint8_t *prefix)
1049 for(int i=0; i < CERT_LEN_PREFIX; ++i)
1051 res |= (((uint32_t) prefix[i]) << ((CERT_LEN_PREFIX - 1 -i) * BYTE_SIZE));
1057 static uint32_t appendCert2Chain(uint8_t *appendPoint, char *cert, uint32_t max_len)
1060 VERIFY_NON_NULL(TAG, appendPoint, ERROR);
1061 VERIFY_NON_NULL(TAG, cert, ERROR);
1064 VERIFY_SUCCESS(TAG, B64_OK == b64Decode(cert, strlen(cert), appendPoint + CERT_LEN_PREFIX,
1065 max_len - CERT_LEN_PREFIX, &certLen), ERROR);
1066 WriteCertPrefix(appendPoint, certLen);
1068 ret = certLen + CERT_LEN_PREFIX;
1073 static OCStackResult GetCAPublicKeyData(CADtlsX509Creds_t *credInfo){
1074 OCStackResult ret = OC_STACK_ERROR;
1075 uint8_t *ccPtr = credInfo->certificateChain;
1076 for(uint32_t i =0; i < credInfo->chainLen - 1; ++i)
1078 ccPtr += CERT_LEN_PREFIX + ParseCertPrefix(ccPtr);
1082 .data = ccPtr + CERT_LEN_PREFIX,
1083 .len = ParseCertPrefix(ccPtr)
1085 CertificateX509 certStruct;
1087 VERIFY_SUCCESS(TAG, PKI_SUCCESS == DecodeCertificate(cert, &certStruct), ERROR);
1089 INC_BYTE_ARRAY(certStruct.pubKey, 2);
1091 memcpy(credInfo->rootPublicKeyX, certStruct.pubKey.data, PUBLIC_KEY_SIZE / 2);
1092 memcpy(credInfo->rootPublicKeyY, certStruct.pubKey.data + PUBLIC_KEY_SIZE / 2, PUBLIC_KEY_SIZE / 2);
1099 static OCStackResult GetCertCredPublicData(CADtlsX509Creds_t *credInfo, OicSecCred_t *cred)
1101 OCStackResult ret = OC_STACK_ERROR;
1102 VERIFY_NON_NULL(TAG, credInfo, ERROR);
1103 VERIFY_NON_NULL(TAG, cred, ERROR);
1104 VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
1105 //VERIFY_SUCCESS(TAG, NULL == credInfo->certificateChain.data, ERROR);
1106 cJSON *jsonRoot = cJSON_Parse(cred->publicData.data);
1107 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
1109 //Get certificate chain
1110 cJSON *jsonObj = cJSON_GetObjectItem(jsonRoot, CERTIFICATE);//TODO define field names constants
1111 VERIFY_SUCCESS(TAG, NULL != jsonObj && cJSON_Array == jsonObj->type, ERROR);
1113 size_t certChainLen = cJSON_GetArraySize(jsonObj);
1114 credInfo->chainLen = certChainLen;
1115 VERIFY_SUCCESS(TAG, MAX_CHAIN_LEN >= certChainLen, ERROR);
1118 for (size_t i = 0; i < certChainLen; ++i)
1120 cJSON *item = cJSON_GetArrayItem(jsonObj, i);
1121 VERIFY_SUCCESS(TAG, cJSON_String == item->type, ERROR);
1122 uint32_t appendedLen = appendCert2Chain(credInfo->certificateChain + len, item->valuestring,
1123 MAX_CERT_MESSAGE_LEN - len);
1124 VERIFY_SUCCESS(TAG, 0 != appendedLen, ERROR);
1127 credInfo->certificateChainLen = len;
1128 VERIFY_SUCCESS(TAG, OC_STACK_OK == GetCAPublicKeyData(credInfo), ERROR);
1131 cJSON_Delete(jsonRoot);
1135 static OCStackResult GetCertCredPrivateData(CADtlsX509Creds_t *credInfo, OicSecCred_t *cred)
1137 OCStackResult ret = OC_STACK_ERROR;
1138 VERIFY_NON_NULL(TAG, credInfo, ERROR);
1139 VERIFY_NON_NULL(TAG, cred, ERROR);
1140 VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
1141 cJSON *jsonRoot = cJSON_Parse(cred->privateData.data);
1142 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
1144 cJSON *jsonObj = cJSON_GetObjectItem(jsonRoot, PRIVATE_KEY);//TODO define field names constants
1145 VERIFY_SUCCESS(TAG, NULL != jsonObj && cJSON_String == jsonObj->type, ERROR);
1148 VERIFY_SUCCESS(TAG, B64_OK == b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring),
1149 credInfo->devicePrivateKey, PRIVATE_KEY_SIZE, &read)
1150 && PRIVATE_KEY_SIZE == read, ERROR);
1155 cJSON_Delete(jsonRoot);
1159 int GetDtlsX509Credentials(CADtlsX509Creds_t *credInfo)
1162 VERIFY_NON_NULL(TAG, credInfo, ERROR);
1165 VERIFY_SUCCESS(TAG, OC_STACK_OK == InitCredResource(), ERROR);
1168 OicSecCred_t *cred = NULL;
1169 LL_SEARCH_SCALAR(gCred, cred, credType, SIGNED_ASYMMETRIC_KEY);
1170 VERIFY_NON_NULL(TAG, cred, ERROR);
1172 VERIFY_SUCCESS(TAG, OC_STACK_OK == GetCertCredPrivateData(credInfo, cred), ERROR);
1173 VERIFY_SUCCESS(TAG, OC_STACK_OK == GetCertCredPublicData(credInfo, cred), ERROR);
1180 #undef CERT_LEN_PREFIX
1181 #endif /* __WITH_X509__ */