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
23 #include "iotivity_config.h"
35 #include "cainterface.h"
36 #include "payload_logging.h"
40 #include "ocserverrequest.h"
41 #include "oic_malloc.h"
42 #include "oic_string.h"
43 #include "ocpayload.h"
44 #include "ocpayloadcbor.h"
46 #include "credresource.h"
47 #include "doxmresource.h"
48 #include "pstatresource.h"
49 #include "iotvticalendar.h"
51 #include "resourcemanager.h"
52 #include "srmresourcestrings.h"
53 #include "srmutility.h"
54 #include "psinterface.h"
55 #include "pinoxmcommon.h"
56 #include "certhelpers.h"
58 #include "secureresourcemanager.h"
59 #include "deviceonboardingstate.h"
62 #include <sys/types.h>
68 #if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
69 #include <mbedtls/ssl_ciphersuites.h>
70 #include <mbedtls/pk.h>
71 #include <mbedtls/base64.h>
72 #include <mbedtls/pem.h>
75 #define TAG "OIC_SRM_CREDL"
82 /** Max credential types number used for TLS */
84 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
85 * The value of payload size is increased until reaching belox max cbor size. */
86 static const uint16_t CBOR_SIZE = 2048;
88 /** CRED size - Number of mandatory items. */
89 static const uint8_t CRED_ROOT_MAP_SIZE = 4;
90 static const uint8_t CRED_EMPTY_ROOT_MAP_SIZE = 2;
91 static const uint8_t CRED_MAP_SIZE = 3;
92 static const uint8_t ROLEID_MAP_SIZE = 1;
95 static OicSecCred_t *gCred = NULL;
96 static OCResourceHandle gCredHandle = NULL;
97 static OicUuid_t gRownerId = { .id = { 0 } };
99 typedef enum CredCompareResult{
101 CRED_CMP_NOT_EQUAL = 1,
103 }CredCompareResult_t;
105 typedef struct CredIdList CredIdList_t;
113 static void DeleteCredIdList(CredIdList_t** list)
117 CredIdList_t *head = *list;
121 CredIdList_t *tmp = head->next;
128 static bool ValueWithinBounds(uint64_t value, uint64_t maxValue)
130 if (value > maxValue)
132 OIC_LOG_V(ERROR, TAG, "The value (%" PRId64 ") is greater than allowed maximum of %" PRId64 ".", value, maxValue);
140 * Internal function to check a subject of SIGNED_ASYMMETRIC_KEY(Certificate).
141 * If that subject is NULL or wildcard, set it to own deviceID.
142 * @param cred credential on SVR DB file
143 * @param deviceID own deviceuuid of doxm resource
146 * true successfully done
150 static bool CheckSubjectOfCertificate(OicSecCred_t* cred, OicUuid_t deviceID)
152 OIC_LOG(DEBUG, TAG, "IN CheckSubjectOfCertificate");
153 VERIFY_NOT_NULL(TAG, cred, ERROR);
155 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
156 const OicUuid_t emptyUuid = { .id = { 0 } };
158 if ( SIGNED_ASYMMETRIC_KEY == cred->credType)
160 if((0 == memcmp(cred->subject.id, emptyUuid.id, sizeof(cred->subject.id))) ||
161 (0 == memcmp(cred->subject.id, &WILDCARD_SUBJECT_ID, sizeof(cred->subject.id))))
163 memcpy(cred->subject.id, deviceID.id, sizeof(deviceID.id));
170 OIC_LOG(DEBUG, TAG, "OUT CheckSubjectOfCertificate");
173 OIC_LOG(ERROR, TAG, "OUT CheckSubjectOfCertificate");
178 * Internal function to check credential
180 static bool IsValidCredential(const OicSecCred_t* cred)
182 OicUuid_t emptyUuid = {.id={0}};
185 OIC_LOG(DEBUG, TAG, "IN IsValidCredential");
187 VERIFY_NOT_NULL(TAG, cred, ERROR);
188 VERIFY_SUCCESS(TAG, 0 != cred->credId, ERROR);
189 OIC_LOG_V(DEBUG, TAG, "Cred ID = %d", cred->credId);
191 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
192 OIC_LOG_V(DEBUG, TAG, "Cred Type = %d", cred->credType);
194 switch(cred->credType)
196 case SYMMETRIC_PAIR_WISE_KEY:
197 case SYMMETRIC_GROUP_KEY:
200 VERIFY_NOT_NULL(TAG, cred->privateData.data, ERROR);
201 VERIFY_SUCCESS(TAG, 0 != cred->privateData.len, ERROR);
202 VERIFY_SUCCESS(TAG, \
203 (OIC_ENCODING_RAW == cred->privateData.encoding || \
204 OIC_ENCODING_BASE64 == cred->privateData.encoding), \
210 VERIFY_NOT_NULL(TAG, cred->publicData.data, ERROR);
211 VERIFY_SUCCESS(TAG, 0 != cred->publicData.len, ERROR);
212 VERIFY_SUCCESS(TAG, \
213 (OIC_ENCODING_UNKNOW < cred->publicData.encoding && \
214 OIC_ENCODING_DER >= cred->publicData.encoding),
218 case SIGNED_ASYMMETRIC_KEY:
220 VERIFY_SUCCESS(TAG, (NULL != cred->publicData.data ||NULL != cred->optionalData.data) , ERROR);
221 VERIFY_SUCCESS(TAG, (0 != cred->publicData.len || 0 != cred->optionalData.len), ERROR);
223 if(NULL != cred->optionalData.data)
225 VERIFY_SUCCESS(TAG, \
226 (OIC_ENCODING_UNKNOW < cred->optionalData.encoding && \
227 OIC_ENCODING_DER >= cred->optionalData.encoding),
232 case ASYMMETRIC_ENCRYPTION_KEY:
234 VERIFY_NOT_NULL(TAG, cred->privateData.data, ERROR);
235 VERIFY_SUCCESS(TAG, 0 != cred->privateData.len, ERROR);
236 VERIFY_SUCCESS(TAG, \
237 (OIC_ENCODING_UNKNOW < cred->privateData.encoding && \
238 OIC_ENCODING_DER >= cred->privateData.encoding),
244 OIC_LOG(WARNING, TAG, "Unknown credential type");
250 VERIFY_SUCCESS(TAG, 0 != memcmp(emptyUuid.id, cred->subject.id, sizeof(cred->subject.id)), ERROR);
252 OIC_LOG(DEBUG, TAG, "OUT IsValidCredential");
255 OIC_LOG(WARNING, TAG, "OUT IsValidCredential : Invalid Credential detected.");
259 static bool IsEmptyCred(const OicSecCred_t* cred)
261 OicUuid_t emptyUuid = {.id={0}};
263 VERIFY_SUCCESS(TAG, (0 == memcmp(cred->subject.id, emptyUuid.id, sizeof(emptyUuid))), ERROR);
264 VERIFY_SUCCESS(TAG, !IsNonEmptyRole(&cred->roleId), ERROR);
265 VERIFY_SUCCESS(TAG, (0 == cred->credId), ERROR);
266 VERIFY_SUCCESS(TAG, (0 == cred->credType), ERROR);
267 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
268 VERIFY_SUCCESS(TAG, (NULL == cred->privateData.data), ERROR);
269 VERIFY_SUCCESS(TAG, (NULL == cred->publicData.data), ERROR);
270 VERIFY_SUCCESS(TAG, (NULL == cred->optionalData.data), ERROR);
271 VERIFY_SUCCESS(TAG, (NULL == cred->credUsage), ERROR);
279 * This function frees OicSecCred_t object's fields and object itself.
281 void FreeCred(OicSecCred_t *cred)
285 OIC_LOG(ERROR, TAG, "Invalid Parameter");
288 //Note: Need further clarification on roleID data type
291 OICFree(cred->roleIds);
294 //Clean PublicData/OptionalData/Credusage
295 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
296 // TODO: Need to check credUsage.
297 OICFree(cred->publicData.data);
298 OICFree(cred->optionalData.data);
299 OICFree(cred->credUsage);
301 #endif /* __WITH_DTLS__ || __WITH_TLS__*/
304 OICClearMemory(cred->privateData.data, cred->privateData.len);
305 OICFree(cred->privateData.data);
308 OICFree(cred->period);
310 #ifdef MULTIPLE_OWNER
312 OICFree(cred->eownerID);
317 //Clean Cred node itself
321 void DeleteCredList(OicSecCred_t* cred)
325 OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
326 LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
328 LL_DELETE(cred, credTmp1);
334 size_t GetCredKeyDataSize(const OicSecCred_t* cred)
339 OicSecCred_t *credPtr = NULL, *credTmp = NULL;
340 LL_FOREACH_SAFE((OicSecCred_t*)cred, credPtr, credTmp)
342 if (credPtr->privateData.data && 0 < credPtr->privateData.len)
344 size += credPtr->privateData.len;
346 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
347 if (credPtr->publicData.data && 0 < credPtr->publicData.len)
349 size += credPtr->publicData.len;
351 if (credPtr->optionalData.data && 0 < credPtr->optionalData.len)
353 size += credPtr->optionalData.len;
358 OIC_LOG_V(DEBUG, TAG, "Cred Key Data Size : %u", (unsigned int) size);
362 static size_t OicSecCredCount(const OicSecCred_t *secCred)
365 for (const OicSecCred_t *cred = secCred; cred; cred = cred->next)
372 static const char* EncodingValueToString(OicEncodingType_t encoding)
376 case OIC_ENCODING_RAW: return OIC_SEC_ENCODING_RAW;
377 case OIC_ENCODING_BASE64: return OIC_SEC_ENCODING_BASE64;
378 case OIC_ENCODING_DER: return OIC_SEC_ENCODING_DER;
379 case OIC_ENCODING_PEM: return OIC_SEC_ENCODING_PEM;
380 default: return NULL;
384 static CborError SerializeEncodingToCborInternal(CborEncoder *map, const OicSecKey_t *value)
386 CborError cborEncoderResult = CborNoError;
387 const char *encoding = EncodingValueToString(value->encoding);
390 cborEncoderResult = cbor_encode_text_string(map, OIC_JSON_ENCODING_NAME,
391 strlen(OIC_JSON_ENCODING_NAME));
392 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Encoding Tag.");
393 cborEncoderResult = cbor_encode_text_string(map, encoding,
395 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Encoding Value.");
397 cborEncoderResult = cbor_encode_text_string(map, OIC_JSON_DATA_NAME,
398 strlen(OIC_JSON_DATA_NAME));
399 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Name Tag.");
400 if (OIC_ENCODING_DER == value->encoding ||
401 OIC_ENCODING_RAW == value->encoding)
403 cborEncoderResult = cbor_encode_byte_string(map,
404 value->data, value->len);
408 cborEncoderResult = cbor_encode_text_string(map,
409 (char*)value->data, value->len);
411 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Name Value.");
415 OIC_LOG_V(ERROR, TAG, "%s: Unknown encoding type: %u.", __func__, value->encoding);
416 return CborErrorUnknownType;
419 return cborEncoderResult;
422 CborError SerializeEncodingToCbor(CborEncoder *rootMap, const char* tag, const OicSecKey_t *value)
424 CborError cborEncoderResult = CborNoError;
426 const size_t mapSize = 2;
428 cborEncoderResult = cbor_encode_text_string(rootMap, tag, strlen(tag));
429 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding PrivateData Tag.");
431 cborEncoderResult = cbor_encoder_create_map(rootMap, &map, mapSize);
432 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Map");
434 cborEncoderResult = SerializeEncodingToCborInternal(&map, value);
435 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed adding OicSecKey_t structure");
437 cborEncoderResult = cbor_encoder_close_container(rootMap, &map);
438 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Closing Map.");
441 return cborEncoderResult;
444 CborError SerializeSecOptToCbor(CborEncoder *rootMap, const char* tag, const OicSecOpt_t *value)
446 CborError cborEncoderResult = CborNoError;
448 const size_t mapSize = 3;
450 cborEncoderResult = cbor_encode_text_string(rootMap, tag, strlen(tag));
451 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding PrivateData Tag.");
453 cborEncoderResult = cbor_encoder_create_map(rootMap, &map, mapSize);
454 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Map");
457 in.data = value->data;
458 in.encoding = value->encoding;
461 cborEncoderResult = SerializeEncodingToCborInternal(&map, &in);
462 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed adding OicSecKey_t structure");
464 cborEncoderResult = cbor_encode_text_string(&map, OIC_JSON_REVOCATION_STATUS_NAME,
465 strlen(OIC_JSON_REVOCATION_STATUS_NAME));
466 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding optional revstat Tag.");
467 cborEncoderResult = cbor_encode_boolean(&map, value->revstat);
468 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding optional revstat Value.");
470 cborEncoderResult = cbor_encoder_close_container(rootMap, &map);
471 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Closing Map.");
474 return cborEncoderResult;
477 static CborError DeserializeEncodingFromCborInternal(CborValue *map, char *name, OicSecKey_t *value)
480 CborError cborFindResult = CborNoError;
483 if (strcmp(name, OIC_JSON_DATA_NAME) == 0)
485 if(cbor_value_is_byte_string(map))
487 cborFindResult = cbor_value_dup_byte_string(map, &value->data,
490 else if(cbor_value_is_text_string(map))
492 cborFindResult = cbor_value_dup_text_string(map, (char**)(&value->data),
497 cborFindResult = CborErrorUnknownType;
498 OIC_LOG(ERROR, TAG, "Unknown type for private data.");
500 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding PrivateData.");
503 // encoding -- Mandatory
504 if (strcmp(name, OIC_JSON_ENCODING_NAME) == 0)
506 char* strEncoding = NULL;
507 cborFindResult = cbor_value_dup_text_string(map, &strEncoding, &len, NULL);
508 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding EncodingType");
510 if(strcmp(strEncoding, OIC_SEC_ENCODING_RAW) == 0)
512 value->encoding = OIC_ENCODING_RAW;
514 else if(strcmp(strEncoding, OIC_SEC_ENCODING_BASE64) == 0)
516 value->encoding = OIC_ENCODING_BASE64;
518 else if(strcmp(strEncoding, OIC_SEC_ENCODING_DER) == 0)
520 value->encoding = OIC_ENCODING_DER;
522 else if(strcmp(strEncoding, OIC_SEC_ENCODING_PEM) == 0)
524 value->encoding = OIC_ENCODING_PEM;
529 value->encoding = OIC_ENCODING_RAW;
530 OIC_LOG_V(WARNING, TAG, "%s: Unknown encoding type detected.", __func__);
532 //Because cbor using malloc directly, it is required to use free() instead of OICFree
536 return cborFindResult;
539 CborError DeserializeEncodingFromCbor(CborValue *rootMap, OicSecKey_t *value)
541 CborValue map = { .parser = NULL };
542 CborError cborFindResult = cbor_value_enter_container(rootMap, &map);
545 while (cbor_value_is_valid(&map))
548 CborType type = cbor_value_get_type(&map);
549 if (type == CborTextStringType && cbor_value_is_text_string(&map))
551 cborFindResult = cbor_value_dup_text_string(&map, &name, &len, NULL);
552 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to get text");
553 cborFindResult = cbor_value_advance(&map);
554 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to advance value");
558 cborFindResult = DeserializeEncodingFromCborInternal(&map, name, value);
559 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to read OicSecKey_t value");
561 if (cbor_value_is_valid(&map))
563 cborFindResult = cbor_value_advance(&map);
564 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Advancing Map.");
566 //Because cbor using malloc directly, it is required to use free() instead of OICFree
570 return cborFindResult;
573 CborError DeserializeSecOptFromCbor(CborValue *rootMap, OicSecOpt_t *value)
575 CborValue map = { .parser = NULL };
576 CborError cborFindResult = cbor_value_enter_container(rootMap, &map);
578 value->revstat = false;
580 while (cbor_value_is_valid(&map))
583 CborType type = cbor_value_get_type(&map);
584 if (type == CborTextStringType && cbor_value_is_text_string(&map))
586 cborFindResult = cbor_value_dup_text_string(&map, &name, &len, NULL);
587 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to get text");
588 cborFindResult = cbor_value_advance(&map);
589 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to advance value");
593 // OptionalData::revstat -- Mandatory
594 if (strcmp(name, OIC_JSON_REVOCATION_STATUS_NAME) == 0)
596 cborFindResult = cbor_value_get_boolean(&map, &value->revstat);
597 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding revstat Value.")
600 cborFindResult = DeserializeEncodingFromCborInternal(&map, name, &out);
601 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to read OicSecKey_t value");
603 value->data = out.data;
604 value->encoding = out.encoding;
605 value->len = out.len;
607 if (cbor_value_is_valid(&map))
609 cborFindResult = cbor_value_advance(&map);
610 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Advancing Map.");
612 //Because cbor using malloc directly, it is required to use free() instead of OICFree
616 return cborFindResult;
619 /* Produce debugging output for all credentials, output metadata. */
620 static void logCredMetadata()
623 OicSecCred_t * temp = NULL;
625 char uuidString[UUID_STRING_SIZE];
628 OIC_LOG_V(DEBUG, TAG, "IN %s:", __func__);
630 if (GetDoxmDeviceID(&ownUuid) == OC_STACK_OK && OCConvertUuidToString(ownUuid.id, uuidString))
632 OIC_LOG_V(DEBUG, TAG, "Own UUID: %s", uuidString);
635 LL_FOREACH(gCred, temp)
638 OIC_LOG(DEBUG, TAG, " ");
639 OIC_LOG_V(DEBUG, TAG, "Cred ID: %d", temp->credId);
640 if (OCConvertUuidToString(temp->subject.id, uuidString))
642 OIC_LOG_V(DEBUG, TAG, "Subject UUID: %s", uuidString);
644 if (IsNonEmptyRole(&temp->roleId))
646 OIC_LOG_V(DEBUG, TAG, "Role ID: %s", temp->roleId.id);
647 OIC_LOG_V(DEBUG, TAG, "Role authority: %s", temp->roleId.authority);
649 OIC_LOG_V(DEBUG, TAG, "Cred Type: %d", temp->credType);
650 OIC_LOG_V(DEBUG, TAG, "privateData length: %" PRIuPTR ", encoding: %d", temp->privateData.len, temp->privateData.encoding);
652 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
653 OIC_LOG_V(DEBUG, TAG, "publicData length: %" PRIuPTR ", encoding: %d", temp->publicData.len, temp->publicData.encoding);
656 OIC_LOG_V(DEBUG, TAG, "credUsage: %s", temp->credUsage);
659 OIC_LOG_V(DEBUG, TAG, "optionalData length: %" PRIuPTR", encoding: %d" PRIuPTR, temp->optionalData.len, temp->optionalData.encoding);
664 OIC_LOG_V(DEBUG, TAG, "Found %" PRIuPTR " credentials.", count);
666 OIC_LOG_V(DEBUG, TAG, "OUT %s:", __func__);
670 OCStackResult CredToCBORPayload(const OicSecCred_t *credS, uint8_t **cborPayload,
671 size_t *cborSize, int secureFlag)
673 OIC_LOG_V(DEBUG, TAG, "IN %s:", __func__);
674 if (NULL == cborPayload || NULL != *cborPayload || NULL == cborSize)
676 return OC_STACK_INVALID_PARAM;
679 OCStackResult ret = OC_STACK_ERROR;
681 CborError cborEncoderResult = CborNoError;
682 uint8_t *outPayload = NULL;
683 size_t cborLen = *cborSize;
686 const OicSecCred_t *cred = credS;
688 CborEncoder credArray;
689 CborEncoder credRootMap;
690 CborEncoder roleIdMap;
697 outPayload = (uint8_t *)OICCalloc(1, cborLen);
698 VERIFY_NOT_NULL_RETURN(TAG, outPayload, ERROR, OC_STACK_ERROR);
700 cbor_encoder_init(&encoder, outPayload, cborLen, 0);
702 size_t credRootMapSize = CRED_ROOT_MAP_SIZE;
704 // Create CRED Root Map (creds, rownerid)
705 cborEncoderResult = cbor_encoder_create_map(&encoder, &credRootMap, credRootMapSize);
706 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Cred Root Map");
709 cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_CREDS_NAME,
710 strlen(OIC_JSON_CREDS_NAME));
711 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding creds Name Tag.");
714 cborEncoderResult = cbor_encoder_create_array(&credRootMap, &credArray, OicSecCredCount(cred));
715 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Cred Array.");
720 size_t mapSize = CRED_MAP_SIZE;
727 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
728 #ifdef MULTIPLE_OWNER
733 #endif //MULTIPLE_OWNER
735 if ((SIGNED_ASYMMETRIC_KEY == cred->credType || ASYMMETRIC_KEY == cred->credType)
736 && cred->publicData.data)
740 if (SIGNED_ASYMMETRIC_KEY == cred->credType && cred->optionalData.data)
748 if (IsNonEmptyRole(&cred->roleId))
752 #endif /* __WITH_DTLS__ || __WITH_TLS__*/
753 if (!secureFlag && cred->privateData.data)
757 cborEncoderResult = cbor_encoder_create_map(&credArray, &credMap, mapSize);
758 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Cred Map");
760 //CredID -- Mandatory
761 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDID_NAME,
762 strlen(OIC_JSON_CREDID_NAME));
763 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Cred Id Tag. ");
764 cborEncoderResult = cbor_encode_int(&credMap, cred->credId);
765 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Cred Id Value.");
767 //Subject -- Mandatory
768 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_SUBJECTID_NAME,
769 strlen(OIC_JSON_SUBJECTID_NAME));
770 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Subject Tag.");
771 inLen = (memcmp(&(cred->subject), &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0) ?
772 WILDCARD_SUBJECT_ID_LEN : sizeof(OicUuid_t);
773 if(inLen == WILDCARD_SUBJECT_ID_LEN)
775 cborEncoderResult = cbor_encode_text_string(&credMap, WILDCARD_RESOURCE_URI,
776 strlen(WILDCARD_RESOURCE_URI));
777 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Addding Subject Id wildcard Value.");
781 char *subject = NULL;
782 ret = ConvertUuidToStr(&cred->subject, &subject);
783 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
784 cborEncoderResult = cbor_encode_text_string(&credMap, subject, strlen(subject));
785 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Addding Subject Id Value.");
789 //Role ID -- optional
790 if (IsNonEmptyRole(&cred->roleId))
792 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_ROLEID_NAME,
793 strlen(OIC_JSON_ROLEID_NAME));
794 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed adding role ID map tag");
796 bool includeAuthority = (0 != memcmp(&cred->roleId.authority, &EMPTY_ROLE.authority, sizeof(EMPTY_ROLE.authority)));
798 cborEncoderResult = cbor_encoder_create_map(&credMap, &roleIdMap, ROLEID_MAP_SIZE + (includeAuthority ? 1 : 0));
799 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed adding role ID map");
801 cborEncoderResult = cbor_encode_text_string(&roleIdMap, OIC_JSON_ROLE_NAME, strlen(OIC_JSON_ROLE_NAME));
802 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed adding role tag");
804 cborEncoderResult = cbor_encode_text_string(&roleIdMap, cred->roleId.id, strlen(cred->roleId.id));
805 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed adding role value");
807 if (includeAuthority)
809 cborEncoderResult = cbor_encode_text_string(&roleIdMap, OIC_JSON_AUTHORITY_NAME, strlen(OIC_JSON_AUTHORITY_NAME));
810 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed adding authority tag");
812 cborEncoderResult = cbor_encode_text_string(&roleIdMap, cred->roleId.authority, strlen(cred->roleId.authority));
813 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed adding authority value");
816 cborEncoderResult = cbor_encoder_close_container(&credMap, &roleIdMap);
817 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed closing role ID map");
820 //CredType -- Mandatory
821 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDTYPE_NAME,
822 strlen(OIC_JSON_CREDTYPE_NAME));
823 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Cred Type Tag.");
824 cborEncoderResult = cbor_encode_int(&credMap, cred->credType);
825 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
827 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
828 //PublicData -- Not Mandatory
829 if ((SIGNED_ASYMMETRIC_KEY == cred->credType || ASYMMETRIC_KEY == cred->credType)
830 && cred->publicData.data)
832 cborEncoderResult = SerializeEncodingToCbor(&credMap,
833 OIC_JSON_PUBLICDATA_NAME, &cred->publicData);
834 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding PublicData Tag.");
836 //OptionalData -- Not Mandatory
837 if (SIGNED_ASYMMETRIC_KEY == cred->credType && cred->optionalData.data)
839 cborEncoderResult = SerializeSecOptToCbor(&credMap,
840 OIC_JSON_OPTDATA_NAME, &cred->optionalData);
841 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding OptionalData Tag.");
843 //CredUsage -- Not Mandatory
846 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDUSAGE_NAME,
847 strlen(OIC_JSON_CREDUSAGE_NAME));
848 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Credusage Name Tag.");
849 cborEncoderResult = cbor_encode_text_string(&credMap, cred->credUsage,
850 strlen(cred->credUsage));
851 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Credusage Name Value.");
853 #endif /* __WITH_DTLS__ || __WITH_TLS__*/
854 //PrivateData -- Not Mandatory
855 if(!secureFlag && cred->privateData.data)
857 cborEncoderResult = SerializeEncodingToCbor(&credMap,
858 OIC_JSON_PRIVATEDATA_NAME, &cred->privateData);
859 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding PrivateData Tag.");
862 //Period -- Not Mandatory
865 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_PERIOD_NAME,
866 strlen(OIC_JSON_PERIOD_NAME));
867 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Period Name Tag.");
868 cborEncoderResult = cbor_encode_text_string(&credMap, cred->period,
869 strlen(cred->period));
870 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Period Name Value.");
873 #ifdef MULTIPLE_OWNER
874 // Eownerid -- Not Mandatory
878 cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_EOWNERID_NAME,
879 strlen(OIC_JSON_EOWNERID_NAME));
880 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding eownerId Name Tag.");
881 ret = ConvertUuidToStr(cred->eownerID, &eowner);
882 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
883 cborEncoderResult = cbor_encode_text_string(&credMap, eowner, strlen(eowner));
884 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Addding eownerId Value.");
887 #endif //MULTIPLE_OWNER
889 cborEncoderResult = cbor_encoder_close_container(&credArray, &credMap);
890 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Closing Cred Map.");
894 cborEncoderResult = cbor_encoder_close_container(&credRootMap, &credArray);
895 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Closing Cred Array.");
902 cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_ROWNERID_NAME,
903 strlen(OIC_JSON_ROWNERID_NAME));
904 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding rownerid Name.");
905 ret = ConvertUuidToStr(&gRownerId, &rowner);
906 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
907 cborEncoderResult = cbor_encode_text_string(&credRootMap, rowner, strlen(rowner));
908 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Addding rownerid Value.");
915 cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_RT_NAME,
916 strlen(OIC_JSON_RT_NAME));
917 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
918 cborEncoderResult = cbor_encoder_create_array(&credRootMap, &rtArray, 1);
919 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Addding RT Value.");
920 for (size_t i = 0; i < 1; i++)
922 cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_CRED,
923 strlen(OIC_RSRC_TYPE_SEC_CRED));
924 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding RT Value.");
926 cborEncoderResult = cbor_encoder_close_container(&credRootMap, &rtArray);
927 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Closing RT.");
931 cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_IF_NAME,
932 strlen(OIC_JSON_IF_NAME));
933 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
934 cborEncoderResult = cbor_encoder_create_array(&credRootMap, &ifArray, 1);
935 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Addding IF Value.");
936 for (size_t i = 0; i < 1; i++)
938 cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
939 strlen(OC_RSRVD_INTERFACE_DEFAULT));
940 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding IF Value.");
942 cborEncoderResult = cbor_encoder_close_container(&credRootMap, &ifArray);
943 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Closing IF.");
946 // Close CRED Root Map
947 cborEncoderResult = cbor_encoder_close_container(&encoder, &credRootMap);
948 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Closing CRED Root Map.");
950 if (CborNoError == cborEncoderResult)
952 OIC_LOG(DEBUG, TAG, "CredToCBORPayload Successed");
953 *cborPayload = outPayload;
954 *cborSize = cbor_encoder_get_buffer_size(&encoder, outPayload);
957 OIC_LOG(DEBUG, TAG, "CredToCBORPayload OUT");
959 if (CborErrorOutOfMemory == cborEncoderResult)
961 OIC_LOG(DEBUG, TAG, "CredToCBORPayload:CborErrorOutOfMemory : retry with more memory");
962 // reallocate and try again!
964 // Since the allocated initial memory failed, double the memory.
965 cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
966 cborEncoderResult = CborNoError;
967 ret = CredToCBORPayload(credS, cborPayload, &cborLen, secureFlag);
971 if (CborNoError != cborEncoderResult)
973 OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
978 ret = OC_STACK_ERROR;
981 OIC_LOG_V(DEBUG, TAG, "OUT %s:", __func__);
986 OCStackResult CBORPayloadToCred(const uint8_t *cborPayload, size_t size,
987 OicSecCred_t **secCred, OicUuid_t **rownerid)
989 if (NULL == cborPayload || NULL == secCred || NULL != *secCred || 0 == size)
991 return OC_STACK_INVALID_PARAM;
994 char* tagName = NULL;
995 char* roleIdTagName = NULL;
997 OCStackResult ret = OC_STACK_ERROR;
998 CborValue credCbor = { .parser = NULL };
999 CborParser parser = { .end = NULL };
1000 CborError cborFindResult = CborNoError;
1001 cbor_parser_init(cborPayload, size, 0, &parser, &credCbor);
1003 if (!cbor_value_is_container(&credCbor))
1005 return OC_STACK_ERROR;
1008 OicSecCred_t *headCred = NULL;
1010 // Enter CRED Root Map
1011 CborValue CredRootMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
1012 cborFindResult = cbor_value_enter_container(&credCbor, &CredRootMap);
1013 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Entering CRED Root Map.");
1015 headCred = (OicSecCred_t *) OICCalloc(1, sizeof(OicSecCred_t));
1016 VERIFY_NOT_NULL(TAG, headCred, ERROR);
1018 while (cbor_value_is_valid(&CredRootMap))
1021 CborType type = cbor_value_get_type(&CredRootMap);
1022 if (type == CborTextStringType && cbor_value_is_text_string(&CredRootMap))
1024 cborFindResult = cbor_value_dup_text_string(&CredRootMap, &tagName, &len, NULL);
1025 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding Name in CRED Root Map.");
1026 cborFindResult = cbor_value_advance(&CredRootMap);
1027 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Advancing Value in CRED Root Map.");
1031 if (strcmp(tagName, OIC_JSON_CREDS_NAME) == 0)
1033 // Enter CREDS Array
1036 CborValue credArray = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
1037 cborFindResult = cbor_value_enter_container(&CredRootMap, &credArray);
1038 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding Cred Array.");
1040 while (cbor_value_is_valid(&credArray))
1043 //CredId -- Mandatory
1044 CborValue credMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
1045 cborFindResult = cbor_value_enter_container(&credArray, &credMap);
1046 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding Cred Map.");
1047 OicSecCred_t *cred = NULL;
1055 cred = (OicSecCred_t *) OICCalloc(1, sizeof(OicSecCred_t));
1056 VERIFY_NOT_NULL(TAG, cred, ERROR);
1057 OicSecCred_t *temp = headCred;
1065 while(cbor_value_is_valid(&credMap) && cbor_value_is_text_string(&credMap))
1067 CborType cmType = cbor_value_get_type(&credMap);
1068 if (cmType == CborTextStringType)
1070 cborFindResult = cbor_value_dup_text_string(&credMap, &name, &tempLen, NULL);
1071 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding Name in CRED Map.");
1072 cborFindResult = cbor_value_advance(&credMap);
1073 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Advancing Value in CRED Map.");
1078 if (strcmp(name, OIC_JSON_CREDID_NAME) == 0)
1080 uint64_t credId = 0;
1081 cborFindResult = cbor_value_get_uint64(&credMap, &credId);
1082 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding CredId.");
1083 cred->credId = (uint16_t)credId;
1086 if (strcmp(name, OIC_JSON_SUBJECTID_NAME) == 0)
1088 char *subjectid = NULL;
1089 cborFindResult = cbor_value_dup_text_string(&credMap, &subjectid, &tempLen, NULL);
1090 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding subjectid Value.");
1091 if(strcmp(subjectid, WILDCARD_RESOURCE_URI) == 0)
1093 cred->subject.id[0] = '*';
1097 ret = ConvertStrToUuid(subjectid, &cred->subject);
1098 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
1100 //Because cbor using malloc directly
1101 //It is required to use free() instead of OICFree
1105 if (strcmp(name, OIC_JSON_ROLEID_NAME) == 0)
1108 size_t unusedLen = 0;
1109 CborValue roleIdMap;
1110 memset(&roleIdMap, 0, sizeof(roleIdMap));
1112 cborFindResult = cbor_value_enter_container(&credMap, &roleIdMap);
1113 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed entering role ID map");
1115 while (cbor_value_is_valid(&roleIdMap) && cbor_value_is_text_string(&roleIdMap))
1117 cborFindResult = cbor_value_dup_text_string(&roleIdMap, &roleIdTagName, &unusedLen, NULL);
1118 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed getting role ID map tag name");
1119 cborFindResult = cbor_value_advance(&roleIdMap);
1120 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed advancing role ID map");
1122 if (NULL != roleIdTagName)
1124 if (strcmp(roleIdTagName, OIC_JSON_ROLE_NAME) == 0)
1126 char *roleId = NULL;
1127 cborFindResult = cbor_value_dup_text_string(&roleIdMap, &roleId, &unusedLen, NULL);
1128 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed getting role id value");
1129 if (strlen(roleId) >= sizeof(cred->roleId.id))
1131 cborFindResult = CborUnknownError;
1133 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Role ID is too long");
1135 OICStrcpy(cred->roleId.id, sizeof(cred->roleId.id), roleId);
1138 else if (strcmp(roleIdTagName, OIC_JSON_AUTHORITY_NAME) == 0)
1140 char *authorityName = NULL;
1141 cborFindResult = cbor_value_dup_text_string(&roleIdMap, &authorityName, &unusedLen, NULL);
1142 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed getting role authority value");
1143 if (strlen(authorityName) >= sizeof(cred->roleId.authority))
1145 cborFindResult = CborUnknownError;
1146 free(authorityName);
1147 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Authority name is too long");
1149 OICStrcpy(cred->roleId.authority, sizeof(cred->roleId.authority), authorityName);
1150 free(authorityName);
1154 OIC_LOG_V(WARNING, TAG, "Unknown tag name in role ID map: %s", roleIdTagName);
1157 free(roleIdTagName);
1158 roleIdTagName = NULL;
1161 if (cbor_value_is_valid(&roleIdMap))
1163 cborFindResult = cbor_value_advance(&roleIdMap);
1164 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed advancing role map");
1168 /* Make sure at least the id is present. */
1169 if ('\0' == cred->roleId.id[0])
1171 cborFindResult = CborUnknownError;
1172 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "ID for role was not present in role map");
1176 if (strcmp(name, OIC_JSON_CREDTYPE_NAME) == 0)
1178 uint64_t credType = 0;
1179 cborFindResult = cbor_value_get_uint64(&credMap, &credType);
1180 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding CredType.");
1181 cred->credType = (OicSecCredType_t)credType;
1184 if (strcmp(name, OIC_JSON_PRIVATEDATA_NAME) == 0)
1186 cborFindResult = DeserializeEncodingFromCbor(&credMap, &cred->privateData);
1187 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to read privateData structure");
1189 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1190 //PublicData -- Not Mandatory
1191 if (strcmp(name, OIC_JSON_PUBLICDATA_NAME) == 0)
1193 cborFindResult = DeserializeEncodingFromCbor(&credMap, &cred->publicData);
1194 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to read publicData structure");
1196 //OptionalData -- Not Mandatory
1197 if (strcmp(name, OIC_JSON_OPTDATA_NAME) == 0)
1199 cborFindResult = DeserializeSecOptFromCbor(&credMap, &cred->optionalData);
1200 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to read optionalData structure");
1202 //Credusage -- Not Mandatory
1203 if (0 == strcmp(OIC_JSON_CREDUSAGE_NAME, name))
1205 cborFindResult = cbor_value_dup_text_string(&credMap, &cred->credUsage, &tempLen, NULL);
1206 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding Period.");
1208 #endif //__WITH_DTLS__ || __WITH_TLS__
1210 if (0 == strcmp(OIC_JSON_PERIOD_NAME, name))
1212 cborFindResult = cbor_value_dup_text_string(&credMap, &cred->period, &tempLen, NULL);
1213 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding Period.");
1216 #ifdef MULTIPLE_OWNER
1217 // Eowner uuid -- Not Mandatory
1218 if (strcmp(OIC_JSON_EOWNERID_NAME, name) == 0 && cbor_value_is_text_string(&credMap))
1220 char *eowner = NULL;
1221 cborFindResult = cbor_value_dup_text_string(&credMap, &eowner, &tempLen, NULL);
1222 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding eownerId Value.");
1223 if(NULL == cred->eownerID)
1225 cred->eownerID = (OicUuid_t*)OICCalloc(1, sizeof(OicUuid_t));
1226 VERIFY_NOT_NULL(TAG, cred->eownerID, ERROR);
1228 ret = ConvertStrToUuid(eowner, cred->eownerID);
1229 //Because cbor using malloc directly
1230 //It is required to use free() instead of OICFree
1232 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
1234 #endif //MULTIPLE_OWNER
1236 if (cbor_value_is_valid(&credMap))
1238 cborFindResult = cbor_value_advance(&credMap);
1239 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Advancing CRED Map.");
1241 //Because cbor using malloc directly
1242 //It is required to use free() instead of OICFree
1248 if (cbor_value_is_valid(&credArray))
1250 cborFindResult = cbor_value_advance(&credArray);
1251 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Advancing CRED Array.");
1256 //ROwner -- Mandatory
1257 if (strcmp(tagName, OIC_JSON_ROWNERID_NAME) == 0 && cbor_value_is_text_string(&CredRootMap))
1259 char *stRowner = NULL;
1260 cborFindResult = cbor_value_dup_text_string(&CredRootMap, &stRowner, &len, NULL);
1261 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding Rownerid Value.");
1262 *rownerid = (OicUuid_t *) OICCalloc(1, sizeof(OicUuid_t));
1263 VERIFY_NOT_NULL(TAG, *rownerid, ERROR);
1264 ret = ConvertStrToUuid(stRowner, *rownerid);
1265 //Because cbor using malloc directly
1266 //It is required to use free() instead of OICFree
1268 VERIFY_SUCCESS(TAG, (ret == OC_STACK_OK), ERROR);
1270 //Because cbor using malloc directly
1271 //It is required to use free() instead of OICFree
1275 if (cbor_value_is_valid(&CredRootMap))
1277 cborFindResult = cbor_value_advance(&CredRootMap);
1278 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Advancing CRED Root Map.");
1282 *secCred = headCred;
1286 if (CborNoError != cborFindResult)
1288 DeleteCredList(headCred);
1291 ret = OC_STACK_ERROR;
1295 free(roleIdTagName);
1301 #ifdef MULTIPLE_OWNER
1302 bool IsValidCredentialAccessForSubOwner(const OicUuid_t* uuid, const uint8_t *cborPayload, size_t size)
1304 OicSecCred_t* cred = NULL;
1305 bool isValidCred = false;
1306 OicUuid_t *rownerId = NULL;
1308 OIC_LOG_BUFFER(DEBUG, TAG, cborPayload, size);
1310 VERIFY_NOT_NULL(TAG, uuid, ERROR);
1311 VERIFY_NOT_NULL(TAG, cborPayload, ERROR);
1312 VERIFY_SUCCESS(TAG, 0 != size, ERROR);
1313 VERIFY_SUCCESS(TAG, OC_STACK_OK == CBORPayloadToCred(cborPayload, size, &cred, &rownerId), ERROR);
1314 VERIFY_NOT_NULL(TAG, cred, ERROR);
1315 VERIFY_NOT_NULL(TAG, cred->eownerID, ERROR);
1316 VERIFY_NOT_NULL(TAG, rownerId, ERROR);
1317 VERIFY_SUCCESS(TAG, (memcmp(cred->eownerID->id, uuid->id, sizeof(uuid->id)) == 0), ERROR);
1323 DeleteCredList(cred);
1328 #endif //MULTIPLE_OWNER
1330 OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t credType,
1331 const OicSecKey_t * publicData, const OicSecKey_t* privateData,
1332 const OicUuid_t * rownerID, const OicUuid_t * eownerID)
1334 OIC_LOG(DEBUG, TAG, "IN GenerateCredential");
1337 OCStackResult ret = OC_STACK_ERROR;
1339 OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
1340 VERIFY_NOT_NULL(TAG, cred, ERROR);
1343 //CredId is assigned before appending new cred to the existing
1344 //credential list and updating svr database in AddCredential().
1347 VERIFY_NOT_NULL(TAG, subject, ERROR);
1348 memcpy(cred->subject.id, subject->id , sizeof(cred->subject.id));
1350 VERIFY_SUCCESS(TAG, credType < (NO_SECURITY_MODE | SYMMETRIC_PAIR_WISE_KEY |
1351 SYMMETRIC_GROUP_KEY | ASYMMETRIC_KEY | SIGNED_ASYMMETRIC_KEY | PIN_PASSWORD), ERROR);
1352 cred->credType = credType;
1354 #ifdef __WITH_DTLS__
1355 if (publicData && publicData->data)
1357 cred->publicData.data = (uint8_t *)OICCalloc(1, publicData->len);
1358 VERIFY_NOT_NULL(TAG, cred->publicData.data, ERROR);
1359 memcpy(cred->publicData.data, publicData->data, publicData->len);
1360 cred->publicData.len = publicData->len;
1361 cred->publicData.encoding = publicData->encoding;
1363 #endif // __WITH_DTLS__
1365 if (privateData && privateData->data)
1367 cred->privateData.data = (uint8_t *)OICCalloc(1, privateData->len);
1368 VERIFY_NOT_NULL(TAG, cred->privateData.data, ERROR);
1369 memcpy(cred->privateData.data, privateData->data, privateData->len);
1370 cred->privateData.len = privateData->len;
1371 cred->privateData.encoding = privateData->encoding;
1374 VERIFY_NOT_NULL(TAG, rownerID, ERROR);
1375 memcpy(&cred->rownerID, rownerID, sizeof(OicUuid_t));
1377 #ifdef MULTIPLE_OWNER
1380 cred->eownerID = (OicUuid_t*)OICCalloc(1, sizeof(OicUuid_t));
1381 VERIFY_NOT_NULL(TAG, cred->eownerID, ERROR);
1382 memcpy(cred->eownerID->id, eownerID->id, sizeof(eownerID->id));
1386 #endif //MULTIPLE_OWNER_
1390 OIC_LOG_V(DEBUG, TAG, "GenerateCredential : result: %d", ret);
1391 OIC_LOG_V(DEBUG, TAG, "GenerateCredential : credId: %d", cred->credId);
1392 OIC_LOG_V(DEBUG, TAG, "GenerateCredential : credType: %d", cred->credType);
1393 OIC_LOG_BUFFER(DEBUG, TAG, cred->subject.id, sizeof(cred->subject.id));
1394 if (cred->privateData.data)
1396 OIC_LOG_V(DEBUG, TAG, "GenerateCredential : privateData len: %"PRIuPTR, cred->privateData.len);
1397 OIC_LOG_BUFFER(DEBUG, TAG, cred->privateData.data, cred->privateData.len);
1399 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1402 OIC_LOG_V(DEBUG, TAG, "GenerateCredential : credUsage: %s", cred->credUsage);
1404 if (cred->publicData.data)
1406 OIC_LOG_V(DEBUG, TAG, "GenerateCredential : publicData len: %" PRIuPTR, cred->publicData.len);
1407 OIC_LOG_BUFFER(DEBUG, TAG, cred->publicData.data, cred->publicData.len);
1410 if (cred->optionalData.data)
1412 OIC_LOG_V(DEBUG, TAG, "GenerateCredential : optionalData len: %" PRIuPTR, cred->optionalData.len);
1413 OIC_LOG_BUFFER(DEBUG, TAG, cred->optionalData.data, cred->optionalData.len);
1414 OIC_LOG_V(DEBUG, TAG, "GenerateCredential : optionalData revstat: %d", cred->optionalData.revstat);
1416 #endif //defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1419 if (OC_STACK_OK != ret)
1421 DeleteCredList(cred);
1424 OIC_LOG(DEBUG, TAG, "OUT GenerateCredential");
1428 #ifdef HAVE_WINDOWS_H
1429 /* Helper for UpdatePersistentStorage. */
1430 static OCStackResult CopyPayload(uint8_t **payload, size_t *payloadSize, const DATA_BLOB *source)
1432 OCStackResult res = OC_STACK_OK;
1434 if (source->cbData > *payloadSize)
1436 /* Need more memory to copy encrypted payload out. */
1437 OICClearMemory(*payload, *payloadSize);
1439 *payload = OICMalloc(source->cbData);
1441 if (NULL == *payload)
1443 OIC_LOG_V(ERROR, TAG, "Failed to OICMalloc for encrypted payload: %u", GetLastError());
1444 res = OC_STACK_NO_MEMORY;
1447 else if (source->cbData < *payloadSize)
1449 /* Zero portion of payload we won't overwrite with the encrypted version. The
1450 * later call to OICClearMemory won't cover this part of the buffer.
1452 OICClearMemory(*payload + source->cbData, *payloadSize - source->cbData);
1455 if (OC_STACK_OK == res)
1457 memcpy(*payload, source->pbData, source->cbData);
1458 *payloadSize = source->cbData;
1465 static bool UpdatePersistentStorage(const OicSecCred_t *cred)
1468 OIC_LOG(DEBUG, TAG, "IN Cred UpdatePersistentStorage");
1470 // Convert Cred data into JSON for update to persistent storage
1473 uint8_t *payload = NULL;
1474 // This added '512' is arbitrary value that is added to cover the name of the resource, map addition and ending
1475 size_t size = GetCredKeyDataSize(cred);
1476 size += (512 * OicSecCredCount(cred));
1477 OIC_LOG_V(DEBUG, TAG, "cred size: %zu", size);
1480 OCStackResult res = CredToCBORPayload(cred, &payload, &size, secureFlag);
1481 #ifdef HAVE_WINDOWS_H
1482 /* On Windows, keep the credential resource encrypted on disk to protect symmetric and private keys. Only the
1483 * current user on this system will be able to decrypt it later, to help prevent credential theft.
1487 if (FAILED(SizeTToDWord(size, &dwordSize)))
1489 OIC_LOG(DEBUG, TAG, "Cred size too large.");
1490 res = OC_STACK_ERROR;
1494 if ((OC_STACK_OK == res) && payload)
1496 DATA_BLOB decryptedPayload;
1497 DATA_BLOB encryptedPayload;
1498 memset(&decryptedPayload, 0, sizeof(decryptedPayload));
1499 memset(&encryptedPayload, 0, sizeof(encryptedPayload));
1500 decryptedPayload.cbData = dwordSize;
1501 decryptedPayload.pbData = payload;
1503 if (CryptProtectData(
1509 CRYPTPROTECT_UI_FORBIDDEN,
1512 res = CopyPayload(&payload, &size, &encryptedPayload);
1513 ret = (OC_STACK_OK == res);
1515 /* For the returned data from CryptProtectData, LocalFree must be used to free. Don't use OICFree. */
1516 if (NULL != LocalFree(encryptedPayload.pbData))
1518 OIC_LOG_V(ERROR, TAG, "LocalFree failed on output from CryptProtectData; memory may be corrupted or leaked. Last error: %u.", GetLastError());
1519 assert(!"LocalFree failed");
1524 OIC_LOG_V(ERROR, TAG, "Failed to CryptProtectData cred resource: %u", GetLastError());
1525 res = OC_STACK_ERROR;
1531 if ((OC_STACK_OK == res) && payload)
1533 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, payload, size))
1539 OICClearMemory(payload, size);
1542 else //Empty cred list
1544 if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, NULL, 0))
1550 OIC_LOG(DEBUG, TAG, "OUT Cred UpdatePersistentStorage");
1558 * Compare function used LL_SORT for sorting credentials.
1560 * @param first pointer to OicSecCred_t struct.
1561 * @param second pointer to OicSecCred_t struct.
1563 *@return -1, if credId of first is less than credId of second.
1564 * 0, if credId of first is equal to credId of second.
1565 * 1, if credId of first is greater than credId of second.
1567 static int CmpCredId(const OicSecCred_t * first, const OicSecCred_t *second)
1569 if (first->credId < second->credId)
1573 else if (first->credId > second->credId)
1582 * GetCredId goes through the cred list and returns the next
1583 * available credId. The next credId could be the credId that is
1584 * available due deletion of OicSecCred_t object or one more than
1585 * credId of last credential in the list.
1587 * @return next available credId if successful, else 0 for error.
1589 static uint16_t GetCredId()
1591 //Sorts credential list in incremental order of credId
1592 /** @todo: Remove pragma for VS2013 warning; Investigate fixing LL_SORT macro */
1594 #pragma warning(suppress:4133)
1595 LL_SORT(gCred, CmpCredId);
1597 LL_SORT(gCred, CmpCredId);
1600 OicSecCred_t *currentCred = NULL, *credTmp = NULL;
1601 uint16_t nextCredId = 1;
1603 LL_FOREACH_SAFE(gCred, currentCred, credTmp)
1605 if (currentCred->credId == nextCredId)
1615 VERIFY_SUCCESS(TAG, nextCredId < UINT16_MAX, ERROR);
1623 * Get the default value.
1625 * @return NULL for now.
1627 static OicSecCred_t* GetCredDefault()
1629 // TODO:Update it when we finalize the default info.
1633 bool IsSameSecOpt(const OicSecOpt_t* sk1, const OicSecOpt_t* sk2)
1635 VERIFY_NOT_NULL(TAG, sk1, WARNING);
1636 VERIFY_NOT_NULL(TAG, sk2, WARNING);
1638 VERIFY_SUCCESS(TAG, (sk1->len == sk2->len), INFO);
1639 VERIFY_SUCCESS(TAG, (sk1->encoding == sk2->encoding), INFO);
1640 VERIFY_SUCCESS(TAG, (0 == memcmp(sk1->data, sk2->data, sk1->len)), INFO);
1646 bool IsSameSecKey(const OicSecKey_t* sk1, const OicSecKey_t* sk2)
1648 VERIFY_NOT_NULL(TAG, sk1, WARNING);
1649 VERIFY_NOT_NULL(TAG, sk2, WARNING);
1651 VERIFY_SUCCESS(TAG, (sk1->len == sk2->len), INFO);
1652 VERIFY_SUCCESS(TAG, (sk1->encoding == sk2->encoding), INFO);
1653 VERIFY_SUCCESS(TAG, (0 == memcmp(sk1->data, sk2->data, sk1->len)), INFO);
1659 #if ((defined(__WITH_DTLS__) || defined(__WITH_TLS__)) && defined(MULTIPLE_OWNER))
1660 static bool IsNewPreconfigPinCredential(OicSecCred_t * oldCred, OicSecCred_t * newCred)
1662 if (oldCred->credUsage &&
1663 newCred->credUsage &&
1664 (0 == strcmp(PRECONFIG_PIN_CRED, oldCred->credUsage)) &&
1665 (0 == strcmp(PRECONFIG_PIN_CRED, newCred->credUsage)))
1672 #endif //(__WITH_DTLS__ or __WITH_TLS__) and MULTIPLE_OWNER
1674 OCStackResult AddCredential(OicSecCred_t * newCred)
1676 OCStackResult result = OC_STACK_ERROR;
1678 OicSecCred_t* cred = NULL;
1679 OicSecCred_t* tempCred = NULL;
1683 //leave IOT-1936 fix for preconfig pin
1684 #if ((defined(__WITH_DTLS__) || defined(__WITH_TLS__)) && defined(MULTIPLE_OWNER))
1685 LL_FOREACH_SAFE(gCred, cred, tempCred)
1687 if (IsNewPreconfigPinCredential(cred, newCred))
1689 //devices can only have one Preconfigured Pin credential at any given time. Check
1690 //if the new credential is an update to an existing Preconfigured Pin credential
1691 //if so, just update existing one.
1693 //save old credid so act like an update
1694 newCred->credId = cred->credId;
1696 LL_DELETE(gCred, cred);
1697 LL_PREPEND(gCred, newCred);
1704 #endif //(__WITH_DTLS__ or __WITH_TLS__) and MULTIPLE_OWNER
1711 if (newCred->credId != 0)
1713 //check if cred with such cred id exists
1714 LL_FOREACH_SAFE(gCred, cred, tempCred)
1716 if (cred->credId == newCred->credId)
1718 //remove old cred with same cred id
1719 LL_DELETE(gCred, cred);
1727 newCred->credId = GetCredId();
1730 OIC_LOG(DEBUG, TAG, "Adding New Cred");
1731 LL_APPEND(gCred, newCred);
1734 OicUuid_t emptyOwner = { .id = {0} };
1735 if (memcmp(&(newCred->rownerID), &emptyOwner, sizeof(OicUuid_t)) != 0)
1737 memcpy(&(gRownerId), &(newCred->rownerID), sizeof(OicUuid_t));
1742 if (UpdatePersistentStorage(gCred))
1744 result = OC_STACK_OK;
1750 OCStackResult RemoveCredential(const OicUuid_t *subject)
1752 OCStackResult ret = OC_STACK_ERROR;
1753 OicSecCred_t *cred = NULL;
1754 OicSecCred_t *tempCred = NULL;
1755 bool deleteFlag = false;
1757 LL_FOREACH_SAFE(gCred, cred, tempCred)
1759 if (memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
1761 LL_DELETE(gCred, cred);
1769 if (UpdatePersistentStorage(gCred))
1771 ret = OC_STACK_RESOURCE_DELETED;
1777 OCStackResult RemoveCredentialByCredId(uint16_t credId)
1779 OCStackResult ret = OC_STACK_ERROR;
1780 OicSecCred_t *cred = NULL;
1781 OicSecCred_t *tempCred = NULL;
1782 bool deleteFlag = false;
1784 OIC_LOG(INFO, TAG, "IN RemoveCredentialByCredId");
1788 return OC_STACK_INVALID_PARAM;
1792 LL_FOREACH_SAFE(gCred, cred, tempCred)
1794 if (cred->credId == credId)
1796 OIC_LOG_V(DEBUG, TAG, "Credential(ID=%d) will be removed.", credId);
1798 LL_DELETE(gCred, cred);
1806 if (UpdatePersistentStorage(gCred))
1808 ret = OC_STACK_RESOURCE_DELETED;
1811 OIC_LOG(INFO, TAG, "OUT RemoveCredentialByCredId");
1817 * This method removes cred's corresponding to given list of credid's from the Cred
1819 * @param credid's of the Cred
1822 * ::OC_STACK_RESOURCE_DELETED on success
1823 * ::OC_STACK_NO_RESOURCE on failure to find the appropriate Cred
1824 * ::OC_STACK_INVALID_PARAM on invalid parameter
1826 static OCStackResult RemoveCredentialByCredIds(CredIdList_t *credIdList)
1828 OCStackResult ret = OC_STACK_ERROR;
1829 OicSecCred_t *cred = NULL;
1830 OicSecCred_t *tempCred = NULL;
1831 CredIdList_t *credIdElem = NULL;
1832 bool deleteFlag = false;
1834 OIC_LOG(INFO, TAG, "IN RemoveCredentialByCredIds");
1836 LL_FOREACH(credIdList, credIdElem)
1838 LL_FOREACH_SAFE(gCred, cred, tempCred)
1840 if (cred->credId == credIdElem->credId)
1842 OIC_LOG_V(DEBUG, TAG, "Credential(ID=%d) will be removed.", cred->credId);
1844 LL_DELETE(gCred, cred);
1847 //TODO: add break when cred's will have unique credid (during IOT-2464 fix)
1854 if (UpdatePersistentStorage(gCred))
1856 ret = OC_STACK_RESOURCE_DELETED;
1859 OIC_LOG(INFO, TAG, "OUT RemoveCredentialByCredIds");
1865 * This method parses the query string received for REST requests and
1866 * retrieves the 'credid' field.
1868 * @param query querystring passed in REST request
1869 * @param credid cred id parsed from query string
1871 * @return true if query parsed successfully and found 'credid', else false.
1873 static bool GetCredIdsFromQueryString(const char *query, CredIdList_t **credid)
1876 OicParseQueryIter_t parseIter = { .attrPos = NULL };
1878 ParseQueryIterInit((unsigned char *) query, &parseIter);
1880 while (GetNextQuery (&parseIter))
1882 if (strncasecmp((char *) parseIter.attrPos, OIC_JSON_CREDID_NAME, parseIter.attrLen) == 0)
1884 VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
1886 //parse credid array value in format "1,2,3"
1887 unsigned char *str = parseIter.valPos;
1889 //remember last symbol (may be '\0' or '&')
1890 unsigned char tmp = str[parseIter.valLen];
1891 //set last symbol to '\0' to use strtok_r
1892 str[parseIter.valLen] = '\0';
1894 char *saveptr = NULL;
1896 for (; ; str = NULL)
1898 char *token = strtok_r((char *)str, ",", &saveptr);
1904 CredIdList_t *newCredIdElem = (CredIdList_t *) OICCalloc(1, sizeof(CredIdList_t));
1905 if (NULL == newCredIdElem)
1907 OIC_LOG(ERROR, TAG, "Failed to allocate CredIdList_t element");
1910 newCredIdElem->credId = (uint16_t)atoi(token);
1912 LL_PREPEND(*credid, newCredIdElem);
1916 //restore last symbol
1917 parseIter.valPos[parseIter.valLen] = tmp;
1926 * Remove all credential data on credential resource and persistent storage
1929 * OC_STACK_OK - no errors
1930 * OC_STACK_ERROR - stack process error
1932 static OCStackResult RemoveAllCredentials()
1934 DeleteCredList(gCred);
1935 gCred = GetCredDefault();
1937 if (!UpdatePersistentStorage(gCred))
1939 return OC_STACK_ERROR;
1945 * This method parses the query string received for REST requests and
1946 * retrieves the 'subjectuuid' field.
1948 * @param query querystring passed in REST request
1949 * @param subject subject UUID parsed from query string
1951 * @return true if query parsed successfully and found 'subject', else false.
1953 static bool GetSubjectFromQueryString(const char *query, OicUuid_t *subject)
1955 OicParseQueryIter_t parseIter = { .attrPos = NULL };
1957 ParseQueryIterInit((unsigned char *) query, &parseIter);
1959 while (GetNextQuery (&parseIter))
1961 if (strncasecmp((char *) parseIter.attrPos, OIC_JSON_SUBJECTID_NAME, parseIter.attrLen) == 0)
1963 VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
1964 //temporary set '\0' symbol instead of copy string
1965 char tmp = parseIter.valPos[parseIter.valLen];
1966 parseIter.valPos[parseIter.valLen] = '\0';
1968 OCStackResult res = ConvertStrToUuid((const char*)parseIter.valPos, subject);
1969 parseIter.valPos[parseIter.valLen] = tmp;
1970 VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1979 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1981 * Internal function to fill private data of owner PSK.
1983 * @param receviedCred recevied owner credential from OBT(PT)
1984 * @param ownerAdd address of OBT(PT)
1985 * @param doxm current device's doxm resource
1988 * true successfully done and valid ower psk information
1989 * false Invalid owner psk information or failed to owner psk generation
1991 static bool FillPrivateDataOfOwnerPSK(OicSecCred_t* receviedCred, const CAEndpoint_t* ownerAddr,
1992 const OicSecDoxm_t* doxm)
1994 //Derive OwnerPSK locally
1995 const char* oxmLabel = GetOxmString(doxm->oxmSel);
1996 char* b64Buf = NULL;
1997 size_t b64BufSize = 0;
1998 VERIFY_NOT_NULL(TAG, oxmLabel, ERROR);
2000 uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
2001 CAResult_t pskRet = CAGenerateOwnerPSK(ownerAddr,
2002 (uint8_t*)oxmLabel, strlen(oxmLabel),
2003 doxm->owner.id, sizeof(doxm->owner.id),
2004 doxm->deviceID.id, sizeof(doxm->deviceID.id),
2005 ownerPSK, OWNER_PSK_LENGTH_128);
2006 VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
2008 OIC_LOG(DEBUG, TAG, "OwnerPSK dump :");
2009 OIC_LOG_BUFFER(DEBUG, TAG, ownerPSK, OWNER_PSK_LENGTH_128);
2011 //Generate owner credential based on recevied credential information
2013 // TODO: Added as workaround, will be replaced soon.
2014 if(OIC_ENCODING_RAW == receviedCred->privateData.encoding)
2016 receviedCred->privateData.data = (uint8_t *)OICCalloc(1, OWNER_PSK_LENGTH_128);
2017 VERIFY_NOT_NULL(TAG, receviedCred->privateData.data, ERROR);
2018 receviedCred->privateData.len = OWNER_PSK_LENGTH_128;
2019 memcpy(receviedCred->privateData.data, ownerPSK, OWNER_PSK_LENGTH_128);
2021 else if(OIC_ENCODING_BASE64 == receviedCred->privateData.encoding)
2023 B64Result b64res = B64_OK;
2024 size_t b64OutSize = 0;
2025 b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
2026 b64Buf = OICCalloc(1, b64BufSize);
2027 VERIFY_NOT_NULL(TAG, b64Buf, ERROR);
2029 b64res = b64Encode(ownerPSK, OWNER_PSK_LENGTH_128, b64Buf, b64BufSize, &b64OutSize);
2030 VERIFY_SUCCESS(TAG, B64_OK == b64res, ERROR);
2032 receviedCred->privateData.data = (uint8_t *)OICCalloc(1, b64OutSize + 1);
2033 VERIFY_NOT_NULL(TAG, receviedCred->privateData.data, ERROR);
2034 receviedCred->privateData.len = b64OutSize;
2035 strncpy((char*)receviedCred->privateData.data, b64Buf, b64OutSize);
2036 receviedCred->privateData.data[b64OutSize] = '\0';
2037 OICClearMemory(b64Buf, b64BufSize);
2043 OIC_LOG_V(ERROR, TAG, "Unknown credential encoding type: %u.", receviedCred->privateData.encoding);
2047 OIC_LOG(INFO, TAG, "PrivateData of OwnerPSK was calculated successfully");
2049 OICClearMemory(ownerPSK, sizeof(ownerPSK));
2051 //Verify OwnerPSK information
2052 return (memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0 &&
2053 receviedCred->credType == SYMMETRIC_PAIR_WISE_KEY);
2055 //receviedCred->privateData.data will be deallocated when deleting credential.
2056 OICClearMemory(ownerPSK, sizeof(ownerPSK));
2057 OICClearMemory(b64Buf, b64BufSize);
2063 #ifdef MULTIPLE_OWNER
2065 * Internal function to fill private data of SubOwner PSK.
2067 * @param receviedCred recevied owner credential from SubOwner
2068 * @param ownerAdd address of SubOwner
2069 * @param doxm current device's doxm resource
2072 * true successfully done and valid subower psk information
2073 * false Invalid subowner psk information or failed to subowner psk generation
2075 static bool FillPrivateDataOfSubOwnerPSK(OicSecCred_t* receivedCred, const CAEndpoint_t* ownerAddr,
2076 const OicSecDoxm_t* doxm, const OicUuid_t* subOwner)
2078 char* b64Buf = NULL;
2079 //Derive OwnerPSK locally
2080 const char* oxmLabel = GetOxmString(doxm->oxmSel);
2081 VERIFY_NOT_NULL(TAG, oxmLabel, ERROR);
2083 uint8_t subOwnerPSK[OWNER_PSK_LENGTH_128] = {0};
2084 CAResult_t pskRet = CAGenerateOwnerPSK(ownerAddr,
2085 (uint8_t*)oxmLabel, strlen(oxmLabel),
2086 subOwner->id, sizeof(subOwner->id),
2087 doxm->deviceID.id, sizeof(doxm->deviceID.id),
2088 subOwnerPSK, OWNER_PSK_LENGTH_128);
2089 VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
2091 OIC_LOG(DEBUG, TAG, "SubOwnerPSK dump :");
2092 OIC_LOG_BUFFER(DEBUG, TAG, subOwnerPSK, OWNER_PSK_LENGTH_128);
2094 //Generate owner credential based on received credential information
2096 if(OIC_ENCODING_RAW == receivedCred->privateData.encoding)
2098 receivedCred->privateData.data = (uint8_t *)OICCalloc(1, OWNER_PSK_LENGTH_128);
2099 VERIFY_NOT_NULL(TAG, receivedCred->privateData.data, ERROR);
2100 receivedCred->privateData.len = OWNER_PSK_LENGTH_128;
2101 memcpy(receivedCred->privateData.data, subOwnerPSK, OWNER_PSK_LENGTH_128);
2103 else if(OIC_ENCODING_BASE64 == receivedCred->privateData.encoding)
2105 size_t b64OutSize = 0;
2106 size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
2107 b64Buf = OICCalloc(1, b64BufSize);
2108 VERIFY_NOT_NULL(TAG, b64Buf, ERROR);
2110 VERIFY_SUCCESS(TAG, \
2111 B64_OK == b64Encode(subOwnerPSK, OWNER_PSK_LENGTH_128, b64Buf, b64BufSize, &b64OutSize), \
2114 receivedCred->privateData.data = (uint8_t *)OICCalloc(1, b64OutSize + 1);
2115 VERIFY_NOT_NULL(TAG, receivedCred->privateData.data, ERROR);
2116 receivedCred->privateData.len = b64OutSize;
2117 strncpy((char*)receivedCred->privateData.data, b64Buf, b64OutSize);
2118 receivedCred->privateData.data[b64OutSize] = '\0';
2122 OIC_LOG_V(ERROR, TAG, "Unknown credential encoding type: %u.", receivedCred->privateData.encoding);
2126 OIC_LOG(INFO, TAG, "PrivateData of SubOwnerPSK was calculated successfully");
2130 //receivedCred->privateData.data will be deallocated when deleting credential.
2134 #endif //MULTIPLE_OWNER
2135 #endif // __WITH_DTLS__ or __WITH_TLS__
2138 static OCEntityHandlerResult HandleNewCredential(OCEntityHandlerRequest *ehRequest, OicSecCred_t *cred, uint16_t previousMsgId)
2140 OCEntityHandlerResult ret = OC_EH_INTERNAL_SERVER_ERROR;
2142 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
2143 OicUuid_t emptyUuid = {.id={0}};
2144 const OicSecDoxm_t *doxm = GetDoxmResourceData();
2145 if(NO_SECURITY_MODE != cred->credType && doxm && false == doxm->owned && memcmp(&(doxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0)
2147 //in case of owner PSK
2148 switch(cred->credType)
2150 case SYMMETRIC_PAIR_WISE_KEY:
2152 OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
2153 if(FillPrivateDataOfOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm))
2155 if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&cred->subject))
2157 OIC_LOG(WARNING, TAG, "The credential with the same subject ID was detected!");
2160 OIC_LOG(ERROR, TAG, "OwnerPSK was generated successfully.");
2161 if(OC_STACK_OK == AddCredential(cred))
2163 ret = OC_EH_CHANGED;
2167 OIC_LOG(ERROR, TAG, "Failed to save the OwnerPSK as cred resource");
2173 OIC_LOG(ERROR, TAG, "Failed to verify receviced OwnerPKS.");
2177 if(OC_EH_CHANGED == ret)
2180 * in case of random PIN based OxM,
2181 * revert get_psk_info callback of tinyDTLS to use owner credential.
2183 if(OIC_RANDOM_DEVICE_PIN == doxm->oxmSel)
2185 SetUuidForPinBasedOxm(&emptyUuid);
2187 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
2188 if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
2190 OIC_LOG(ERROR, TAG, "Failed to revert TLS credential handler.");
2194 #endif // __WITH_DTLS__ or __WITH_TLS__
2197 //Select cipher suite to use owner PSK
2198 if(CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false))
2200 OIC_LOG(ERROR, TAG, "Failed to disable anonymous cipher suite");
2205 OIC_LOG(INFO, TAG, "Anonymous cipher suite is DISABLED");
2208 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
2209 if(CA_STATUS_OK != CASelectCipherSuite(
2210 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_IP))
2212 OIC_LOG(ERROR, TAG, "Failed to enable PSK cipher suite");
2217 OIC_LOG(INFO, TAG, "PSK cipher suite is ENABLED");
2219 #endif // __WITH_DTLS__ or __WITH_TLS__
2224 case SYMMETRIC_GROUP_KEY:
2225 case ASYMMETRIC_KEY:
2226 case SIGNED_ASYMMETRIC_KEY:
2228 case ASYMMETRIC_ENCRYPTION_KEY:
2230 OIC_LOG(WARNING, TAG, "Unsupported credential type for owner credential.");
2236 OIC_LOG(WARNING, TAG, "Unknown credential type for owner credential.");
2242 if(OC_EH_CHANGED != ret)
2245 * If some error is occured while ownership transfer,
2246 * ownership transfer related resource should be revert back to initial status.
2248 const OicSecDoxm_t *ownershipDoxm = GetDoxmResourceData();
2251 if(!ownershipDoxm->owned)
2253 OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request");
2255 if((OC_ADAPTER_IP == ehRequest->devAddr.adapter && previousMsgId != ehRequest->messageID)
2256 || OC_ADAPTER_TCP == ehRequest->devAddr.adapter)
2258 RestoreDoxmToInitState();
2259 RestorePstatToInitState();
2260 OIC_LOG(WARNING, TAG, "DOXM will be reverted.");
2266 OIC_LOG(ERROR, TAG, "Invalid DOXM resource");
2270 #ifdef MULTIPLE_OWNER
2271 // In case SubOwner Credential
2272 else if(doxm && doxm->owned && doxm->mom &&
2273 OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode &&
2274 0 == cred->privateData.len &&
2275 0 == cred->optionalData.len &&
2276 0 == cred->publicData.len )
2278 switch(cred->credType)
2280 case SYMMETRIC_PAIR_WISE_KEY:
2282 OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
2283 if(FillPrivateDataOfSubOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm, &cred->subject))
2285 if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&cred->subject))
2287 OIC_LOG(WARNING, TAG, "The credential with the same subject ID was detected!");
2290 OIC_LOG(ERROR, TAG, "SubOwnerPSK was generated successfully.");
2291 if(OC_STACK_OK == AddCredential(cred))
2293 ret = OC_EH_CHANGED;
2297 OIC_LOG(ERROR, TAG, "Failed to save the SubOwnerPSK as cred resource");
2303 OIC_LOG(ERROR, TAG, "Failed to verify receviced SubOwner PSK.");
2309 case SYMMETRIC_GROUP_KEY:
2310 case ASYMMETRIC_KEY:
2311 case SIGNED_ASYMMETRIC_KEY:
2313 case ASYMMETRIC_ENCRYPTION_KEY:
2315 OIC_LOG(WARNING, TAG, "Unsupported credential type for SubOwner credential.");
2321 OIC_LOG(WARNING, TAG, "Unknown credential type for SubOwner credential.");
2327 #endif //MULTIPLE_OWNER
2330 if(IsEmptyCred(cred))
2332 if (UpdatePersistentStorage(gCred))
2334 ret = OC_EH_CHANGED;
2344 * If the post request credential has credId, it will be
2345 * discarded and the next available credId will be assigned
2346 * to it before getting appended to the existing credential
2347 * list and updating svr database.
2349 ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_CHANGED : OC_EH_ERROR;
2352 #else //not __WITH_DTLS__
2354 * If the post request credential has credId, it will be
2355 * discarded and the next available credId will be assigned
2356 * to it before getting appended to the existing credential
2357 * list and updating svr database.
2359 ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_CHANGED : OC_EH_ERROR;
2360 OC_UNUSED(previousMsgId);
2361 OC_UNUSED(ehRequest);
2362 #endif//__WITH_DTLS__
2367 static OCEntityHandlerResult HandlePostRequest(OCEntityHandlerRequest* ehRequest)
2369 OCEntityHandlerResult ret = OC_EH_INTERNAL_SERVER_ERROR;
2370 OIC_LOG(DEBUG, TAG, "HandleCREDPostRequest IN");
2372 OicSecDostype_t dos;
2373 static uint16_t previousMsgId = 0;
2374 // Get binary representation of cbor
2375 OicSecCred_t *cred = NULL;
2376 OicUuid_t *rownerId = NULL;
2377 uint8_t *payload = (((OCSecurityPayload*)ehRequest->payload)->securityData);
2378 size_t size = (((OCSecurityPayload*)ehRequest->payload)->payloadSize);
2380 OCStackResult res = OC_STACK_OK;
2382 VERIFY_SUCCESS(TAG, OC_STACK_OK == GetDos(&dos), ERROR);
2383 if ((DOS_RESET == dos.state) ||
2384 (DOS_RFNOP == dos.state))
2386 OIC_LOG_V(WARNING, TAG, "%s /cred resource is read-only in RESET and RFNOP.", __func__);
2387 ret = OC_EH_NOT_ACCEPTABLE;
2391 res = CBORPayloadToCred(payload, size, &cred, &rownerId);
2393 if (OC_STACK_OK == res)
2395 OicSecCred_t *newCred = NULL;
2396 OicSecCred_t *newCredTemp = NULL;
2398 LL_FOREACH_SAFE(cred, newCred, newCredTemp)
2400 ret = HandleNewCredential(ehRequest, newCred, previousMsgId);
2402 if (OC_EH_CHANGED != ret)
2404 // Remove the credentials added so far.
2405 OicSecCred_t *removedCred = NULL;
2406 OicSecCred_t *removedCredTemp = NULL;
2407 LL_FOREACH_SAFE(cred, removedCred, removedCredTemp)
2409 if (removedCred == newCred)
2414 if (RemoveCredential(&cred->subject) != OC_STACK_OK)
2416 OIC_LOG(WARNING, TAG, "Failed to remove credential");
2423 if (OC_EH_CHANGED == ret && NULL != rownerId)
2425 memcpy(&gRownerId, rownerId, sizeof(OicUuid_t));
2431 if (OC_EH_CHANGED != ret)
2435 DeleteCredList(cred);
2440 if (OC_ADAPTER_IP == ehRequest->devAddr.adapter)
2442 previousMsgId = ehRequest->messageID++;
2446 // Send response to request originator
2447 ret = ((SendSRMResponse(ehRequest, ret, NULL, 0)) == OC_STACK_OK) ?
2448 OC_EH_OK : OC_EH_ERROR;
2450 OIC_LOG(DEBUG, TAG, "HandleCREDPostRequest OUT");
2455 * The entity handler determines how to process a GET request.
2457 static OCEntityHandlerResult HandleGetRequest (const OCEntityHandlerRequest * ehRequest)
2459 OIC_LOG(INFO, TAG, "HandleGetRequest processing GET request");
2461 // Convert Cred data into CBOR for transmission
2463 uint8_t *payload = NULL;
2466 const OicSecCred_t *cred = gCred;
2468 // This added '256' is arbitrary value that is added to cover the name of the resource, map addition and ending
2469 size = GetCredKeyDataSize(cred);
2470 size += (256 * OicSecCredCount(cred));
2471 OCStackResult res = CredToCBORPayload(cred, &payload, &size, secureFlag);
2473 // A device should always have a default cred. Therefore, payload should never be NULL.
2474 OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
2476 //Send payload to request originator
2477 ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ?
2478 OC_EH_OK : OC_EH_ERROR;
2479 OICClearMemory(payload, size);
2484 static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
2486 OIC_LOG(DEBUG, TAG, "Processing CredDeleteRequest");
2488 OCEntityHandlerResult ehRet = OC_EH_ERROR;
2489 CredIdList_t *credIdList = NULL;
2490 OicUuid_t subject = { .id= { 0 } };
2492 if (NULL == ehRequest->query)
2497 if (GetCredIdsFromQueryString(ehRequest->query, &credIdList))
2499 if (OC_STACK_RESOURCE_DELETED == RemoveCredentialByCredIds(credIdList))
2501 ehRet = OC_EH_RESOURCE_DELETED;
2503 DeleteCredIdList(&credIdList);
2505 else if (GetSubjectFromQueryString(ehRequest->query, &subject))
2507 if (OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
2509 ehRet = OC_EH_RESOURCE_DELETED;
2514 if (OC_STACK_OK == RemoveAllCredentials())
2516 ehRet = OC_EH_RESOURCE_DELETED;
2520 //Send response to request originator
2521 ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
2522 OC_EH_OK : OC_EH_ERROR;
2526 OCEntityHandlerResult CredEntityHandler(OCEntityHandlerFlag flag,
2527 OCEntityHandlerRequest * ehRequest,
2528 void* callbackParameter)
2530 (void)callbackParameter;
2531 OCEntityHandlerResult ret = OC_EH_ERROR;
2537 if (flag & OC_REQUEST_FLAG)
2539 OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
2540 //TODO : Remove Handle PUT methods once CTT have changed to POST on OTM
2541 switch (ehRequest->method)
2544 ret = HandleGetRequest(ehRequest);
2548 ret = HandlePostRequest(ehRequest);
2550 case OC_REST_DELETE:
2551 ret = HandleDeleteRequest(ehRequest);
2554 ret = ((SendSRMResponse(ehRequest, ret, NULL, 0)) == OC_STACK_OK) ?
2555 OC_EH_OK : OC_EH_ERROR;
2562 OCStackResult CreateCredResource()
2564 OCStackResult ret = OCCreateResource(&gCredHandle,
2565 OIC_RSRC_TYPE_SEC_CRED,
2566 OC_RSRVD_INTERFACE_DEFAULT,
2573 if (OC_STACK_OK != ret)
2575 OIC_LOG (FATAL, TAG, "Unable to instantiate Cred resource");
2576 DeInitCredResource();
2581 OCStackResult InitCredResource()
2583 OCStackResult ret = OC_STACK_ERROR;
2584 OicSecCred_t* cred = NULL;
2585 OicUuid_t *rownerId = NULL;
2587 //Read Cred resource from PS
2588 uint8_t *data = NULL;
2590 ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_CRED_NAME, &data, &size);
2591 // If database read failed
2592 if (ret != OC_STACK_OK)
2594 OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
2597 if ((ret == OC_STACK_OK) && data)
2599 // Read Cred resource from PS
2600 ret = CBORPayloadToCred(data, size, &gCred, &rownerId);
2602 #ifdef HAVE_WINDOWS_H
2603 /* On Windows, if the credential payload isn't cleartext CBOR, it is encrypted. Decrypt and retry. */
2606 if (FAILED(SizeTToDWord(size, &dwordSize)))
2608 OIC_LOG(DEBUG, TAG, "Cred size too large.");
2609 ret = OC_STACK_ERROR;
2612 if (ret != OC_STACK_OK)
2614 DATA_BLOB decryptedPayload;
2615 DATA_BLOB encryptedPayload;
2616 memset(&decryptedPayload, 0, sizeof(decryptedPayload));
2617 memset(&encryptedPayload, 0, sizeof(encryptedPayload));
2618 encryptedPayload.cbData = dwordSize;
2619 encryptedPayload.pbData = data;
2621 if (CryptUnprotectData(
2627 CRYPTPROTECT_UI_FORBIDDEN,
2630 ret = CBORPayloadToCred(decryptedPayload.pbData, decryptedPayload.cbData, &gCred, &rownerId);
2632 /* For the returned data from CryptUnprotectData, LocalFree must be used to free. Don't use OICFree. */
2633 OICClearMemory(decryptedPayload.pbData, decryptedPayload.cbData);
2634 if (NULL != LocalFree(decryptedPayload.pbData))
2636 OIC_LOG_V(ERROR, TAG, "LocalFree failed on output from CryptUnprotectData; memory may be corrupted or leaked. Last error: %u.", GetLastError());
2637 assert(!"LocalFree failed");
2642 /* Credential resource is corrupted, or we no longer have access to the encryption key to decrypt it. */
2643 OIC_LOG_V(ERROR, TAG, "Failed to CryptUnprotectData cred resource: %u", GetLastError());
2644 ret = OC_STACK_ERROR;
2651 * If SVR database in persistent storage got corrupted or
2652 * is not available for some reason, a default Cred is created
2653 * which allows user to initiate Cred provisioning again.
2655 if (ret != OC_STACK_OK || !data || !gCred)
2657 gCred = GetCredDefault();
2663 OicUuid_t emptyUuid = {.id={0}};
2665 ret = GetDoxmDeviceID(&deviceID);
2666 if (ret != OC_STACK_OK)
2668 OIC_LOG_V(WARNING, TAG, "%s: GetDoxmDeviceID failed, error %d", __func__, ret);
2669 //Unit tests expect error code OC_STACK_INVALID_PARAM.
2670 ret = OC_STACK_INVALID_PARAM;
2674 //Add a log to track the invalid credential.
2675 LL_FOREACH(gCred, cred)
2677 if (false == CheckSubjectOfCertificate(cred, deviceID))
2679 OIC_LOG(WARNING, TAG, "Check subject of Certificate was failed while InitCredResource");
2681 if (false == IsValidCredential(cred))
2683 OIC_LOG(WARNING, TAG, "Invalid credential data was dectected while InitCredResource");
2684 OIC_LOG_V(WARNING, TAG, "Invalid credential ID = %d", cred->credId);
2688 if (NULL == rownerId || 0 == memcmp(rownerId, &emptyUuid, sizeof(OicUuid_t)))
2690 memcpy(&gRownerId, &deviceID, sizeof(OicUuid_t));
2694 memcpy(&gRownerId, rownerId, sizeof(OicUuid_t));
2697 if (!UpdatePersistentStorage(gCred))
2699 OIC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
2702 //Instantiate 'oic.sec.cred'
2703 ret = CreateCredResource();
2706 OIC_LOG(DEBUG, TAG, "OUT InitCredResource.");
2707 OICClearMemory(data, size);
2713 OCStackResult DeInitCredResource()
2715 OCStackResult result = OCDeleteResource(gCredHandle);
2716 DeleteCredList(gCred);
2721 OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
2723 OicSecCred_t *cred = NULL;
2725 if ( NULL == subject)
2730 LL_FOREACH(gCred, cred)
2732 if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
2740 const OicSecCred_t* GetCredList()
2745 OicSecCred_t* GetCredEntryByCredId(const uint16_t credId)
2747 OicSecCred_t *cred = NULL;
2748 OicSecCred_t *tmpCred = NULL;
2755 LL_FOREACH(gCred, tmpCred)
2757 if(tmpCred->credId == credId)
2759 cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
2760 VERIFY_NOT_NULL(TAG, cred, ERROR);
2764 cred->credId = tmpCred->credId;
2765 cred->credType = tmpCred->credType;
2766 memcpy(cred->subject.id, tmpCred->subject.id , sizeof(cred->subject.id));
2767 if (tmpCred->period)
2769 cred->period = OICStrdup(tmpCred->period);
2773 if (tmpCred->privateData.data)
2775 cred->privateData.data = (uint8_t *)OICCalloc(1, tmpCred->privateData.len);
2776 VERIFY_NOT_NULL(TAG, cred->privateData.data, ERROR);
2778 memcpy(cred->privateData.data, tmpCred->privateData.data, tmpCred->privateData.len);
2779 cred->privateData.len = tmpCred->privateData.len;
2780 cred->privateData.encoding = tmpCred->privateData.encoding;
2782 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
2783 if (tmpCred->publicData.data)
2785 cred->publicData.data = (uint8_t *)OICCalloc(1, tmpCred->publicData.len);
2786 VERIFY_NOT_NULL(TAG, cred->publicData.data, ERROR);
2788 memcpy(cred->publicData.data, tmpCred->publicData.data, tmpCred->publicData.len);
2789 cred->publicData.len = tmpCred->publicData.len;
2790 cred->publicData.encoding = tmpCred->publicData.encoding;
2792 if (tmpCred->optionalData.data)
2794 cred->optionalData.data = (uint8_t *)OICCalloc(1, tmpCred->optionalData.len);
2795 VERIFY_NOT_NULL(TAG, cred->optionalData.data, ERROR);
2797 memcpy(cred->optionalData.data, tmpCred->optionalData.data, tmpCred->optionalData.len);
2798 cred->optionalData.len = tmpCred->optionalData.len;
2799 cred->optionalData.encoding = tmpCred->optionalData.encoding;
2800 cred->optionalData.revstat= tmpCred->optionalData.revstat;
2802 if (tmpCred->credUsage)
2804 cred->credUsage = OICStrdup(tmpCred->credUsage);
2806 #endif /* __WITH_DTLS__ or __WITH_TLS__*/
2817 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
2818 int32_t GetDtlsPskCredentials(CADtlsPskCredType_t type,
2819 const uint8_t *desc, size_t desc_len,
2820 uint8_t *result, size_t result_length)
2831 case CA_DTLS_PSK_HINT:
2832 case CA_DTLS_PSK_IDENTITY:
2834 OicUuid_t deviceID = {.id={0}};
2835 // Retrieve Device ID from doxm resource
2836 if ( OC_STACK_OK != GetDoxmDeviceID(&deviceID) )
2838 OIC_LOG (ERROR, TAG, "Unable to retrieve doxm Device ID");
2842 if (result_length < sizeof(deviceID.id))
2844 OIC_LOG (ERROR, TAG, "Wrong value for result_length");
2847 memcpy(result, deviceID.id, sizeof(deviceID.id));
2848 return (sizeof(deviceID.id));
2852 case CA_DTLS_PSK_KEY:
2854 OicSecCred_t *cred = NULL;
2855 LL_FOREACH(gCred, cred)
2857 if (cred->credType != SYMMETRIC_PAIR_WISE_KEY)
2862 if ((desc_len == sizeof(cred->subject.id)) &&
2863 (memcmp(desc, cred->subject.id, sizeof(cred->subject.id)) == 0))
2866 * If the credentials are valid for limited time,
2867 * check their expiry.
2871 if(IOTVTICAL_VALID_ACCESS != IsRequestWithinValidTime(cred->period, NULL))
2873 OIC_LOG (INFO, TAG, "Credentials are expired.");
2879 // TODO: Added as workaround. Will be replaced soon.
2880 if(OIC_ENCODING_RAW == cred->privateData.encoding)
2882 if (ValueWithinBounds(cred->privateData.len, INT32_MAX))
2884 size_t len = cred->privateData.len;
2885 if (result_length < len)
2887 OIC_LOG (ERROR, TAG, "Wrong value for result_length");
2890 memcpy(result, cred->privateData.data, len);
2894 else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
2896 size_t outBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
2897 uint8_t* outKey = OICCalloc(1, outBufSize);
2901 OIC_LOG (ERROR, TAG, "Failed to allocate memory.");
2905 if(B64_OK == b64Decode((char*)cred->privateData.data, cred->privateData.len, outKey, outBufSize, &outKeySize))
2907 if (ValueWithinBounds(outKeySize, INT32_MAX))
2909 if (result_length < outKeySize)
2911 OIC_LOG (ERROR, TAG, "Wrong value for result_length");
2914 memcpy(result, outKey, outKeySize);
2915 ret = (int32_t)outKeySize;
2920 OIC_LOG (ERROR, TAG, "Failed base64 decoding.");
2926 if (OC_STACK_OK != RegisterSymmetricCredentialRole(cred))
2928 OIC_LOG(WARNING, TAG, "Couldn't RegisterRoleForSubject");
2934 OIC_LOG(DEBUG, TAG, "Can not find subject matched credential.");
2936 #ifdef MULTIPLE_OWNER
2937 const OicSecDoxm_t* doxm = GetDoxmResourceData();
2938 if(doxm && doxm->mom && OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode)
2940 // in case of multiple owner transfer authentication
2941 if(OIC_PRECONFIG_PIN == doxm->oxmSel)
2943 OicSecCred_t* wildCardCred = GetCredResourceData(&WILDCARD_SUBJECT_ID);
2946 OIC_LOG(DEBUG, TAG, "Detected wildcard credential.");
2947 if(PIN_PASSWORD == wildCardCred->credType)
2950 char* pinBuffer = NULL;
2951 size_t pinLength = 0;
2952 if(OIC_ENCODING_RAW == wildCardCred->privateData.encoding)
2954 pinBuffer = OICCalloc(1, wildCardCred->privateData.len + 1);
2955 if(NULL == pinBuffer)
2957 OIC_LOG (ERROR, TAG, "Failed to allocate memory.");
2960 pinLength = wildCardCred->privateData.len;
2961 memcpy(pinBuffer, wildCardCred->privateData.data, pinLength);
2963 else if(OIC_ENCODING_BASE64 == wildCardCred->privateData.encoding)
2965 size_t pinBufSize = B64DECODE_OUT_SAFESIZE((wildCardCred->privateData.len + 1));
2966 pinBuffer = OICCalloc(1, pinBufSize);
2967 if(NULL == pinBuffer)
2969 OIC_LOG (ERROR, TAG, "Failed to allocate memory.");
2973 if(B64_OK != b64Decode((char*)wildCardCred->privateData.data, wildCardCred->privateData.len, (uint8_t*)pinBuffer, pinBufSize, &pinLength))
2975 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
2981 OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
2985 //Set the PIN/PW to derive PSK
2986 if (OC_STACK_OK != SetPreconfigPin(pinBuffer, pinLength))
2989 OIC_LOG(ERROR, TAG, "Failed to load PIN data.");
2995 if(OC_STACK_OK != GetDoxmDeviceID(&myUuid))
2997 OIC_LOG(ERROR, TAG, "Failed to read device ID");
3000 SetUuidForPinBasedOxm(&myUuid);
3002 //Calculate PSK using PIN/PW
3003 if(0 == DerivePSKUsingPIN((uint8_t*)result))
3005 ret = OWNER_PSK_LENGTH_128;
3009 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN");
3012 if(CA_STATUS_OK != CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB))
3014 OIC_LOG(WARNING, TAG, "Error while bind the DTLS Handshake Callback.");
3019 else if(OIC_RANDOM_DEVICE_PIN == doxm->oxmSel)
3021 if(0 == DerivePSKUsingPIN((uint8_t*)result))
3023 ret = OWNER_PSK_LENGTH_128;
3027 OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
3032 #endif //MULTIPLE_OWNER
3041 * Add temporal PSK to PIN based OxM
3043 * @param[in] tmpSubject UUID of target device
3044 * @param[in] credType Type of credential to be added
3045 * @param[in] pin numeric characters
3046 * @param[in] pinSize length of 'pin'
3047 * @param[in] rownerID Resource owner's UUID
3048 * @param[out] tmpCredSubject Generated credential's subject.
3050 * @return OC_STACK_OK for success and errorcode otherwise.
3052 OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
3053 const char * pin, size_t pinSize,
3054 const OicUuid_t * rownerID, OicUuid_t* tmpCredSubject)
3056 OCStackResult ret = OC_STACK_ERROR;
3057 OIC_LOG(DEBUG, TAG, "AddTmpPskWithPIN IN");
3059 if(NULL == tmpSubject || NULL == pin || 0 == pinSize || NULL == tmpCredSubject)
3061 return OC_STACK_INVALID_PARAM;
3064 uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
3065 OicSecKey_t privKey;
3066 memset(&privKey, 0, sizeof(privKey));
3067 privKey.data = privData;
3068 privKey.len = OWNER_PSK_LENGTH_128;
3069 privKey.encoding = OIC_ENCODING_RAW;
3071 OicSecCred_t* cred = NULL;
3072 int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, rownerID->id,
3073 UUID_LENGTH, PBKDF_ITERATIONS,
3074 OWNER_PSK_LENGTH_128, privData);
3075 VERIFY_SUCCESS(TAG, (0 == dtlsRes) , ERROR);
3077 cred = GenerateCredential(tmpSubject, credType, NULL,
3078 &privKey, rownerID, NULL);
3079 OICClearMemory(privData, sizeof(privData));
3082 OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
3083 return OC_STACK_ERROR;
3086 memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
3088 ret = AddCredential(cred);
3089 if( OC_STACK_OK != ret)
3091 RemoveCredential(tmpSubject);
3092 OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
3094 OIC_LOG(DEBUG, TAG, "AddTmpPskWithPIN OUT");
3100 #endif /* __WITH_DTLS__ */
3102 OCStackResult SetCredRownerId(const OicUuid_t* newROwner)
3104 OCStackResult ret = OC_STACK_ERROR;
3105 OicUuid_t prevId = {.id={0}};
3107 if(NULL == newROwner)
3109 ret = OC_STACK_INVALID_PARAM;
3114 memcpy(prevId.id, gRownerId.id, sizeof(prevId.id));
3115 memcpy(gRownerId.id, newROwner->id, sizeof(newROwner->id));
3117 VERIFY_SUCCESS(TAG, UpdatePersistentStorage(gCred), ERROR);
3125 memcpy(gRownerId.id, prevId.id, sizeof(prevId.id));
3129 OCStackResult GetCredRownerId(OicUuid_t *rowneruuid)
3133 memcpy(&(rowneruuid->id), &(gRownerId.id), sizeof(rowneruuid->id));
3136 return OC_STACK_ERROR;
3139 #if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
3140 /* Caller must call OICFree on *der when finished. */
3141 static int ConvertPemCertToDer(const char *pem, size_t pemLen, uint8_t** der, size_t* derLen)
3143 const char* pemHeader = "-----BEGIN CERTIFICATE-----"; /* no newlines allowed here */
3144 const char* pemFooter = "-----END CERTIFICATE-----";
3146 mbedtls_pem_context ctx;
3151 mbedtls_pem_init(&ctx);
3153 ret = mbedtls_pem_read_buffer(&ctx, pemHeader, pemFooter, (const uint8_t*) pem, NULL, 0, &usedLen);
3156 OIC_LOG_V(ERROR, TAG, "%s: failed reading PEM cert", __func__);
3160 uint8_t *buf = OICCalloc(1, ctx.buflen);
3163 OIC_LOG(ERROR, TAG, "Failed to allocate memory");
3168 memcpy(buf, ctx.buf, ctx.buflen);
3171 *derLen = ctx.buflen;
3174 mbedtls_pem_free(&ctx);
3179 /* Caller must call OICFree on *pem when finished. */
3180 static int ConvertDerCertToPem(const uint8_t* der, size_t derLen, uint8_t** pem)
3182 const char* pemHeader = "-----BEGIN CERTIFICATE-----\n";
3183 const char* pemFooter = "-----END CERTIFICATE-----\n";
3185 /* Get the length required for output */
3187 int ret = mbedtls_pem_write_buffer(pemHeader,
3194 if (ret != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL)
3196 OIC_LOG_V(ERROR, TAG, "Couldn't convert cert into PEM, failed getting required length: %d", ret);
3200 *pem = OICCalloc(1, pemLen + 1);
3203 OIC_LOG(ERROR, TAG, "Failed to allocate memory for PEM cert");
3207 /* Try the conversion */
3208 ret = mbedtls_pem_write_buffer(pemHeader,
3217 OIC_LOG_V(ERROR, TAG, "Couldn't convert cert into PEM, failed writing PEM: %d", ret);
3218 OICFreeAndSetToNull((void **) pem);
3225 static OCStackResult GetCaCert(ByteArray_t * crt, const char * usage, OicEncodingType_t desiredEncoding)
3227 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
3228 if (NULL == crt || NULL == usage)
3230 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
3231 return OC_STACK_INVALID_PARAM;
3234 switch (desiredEncoding)
3236 case OIC_ENCODING_PEM:
3237 case OIC_ENCODING_DER:
3238 case OIC_ENCODING_BASE64:
3241 OIC_LOG_V(ERROR, TAG, "%s: Unsupported encoding %d", __func__, desiredEncoding);
3242 return OC_STACK_INVALID_PARAM;
3246 OicSecCred_t* temp = NULL;
3248 LL_FOREACH(gCred, temp)
3250 if ((SIGNED_ASYMMETRIC_KEY == temp->credType) &&
3251 (temp->credUsage != NULL) &&
3252 (0 == strcmp(temp->credUsage, usage)) && (false == temp->optionalData.revstat))
3255 if ((OIC_ENCODING_BASE64 != temp->publicData.encoding) &&
3256 (OIC_ENCODING_PEM != temp->publicData.encoding) &&
3257 (OIC_ENCODING_DER != temp->publicData.encoding))
3259 OIC_LOG_V(WARNING, TAG, "%s: Unknown encoding type", __func__);
3263 if (OIC_ENCODING_DER == desiredEncoding)
3265 if ((OIC_ENCODING_BASE64 == temp->publicData.encoding) ||
3266 (OIC_ENCODING_PEM == temp->publicData.encoding))
3268 uint8_t* buf = NULL;
3270 int ret = ConvertPemCertToDer((const char*)temp->publicData.data, temp->publicData.len, &buf, &outSize);
3273 OIC_LOG(ERROR, TAG, "Could not convert PEM cert to DER");
3274 return OC_STACK_ERROR;
3277 uint8_t *savePtr = crt->data;
3278 crt->data = OICRealloc(crt->data, crt->len + outSize);
3279 if (NULL == crt->data)
3281 OIC_LOG(ERROR, TAG, "No memory reallocating crt->data");
3284 return OC_STACK_NO_MEMORY;
3286 memcpy(crt->data + crt->len, buf, outSize);
3287 crt->len += outSize;
3292 uint8_t *savePtr = crt->data;
3293 crt->data = OICRealloc(crt->data, crt->len + temp->publicData.len);
3294 if (NULL == crt->data)
3296 OIC_LOG(ERROR, TAG, "No memory reallocating crt->data");
3298 return OC_STACK_NO_MEMORY;
3300 memcpy(crt->data + crt->len, temp->publicData.data, temp->publicData.len);
3301 crt->len += temp->publicData.len;
3303 OIC_LOG_V(DEBUG, TAG, "%s found", usage);
3308 uint8_t *pem = NULL;
3310 if ((OIC_ENCODING_BASE64 == temp->publicData.encoding) ||
3311 (OIC_ENCODING_PEM == temp->publicData.encoding))
3313 pem = temp->publicData.data;
3314 pemLen = temp->publicData.len;
3318 int ret = ConvertDerCertToPem(temp->publicData.data, temp->publicData.len, &pem);
3321 OIC_LOG_V(ERROR, TAG, "Failed converting DER cert to PEM: %d", ret);
3322 return OC_STACK_ERROR;
3324 pemLen = strlen((char *)pem) + 1;
3327 uint8_t *oldData = crt->data;
3328 crt->data = OICRealloc(crt->data, crt->len + pemLen);
3329 if (NULL == crt->data)
3331 OIC_LOG(ERROR, TAG, "No memory reallocating crt->data");
3333 return OC_STACK_NO_MEMORY;
3335 memcpy(crt->data + crt->len, pem, pemLen);
3342 OIC_LOG_V(WARNING, TAG, "%s not found", usage);
3343 return OC_STACK_NO_RESOURCE;
3346 if (OIC_ENCODING_PEM == desiredEncoding)
3348 /* mbedtls_x509_crt_parse requires a null terminator to determine that the format is PEM */
3349 size_t crtLength = crt->len;
3350 bool addNull = (crt->data[crtLength - 1] != 0);
3354 OIC_LOG_V(DEBUG, TAG, "%s: adding null terminator at the end of the cert", __func__);
3355 uint8_t *oldData = crt->data;
3356 crt->data = OICRealloc(crt->data, crtLength + 1);
3357 if (NULL == crt->data)
3359 OIC_LOG(ERROR, TAG, "No memory reallocating crt->data");
3361 return OC_STACK_NO_MEMORY;
3363 crt->data[crtLength] = 0;
3364 crt->len = crtLength + 1;
3368 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
3372 OCStackResult GetPemCaCert(ByteArray_t * crt, const char * usage)
3374 return GetCaCert(crt, usage, OIC_ENCODING_PEM);
3377 static int cloneSecKey(OicSecKey_t * dst, OicSecKey_t * src)
3379 if ((src == NULL) || (dst == NULL))
3386 dst->data = OICCalloc(src->len, 1);
3387 if (dst->data == NULL)
3389 OIC_LOG_V(ERROR, TAG, "%s memory allocation failed", __func__);
3392 memcpy(dst->data, src->data, src->len);
3399 dst->len = src->len;
3400 dst->encoding = src->encoding;
3405 /* Caller must call FreeRoleCertChainList on roleEntries when finished. */
3406 OCStackResult GetAllRoleCerts(RoleCertChain_t ** output)
3408 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
3412 OicSecCred_t * temp = NULL;
3413 LL_FOREACH(gCred, temp)
3415 if ((SIGNED_ASYMMETRIC_KEY == temp->credType) &&
3416 (temp->credUsage != NULL) &&
3417 (0 == strcmp(temp->credUsage, ROLE_CERT)))
3419 if (temp->publicData.data == NULL)
3421 OIC_LOG_V(WARNING, TAG, "%s missing certificate data in role certificate", __func__);
3425 RoleCertChain_t * add = (RoleCertChain_t *) OICCalloc(1, sizeof(RoleCertChain_t));
3428 OIC_LOG_V(ERROR, TAG, "%s Failed to allocate memory", __func__);
3431 LL_APPEND(*output, add);
3432 add->credId = temp->credId;
3433 if (cloneSecKey(&add->certificate, &temp->publicData) != 0)
3435 OIC_LOG_V(ERROR, TAG, "%s failed to copy certificate data", __func__);
3441 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
3445 FreeRoleCertChainList(*output);
3447 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
3448 return OC_STACK_ERROR;
3451 void GetPemOwnCert(ByteArray_t * crt, const char * usage)
3453 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
3454 if (NULL == crt || NULL == usage)
3456 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
3460 OicSecCred_t * temp = NULL;
3461 LL_FOREACH(gCred, temp)
3463 if (SIGNED_ASYMMETRIC_KEY == temp->credType &&
3464 temp->credUsage != NULL &&
3465 0 == strcmp(temp->credUsage, usage))
3469 uint8_t *pem = NULL;
3471 bool mustFreePem = false;
3472 bool mustAddNull = true;
3474 switch (temp->publicData.encoding)
3476 case OIC_ENCODING_DER:
3477 case OIC_ENCODING_RAW:
3478 mbedRet = ConvertDerCertToPem(temp->publicData.data, temp->publicData.len, &pem);
3481 OIC_LOG_V(ERROR, TAG, "Failed to ConvertDerCertToPem: %d", mbedRet);
3485 mustAddNull = false; /* mbedTLS always NULL-terminates. */
3486 pemLen = strlen((char *)pem) + 1;
3489 case OIC_ENCODING_PEM:
3490 case OIC_ENCODING_BASE64:
3491 pem = temp->publicData.data;
3492 pemLen = temp->publicData.len;
3494 /* Make sure the buffer has a terminating NULL. If not, make sure we add one later. */
3495 for (size_t i = pemLen - 1; i > 0; i--)
3497 if ('\0' == (char)pem[i])
3499 mustAddNull = false;
3506 OIC_LOG_V(ERROR, TAG, "Unsupported encoding %d", temp->publicData.encoding);
3511 crt->data = OICRealloc(crt->data, crt->len + pemLen + (mustAddNull ? 1 : 0));
3512 if (NULL == crt->data)
3514 OIC_LOG(ERROR, TAG, "No memory reallocating crt->data");
3523 /* If we're appending, subtract one from crt->len below so we overwrite the current terminating
3524 * NULL with the beginning of the new data.
3528 assert(crt->data[crt->len - 1] == '\0');
3529 memcpy(crt->data + crt->len - 1, pem, pemLen);
3530 crt->len += pemLen - 1;
3534 memcpy(crt->data, pem, pemLen);
3538 /* If pem doesn't contain a terminating NULL, add one. */
3541 assert(crt->data[crt->len - 1] != '\0');
3542 crt->data[crt->len] = '\0';
3551 OIC_LOG_V(DEBUG, TAG, "%s found", usage);
3556 OIC_LOG_V(WARNING, TAG, "%s not found", usage);
3558 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
3562 void GetDerKey(ByteArray_t * key, const char * usage)
3564 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
3565 if (NULL == key || NULL == usage)
3567 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
3571 OicSecCred_t * temp = NULL;
3573 LL_FOREACH(gCred, temp)
3575 if ((SIGNED_ASYMMETRIC_KEY == temp->credType || ASYMMETRIC_KEY == temp->credType) &&
3576 temp->privateData.len > 0 &&
3577 NULL != temp->credUsage &&
3578 0 == strcmp(temp->credUsage, usage))
3581 if (temp->privateData.encoding == OIC_ENCODING_PEM)
3583 /* Convert PEM to DER */
3584 const char* pemHeader = "-----BEGIN EC PRIVATE KEY-----"; /* no newlines allowed here */
3585 const char* pemFooter = "-----END EC PRIVATE KEY-----";
3586 uint8_t *data = temp->privateData.data;
3587 size_t length = temp->privateData.len;
3588 bool freeData = false;
3590 if (data[length - 1] != 0)
3592 /* Add a null terminator, because mbedtls_pem_read_buffer requires it */
3593 OIC_LOG_V(DEBUG, TAG, "%s: adding null terminator to privateData", __func__);
3595 data = OICMalloc(length + 1);
3598 OIC_LOG(ERROR, TAG, "Failed to allocate memory");
3602 memcpy(data, temp->privateData.data, length);
3607 mbedtls_pem_context ctx;
3611 mbedtls_pem_init(&ctx);
3612 ret = mbedtls_pem_read_buffer(&ctx, pemHeader, pemFooter, data, NULL, 0, &usedLen);
3621 OIC_LOG_V(ERROR, TAG, "%s: failed reading PEM key", __func__);
3622 mbedtls_pem_free(&ctx);
3626 uint8_t *tmp = OICRealloc(key->data, ctx.buflen);
3631 OIC_LOG(ERROR, TAG, "Failed to allocate memory");
3632 mbedtls_pem_free(&ctx);
3637 memcpy(key->data, ctx.buf, ctx.buflen);
3638 key->len = ctx.buflen;
3639 mbedtls_pem_free(&ctx);
3642 else if(temp->privateData.encoding == OIC_ENCODING_DER || temp->privateData.encoding == OIC_ENCODING_RAW)
3644 uint8_t *tmp = OICRealloc(key->data, key->len + temp->privateData.len);
3649 OIC_LOG(ERROR, TAG, "Failed to allocate memory");
3653 memcpy(key->data + key->len, temp->privateData.data, temp->privateData.len);
3654 key->len += temp->privateData.len;
3655 OIC_LOG_V(DEBUG, TAG, "Key for %s found", usage);
3660 OIC_LOG_V(WARNING, TAG, "Key for %s found, but it has an unknown encoding (%d)", usage, temp->privateData.encoding);
3666 OIC_LOG_V(WARNING, TAG, "Key for %s not found", usage);
3668 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
3671 void InitCipherSuiteListInternal(bool * list, const char * usage, const char *deviceId)
3673 OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
3674 if (NULL == list || NULL == usage)
3676 OIC_LOG(DEBUG, TAG, "NULL passed");
3677 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
3680 OicSecCred_t * temp = NULL;
3681 LL_FOREACH(gCred, temp)
3683 switch (temp->credType)
3688 OIC_LOG(DEBUG, TAG, "PIN_PASSWORD found");
3691 case SYMMETRIC_PAIR_WISE_KEY:
3695 if (NULL == deviceId || deviceId[0] == '\0' ||
3696 OC_STACK_OK != ConvertStrToUuid(deviceId, &uuid) ||
3697 0 == memcmp(uuid.id, temp->subject.id, sizeof(uuid.id)))
3700 OIC_LOG(DEBUG, TAG, "SYMMETRIC_PAIR_WISE_KEY found");
3704 case SIGNED_ASYMMETRIC_KEY:
3706 if (NULL != temp->credUsage && 0 == strcmp(temp->credUsage, usage))
3709 OIC_LOG_V(DEBUG, TAG, "SIGNED_ASYMMETRIC_KEY found for %s", usage);
3713 case SYMMETRIC_GROUP_KEY:
3714 case ASYMMETRIC_KEY:
3715 case ASYMMETRIC_ENCRYPTION_KEY:
3717 OIC_LOG(WARNING, TAG, "Unsupported credential type for TLS.");
3722 OIC_LOG(WARNING, TAG, "Unknown credential type for TLS.");
3727 OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);