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"
39 #include "ocserverrequest.h"
48 #define TAG "SRM-CREDL"
51 static OicSecCred_t *gCred = NULL;
52 static OCResourceHandle gCredHandle = NULL;
55 * This function frees OicSecCred_t object's fields and object itself.
57 static void FreeCred(OicSecCred_t *cred)
61 OIC_LOG (ERROR, TAG, "Invalid Parameter");
64 //Note: Need further clarification on roleID data type
67 OICFree(cred->roleIds);
71 OICFree(cred->publicData.data);
74 OICFree(cred->privateData.data);
77 OICFree(cred->period);
80 OICFree(cred->owners);
82 //Clean Cred node itself
86 void DeleteCredList(OicSecCred_t* cred)
90 OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
91 LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
93 LL_DELETE(cred, credTmp1);
100 * This function converts credential data into JSON format.
101 * Caller needs to invoke 'free' when done using
103 * @param cred pointer to instance of OicSecCred_t structure.
106 * pointer to JSON credential representation - if credential for subjectId found
107 * NULL - if credential for subjectId not found
109 char * BinToCredJSON(const OicSecCred_t * cred)
111 cJSON *jsonRoot = NULL;
112 char *jsonStr = NULL;
116 char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
118 B64Result b64Ret = B64_OK;
120 jsonRoot = cJSON_CreateObject();
121 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
123 cJSON *jsonCredArray = NULL;
124 cJSON_AddItemToObject(jsonRoot, OIC_JSON_CRED_NAME,
125 jsonCredArray = cJSON_CreateArray());
126 VERIFY_NON_NULL(TAG, jsonCredArray, ERROR);
130 cJSON *jsonCred = cJSON_CreateObject();
131 VERIFY_NON_NULL(TAG, jsonCred, ERROR);
133 //CredID -- Mandatory
134 cJSON_AddNumberToObject(jsonCred, OIC_JSON_CREDID_NAME, (int)cred->credId);
136 //Subject -- Mandatory
138 memset(base64Buff, 0, sizeof(base64Buff));
139 b64Ret = b64Encode(cred->subject.id, sizeof(cred->subject.id), base64Buff,
140 sizeof(base64Buff), &outLen);
141 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
142 cJSON_AddStringToObject(jsonCred, OIC_JSON_SUBJECT_NAME, base64Buff);
144 //Note: Need further clarification on roleID data type
146 //RoleId -- Not Mandatory
147 if(cred->roleIdsLen > 0)
149 cJSON *jsonRoleIdsArray = NULL;
150 cJSON_AddItemToObject (jsonCred, OIC_JSON_ROLEIDS_NAME,
151 jsonRoleIdsArray = cJSON_CreateArray());
152 VERIFY_NON_NULL(TAG, jsonRoleIdsArray, ERROR);
153 for (size_t i = 0; i < cred->roleIdsLen; i++)
155 cJSON_AddItemToArray (jsonRoleIdsArray,
156 cJSON_CreateString((char *)cred->roleIds[i].id));
161 //CredType -- Mandatory
162 cJSON_AddNumberToObject(jsonCred, OIC_JSON_CREDTYPE_NAME,(int)cred->credType);
165 //PublicData -- Not Mandatory
166 if(cred->publicData.data)
168 if (SIGNED_ASYMMETRIC_KEY == cred->credType)
170 cJSON_AddItemToObject(jsonCred, OIC_JSON_PUBLICDATA_NAME,
171 cJSON_Parse(cred->publicData.data));
175 cJSON_AddStringToObject(jsonCred, OIC_JSON_PUBLICDATA_NAME, cred->publicData.data);
178 #endif /*__WITH_X509__*/
179 //PrivateData -- Not Mandatory
180 if(cred->privateData.data)
183 if (SIGNED_ASYMMETRIC_KEY == cred->credType)
185 cJSON_AddItemToObject(jsonCred, OIC_JSON_PRIVATEDATA_NAME,
186 cJSON_Parse(cred->privateData.data));
190 cJSON_AddStringToObject(jsonCred, OIC_JSON_PRIVATEDATA_NAME, cred->privateData.data);
193 cJSON_AddStringToObject(jsonCred, OIC_JSON_PRIVATEDATA_NAME, cred->privateData.data);
197 //Period -- Not Mandatory
200 cJSON_AddStringToObject(jsonCred, OIC_JSON_PERIOD_NAME,
204 //Owners -- Mandatory
205 cJSON *jsonOwnrArray = NULL;
206 cJSON_AddItemToObject (jsonCred, OIC_JSON_OWNERS_NAME,
207 jsonOwnrArray = cJSON_CreateArray());
208 VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
209 for (size_t i = 0; i < cred->ownersLen; i++)
212 memset(base64Buff, 0, sizeof(base64Buff));
213 b64Ret = b64Encode(cred->owners[i].id, sizeof(cred->owners[i].id),
214 base64Buff, sizeof(base64Buff), &outLen);
215 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
216 cJSON_AddItemToArray (jsonOwnrArray,
217 cJSON_CreateString((char *)(base64Buff)));
220 /* Attach current cred node to cred Array */
221 cJSON_AddItemToArray(jsonCredArray, jsonCred);
225 jsonStr = cJSON_PrintUnformatted(jsonRoot);
231 cJSON_Delete(jsonRoot);
237 * This internal method converts JSON cred into binary cred.
239 OicSecCred_t * JSONToCredBin(const char * jsonStr)
241 OCStackResult ret = OC_STACK_ERROR;
242 OicSecCred_t * headCred = NULL;
243 OicSecCred_t * prevCred = NULL;
244 cJSON *jsonCredArray = NULL;
246 cJSON *jsonRoot = cJSON_Parse(jsonStr);
247 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
249 jsonCredArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_CRED_NAME);
250 VERIFY_NON_NULL(TAG, jsonCredArray, ERROR);
251 if (cJSON_Array == jsonCredArray->type)
253 int numCred = cJSON_GetArraySize(jsonCredArray);
256 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
258 B64Result b64Ret = B64_OK;
260 VERIFY_SUCCESS(TAG, numCred > 0, ERROR);
263 cJSON *jsonCred = cJSON_GetArrayItem(jsonCredArray, idx);
264 VERIFY_NON_NULL(TAG, jsonCred, ERROR);
266 OicSecCred_t *cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
267 VERIFY_NON_NULL(TAG, cred, ERROR);
269 headCred = (headCred) ? headCred : cred;
272 prevCred->next = cred;
274 size_t jsonObjLen = 0;
275 cJSON *jsonObj = NULL;
277 //CredId -- Mandatory
278 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_CREDID_NAME);
281 VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
282 cred->credId = jsonObj->valueint;
285 //subject -- Mandatory
286 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_SUBJECT_NAME);
287 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
288 VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
290 memset(base64Buff, 0, sizeof(base64Buff));
291 b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring),
292 base64Buff, sizeof(base64Buff), &outLen);
293 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(cred->subject.id)),
295 memcpy(cred->subject.id, base64Buff, outLen);
297 //CredType -- Mandatory
298 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_CREDTYPE_NAME);
299 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
300 VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
301 cred->credType = (OicSecCredType_t)jsonObj->valueint;
303 //PrivateData is mandatory for some of the credential types listed below.
304 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PRIVATEDATA_NAME);
305 if ((cred->credType & SYMMETRIC_PAIR_WISE_KEY) ||
306 (cred->credType & SYMMETRIC_GROUP_KEY) ||
307 (cred->credType & PIN_PASSWORD))
309 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
310 VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
313 else if (cred->credType & SIGNED_ASYMMETRIC_KEY)
315 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
316 VERIFY_SUCCESS(TAG, cJSON_Object == jsonObj->type, ERROR);
318 #endif // __WITH_X509__
321 if (cJSON_String == jsonObj->type)
323 jsonObjLen = strlen(jsonObj->valuestring) + 1;
324 cred->privateData.data = (char *)OICMalloc(jsonObjLen);
325 VERIFY_NON_NULL(TAG, (cred->privateData.data), ERROR);
326 strncpy((char *)cred->privateData.data, (char *)jsonObj->valuestring, jsonObjLen);
329 else if (SIGNED_ASYMMETRIC_KEY == cred->credType && cJSON_Object == jsonObj->type)
331 cred->privateData.data = cJSON_PrintUnformatted(jsonObj);
332 VERIFY_NON_NULL(TAG, (cred->privateData.data), ERROR);
334 #endif // __WITH_X509__
337 //PublicData is mandatory only for SIGNED_ASYMMETRIC_KEY credentials type.
338 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PUBLICDATA_NAME);
340 if (cred->credType & SIGNED_ASYMMETRIC_KEY)
342 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
343 VERIFY_SUCCESS(TAG, cJSON_Object == jsonObj->type, ERROR);
345 #endif // __WITH_X509__
348 if (cJSON_String == jsonObj->type)
350 jsonObjLen = strlen(jsonObj->valuestring) + 1;
351 cred->publicData.data = (char *)OICMalloc(jsonObjLen);
352 VERIFY_NON_NULL(TAG, (cred->publicData.data), ERROR);
353 strncpy((char *)cred->publicData.data, (char *)jsonObj->valuestring, jsonObjLen);
356 else if (SIGNED_ASYMMETRIC_KEY == cred->credType && cJSON_Object == jsonObj->type)
358 cred->publicData.data = cJSON_PrintUnformatted(jsonObj);
359 VERIFY_NON_NULL(TAG, (cred->publicData.data), ERROR);
361 #endif // __WITH_X509__
364 //Period -- Not Mandatory
365 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PERIOD_NAME);
366 if(jsonObj && cJSON_String == jsonObj->type)
368 jsonObjLen = strlen(jsonObj->valuestring) + 1;
369 cred->period = (char *)OICMalloc(jsonObjLen);
370 VERIFY_NON_NULL(TAG, cred->period, ERROR);
371 strncpy(cred->period, jsonObj->valuestring, jsonObjLen);
374 //Owners -- Mandatory
375 jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_OWNERS_NAME);
376 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
377 VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
378 cred->ownersLen = (size_t)cJSON_GetArraySize(jsonObj);
379 VERIFY_SUCCESS(TAG, cred->ownersLen > 0, ERROR);
380 cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
381 VERIFY_NON_NULL(TAG, (cred->owners), ERROR);
382 for(size_t i = 0; i < cred->ownersLen; i++)
384 cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, i);
385 VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
386 VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
388 memset(base64Buff, 0, sizeof(base64Buff));
389 b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring),
390 base64Buff, sizeof(base64Buff), &outLen);
391 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK &&
392 outLen <= sizeof(cred->owners[i].id)), ERROR);
393 memcpy(cred->owners[i].id, base64Buff, outLen);
396 } while( ++idx < numCred);
402 cJSON_Delete(jsonRoot);
403 if (OC_STACK_OK != ret)
405 DeleteCredList(headCred);
412 * This function generates the bin credential data.
414 * @param subject pointer to subject of this credential.
415 * @param credType credential type.
416 * @param publicData public data such as public key.
417 * @param privateData private data such as private key.
418 * The privateData is expected in base64 encoded format.
419 * @param ownersLen length of owners array
420 * @param owners array of owners.
423 * pointer to instance of OicSecCred_t - success
426 OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t credType,
427 const char * publicData, const char * privateData,
428 size_t ownersLen, const OicUuid_t * owners)
431 OCStackResult ret = OC_STACK_ERROR;
433 OicSecCred_t *cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
434 VERIFY_NON_NULL(TAG, cred, ERROR);
436 //CredId is assigned before appending new cred to the existing
437 //credential list and updating svr database in AddCredential().
440 VERIFY_NON_NULL(TAG, subject, ERROR);
441 memcpy(cred->subject.id, subject->id , sizeof(cred->subject.id));
443 VERIFY_SUCCESS(TAG, credType < (NO_SECURITY_MODE | SYMMETRIC_PAIR_WISE_KEY |
444 SYMMETRIC_GROUP_KEY | ASYMMETRIC_KEY | SIGNED_ASYMMETRIC_KEY | PIN_PASSWORD), ERROR);
445 cred->credType = credType;
450 cred->publicData.data = (char *)OICMalloc(strlen(publicData)+1);
451 VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
452 strncpy((char *)cred->publicData.data, publicData, strlen(publicData)+1);
454 #endif // __WITH_X509__
458 cred->privateData.data = (char *)OICMalloc(strlen(privateData)+1);
459 VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
460 strncpy((char *)cred->privateData.data, privateData, strlen(privateData)+1);
463 VERIFY_SUCCESS(TAG, ownersLen > 0, ERROR);
464 cred->ownersLen = ownersLen;
466 cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
467 VERIFY_NON_NULL(TAG, cred->owners, ERROR);
468 for(size_t i = 0; i < cred->ownersLen; i++)
470 memcpy(cred->owners[i].id, owners[i].id, sizeof(cred->owners[i].id));
475 if (OC_STACK_OK != ret)
477 DeleteCredList(cred);
483 static bool UpdatePersistentStorage(const OicSecCred_t *cred)
487 // Convert Cred data into JSON for update to persistent storage
488 char *jsonStr = BinToCredJSON(cred);
491 cJSON *jsonCred = cJSON_Parse(jsonStr);
495 (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, jsonCred)))
499 cJSON_Delete(jsonCred );
501 else //Empty cred list
503 if (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, NULL))
512 * Compare function used LL_SORT for sorting credentials
514 * @param first pointer to OicSecCred_t struct
515 * @param second pointer to OicSecCred_t struct
518 * -1 if credId of first is less than credId of second
519 * 0 if credId of first is equal to credId of second
520 * 1 if credId of first is greater than credId of second
522 static int CmpCredId(const OicSecCred_t * first, const OicSecCred_t *second)
524 if(first->credId < second->credId)
528 else if(first->credId > second->credId)
537 * GetCredId goes through the cred list and returns the next
538 * available credId. The next credId could be the credId that is
539 * available due deletion of OicSecCred_t object or one more than
540 * credId of last credential in the list.
543 * next available credId - success
547 static uint16_t GetCredId()
549 //Sorts credential list in incremental order of credId
550 LL_SORT(gCred, CmpCredId);
553 OicSecCred_t *currentCred = NULL, *credTmp = NULL;
554 uint16_t nextCredId = 1;
556 LL_FOREACH_SAFE(gCred, currentCred, credTmp)
558 if(currentCred->credId == nextCredId)
568 VERIFY_SUCCESS(TAG, nextCredId < UINT16_MAX, ERROR);
576 * Get the default value
577 * @retval NULL for now. Update it when we finalize the default info.
579 static OicSecCred_t* GetCredDefault()
585 * This function adds the new cred to the credential list.
587 * @param cred pointer to new credential.
590 * OC_STACK_OK - cred not NULL and persistent storage gets updated
591 * OC_STACK_ERROR - cred is NULL or fails to update persistent storage
593 OCStackResult AddCredential(OicSecCred_t * newCred)
595 OCStackResult ret = OC_STACK_ERROR;
597 VERIFY_SUCCESS(TAG, NULL != newCred, ERROR);
599 //Assigning credId to the newCred
600 newCred->credId = GetCredId();
602 VERIFY_SUCCESS(TAG, newCred->credId != 0, ERROR);
604 //Append the new Cred to existing list
605 LL_APPEND(gCred, newCred);
607 if(UpdatePersistentStorage(gCred))
616 OCStackResult RemoveCredential(const OicUuid_t *subject)
618 OCStackResult ret = OC_STACK_ERROR;
619 OicSecCred_t *cred = NULL;
620 OicSecCred_t *tempCred = NULL;
621 bool deleteFlag = false;
623 LL_FOREACH_SAFE(gCred, cred, tempCred)
625 if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
627 LL_DELETE(gCred, cred);
635 if(UpdatePersistentStorage(gCred))
637 ret = OC_STACK_RESOURCE_DELETED;
645 * Remove all credential data on credential resource and persistent storage
648 * OC_STACK_OK - no errors
649 * OC_STACK_ERROR - stack process error
651 OCStackResult RemoveAllCredentials(void)
653 DeleteCredList(gCred);
654 gCred = GetCredDefault();
656 if(!UpdatePersistentStorage(gCred))
658 return OC_STACK_ERROR;
665 * Internal function to verify recevied owner PSK.
667 * @param receviedCred recevied Owner Credential from OBT(PT)
668 * @param ownerAdd address of OBT(PT)
669 * @param doxm current device's doxm resource
672 * true valid ower psk
673 * false Invalid owner psk or failed to owner psk verification
675 static bool isValidOwnerPSK(const OicSecCred_t* receviedCred, const CAEndpoint_t* ownerAddr,
676 const OicSecDoxm_t* doxm)
678 //Decode received PSK to verify OwnerPSKs match
679 uint32_t privLen = strlen(receviedCred->privateData.data);
680 size_t b64BufSize = B64DECODE_OUT_SAFESIZE((privLen + 1) * sizeof(char));
681 uint8_t* decodeBuff = OICMalloc(b64BufSize);
682 VERIFY_NON_NULL(TAG, decodeBuff, ERROR);
683 uint32_t decodedSize = 0;
684 B64Result b64Ret = b64Decode(receviedCred->privateData.data, privLen,
685 decodeBuff, b64BufSize, &decodedSize);
686 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
688 //Derive OwnerPSK locally
689 const char* oxmLabel = GetOxmString(doxm->oxmSel);
690 VERIFY_NON_NULL(TAG, oxmLabel, ERROR);
692 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
693 CAResult_t pskRet = CAGenerateOwnerPSK(ownerAddr,
694 (uint8_t*)oxmLabel, strlen(oxmLabel),
695 doxm->owner.id, sizeof(doxm->owner.id),
696 doxm->deviceID.id, sizeof(doxm->deviceID.id),
697 ownerPSK, OWNER_PSK_LENGTH_128);
698 VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
700 OIC_LOG_V(DEBUG, TAG, "Oxm Label = %s", oxmLabel);
701 OIC_LOG_V(DEBUG, TAG, "PSK size compare : %s",
702 OWNER_PSK_LENGTH_128 == decodedSize ? "TRUE" : "FALSE");
703 OIC_LOG_V(DEBUG, TAG, "SubjectID compare = %s",
704 memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0 ?
706 OIC_LOG_V(DEBUG, TAG, "Owner PSK compare = %s",
707 memcmp(ownerPSK, decodeBuff, OWNER_PSK_LENGTH_128) == 0 ? "TRUE" : "FALSE");
709 //Verify OwnerPSKs match
710 return (OWNER_PSK_LENGTH_128 == decodedSize &&
711 memcmp(ownerPSK, decodeBuff, OWNER_PSK_LENGTH_128) == 0 &&
712 memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0);
717 #endif //__WITH_DTLS__
719 static OCEntityHandlerResult HandlePutRequest(const OCEntityHandlerRequest * ehRequest)
721 OCEntityHandlerResult ret = OC_EH_ERROR;
723 //Get binary representation of json
724 OicSecCred_t * cred = JSONToCredBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
729 OicUuid_t emptyUuid = {.id={0}};
730 const OicSecDoxm_t* doxm = GetDoxmResourceData();
731 if(false == doxm->owned && memcmp(&(doxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0)
733 //in case of owner PSK
734 switch(cred->credType)
736 case SYMMETRIC_PAIR_WISE_KEY:
738 OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
739 if(isValidOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm))
741 OIC_LOG(ERROR, TAG, "OwnerPKS is matched");
742 if(OC_STACK_OK == AddCredential(cred))
744 ret = OC_EH_RESOURCE_CREATED;
748 OIC_LOG(ERROR, TAG, "Failed to save the OwnerPSK as cred resource");
754 OIC_LOG(ERROR, TAG, "Failed to verify receviced OwnerPKS.");
760 case SYMMETRIC_GROUP_KEY:
762 case SIGNED_ASYMMETRIC_KEY:
764 case ASYMMETRIC_ENCRYPTION_KEY:
766 OIC_LOG(WARNING, TAG, "Unsupported credential type for owner credential.");
772 OIC_LOG(WARNING, TAG, "Unknow credential type for owner credential.");
781 * If the post request credential has credId, it will be
782 * discarded and the next available credId will be assigned
783 * to it before getting appended to the existing credential
784 * list and updating svr database.
786 ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
788 #else //not __WITH_DTLS__
790 * If the post request credential has credId, it will be
791 * discarded and the next available credId will be assigned
792 * to it before getting appended to the existing credential
793 * list and updating svr database.
795 ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
796 #endif//__WITH_DTLS__
802 static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
804 OCEntityHandlerResult ret = OC_EH_ERROR;
806 //Get binary representation of json
807 OicSecCred_t * cred = JSONToCredBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
811 //If the Post request credential has credId, it will be
812 //discarded and the next available credId will be assigned
813 //to it before getting appended to the existing credential
814 //list and updating svr database.
815 ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
\r
821 static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
823 OIC_LOG(DEBUG, TAG, "Processing CredDeleteRequest");
825 OCEntityHandlerResult ehRet = OC_EH_ERROR;
827 if(NULL == ehRequest->query)
832 OicParseQueryIter_t parseIter = {.attrPos=NULL};
833 OicUuid_t subject = {.id={0}};
835 //Parsing REST query to get the subject
836 ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
837 while(GetNextQuery(&parseIter))
839 if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME,
840 parseIter.attrLen) == 0)
842 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
844 B64Result b64Ret = B64_OK;
846 b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen,
847 base64Buff, sizeof(base64Buff), &outLen);
849 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(subject.id)), ERROR);
850 memcpy(subject.id, base64Buff, outLen);
854 if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
856 ehRet = OC_EH_RESOURCE_DELETED;
864 * This internal method is the entity handler for Cred resources
865 * to handle REST request (PUT/POST/DEL)
867 OCEntityHandlerResult CredEntityHandler (OCEntityHandlerFlag flag,
868 OCEntityHandlerRequest * ehRequest,
869 void* callbackParameter)
871 (void)callbackParameter;
872 OCEntityHandlerResult ret = OC_EH_ERROR;
878 if (flag & OC_REQUEST_FLAG)
880 OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
881 //TODO : Handle PUT/DEL methods
882 switch(ehRequest->method)
885 ret = OC_EH_FORBIDDEN;
888 ret = HandlePutRequest(ehRequest);
891 ret = HandlePostRequest(ehRequest);
894 ret = HandleDeleteRequest(ehRequest);
902 //Send payload to request originator
903 ret = (SendSRMResponse(ehRequest, ret, NULL) == OC_STACK_OK ?
910 * This internal method is used to create '/oic/sec/Cred' resource.
912 OCStackResult CreateCredResource()
916 ret = OCCreateResource(&gCredHandle,
917 OIC_RSRC_TYPE_SEC_CRED,
924 if (OC_STACK_OK != ret)
926 OIC_LOG (FATAL, TAG, "Unable to instantiate Cred resource");
927 DeInitCredResource();
933 * Initialize Cred resource by loading data from persistent storage.
936 * OC_STACK_OK - no errors
937 * OC_STACK_ERROR - stack process error
939 OCStackResult InitCredResource()
941 OCStackResult ret = OC_STACK_ERROR;
943 //Read Cred resource from PS
944 char* jsonSVRDatabase = GetSVRDatabase();
948 //Convert JSON Cred into binary format
949 gCred = JSONToCredBin(jsonSVRDatabase);
952 * If SVR database in persistent storage got corrupted or
953 * is not available for some reason, a default Cred is created
954 * which allows user to initiate Cred provisioning again.
956 if (!jsonSVRDatabase || !gCred)
958 gCred = GetCredDefault();
960 //Instantiate 'oic.sec.cred'
961 ret = CreateCredResource();
962 OICFree(jsonSVRDatabase);
967 * Perform cleanup for Cred resources.
970 * OC_STACK_OK - no errors
971 * OC_STACK_ERROR - stack process error
972 * OC_STACK_NO_RESOURCE - resource not found
973 * OC_STACK_INVALID_PARAM - invalid param
975 OCStackResult DeInitCredResource()
977 OCStackResult result = OCDeleteResource(gCredHandle);
978 DeleteCredList(gCred);
984 * This method is used by tinydtls/SRM to retrieve credential for given Subject.
986 * @param subject - subject for which credential is required.
989 * reference to OicSecCred_t - if credential is found
990 * NULL - if credential not found
992 const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
994 OicSecCred_t *cred = NULL;
996 if ( NULL == subject)
1001 LL_FOREACH(gCred, cred)
1003 if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
1012 #if defined(__WITH_DTLS__)
1014 * This internal callback is used by lower stack (i.e. CA layer) to
1015 * retrieve PSK credentials from RI security layer.
1017 * @param[in] type type of PSK data required by tinyDTLS layer during DTLS handshake.
1018 * @param[in] desc Additional request information.
1019 * @param[in] desc_len The actual length of desc.
1020 * @param[out] result Must be filled with the requested information.
1021 * @param[in] result_length Maximum size of @p result.
1023 * @return The number of bytes written to @p result or a value
1024 * less than zero on error.
1026 int32_t GetDtlsPskCredentials( CADtlsPskCredType_t type,
1027 const unsigned char *desc, size_t desc_len,
1028 unsigned char *result, size_t result_length)
1039 case CA_DTLS_PSK_HINT:
1040 case CA_DTLS_PSK_IDENTITY:
1042 OicUuid_t deviceID = {.id={}};
1043 // Retrieve Device ID from doxm resource
1044 if ( OC_STACK_OK != GetDoxmDeviceID(&deviceID) )
1046 OIC_LOG (ERROR, TAG, "Unable to retrieve doxm Device ID");
1050 if (result_length < sizeof(deviceID.id))
1052 OIC_LOG (ERROR, TAG, "Wrong value for result_length");
1055 memcpy(result, deviceID.id, sizeof(deviceID.id));
1056 return (sizeof(deviceID.id));
1060 case CA_DTLS_PSK_KEY:
1062 OicSecCred_t *cred = NULL;
1063 LL_FOREACH(gCred, cred)
1065 if (cred->credType != SYMMETRIC_PAIR_WISE_KEY)
1070 if ((desc_len == sizeof(cred->subject.id)) &&
1071 (memcmp(desc, cred->subject.id, sizeof(cred->subject.id)) == 0))
1074 * If the credentials are valid for limited time,
1075 * check their expiry.
1079 if(IOTVTICAL_VALID_ACCESS != IsRequestWithinValidTime(cred->period, NULL))
1081 OIC_LOG (INFO, TAG, "Credentials are expired.");
1087 // Convert PSK from Base64 encoding to binary before copying
1088 uint32_t outLen = 0;
1089 B64Result b64Ret = b64Decode(cred->privateData.data,
1090 strlen(cred->privateData.data), result,
1091 result_length, &outLen);
1092 if (B64_OK != b64Ret)
1094 OIC_LOG (ERROR, TAG, "Base64 decoding failed.");
1106 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
1115 #endif /* __WITH_DTLS__ */
1116 #ifdef __WITH_X509__
1117 #define CERT_LEN_PREFIX (3)
1118 #define BYTE_SIZE (8) //bits
1119 #define PUB_KEY_X_COORD ("x")
1120 #define PUB_KEY_Y_COORD ("y")
1121 #define CERTIFICATE ("x5c")
1122 #define PRIVATE_KEY ("d")
1125 static void WriteCertPrefix(uint8_t *prefix, uint32_t certLen)
1127 for (size_t i = 0; i < CERT_LEN_PREFIX; ++i)
1129 prefix[i] = (certLen >> (BYTE_SIZE * (CERT_LEN_PREFIX - 1 - i))) & 0xFF;
1133 static uint32_t ParseCertPrefix(uint8_t *prefix)
1138 for(int i=0; i < CERT_LEN_PREFIX; ++i)
1140 res |= (((uint32_t) prefix[i]) << ((CERT_LEN_PREFIX - 1 -i) * BYTE_SIZE));
1146 static uint32_t appendCert2Chain(uint8_t *appendPoint, char *cert, uint32_t max_len)
1149 VERIFY_NON_NULL(TAG, appendPoint, ERROR);
1150 VERIFY_NON_NULL(TAG, cert, ERROR);
1153 VERIFY_SUCCESS(TAG, B64_OK == b64Decode(cert, strlen(cert), appendPoint + CERT_LEN_PREFIX,
1154 max_len - CERT_LEN_PREFIX, &certLen), ERROR);
1155 WriteCertPrefix(appendPoint, certLen);
1157 ret = certLen + CERT_LEN_PREFIX;
1162 static OCStackResult GetCAPublicKeyData(CADtlsX509Creds_t *credInfo){
1163 OCStackResult ret = OC_STACK_ERROR;
1164 uint8_t *ccPtr = credInfo->certificateChain;
1165 for(uint32_t i =0; i < credInfo->chainLen - 1; ++i)
1167 ccPtr += CERT_LEN_PREFIX + ParseCertPrefix(ccPtr);
1171 .data = ccPtr + CERT_LEN_PREFIX,
1172 .len = ParseCertPrefix(ccPtr)
1174 CertificateX509 certStruct;
1176 VERIFY_SUCCESS(TAG, PKI_SUCCESS == DecodeCertificate(cert, &certStruct), ERROR);
1178 INC_BYTE_ARRAY(certStruct.pubKey, 2);
1180 memcpy(credInfo->rootPublicKeyX, certStruct.pubKey.data, PUBLIC_KEY_SIZE / 2);
1181 memcpy(credInfo->rootPublicKeyY, certStruct.pubKey.data + PUBLIC_KEY_SIZE / 2, PUBLIC_KEY_SIZE / 2);
1188 static OCStackResult GetCertCredPublicData(CADtlsX509Creds_t *credInfo, OicSecCred_t *cred)
1190 OCStackResult ret = OC_STACK_ERROR;
1191 cJSON *jsonRoot = NULL;
1193 VERIFY_NON_NULL(TAG, credInfo, ERROR);
1194 VERIFY_NON_NULL(TAG, cred, ERROR);
1195 VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
1196 //VERIFY_SUCCESS(TAG, NULL == credInfo->certificateChain.data, ERROR);
1197 jsonRoot = cJSON_Parse(cred->publicData.data);
1198 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
1200 //Get certificate chain
1201 cJSON *jsonObj = cJSON_GetObjectItem(jsonRoot, CERTIFICATE);//TODO define field names constants
1202 VERIFY_SUCCESS(TAG, NULL != jsonObj && cJSON_Array == jsonObj->type, ERROR);
1204 size_t certChainLen = (size_t)cJSON_GetArraySize(jsonObj);
1205 credInfo->chainLen = certChainLen;
1206 VERIFY_SUCCESS(TAG, MAX_CHAIN_LEN >= certChainLen, ERROR);
1209 for (size_t i = 0; i < certChainLen; ++i)
1211 cJSON *item = cJSON_GetArrayItem(jsonObj, i);
1212 VERIFY_NON_NULL(TAG, item, ERROR);
1213 VERIFY_SUCCESS(TAG, cJSON_String == item->type, ERROR);
1214 uint32_t appendedLen = appendCert2Chain(credInfo->certificateChain + len, item->valuestring,
1215 MAX_CERT_MESSAGE_LEN - len);
1216 VERIFY_SUCCESS(TAG, 0 != appendedLen, ERROR);
1219 credInfo->certificateChainLen = len;
1220 VERIFY_SUCCESS(TAG, OC_STACK_OK == GetCAPublicKeyData(credInfo), ERROR);
1223 cJSON_Delete(jsonRoot);
1227 static OCStackResult GetCertCredPrivateData(CADtlsX509Creds_t *credInfo, OicSecCred_t *cred)
1229 OCStackResult ret = OC_STACK_ERROR;
1230 cJSON *jsonRoot = NULL;
1231 VERIFY_NON_NULL(TAG, credInfo, ERROR);
1232 VERIFY_NON_NULL(TAG, cred, ERROR);
1233 VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
1234 jsonRoot = cJSON_Parse(cred->privateData.data);
1235 VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
1237 cJSON *jsonObj = cJSON_GetObjectItem(jsonRoot, PRIVATE_KEY);//TODO define field names constants
1238 VERIFY_SUCCESS(TAG, NULL != jsonObj && cJSON_String == jsonObj->type, ERROR);
1241 VERIFY_SUCCESS(TAG, B64_OK == b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring),
1242 credInfo->devicePrivateKey, PRIVATE_KEY_SIZE, &read)
1243 && PRIVATE_KEY_SIZE == read, ERROR);
1248 cJSON_Delete(jsonRoot);
1252 int GetDtlsX509Credentials(CADtlsX509Creds_t *credInfo)
1255 VERIFY_NON_NULL(TAG, credInfo, ERROR);
1258 VERIFY_SUCCESS(TAG, OC_STACK_OK == InitCredResource(), ERROR);
1261 OicSecCred_t *cred = NULL;
1262 LL_SEARCH_SCALAR(gCred, cred, credType, SIGNED_ASYMMETRIC_KEY);
1263 VERIFY_NON_NULL(TAG, cred, ERROR);
1265 VERIFY_SUCCESS(TAG, OC_STACK_OK == GetCertCredPrivateData(credInfo, cred), ERROR);
1266 VERIFY_SUCCESS(TAG, OC_STACK_OK == GetCertCredPublicData(credInfo, cred), ERROR);
1273 #undef CERT_LEN_PREFIX
1274 #endif /* __WITH_X509__ */