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
31 #include "cainterface.h"
32 #include "payload_logging.h"
35 #include "ocserverrequest.h"
36 #include "oic_malloc.h"
37 #include "ocpayload.h"
39 #include "credresource.h"
40 #include "doxmresource.h"
41 #include "pstatresource.h"
42 #include "iotvticalendar.h"
44 #include "resourcemanager.h"
45 #include "srmresourcestrings.h"
46 #include "srmutility.h"
47 #include "psinterface.h"
48 #include "pinoxmcommon.h"
54 #define TAG "SRM-CREDL"
56 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
57 * The value of payload size is increased until reaching belox max cbor size. */
58 static const uint8_t CBOR_SIZE = 255;
60 /** Max cbor size payload. */
61 static const uint16_t CBOR_MAX_SIZE = 4400;
63 /** CRED Map size - Number of mandatory items. */
64 static const uint8_t CRED_MAP_SIZE = 4;
66 static OicSecCred_t *gCred = NULL;
67 static OCResourceHandle gCredHandle = NULL;
70 * This function frees OicSecCred_t object's fields and object itself.
72 static void FreeCred(OicSecCred_t *cred)
76 OIC_LOG(ERROR, TAG, "Invalid Parameter");
79 //Note: Need further clarification on roleID data type
82 OICFree(cred->roleIds);
86 OICFree(cred->publicData.data);
89 OICFree(cred->privateData.data);
92 OICFree(cred->period);
95 OICFree(cred->owners);
97 //Clean Cred node itself
101 void DeleteCredList(OicSecCred_t* cred)
105 OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
106 LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
108 LL_DELETE(cred, credTmp1);
114 static size_t OicSecCredCount(const OicSecCred_t *secCred)
117 for (const OicSecCred_t *cred = secCred; cred; cred = cred->next)
124 OCStackResult CredToCBORPayload(const OicSecCred_t *credS, uint8_t **cborPayload,
127 if (NULL == credS || NULL == cborPayload || NULL != *cborPayload || NULL == cborSize)
129 return OC_STACK_INVALID_PARAM;
132 OCStackResult ret = OC_STACK_ERROR;
133 size_t cborLen = *cborSize;
142 CborEncoder encoder = { {.ptr = NULL }, .end = 0 };
143 CborEncoder credArray = { {.ptr = NULL }, .end = 0 };
144 CborError cborEncoderResult = CborNoError;
146 const OicSecCred_t *cred = credS;
147 size_t mapSize = CRED_MAP_SIZE;
152 if (cred->publicData.data)
156 if (cred->privateData.data)
164 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
165 VERIFY_NON_NULL(TAG, outPayload, ERROR);
166 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
169 cborEncoderResult = cbor_encoder_create_array(&encoder, &credArray, OicSecCredCount(cred));
170 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding0 Cred Array.");
174 CborEncoder credMap = { {.ptr = NULL }, .end = 0 };
175 cborEncoderResult = cbor_encoder_create_map(&credArray, &credMap, mapSize);
176 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Map");
178 //CredID -- Mandatory
179 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDID_NAME,
180 strlen(OIC_JSON_CREDID_NAME));
181 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Id Tag. ");
182 cborEncoderResult = cbor_encode_int(&credMap, cred->credId);
183 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Id Value.");
185 //Subject -- Mandatory
186 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_SUBJECT_NAME,
187 strlen(OIC_JSON_SUBJECT_NAME));
188 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Subject Tag.");
189 cborEncoderResult = cbor_encode_byte_string(&credMap, cred->subject.id,
190 sizeof(cred->subject.id));
191 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Subject Value.");
193 //CredType -- Mandatory
194 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDTYPE_NAME,
195 strlen(OIC_JSON_CREDTYPE_NAME));
196 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Tag.");
197 cborEncoderResult = cbor_encode_int(&credMap, cred->credType);
198 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
201 //PublicData -- Not Mandatory
202 if (cred->publicData.data)
204 cborEncoderResult = cbor_encode_text_string(&credMap,
205 OIC_JSON_PUBLICDATA_NAME, strlen(OIC_JSON_PUBLICDATA_NAME));
206 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Public Data Tag.");
207 cborEncoderResult = cbor_encode_byte_string(&credMap, cred->publicData.data,
208 sizeof(cred->publicData.data));
209 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Public Tag Value.");
211 #endif /*__WITH_X509__*/
212 //PrivateData -- Not Mandatory
213 if(cred->privateData.data)
215 cborEncoderResult = cbor_encode_text_string(&credMap,
216 OIC_JSON_PRIVATEDATA_NAME, strlen(OIC_JSON_PRIVATEDATA_NAME));
217 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Data Tag");
218 cborEncoderResult = cbor_encode_byte_string(&credMap, cred->privateData.data,
219 sizeof(cred->privateData.data));
220 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Data Value.");
223 //Period -- Not Mandatory
226 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_PERIOD_NAME,
227 strlen(OIC_JSON_PERIOD_NAME));
228 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Name Tag.");
229 cborEncoderResult = cbor_encode_text_string(&credMap, cred->period,
230 strlen(cred->period));
231 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Name Value.");
234 //Owners -- Mandatory
236 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_OWNERS_NAME,
237 strlen(OIC_JSON_OWNERS_NAME));
238 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owners Name Tag.");
239 CborEncoder owners = { {.ptr = NULL }, .end = 0 };
240 cborEncoderResult = cbor_encoder_create_array(&credMap, &owners, cred->ownersLen);
241 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owners Name Array.");
242 for (size_t i = 0; i < cred->ownersLen; i++)
244 cborEncoderResult = cbor_encode_byte_string(&owners,
245 (uint8_t *)cred->owners[i].id,
246 sizeof(cred->owners[i].id));
247 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owners Array Value.");
249 cborEncoderResult = cbor_encoder_close_container(&credMap, &owners);
250 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Owners Name Array.");
252 cborEncoderResult = cbor_encoder_close_container(&credArray, &credMap);
253 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Cred Map.");
257 cborEncoderResult = cbor_encoder_close_container(&encoder, &credArray);
258 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Cred Array.");
260 if (CborNoError == cborEncoderResult)
262 *cborPayload = outPayload;
263 *cborSize = encoder.ptr - outPayload;
268 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
270 // reallocate and try again!
273 // Since the allocated initial memory failed, double the memory.
274 cborLen += encoder.ptr - encoder.end;
275 cborEncoderResult = CborNoError;
276 ret = CredToCBORPayload(credS, cborPayload, &cborLen);
277 if (CborNoError == cborEncoderResult)
284 if (CborNoError != cborEncoderResult)
290 ret = OC_STACK_ERROR;
296 OCStackResult CBORPayloadToCred(const uint8_t *cborPayload, size_t size,
297 OicSecCred_t **secCred)
299 if (NULL == cborPayload || NULL == secCred || NULL != *secCred)
301 return OC_STACK_INVALID_PARAM;
306 OCStackResult ret = OC_STACK_ERROR;
308 CborValue credCbor = { .parser = NULL };
309 CborParser parser = { .end = NULL };
310 CborError cborFindResult = CborNoError;
311 OicSecCred_t *cred = NULL;
319 cbor_parser_init(cborPayload, cborLen, 0, &parser, &credCbor);
321 OicSecCred_t *headCred = NULL;
323 CborValue credArray = { .parser = NULL };
324 cborFindResult = cbor_value_enter_container(&credCbor, &credArray);
325 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Array.");
327 while (cbor_value_is_valid(&credArray))
329 CborValue credMap = { .parser = NULL };
330 cborFindResult = cbor_value_enter_container(&credArray, &credMap);
331 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Map.");
333 cred = (OicSecCred_t *) OICCalloc(1, sizeof(*cred));
334 VERIFY_NON_NULL(TAG, cred, ERROR);
336 while (cbor_value_is_valid(&credMap))
339 cborFindResult = cbor_value_dup_text_string(&credMap, &name, &len, NULL);
340 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Name.");
341 cborFindResult = cbor_value_advance(&credMap);
342 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Cred Name. ");
344 CborType type = cbor_value_get_type(&credMap);
346 //CredId -- Mandatory
347 if (0 == strcmp(OIC_JSON_CREDID_NAME, name))
349 cborFindResult = cbor_value_get_int(&credMap, (int *) &cred->credId);
350 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Id Value.");
352 //subject -- Mandatory
353 if (0 == strcmp(OIC_JSON_SUBJECT_NAME, name))
356 cborFindResult = cbor_value_dup_byte_string(&credMap, &id, &len, NULL);
357 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Subject Name Value.");
358 memcpy(cred->subject.id, id, len);
361 //CredType -- Mandatory
362 if (0 == strcmp(OIC_JSON_CREDTYPE_NAME, name))
364 cborFindResult = cbor_value_get_int(&credMap, (int *) &cred->credType);
365 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Type Value.");
367 //Owners -- Mandatory
368 if (0 == strcmp(OIC_JSON_OWNERS_NAME, name))
370 CborValue owners = { .parser = NULL };
371 cborFindResult = cbor_value_get_array_length(&credMap, &cred->ownersLen);
372 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owners Name Array Len.");
373 cborFindResult = cbor_value_enter_container(&credMap, &owners);
374 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owners Name.");
376 cred->owners = (OicUuid_t *)OICCalloc(cred->ownersLen, sizeof(*cred->owners));
377 VERIFY_NON_NULL(TAG, cred->owners, ERROR);
378 while (cbor_value_is_valid(&owners))
380 uint8_t *owner = NULL;
381 cborFindResult = cbor_value_dup_byte_string(&owners, &owner, &len, NULL);
382 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owner Value.");
383 memcpy(cred->owners[i].id, owner, len);
385 cborFindResult = cbor_value_advance(&owners);
386 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Owner Value.");
389 //PrivateData is mandatory for some of the credential types listed below.
390 if (0 == strcmp(OIC_JSON_PRIVATEDATA_NAME, name))
392 if ((cred->credType & SYMMETRIC_PAIR_WISE_KEY) ||
393 (cred->credType & SYMMETRIC_GROUP_KEY) ||
394 (cred->credType & PIN_PASSWORD))
396 cborFindResult = cbor_value_dup_byte_string(&credMap,
397 &cred->privateData.data, &len, NULL);
398 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Private Data Value.");
403 cred->privateData.data = NULL;
406 //PublicData is mandatory only for SIGNED_ASYMMETRIC_KEY credentials type.
407 if (0 == strcmp(OIC_JSON_PUBLICDATA_NAME, name))
409 if (cred->credType & SIGNED_ASYMMETRIC_KEY)
411 cborFindResult = cbor_value_dup_byte_string(&credMap,
412 &cred->publicData.data, &len, NULL);
413 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ");
416 //Period -- Not Mandatory
417 if (0 == strcmp(OIC_JSON_PERIOD_NAME, name))
419 cborFindResult = cbor_value_dup_text_string(&credMap,
420 &cred->period, &len, NULL);
421 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Period Name Value.");
423 if (CborMapType != type && cbor_value_is_valid(&credMap))
425 cborFindResult = cbor_value_advance(&credMap);
426 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Cred Map.");
433 if (NULL == headCred)
439 OicSecCred_t *temp = headCred;
446 if (cbor_value_is_valid(&credArray))
448 cborFindResult = cbor_value_advance(&credArray);
449 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Cred Array. ");
455 if (CborNoError != cborFindResult)
457 DeleteCredList(headCred);
459 ret = OC_STACK_ERROR;
463 DeleteCredList(cred);
472 OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t credType,
473 const uint8_t * publicData, const uint8_t* privateData,
474 size_t ownersLen, const OicUuid_t * owners)
477 OCStackResult ret = OC_STACK_ERROR;
479 OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
480 VERIFY_NON_NULL(TAG, cred, ERROR);
482 //CredId is assigned before appending new cred to the existing
483 //credential list and updating svr database in AddCredential().
486 VERIFY_NON_NULL(TAG, subject, ERROR);
487 memcpy(cred->subject.id, subject->id , sizeof(cred->subject.id));
489 VERIFY_SUCCESS(TAG, credType < (NO_SECURITY_MODE | SYMMETRIC_PAIR_WISE_KEY |
490 SYMMETRIC_GROUP_KEY | ASYMMETRIC_KEY | SIGNED_ASYMMETRIC_KEY | PIN_PASSWORD), ERROR);
491 cred->credType = credType;
496 cred->publicData.data = (uint8_t *)OICCalloc(1, PUBLIC_KEY_SIZE);
497 VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
498 memcpy(cred->publicData.data, publicData, PUBLIC_KEY_SIZE);
500 #endif // __WITH_X509__
505 cred->privateData.data = (uint8_t *)OICCalloc(1, PRIVATE_KEY_SIZE);
506 VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
507 memcpy(cred->privateData.data, privateData, PRIVATE_KEY_SIZE);
508 #endif // __WITH_X509__
511 VERIFY_SUCCESS(TAG, ownersLen > 0, ERROR);
512 cred->ownersLen = ownersLen;
514 cred->owners = (OicUuid_t *)OICCalloc(cred->ownersLen, sizeof(*cred->owners));
515 VERIFY_NON_NULL(TAG, cred->owners, ERROR);
516 for (size_t i = 0; i < cred->ownersLen; i++)
518 memcpy(cred->owners[i].id, owners[i].id, sizeof(cred->owners[i].id));
523 if (OC_STACK_OK != ret)
525 DeleteCredList(cred);
531 static bool UpdatePersistentStorage(const OicSecCred_t *cred)
535 // Convert Cred data into JSON for update to persistent storage
536 uint8_t *payload = NULL;
538 OCStackResult res = CredToCBORPayload(cred, &payload, &size);
539 if ((OC_STACK_OK == res) && payload)
541 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, payload, size))
547 else //Empty cred list
549 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, NULL, size))
558 * Compare function used LL_SORT for sorting credentials.
560 * @param first pointer to OicSecCred_t struct.
561 * @param second pointer to OicSecCred_t struct.
563 *@return -1, if credId of first is less than credId of second.
564 * 0, if credId of first is equal to credId of second.
565 * 1, if credId of first is greater than credId of second.
567 static int CmpCredId(const OicSecCred_t * first, const OicSecCred_t *second)
569 if (first->credId < second->credId)
573 else if (first->credId > second->credId)
582 * GetCredId goes through the cred list and returns the next
583 * available credId. The next credId could be the credId that is
584 * available due deletion of OicSecCred_t object or one more than
585 * credId of last credential in the list.
587 * @return next available credId if successful, else 0 for error.
589 static uint16_t GetCredId()
591 //Sorts credential list in incremental order of credId
592 LL_SORT(gCred, CmpCredId);
594 OicSecCred_t *currentCred = NULL, *credTmp = NULL;
595 uint16_t nextCredId = 1;
597 LL_FOREACH_SAFE(gCred, currentCred, credTmp)
599 if (currentCred->credId == nextCredId)
609 VERIFY_SUCCESS(TAG, nextCredId < UINT16_MAX, ERROR);
617 * Get the default value.
619 * @return NULL for now.
621 static OicSecCred_t* GetCredDefault()
623 // TODO:Update it when we finalize the default info.
627 OCStackResult AddCredential(OicSecCred_t * newCred)
629 OCStackResult ret = OC_STACK_ERROR;
630 VERIFY_SUCCESS(TAG, NULL != newCred, ERROR);
632 //Assigning credId to the newCred
633 newCred->credId = GetCredId();
634 VERIFY_SUCCESS(TAG, newCred->credId != 0, ERROR);
636 //Append the new Cred to existing list
637 LL_APPEND(gCred, newCred);
639 if (UpdatePersistentStorage(gCred))
648 OCStackResult RemoveCredential(const OicUuid_t *subject)
650 OCStackResult ret = OC_STACK_ERROR;
651 OicSecCred_t *cred = NULL;
652 OicSecCred_t *tempCred = NULL;
653 bool deleteFlag = false;
655 LL_FOREACH_SAFE(gCred, cred, tempCred)
657 if (memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
659 LL_DELETE(gCred, cred);
667 if (UpdatePersistentStorage(gCred))
669 ret = OC_STACK_RESOURCE_DELETED;
677 * Remove all credential data on credential resource and persistent storage
680 * OC_STACK_OK - no errors
681 * OC_STACK_ERROR - stack process error
683 OCStackResult RemoveAllCredentials(void)
685 DeleteCredList(gCred);
686 gCred = GetCredDefault();
688 if (!UpdatePersistentStorage(gCred))
690 return OC_STACK_ERROR;
697 * Internal function to fill private data of owner PSK.
699 * @param receviedCred recevied owner credential from OBT(PT)
700 * @param ownerAdd address of OBT(PT)
701 * @param doxm current device's doxm resource
704 * true successfully done and valid ower psk information
705 * false Invalid owner psk information or failed to owner psk generation
707 static bool FillPrivateDataOfOwnerPSK(OicSecCred_t* receviedCred, const CAEndpoint_t* ownerAddr,
708 const OicSecDoxm_t* doxm)
710 //Derive OwnerPSK locally
711 const char* oxmLabel = GetOxmString(doxm->oxmSel);
712 VERIFY_NON_NULL(TAG, oxmLabel, ERROR);
714 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
715 CAResult_t pskRet = CAGenerateOwnerPSK(ownerAddr,
716 (uint8_t*)oxmLabel, strlen(oxmLabel),
717 doxm->owner.id, sizeof(doxm->owner.id),
718 doxm->deviceID.id, sizeof(doxm->deviceID.id),
719 ownerPSK, OWNER_PSK_LENGTH_128);
720 VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
722 OIC_LOG(DEBUG, TAG, "OwnerPSK dump :");
723 OIC_LOG_BUFFER(DEBUG, TAG, ownerPSK, OWNER_PSK_LENGTH_128);
725 //Generate owner credential based on recevied credential information
726 receviedCred->privateData.data = (uint8_t *)OICCalloc(1, OWNER_PSK_LENGTH_128);
727 VERIFY_NON_NULL(TAG, receviedCred->privateData.data, ERROR);
728 memcpy(receviedCred->privateData.data, ownerPSK, OWNER_PSK_LENGTH_128);
730 OIC_LOG(INFO, TAG, "PrivateData of OwnerPSK was calculated successfully");
732 //Verify OwnerPSK information
733 return (memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0 &&
734 receviedCred->credType == SYMMETRIC_PAIR_WISE_KEY);
736 //receviedCred->privateData.data will be deallocated when deleting credential.
740 #endif //__WITH_DTLS__
742 static OCEntityHandlerResult HandlePutRequest(const OCEntityHandlerRequest * ehRequest)
744 OCEntityHandlerResult ret = OC_EH_ERROR;
746 //Get binary representation of json
747 OicSecCred_t * cred = NULL;
748 uint8_t *payload = (((OCSecurityPayload*)ehRequest->payload)->securityData1);
749 //size_t size = (((OCSecurityPayload*)ehRequest->payload)->payloadSize);
750 OCStackResult res = CBORPayloadToCred(payload, 0, &cred);
751 if (res == OC_STACK_OK)
754 OicUuid_t emptyUuid = {.id={0}};
755 const OicSecDoxm_t* doxm = GetDoxmResourceData();
756 if(false == doxm->owned && memcmp(&(doxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0)
758 //in case of owner PSK
759 switch(cred->credType)
761 case SYMMETRIC_PAIR_WISE_KEY:
763 OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
764 if(FillPrivateDataOfOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm))
766 if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&cred->subject))
768 OIC_LOG(WARNING, TAG, "The credential with the same subject ID was detected!");
771 OIC_LOG(ERROR, TAG, "OwnerPSK was generated successfully.");
772 if(OC_STACK_OK == AddCredential(cred))
774 ret = OC_EH_RESOURCE_CREATED;
778 OIC_LOG(ERROR, TAG, "Failed to save the OwnerPSK as cred resource");
784 OIC_LOG(ERROR, TAG, "Failed to verify receviced OwnerPKS.");
788 if(OC_EH_RESOURCE_CREATED == ret)
791 * in case of random PIN based OxM,
792 * revert get_psk_info callback of tinyDTLS to use owner credential.
794 if(OIC_RANDOM_DEVICE_PIN == doxm->oxmSel)
796 OicUuid_t emptyUuid = { .id={0}};
797 SetUuidForRandomPinOxm(&emptyUuid);
799 if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
801 OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
807 //Select cipher suite to use owner PSK
808 if(CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false))
810 OIC_LOG(ERROR, TAG, "Failed to disable anonymous cipher suite");
815 OIC_LOG(INFO, TAG, "Anonymous cipher suite is DISABLED");
819 CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256))
821 OIC_LOG(ERROR, TAG, "Failed to select cipher suite");
828 case SYMMETRIC_GROUP_KEY:
830 case SIGNED_ASYMMETRIC_KEY:
832 case ASYMMETRIC_ENCRYPTION_KEY:
834 OIC_LOG(WARNING, TAG, "Unsupported credential type for owner credential.");
840 OIC_LOG(WARNING, TAG, "Unknow credential type for owner credential.");
846 if(OC_EH_RESOURCE_CREATED != ret)
849 * If some error is occured while ownership transfer,
850 * ownership transfer related resource should be revert back to initial status.
852 RestoreDoxmToInitState();
853 RestorePstatToInitState();
859 * If the post request credential has credId, it will be
860 * discarded and the next available credId will be assigned
861 * to it before getting appended to the existing credential
862 * list and updating svr database.
864 ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
866 #else //not __WITH_DTLS__
868 * If the post request credential has credId, it will be
869 * discarded and the next available credId will be assigned
870 * to it before getting appended to the existing credential
871 * list and updating svr database.
873 ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
874 #endif//__WITH_DTLS__
877 if (OC_EH_RESOURCE_CREATED != ret)
879 if(OC_STACK_OK != RemoveCredential(&cred->subject))
881 OIC_LOG(WARNING, TAG, "Failed to remove the invalid credential");
889 static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
891 OCEntityHandlerResult ret = OC_EH_ERROR;
893 //Get binary representation of CBOR
894 OicSecCred_t *cred = NULL;
895 uint8_t *payload = ((OCSecurityPayload*)ehRequest->payload)->securityData1;
896 OCStackResult res = CBORPayloadToCred(payload, 0, &cred);
897 if ((OC_STACK_OK == res) && cred)
899 //If the Post request credential has credId, it will be
900 //discarded and the next available credId will be assigned
901 //to it before getting appended to the existing credential
902 //list and updating svr database.
903 ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
909 static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
911 OIC_LOG(DEBUG, TAG, "Processing CredDeleteRequest");
913 OCEntityHandlerResult ehRet = OC_EH_ERROR;
915 if (NULL == ehRequest->query)
920 OicParseQueryIter_t parseIter = { .attrPos=NULL };
921 OicUuid_t subject = {.id={0}};
923 //Parsing REST query to get the subject
924 ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
925 while (GetNextQuery(&parseIter))
927 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME,
928 parseIter.attrLen) == 0)
930 memcpy(subject.id, parseIter.valPos, parseIter.valLen);
934 if (OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
936 ehRet = OC_EH_RESOURCE_DELETED;
942 OCEntityHandlerResult CredEntityHandler(OCEntityHandlerFlag flag,
943 OCEntityHandlerRequest * ehRequest,
944 void* callbackParameter)
946 (void)callbackParameter;
947 OCEntityHandlerResult ret = OC_EH_ERROR;
953 if (flag & OC_REQUEST_FLAG)
955 OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
956 //TODO : Handle PUT/DEL methods
957 switch (ehRequest->method)
960 ret = OC_EH_FORBIDDEN;
963 ret = HandlePutRequest(ehRequest);
966 ret = HandlePostRequest(ehRequest);
969 ret = HandleDeleteRequest(ehRequest);
977 //Send payload to request originator
978 ret = (SendSRMCBORResponse(ehRequest, ret, NULL) == OC_STACK_OK) ?
984 OCStackResult CreateCredResource()
986 OCStackResult ret = OCCreateResource(&gCredHandle,
987 OIC_RSRC_TYPE_SEC_CRED,
994 if (OC_STACK_OK != ret)
996 OIC_LOG (FATAL, TAG, "Unable to instantiate Cred resource");
997 DeInitCredResource();
1002 OCStackResult InitCredResource()
1004 OCStackResult ret = OC_STACK_ERROR;
1006 //Read Cred resource from PS
1007 uint8_t *data = NULL;
1009 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_CRED_NAME, &data, &size);
1010 // If database read failed
1011 if (ret != OC_STACK_OK)
1013 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1017 // Read ACL resource from PS
1018 ret = CBORPayloadToCred(data, size, &gCred);
1022 * If SVR database in persistent storage got corrupted or
1023 * is not available for some reason, a default Cred is created
1024 * which allows user to initiate Cred provisioning again.
1026 if (ret != OC_STACK_OK || !data || !gCred)
1028 gCred = GetCredDefault();
1030 //Instantiate 'oic.sec.cred'
1031 ret = CreateCredResource();
1036 OCStackResult DeInitCredResource()
1038 OCStackResult result = OCDeleteResource(gCredHandle);
1039 DeleteCredList(gCred);
1044 const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
1046 OicSecCred_t *cred = NULL;
1048 if ( NULL == subject)
1053 LL_FOREACH(gCred, cred)
1055 if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
1064 #if defined(__WITH_DTLS__)
1065 int32_t GetDtlsPskCredentials(CADtlsPskCredType_t type,
1066 const uint8_t *desc, size_t desc_len,
1067 uint8_t *result, size_t result_length)
1078 case CA_DTLS_PSK_HINT:
1079 case CA_DTLS_PSK_IDENTITY:
1081 OicUuid_t deviceID = {.id={}};
1082 // Retrieve Device ID from doxm resource
1083 if ( OC_STACK_OK != GetDoxmDeviceID(&deviceID) )
1085 OIC_LOG (ERROR, TAG, "Unable to retrieve doxm Device ID");
1089 if (result_length < sizeof(deviceID.id))
1091 OIC_LOG (ERROR, TAG, "Wrong value for result_length");
1094 memcpy(result, deviceID.id, sizeof(deviceID.id));
1095 return (sizeof(deviceID.id));
1099 case CA_DTLS_PSK_KEY:
1101 OicSecCred_t *cred = NULL;
1102 LL_FOREACH(gCred, cred)
1104 if (cred->credType != SYMMETRIC_PAIR_WISE_KEY)
1109 if ((desc_len == sizeof(cred->subject.id)) &&
1110 (memcmp(desc, cred->subject.id, sizeof(cred->subject.id)) == 0))
1113 * If the credentials are valid for limited time,
1114 * check their expiry.
1118 if(IOTVTICAL_VALID_ACCESS != IsRequestWithinValidTime(cred->period, NULL))
1120 OIC_LOG (INFO, TAG, "Credentials are expired.");
1127 result_length = sizeof(cred->privateData.data);
1128 memcpy(result, cred->privateData.data, result_length);
1129 return result_length;
1137 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
1147 * Add temporal PSK to PIN based OxM
1149 * @param[in] tmpSubject UUID of target device
1150 * @param[in] credType Type of credential to be added
1151 * @param[in] pin numeric characters
1152 * @param[in] pinSize length of 'pin'
1153 * @param[in] ownersLen Number of owners
1154 * @param[in] owners Array of owners
1155 * @param[out] tmpCredSubject Generated credential's subject.
1157 * @return OC_STACK_OK for success and errorcode otherwise.
1159 OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
1160 const char * pin, size_t pinSize,
1161 size_t ownersLen, const OicUuid_t * owners, OicUuid_t* tmpCredSubject)
1163 OCStackResult ret = OC_STACK_ERROR;
1165 if(NULL == tmpSubject || NULL == pin || 0 == pinSize || NULL == tmpCredSubject)
1167 return OC_STACK_INVALID_PARAM;
1170 uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
1171 OicSecCred_t* cred = NULL;
1172 int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, owners->id,
1173 UUID_LENGTH, PBKDF_ITERATIONS,
1174 OWNER_PSK_LENGTH_128, privData);
1175 VERIFY_SUCCESS(TAG, (0 == dtlsRes) , ERROR);
1177 cred = GenerateCredential(tmpSubject, credType, NULL,
1178 privData, ownersLen, owners);
1181 OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
1182 return OC_STACK_ERROR;
1185 memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
1187 ret = AddCredential(cred);
1188 if( OC_STACK_OK != ret)
1190 RemoveCredential(tmpSubject);
1191 OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
1198 #endif /* __WITH_DTLS__ */
1199 #ifdef __WITH_X509__
1200 #define CERT_LEN_PREFIX (3)
1201 #define BYTE_SIZE (8) //bits
1202 #define PUB_KEY_X_COORD ("x")
1203 #define PUB_KEY_Y_COORD ("y")
1204 #define CERTIFICATE ("x5c")
1205 #define PRIVATE_KEY ("d")
1207 static void WriteCertPrefix(uint8_t *prefix, uint32_t certLen)
1209 for (size_t i = 0; i < CERT_LEN_PREFIX; ++i)
1211 prefix[i] = (certLen >> (BYTE_SIZE * (CERT_LEN_PREFIX - 1 - i))) & 0xFF;
1215 static uint32_t ParseCertPrefix(uint8_t *prefix)
1220 for (int i = 0; i < CERT_LEN_PREFIX; ++i)
1222 res |= (((uint32_t) prefix[i]) << ((CERT_LEN_PREFIX - 1 -i) * BYTE_SIZE));
1228 static uint32_t appendCert2Chain(uint8_t *appendPoint, uint8_t *cert, size_t len, uint32_t max_len)
1231 VERIFY_NON_NULL(TAG, appendPoint, ERROR);
1232 VERIFY_NON_NULL(TAG, cert, ERROR);
1234 memcpy(appendPoint + CERT_LEN_PREFIX, cert, max_len - CERT_LEN_PREFIX);
1235 WriteCertPrefix(appendPoint, len);
1237 ret = len + CERT_LEN_PREFIX;
1242 static OCStackResult GetCAPublicKeyData(CADtlsX509Creds_t *credInfo)
1244 OCStackResult ret = OC_STACK_ERROR;
1245 uint8_t *ccPtr = credInfo->certificateChain;
1246 for (uint8_t i = 0; i < credInfo->chainLen - 1; ++i)
1248 ccPtr += CERT_LEN_PREFIX + ParseCertPrefix(ccPtr);
1251 ByteArray cert = { .data = ccPtr + CERT_LEN_PREFIX, .len = ParseCertPrefix(ccPtr) };
1252 CertificateX509 certStruct;
1254 VERIFY_SUCCESS(TAG, PKI_SUCCESS == DecodeCertificate(cert, &certStruct), ERROR);
1256 INC_BYTE_ARRAY(certStruct.pubKey, 2);
1258 memcpy(credInfo->rootPublicKeyX, certStruct.pubKey.data, PUBLIC_KEY_SIZE / 2);
1259 memcpy(credInfo->rootPublicKeyY, certStruct.pubKey.data + PUBLIC_KEY_SIZE / 2, PUBLIC_KEY_SIZE / 2);
1266 int GetDtlsX509Credentials(CADtlsX509Creds_t *credInfo)
1269 VERIFY_NON_NULL(TAG, credInfo, ERROR);
1272 VERIFY_SUCCESS(TAG, OC_STACK_OK == InitCredResource(), ERROR);
1275 OicSecCred_t *cred = NULL;
1276 LL_SEARCH_SCALAR(gCred, cred, credType, SIGNED_ASYMMETRIC_KEY);
1277 VERIFY_NON_NULL(TAG, cred, ERROR);
1279 CborValue credCbor = { .parser = NULL };
1280 CborParser parser = { .end = NULL };
1281 CborError cborFindResult = CborNoError;
1282 uint8_t *cborPayload = cred->publicData.data;
1283 int cborLen = cred->publicData.len;
1284 cbor_parser_init(cborPayload, cborLen, 0, &parser, &credCbor);
1286 cborFindResult = cbor_value_enter_container(&credCbor, &certMap);
1287 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Map.");
1290 cborFindResult = cbor_value_map_find_value(&certs, CERTIFICATE, &certs);
1291 if (cbor_value_is_array(&certs))
1293 cborFindResult = cbor_value_get_array_length(&certs, (size_t *)&credInfo->chainLen);
1294 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Chain Len.");
1296 cborFindResult = cbor_value_enter_container(&certs, &cert);
1297 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Container.");
1300 uint8_t *val = NULL;
1301 while (cbor_value_is_byte_string(&cert))
1303 cborFindResult = cbor_value_dup_byte_string(&cert, &val, &certLen, NULL);
1304 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Period Array Value.");
1305 cborFindResult = cbor_value_advance(&cert);
1306 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing a Period Array.");
1307 uint32_t appendedLen = appendCert2Chain(credInfo->certificateChain + len, val, certLen, MAX_CERT_MESSAGE_LEN - len);
1310 credInfo->certificateChainLen = len;
1311 GetCAPublicKeyData(credInfo);
1313 memcpy(credInfo->devicePrivateKey, cred->privateData.data, PRIVATE_KEY_SIZE);
1320 #undef CERT_LEN_PREFIX
1321 #endif /* __WITH_X509__ */