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"
36 #include "ocserverrequest.h"
37 #include "oic_malloc.h"
38 #include "ocpayload.h"
40 #include "credresource.h"
41 #include "doxmresource.h"
42 #include "pstatresource.h"
43 #include "iotvticalendar.h"
45 #include "resourcemanager.h"
46 #include "srmresourcestrings.h"
47 #include "srmutility.h"
48 #include "psinterface.h"
49 #include "pinoxmcommon.h"
55 #define TAG "SRM-CREDL"
57 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
58 * The value of payload size is increased until reaching belox max cbor size. */
60 static const uint8_t CBOR_SIZE = 255;
62 static const uint16_t CBOR_SIZE = 1024;
65 /** Max cbor size payload. */
66 static const uint16_t CBOR_MAX_SIZE = 4400;
68 /** CRED Map size - Number of mandatory items. */
69 static const uint8_t CRED_MAP_SIZE = 4;
71 static OicSecCred_t *gCred = NULL;
72 static OCResourceHandle gCredHandle = NULL;
75 * This function frees OicSecCred_t object's fields and object itself.
77 static void FreeCred(OicSecCred_t *cred)
81 OIC_LOG(ERROR, TAG, "Invalid Parameter");
84 //Note: Need further clarification on roleID data type
87 OICFree(cred->roleIds);
92 OICFree(cred->publicData.data);
96 OICFree(cred->privateData.data);
99 OICFree(cred->period);
102 OICFree(cred->owners);
104 //Clean Cred node itself
108 void DeleteCredList(OicSecCred_t* cred)
112 OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
113 LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
115 LL_DELETE(cred, credTmp1);
121 static size_t OicSecCredCount(const OicSecCred_t *secCred)
124 for (const OicSecCred_t *cred = secCred; cred; cred = cred->next)
131 OCStackResult CredToCBORPayload(const OicSecCred_t *credS, uint8_t **cborPayload,
134 if (NULL == credS || NULL == cborPayload || NULL != *cborPayload || NULL == cborSize)
136 return OC_STACK_INVALID_PARAM;
138 OIC_LOG(DEBUG, TAG, "CredToCBORPayload IN");
139 OCStackResult ret = OC_STACK_ERROR;
140 size_t cborLen = *cborSize;
149 CborEncoder encoder = { {.ptr = NULL }, .end = 0 };
150 CborEncoder credArray = { {.ptr = NULL }, .end = 0 };
151 int64_t cborEncoderResult = CborNoError;
153 const OicSecCred_t *cred = credS;
154 uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
155 VERIFY_NON_NULL(TAG, outPayload, ERROR);
156 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
159 cborEncoderResult |= cbor_encoder_create_array(&encoder, &credArray, OicSecCredCount(cred));
160 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding0 Cred Array.");
164 CborEncoder credMap = { {.ptr = NULL }, .end = 0, .added = 0, .flags = 0 };
165 size_t mapSize = CRED_MAP_SIZE;
171 if (cred->publicData.data)
175 #endif /* __WITH_X509__ */
176 if (cred->privateData.data)
180 cborEncoderResult |= cbor_encoder_create_map(&credArray, &credMap, mapSize);
181 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Map");
183 //CredID -- Mandatory
184 cborEncoderResult |= cbor_encode_text_string(&credMap, OIC_JSON_CREDID_NAME,
185 strlen(OIC_JSON_CREDID_NAME));
186 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Id Tag. ");
187 cborEncoderResult |= cbor_encode_int(&credMap, cred->credId);
188 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Id Value.");
190 //Subject -- Mandatory
191 cborEncoderResult |= cbor_encode_text_string(&credMap, OIC_JSON_SUBJECT_NAME,
192 strlen(OIC_JSON_SUBJECT_NAME));
193 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Subject Tag.");
194 cborEncoderResult |= cbor_encode_byte_string(&credMap, cred->subject.id,
195 sizeof(cred->subject.id));
196 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Subject Value.");
198 //CredType -- Mandatory
199 cborEncoderResult |= cbor_encode_text_string(&credMap, OIC_JSON_CREDTYPE_NAME,
200 strlen(OIC_JSON_CREDTYPE_NAME));
201 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Tag.");
202 cborEncoderResult |= cbor_encode_int(&credMap, cred->credType);
203 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
206 //PublicData -- Not Mandatory
207 if (cred->publicData.data)
209 cborEncoderResult |= cbor_encode_text_string(&credMap,
210 OIC_JSON_PUBLICDATA_NAME, strlen(OIC_JSON_PUBLICDATA_NAME));
211 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Public Data Tag.");
212 cborEncoderResult |= cbor_encode_byte_string(&credMap, cred->publicData.data,
213 cred->publicData.len);
214 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Public Tag Value.");
216 #endif /*__WITH_X509__*/
217 //PrivateData -- Not Mandatory
218 if(cred->privateData.data)
220 cborEncoderResult |= cbor_encode_text_string(&credMap,
221 OIC_JSON_PRIVATEDATA_NAME, strlen(OIC_JSON_PRIVATEDATA_NAME));
222 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Data Tag");
223 cborEncoderResult |= cbor_encode_byte_string(&credMap, cred->privateData.data,
224 cred->privateData.len);
225 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Data Value.");
228 //Period -- Not Mandatory
231 cborEncoderResult |= cbor_encode_text_string(&credMap, OIC_JSON_PERIOD_NAME,
232 strlen(OIC_JSON_PERIOD_NAME));
233 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Name Tag.");
234 cborEncoderResult |= cbor_encode_text_string(&credMap, cred->period,
235 strlen(cred->period));
236 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Name Value.");
239 //Owners -- Mandatory
241 cborEncoderResult |= cbor_encode_text_string(&credMap, OIC_JSON_OWNERS_NAME,
242 strlen(OIC_JSON_OWNERS_NAME));
243 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owners Name Tag.");
244 CborEncoder owners = { {.ptr = NULL }, .end = 0 };
245 cborEncoderResult |= cbor_encoder_create_array(&credMap, &owners, cred->ownersLen);
246 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owners Name Array.");
247 for (size_t i = 0; i < cred->ownersLen; i++)
249 cborEncoderResult |= cbor_encode_byte_string(&owners, (uint8_t *)cred->owners[i].id,
250 sizeof(cred->owners[i].id));
251 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owners Array Value.");
253 cborEncoderResult |= cbor_encoder_close_container(&credMap, &owners);
254 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Owners Name Array.");
256 cborEncoderResult |= cbor_encoder_close_container(&credArray, &credMap);
257 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Cred Map.");
261 cborEncoderResult |= cbor_encoder_close_container(&encoder, &credArray);
262 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Cred Array.");
264 if (CborNoError == cborEncoderResult)
266 *cborPayload = outPayload;
267 *cborSize = encoder.ptr - outPayload;
270 OIC_LOG(DEBUG, TAG, "CredToCBORPayload OUT");
272 if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
274 // reallocate and try again!
277 // Since the allocated initial memory failed, double the memory.
278 cborLen += encoder.ptr - encoder.end;
279 cborEncoderResult = CborNoError;
280 ret = CredToCBORPayload(credS, cborPayload, &cborLen);
281 if (OC_STACK_OK == ret)
287 if (CborNoError != cborEncoderResult)
293 ret = OC_STACK_ERROR;
299 OCStackResult CBORPayloadToCred(const uint8_t *cborPayload, size_t size,
300 OicSecCred_t **secCred)
302 if (NULL == cborPayload || NULL == secCred || NULL != *secCred)
304 return OC_STACK_INVALID_PARAM;
306 OIC_LOG(DEBUG, TAG, "CBORPayloadToCred IN");
310 OCStackResult ret = OC_STACK_ERROR;
314 CborError cborFindResult = CborNoError;
315 OicSecCred_t *cred = NULL;
322 cbor_parser_init(cborPayload, cborLen, 0, &parser, &credCbor);
324 OicSecCred_t *headCred = NULL;
328 cborFindResult = cbor_value_enter_container(&credCbor, &credArray);
329 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Array.");
331 while (cbor_value_is_valid(&credArray))
333 cred = (OicSecCred_t *) OICCalloc(1, sizeof(OicSecCred_t));
334 VERIFY_NON_NULL(TAG, cred, ERROR);
336 //CredId -- Mandatory
338 cborFindResult = cbor_value_map_find_value(&credArray, OIC_JSON_CREDID_NAME, &credMap);
339 if (CborNoError == cborFindResult && cbor_value_is_integer(&credMap))
341 cborFindResult = cbor_value_get_int(&credMap, (int *) &cred->credId);
342 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CredId.");
344 //subject -- Mandatory
345 cborFindResult = cbor_value_map_find_value(&credArray, OIC_JSON_SUBJECT_NAME, &credMap);
346 if (CborNoError == cborFindResult && cbor_value_is_byte_string(&credMap))
349 cborFindResult = cbor_value_dup_byte_string(&credMap, &id, &len, NULL);
350 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Subject Name.");
351 memcpy(cred->subject.id, id, len);
354 //CredType -- Mandatory
355 cborFindResult = cbor_value_map_find_value(&credArray, OIC_JSON_CREDTYPE_NAME, &credMap);
356 if (CborNoError == cborFindResult && cbor_value_is_integer(&credMap))
358 cborFindResult = cbor_value_get_int(&credMap, (int *) &cred->credType);
359 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CredType.");
361 //Owners -- Mandatory
362 cborFindResult = cbor_value_map_find_value(&credArray, OIC_JSON_OWNERS_NAME, &credMap);
363 if (CborNoError == cborFindResult && cbor_value_is_array(&credMap))
366 cborFindResult = cbor_value_get_array_length(&credMap, &cred->ownersLen);
367 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Array Len.");
368 cborFindResult = cbor_value_enter_container(&credMap, &owners);
369 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Container.");
371 cred->owners = (OicUuid_t *)OICCalloc(cred->ownersLen, sizeof(*cred->owners));
372 VERIFY_NON_NULL(TAG, cred->owners, ERROR);
373 while (cbor_value_is_valid(&owners))
375 uint8_t *owner = NULL;
376 cborFindResult = cbor_value_dup_byte_string(&owners, &owner, &len, NULL);
377 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owner Byte String.");
378 memcpy(cred->owners[i++].id, owner, len);
380 cborFindResult = cbor_value_advance(&owners);
381 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Array.");
384 //PrivateData is mandatory for some of the credential types listed below.
385 cborFindResult = cbor_value_map_find_value(&credArray, OIC_JSON_PRIVATEDATA_NAME, &credMap);
386 if (CborNoError == cborFindResult && cbor_value_is_byte_string(&credMap))
388 cborFindResult = cbor_value_dup_byte_string(&credMap,
389 &cred->privateData.data, &cred->privateData.len, NULL);
390 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Byte Array.");
393 //PublicData is mandatory only for SIGNED_ASYMMETRIC_KEY credentials type.
394 cborFindResult = cbor_value_map_find_value(&credArray, OIC_JSON_PUBLICDATA_NAME, &credMap);
395 if (CborNoError == cborFindResult && cbor_value_is_byte_string(&credMap))
397 if (cred->credType & SIGNED_ASYMMETRIC_KEY)
399 cborFindResult = cbor_value_dup_byte_string(&credMap, &cred->publicData.data,
400 &cred->publicData.len, NULL);
401 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Public Data.");
404 #endif //__WITH_X509__
405 //Period -- Not Mandatory
406 cborFindResult = cbor_value_map_find_value(&credArray, OIC_JSON_PERIOD_NAME, &credMap);
407 if (CborNoError == cborFindResult && cbor_value_is_text_string(&credMap))
409 cborFindResult = cbor_value_dup_text_string(&credMap, &cred->period, &len, NULL);
410 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Period.");
413 if (NULL == headCred)
419 OicSecCred_t *temp = headCred;
426 if (cbor_value_is_valid(&credArray))
428 cborFindResult = cbor_value_advance(&credArray);
429 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Cred Array.");
435 OIC_LOG(DEBUG, TAG, "CBORPayloadToCred OUT");
438 if (CborNoError != cborFindResult)
440 DeleteCredList(headCred);
442 ret = OC_STACK_ERROR;
448 OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t credType,
449 const OicSecCert_t * publicData, const OicSecKey_t* privateData,
450 size_t ownersLen, const OicUuid_t * owners)
453 OCStackResult ret = OC_STACK_ERROR;
455 OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
456 VERIFY_NON_NULL(TAG, cred, ERROR);
458 //CredId is assigned before appending new cred to the existing
459 //credential list and updating svr database in AddCredential().
462 VERIFY_NON_NULL(TAG, subject, ERROR);
463 memcpy(cred->subject.id, subject->id , sizeof(cred->subject.id));
465 VERIFY_SUCCESS(TAG, credType < (NO_SECURITY_MODE | SYMMETRIC_PAIR_WISE_KEY |
466 SYMMETRIC_GROUP_KEY | ASYMMETRIC_KEY | SIGNED_ASYMMETRIC_KEY | PIN_PASSWORD), ERROR);
467 cred->credType = credType;
470 if (publicData && publicData->data)
472 cred->publicData.data = (uint8_t *)OICCalloc(1, publicData->len);
473 VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
474 memcpy(cred->publicData.data, publicData->data, publicData->len);
475 cred->publicData.len = publicData->len;
477 #endif // __WITH_X509__
479 if (privateData && privateData->data)
481 cred->privateData.data = (uint8_t *)OICCalloc(1, privateData->len);
482 VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
483 memcpy(cred->privateData.data, privateData->data, privateData->len);
484 cred->privateData.len = privateData->len;
487 VERIFY_SUCCESS(TAG, ownersLen > 0, ERROR);
488 cred->ownersLen = ownersLen;
490 cred->owners = (OicUuid_t *)OICCalloc(cred->ownersLen, sizeof(*cred->owners));
491 VERIFY_NON_NULL(TAG, cred->owners, ERROR);
492 for (size_t i = 0; i < cred->ownersLen; i++)
494 memcpy(cred->owners[i].id, owners[i].id, sizeof(cred->owners[i].id));
499 if (OC_STACK_OK != ret)
501 DeleteCredList(cred);
507 static bool UpdatePersistentStorage(const OicSecCred_t *cred)
511 // Convert Cred data into JSON for update to persistent storage
514 uint8_t *payload = NULL;
516 OCStackResult res = CredToCBORPayload(cred, &payload, &size);
517 if ((OC_STACK_OK == res) && payload)
519 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, payload, size))
526 else //Empty cred list
528 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, NULL, 0))
537 * Compare function used LL_SORT for sorting credentials.
539 * @param first pointer to OicSecCred_t struct.
540 * @param second pointer to OicSecCred_t struct.
542 *@return -1, if credId of first is less than credId of second.
543 * 0, if credId of first is equal to credId of second.
544 * 1, if credId of first is greater than credId of second.
546 static int CmpCredId(const OicSecCred_t * first, const OicSecCred_t *second)
548 if (first->credId < second->credId)
552 else if (first->credId > second->credId)
561 * GetCredId goes through the cred list and returns the next
562 * available credId. The next credId could be the credId that is
563 * available due deletion of OicSecCred_t object or one more than
564 * credId of last credential in the list.
566 * @return next available credId if successful, else 0 for error.
568 static uint16_t GetCredId()
570 //Sorts credential list in incremental order of credId
571 LL_SORT(gCred, CmpCredId);
573 OicSecCred_t *currentCred = NULL, *credTmp = NULL;
574 uint16_t nextCredId = 1;
576 LL_FOREACH_SAFE(gCred, currentCred, credTmp)
578 if (currentCred->credId == nextCredId)
588 VERIFY_SUCCESS(TAG, nextCredId < UINT16_MAX, ERROR);
596 * Get the default value.
598 * @return NULL for now.
600 static OicSecCred_t* GetCredDefault()
602 // TODO:Update it when we finalize the default info.
606 OCStackResult AddCredential(OicSecCred_t * newCred)
608 OCStackResult ret = OC_STACK_ERROR;
609 VERIFY_SUCCESS(TAG, NULL != newCred, ERROR);
611 //Assigning credId to the newCred
612 newCred->credId = GetCredId();
613 VERIFY_SUCCESS(TAG, newCred->credId != 0, ERROR);
615 //Append the new Cred to existing list
616 LL_APPEND(gCred, newCred);
618 if (UpdatePersistentStorage(gCred))
627 OCStackResult RemoveCredential(const OicUuid_t *subject)
629 OCStackResult ret = OC_STACK_ERROR;
630 OicSecCred_t *cred = NULL;
631 OicSecCred_t *tempCred = NULL;
632 bool deleteFlag = false;
634 LL_FOREACH_SAFE(gCred, cred, tempCred)
636 if (memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
638 LL_DELETE(gCred, cred);
646 if (UpdatePersistentStorage(gCred))
648 ret = OC_STACK_RESOURCE_DELETED;
656 * Remove all credential data on credential resource and persistent storage
659 * OC_STACK_OK - no errors
660 * OC_STACK_ERROR - stack process error
662 OCStackResult RemoveAllCredentials(void)
664 DeleteCredList(gCred);
665 gCred = GetCredDefault();
667 if (!UpdatePersistentStorage(gCred))
669 return OC_STACK_ERROR;
676 * Internal function to fill private data of owner PSK.
678 * @param receviedCred recevied owner credential from OBT(PT)
679 * @param ownerAdd address of OBT(PT)
680 * @param doxm current device's doxm resource
683 * true successfully done and valid ower psk information
684 * false Invalid owner psk information or failed to owner psk generation
686 static bool FillPrivateDataOfOwnerPSK(OicSecCred_t* receviedCred, const CAEndpoint_t* ownerAddr,
687 const OicSecDoxm_t* doxm)
689 //Derive OwnerPSK locally
690 const char* oxmLabel = GetOxmString(doxm->oxmSel);
691 VERIFY_NON_NULL(TAG, oxmLabel, ERROR);
693 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
694 CAResult_t pskRet = CAGenerateOwnerPSK(ownerAddr,
695 (uint8_t*)oxmLabel, strlen(oxmLabel),
696 doxm->owner.id, sizeof(doxm->owner.id),
697 doxm->deviceID.id, sizeof(doxm->deviceID.id),
698 ownerPSK, OWNER_PSK_LENGTH_128);
699 VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
701 OIC_LOG(DEBUG, TAG, "OwnerPSK dump :");
702 OIC_LOG_BUFFER(DEBUG, TAG, ownerPSK, OWNER_PSK_LENGTH_128);
704 //Generate owner credential based on recevied credential information
705 receviedCred->privateData.data = (uint8_t *)OICCalloc(1, OWNER_PSK_LENGTH_128);
706 VERIFY_NON_NULL(TAG, receviedCred->privateData.data, ERROR);
707 receviedCred->privateData.len = OWNER_PSK_LENGTH_128;
708 memcpy(receviedCred->privateData.data, ownerPSK, OWNER_PSK_LENGTH_128);
710 OIC_LOG(INFO, TAG, "PrivateData of OwnerPSK was calculated successfully");
712 //Verify OwnerPSK information
713 return (memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0 &&
714 receviedCred->credType == SYMMETRIC_PAIR_WISE_KEY);
716 //receviedCred->privateData.data will be deallocated when deleting credential.
720 #endif //__WITH_DTLS__
722 static OCEntityHandlerResult HandlePutRequest(const OCEntityHandlerRequest * ehRequest)
724 OCEntityHandlerResult ret = OC_EH_ERROR;
725 OIC_LOG(DEBUG, TAG, "HandleCREDPutRequest IN");
727 //Get binary representation of cbor
728 OicSecCred_t *cred = NULL;
729 uint8_t *payload = (((OCSecurityPayload*)ehRequest->payload)->securityData1);
730 size_t size = (((OCSecurityPayload*)ehRequest->payload)->payloadSize);
731 OCStackResult res = CBORPayloadToCred(payload, size, &cred);
732 if (res == OC_STACK_OK)
735 OicUuid_t emptyUuid = {.id={0}};
736 const OicSecDoxm_t* doxm = GetDoxmResourceData();
737 if(false == doxm->owned && memcmp(&(doxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0)
739 //in case of owner PSK
740 switch(cred->credType)
742 case SYMMETRIC_PAIR_WISE_KEY:
744 OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
745 if(FillPrivateDataOfOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm))
747 if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&cred->subject))
749 OIC_LOG(WARNING, TAG, "The credential with the same subject ID was detected!");
752 OIC_LOG(ERROR, TAG, "OwnerPSK was generated successfully.");
753 if(OC_STACK_OK == AddCredential(cred))
755 ret = OC_EH_RESOURCE_CREATED;
759 OIC_LOG(ERROR, TAG, "Failed to save the OwnerPSK as cred resource");
765 OIC_LOG(ERROR, TAG, "Failed to verify receviced OwnerPKS.");
769 if(OC_EH_RESOURCE_CREATED == ret)
772 * in case of random PIN based OxM,
773 * revert get_psk_info callback of tinyDTLS to use owner credential.
775 if(OIC_RANDOM_DEVICE_PIN == doxm->oxmSel)
777 OicUuid_t emptyUuid = { .id={0}};
778 SetUuidForRandomPinOxm(&emptyUuid);
780 if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
782 OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
788 //Select cipher suite to use owner PSK
789 if(CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false))
791 OIC_LOG(ERROR, TAG, "Failed to disable anonymous cipher suite");
796 OIC_LOG(INFO, TAG, "Anonymous cipher suite is DISABLED");
800 CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256))
802 OIC_LOG(ERROR, TAG, "Failed to select cipher suite");
809 case SYMMETRIC_GROUP_KEY:
811 case SIGNED_ASYMMETRIC_KEY:
813 case ASYMMETRIC_ENCRYPTION_KEY:
815 OIC_LOG(WARNING, TAG, "Unsupported credential type for owner credential.");
821 OIC_LOG(WARNING, TAG, "Unknow credential type for owner credential.");
827 if(OC_EH_RESOURCE_CREATED != ret)
830 * If some error is occured while ownership transfer,
831 * ownership transfer related resource should be revert back to initial status.
833 RestoreDoxmToInitState();
834 RestorePstatToInitState();
840 * If the post request credential has credId, it will be
841 * discarded and the next available credId will be assigned
842 * to it before getting appended to the existing credential
843 * list and updating svr database.
845 ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
847 #else //not __WITH_DTLS__
849 * If the post request credential has credId, it will be
850 * discarded and the next available credId will be assigned
851 * to it before getting appended to the existing credential
852 * list and updating svr database.
854 ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
855 #endif//__WITH_DTLS__
858 if (OC_EH_RESOURCE_CREATED != ret)
860 if(OC_STACK_OK != RemoveCredential(&cred->subject))
862 OIC_LOG(WARNING, TAG, "Failed to remove the invalid credential");
866 OIC_LOG(DEBUG, TAG, "HandleCREDPutRequest OUT");
870 static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
872 OCEntityHandlerResult ret = OC_EH_ERROR;
874 //Get binary representation of CBOR
875 OicSecCred_t *cred = NULL;
876 uint8_t *payload = ((OCSecurityPayload*)ehRequest->payload)->securityData1;
877 size_t size = ((OCSecurityPayload*)ehRequest->payload)->payloadSize;
878 OCStackResult res = CBORPayloadToCred(payload, size, &cred);
879 if ((OC_STACK_OK == res) && cred)
881 //If the Post request credential has credId, it will be
882 //discarded and the next available credId will be assigned
883 //to it before getting appended to the existing credential
884 //list and updating svr database.
885 ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
891 static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
893 OIC_LOG(DEBUG, TAG, "Processing CredDeleteRequest");
895 OCEntityHandlerResult ehRet = OC_EH_ERROR;
897 unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
898 B64Result b64Ret = B64_OK;
901 if (NULL == ehRequest->query)
906 OicParseQueryIter_t parseIter = { .attrPos=NULL };
907 OicUuid_t subject = {.id={0}};
909 //Parsing REST query to get the subject
910 ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
911 while (GetNextQuery(&parseIter))
913 if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME,
914 parseIter.attrLen) == 0)
916 b64Ret = b64Decode((char*)parseIter.valPos, parseIter.valLen, base64Buff,
917 sizeof(base64Buff), &outLen);
918 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(subject.id)), ERROR);
919 memcpy(subject.id, base64Buff, outLen);
923 if (OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
925 ehRet = OC_EH_RESOURCE_DELETED;
932 OCEntityHandlerResult CredEntityHandler(OCEntityHandlerFlag flag,
933 OCEntityHandlerRequest * ehRequest,
934 void* callbackParameter)
936 (void)callbackParameter;
937 OCEntityHandlerResult ret = OC_EH_ERROR;
943 if (flag & OC_REQUEST_FLAG)
945 OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
946 //TODO : Handle PUT/DEL methods
947 switch (ehRequest->method)
950 ret = OC_EH_FORBIDDEN;
953 ret = HandlePutRequest(ehRequest);
956 ret = HandlePostRequest(ehRequest);
959 ret = HandleDeleteRequest(ehRequest);
967 //Send payload to request originator
968 ret = (SendSRMCBORResponse(ehRequest, ret, NULL, 0) == OC_STACK_OK) ?
974 OCStackResult CreateCredResource()
976 OCStackResult ret = OCCreateResource(&gCredHandle,
977 OIC_RSRC_TYPE_SEC_CRED,
984 if (OC_STACK_OK != ret)
986 OIC_LOG (FATAL, TAG, "Unable to instantiate Cred resource");
987 DeInitCredResource();
992 OCStackResult InitCredResource()
994 OCStackResult ret = OC_STACK_ERROR;
996 //Read Cred resource from PS
997 uint8_t *data = NULL;
999 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_CRED_NAME, &data, &size);
1000 // If database read failed
1001 if (ret != OC_STACK_OK)
1003 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1007 // Read ACL resource from PS
1008 ret = CBORPayloadToCred(data, size, &gCred);
1012 * If SVR database in persistent storage got corrupted or
1013 * is not available for some reason, a default Cred is created
1014 * which allows user to initiate Cred provisioning again.
1016 if (ret != OC_STACK_OK || !data || !gCred)
1018 gCred = GetCredDefault();
1020 //Instantiate 'oic.sec.cred'
1021 ret = CreateCredResource();
1026 OCStackResult DeInitCredResource()
1028 OCStackResult result = OCDeleteResource(gCredHandle);
1029 DeleteCredList(gCred);
1034 const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
1036 OicSecCred_t *cred = NULL;
1038 if ( NULL == subject)
1043 LL_FOREACH(gCred, cred)
1045 if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
1054 #if defined(__WITH_DTLS__)
1055 int32_t GetDtlsPskCredentials(CADtlsPskCredType_t type,
1056 const uint8_t *desc, size_t desc_len,
1057 uint8_t *result, size_t result_length)
1068 case CA_DTLS_PSK_HINT:
1069 case CA_DTLS_PSK_IDENTITY:
1071 OicUuid_t deviceID = {.id={}};
1072 // Retrieve Device ID from doxm resource
1073 if ( OC_STACK_OK != GetDoxmDeviceID(&deviceID) )
1075 OIC_LOG (ERROR, TAG, "Unable to retrieve doxm Device ID");
1079 if (result_length < sizeof(deviceID.id))
1081 OIC_LOG (ERROR, TAG, "Wrong value for result_length");
1084 memcpy(result, deviceID.id, sizeof(deviceID.id));
1085 return (sizeof(deviceID.id));
1089 case CA_DTLS_PSK_KEY:
1091 OicSecCred_t *cred = NULL;
1092 LL_FOREACH(gCred, cred)
1094 if (cred->credType != SYMMETRIC_PAIR_WISE_KEY)
1099 if ((desc_len == sizeof(cred->subject.id)) &&
1100 (memcmp(desc, cred->subject.id, sizeof(cred->subject.id)) == 0))
1103 * If the credentials are valid for limited time,
1104 * check their expiry.
1108 if(IOTVTICAL_VALID_ACCESS != IsRequestWithinValidTime(cred->period, NULL))
1110 OIC_LOG (INFO, TAG, "Credentials are expired.");
1117 result_length = cred->privateData.len;
1118 memcpy(result, cred->privateData.data, result_length);
1119 return result_length;
1127 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
1137 * Add temporal PSK to PIN based OxM
1139 * @param[in] tmpSubject UUID of target device
1140 * @param[in] credType Type of credential to be added
1141 * @param[in] pin numeric characters
1142 * @param[in] pinSize length of 'pin'
1143 * @param[in] ownersLen Number of owners
1144 * @param[in] owners Array of owners
1145 * @param[out] tmpCredSubject Generated credential's subject.
1147 * @return OC_STACK_OK for success and errorcode otherwise.
1149 OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
1150 const char * pin, size_t pinSize,
1151 size_t ownersLen, const OicUuid_t * owners, OicUuid_t* tmpCredSubject)
1153 OCStackResult ret = OC_STACK_ERROR;
1154 OIC_LOG(DEBUG, TAG, "AddTmpPskWithPIN IN");
1156 if(NULL == tmpSubject || NULL == pin || 0 == pinSize || NULL == tmpCredSubject)
1158 return OC_STACK_INVALID_PARAM;
1161 uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
1162 OicSecKey_t privKey = {privData, OWNER_PSK_LENGTH_128};
1163 OicSecCred_t* cred = NULL;
1164 int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, owners->id,
1165 UUID_LENGTH, PBKDF_ITERATIONS,
1166 OWNER_PSK_LENGTH_128, privData);
1167 VERIFY_SUCCESS(TAG, (0 == dtlsRes) , ERROR);
1169 cred = GenerateCredential(tmpSubject, credType, NULL,
1170 &privKey, ownersLen, owners);
1173 OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
1174 return OC_STACK_ERROR;
1177 memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
1179 ret = AddCredential(cred);
1180 if( OC_STACK_OK != ret)
1182 RemoveCredential(tmpSubject);
1183 OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
1185 OIC_LOG(DEBUG, TAG, "AddTmpPskWithPIN OUT");
1191 #endif /* __WITH_DTLS__ */
1192 #ifdef __WITH_X509__
1193 #define CERT_LEN_PREFIX (3)
1194 #define BYTE_SIZE (8) //bits
1195 #define PUB_KEY_X_COORD ("x")
1196 #define PUB_KEY_Y_COORD ("y")
1197 #define CERTIFICATE ("x5c")
1198 #define PRIVATE_KEY ("d")
1200 static uint32_t parseCertPrefix(uint8_t *prefix)
1205 for (int i = 0; i < CERT_LEN_PREFIX; ++i)
1207 res |= (((uint32_t) prefix[i]) << ((CERT_LEN_PREFIX - 1 -i) * BYTE_SIZE));
1213 static OCStackResult GetCAPublicKeyData(CADtlsX509Creds_t *credInfo)
1215 OCStackResult ret = OC_STACK_ERROR;
1216 uint8_t *ccPtr = credInfo->certificateChain;
1217 for (uint8_t i = 0; i < credInfo->chainLen - 1; ++i)
1219 ccPtr += CERT_LEN_PREFIX + parseCertPrefix(ccPtr);
1222 ByteArray cert = { .data = ccPtr + CERT_LEN_PREFIX, .len = parseCertPrefix(ccPtr) };
1223 CertificateX509 certStruct;
1225 VERIFY_SUCCESS(TAG, PKI_SUCCESS == DecodeCertificate(cert, &certStruct), ERROR);
1227 INC_BYTE_ARRAY(certStruct.pubKey, 2);
1229 memcpy(credInfo->rootPublicKeyX, certStruct.pubKey.data, PUBLIC_KEY_SIZE / 2);
1230 memcpy(credInfo->rootPublicKeyY, certStruct.pubKey.data + PUBLIC_KEY_SIZE / 2, PUBLIC_KEY_SIZE / 2);
1237 int GetDtlsX509Credentials(CADtlsX509Creds_t *credInfo)
1240 VERIFY_NON_NULL(TAG, credInfo, ERROR);
1243 VERIFY_SUCCESS(TAG, OC_STACK_OK == InitCredResource(), ERROR);
1246 OicSecCred_t *cred = NULL;
1247 LL_SEARCH_SCALAR(gCred, cred, credType, SIGNED_ASYMMETRIC_KEY);
1248 VERIFY_NON_NULL(TAG, cred, ERROR);
1250 if (cred->publicData.len > MAX_CERT_MESSAGE_LEN || cred->privateData.len > PRIVATE_KEY_SIZE)
1254 memcpy(credInfo->certificateChain, cred->publicData.data, cred->publicData.len);
1255 memcpy(credInfo->devicePrivateKey, cred->privateData.data, cred->privateData.len);
1256 credInfo->certificateChainLen = parseCertPrefix(cred->publicData.data);
1257 GetCAPublicKeyData(credInfo);
1263 #undef CERT_LEN_PREFIX
1264 #endif /* __WITH_X509__ */