cdde702bfe03c1f9dd363c2f4127e60ea1531933
[iotivity.git] / resource / csdk / security / src / credresource.c
1 //******************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #define __STDC_LIMIT_MACROS
22
23 #include "iotivity_config.h"
24 #include <stdlib.h>
25 #ifdef HAVE_STRING_H
26 #include <string.h>
27 #endif
28 #ifdef HAVE_STRINGS_H
29 #include <strings.h>
30 #endif
31 #include <stdint.h>
32 #include <stdbool.h>
33 #include <inttypes.h>
34
35 #include "cainterface.h"
36 #include "payload_logging.h"
37 #include "ocstack.h"
38 #include "ocrandom.h"
39 #include "base64.h"
40 #include "ocserverrequest.h"
41 #include "oic_malloc.h"
42 #include "oic_string.h"
43 #include "ocpayload.h"
44 #include "ocpayloadcbor.h"
45 #include "utlist.h"
46 #include "credresource.h"
47 #include "doxmresource.h"
48 #include "pstatresource.h"
49 #include "iotvticalendar.h"
50 #include "pbkdf2.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"
57 #include "cacommon.h"
58 #include "secureresourcemanager.h"
59 #include "deviceonboardingstate.h"
60
61 #ifdef __unix__
62 #include <sys/types.h>
63 #include <sys/stat.h>
64 #include <fcntl.h>
65 #include <unistd.h>
66 #endif
67
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>
73 #endif
74
75 #define TAG  "OIC_SRM_CREDL"
76
77 #ifdef HAVE_WINDOWS_H
78 #include <wincrypt.h>
79 #include <intsafe.h>
80 #endif
81
82 /** Max credential types number used for TLS */
83 #define MAX_TYPE 2
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;
87
88 /** CRED size - Number of mandatory items. */
89 static const uint8_t CRED_ROOT_MAP_SIZE = 4;
90 static const uint8_t CRED_MAP_SIZE = 3;
91 static const uint8_t ROLEID_MAP_SIZE = 1;
92
93
94 static OicSecCred_t        *gCred = NULL;
95 static OCResourceHandle    gCredHandle = NULL;
96 static OicUuid_t           gRownerId = { .id = { 0 } };
97
98 typedef enum CredCompareResult{
99     CRED_CMP_EQUAL = 0,
100     CRED_CMP_NOT_EQUAL = 1,
101     CRED_CMP_ERROR = 2
102 }CredCompareResult_t;
103
104 typedef struct CredIdList CredIdList_t;
105
106 struct CredIdList
107 {
108     uint16_t credId;
109     CredIdList_t *next;
110 };
111
112 static void DeleteCredIdList(CredIdList_t** list)
113 {
114     if (list)
115     {
116         CredIdList_t *head = *list;
117
118         while (head)
119         {
120             CredIdList_t *tmp = head->next;
121             OICFree(head);
122             head = tmp;
123         }
124     }
125 }
126
127 /**
128  * Internal function to check a subject of SIGNED_ASYMMETRIC_KEY(Certificate).
129  * If that subject is NULL or wildcard, set it to own deviceID.
130  * @param cred credential on SVR DB file
131  * @param deviceID own deviceuuid of doxm resource
132  *
133  * @return
134  *     true successfully done
135  *     false Invalid cred
136  */
137
138 static bool CheckSubjectOfCertificate(OicSecCred_t* cred, OicUuid_t deviceID)
139 {
140     OIC_LOG(DEBUG, TAG, "IN CheckSubjectOfCertificate");
141     VERIFY_NOT_NULL(TAG, cred, ERROR);
142
143 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
144     const OicUuid_t emptyUuid = { .id = { 0 } };
145
146     if ( SIGNED_ASYMMETRIC_KEY == cred->credType)
147     {
148         if((0 == memcmp(cred->subject.id, emptyUuid.id, sizeof(cred->subject.id))) ||
149             (0 == memcmp(cred->subject.id, &WILDCARD_SUBJECT_ID, sizeof(cred->subject.id))))
150         {
151             memcpy(cred->subject.id, deviceID.id, sizeof(deviceID.id));
152         }
153     }
154 #else
155     OC_UNUSED(deviceID);
156 #endif
157
158     OIC_LOG(DEBUG, TAG, "OUT CheckSubjectOfCertificate");
159     return true;
160 exit:
161     OIC_LOG(ERROR, TAG, "OUT CheckSubjectOfCertificate");
162     return false;
163 }
164
165 /**
166  * Internal function to check credential
167  */
168 static bool IsValidCredential(const OicSecCred_t* cred)
169 {
170     OicUuid_t emptyUuid = {.id={0}};
171
172
173     OIC_LOG(DEBUG, TAG, "IN IsValidCredential");
174
175     VERIFY_NOT_NULL(TAG, cred, ERROR);
176     VERIFY_SUCCESS(TAG, 0 != cred->credId, ERROR);
177     OIC_LOG_V(DEBUG, TAG, "Cred ID = %d", cred->credId);
178
179 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
180     OIC_LOG_V(DEBUG, TAG, "Cred Type = %d", cred->credType);
181
182     switch(cred->credType)
183     {
184         case SYMMETRIC_PAIR_WISE_KEY:
185         case SYMMETRIC_GROUP_KEY:
186         case PIN_PASSWORD:
187         {
188             VERIFY_NOT_NULL(TAG, cred->privateData.data, ERROR);
189             VERIFY_SUCCESS(TAG, 0 != cred->privateData.len, ERROR);
190             VERIFY_SUCCESS(TAG, \
191                            (OIC_ENCODING_RAW == cred->privateData.encoding || \
192                            OIC_ENCODING_BASE64 == cred->privateData.encoding), \
193                            ERROR);
194             break;
195         }
196         case ASYMMETRIC_KEY:
197         {
198             VERIFY_NOT_NULL(TAG, cred->publicData.data, ERROR);
199             VERIFY_SUCCESS(TAG, 0 != cred->publicData.len, ERROR);
200             VERIFY_SUCCESS(TAG, \
201                            (OIC_ENCODING_UNKNOW < cred->publicData.encoding && \
202                             OIC_ENCODING_DER >= cred->publicData.encoding),
203                            ERROR);
204             break;
205         }
206         case SIGNED_ASYMMETRIC_KEY:
207         {
208             VERIFY_SUCCESS(TAG, (NULL != cred->publicData.data ||NULL != cred->optionalData.data) , ERROR);
209             VERIFY_SUCCESS(TAG, (0 != cred->publicData.len || 0 != cred->optionalData.len), ERROR);
210
211             if(NULL != cred->optionalData.data)
212             {
213                 VERIFY_SUCCESS(TAG, \
214                                (OIC_ENCODING_UNKNOW < cred->optionalData.encoding && \
215                                 OIC_ENCODING_DER >= cred->optionalData.encoding),
216                                ERROR);
217             }
218             break;
219         }
220         case ASYMMETRIC_ENCRYPTION_KEY:
221         {
222             VERIFY_NOT_NULL(TAG, cred->privateData.data, ERROR);
223             VERIFY_SUCCESS(TAG, 0 != cred->privateData.len, ERROR);
224             VERIFY_SUCCESS(TAG, \
225                            (OIC_ENCODING_UNKNOW < cred->privateData.encoding && \
226                             OIC_ENCODING_DER >= cred->privateData.encoding),
227                            ERROR);
228             break;
229         }
230         default:
231         {
232             OIC_LOG(WARNING, TAG, "Unknown credential type");
233             return false;
234         }
235     }
236 #endif
237
238     VERIFY_SUCCESS(TAG, 0 != memcmp(emptyUuid.id, cred->subject.id, sizeof(cred->subject.id)), ERROR);
239
240     OIC_LOG(DEBUG, TAG, "OUT IsValidCredential");
241     return true;
242 exit:
243     OIC_LOG(WARNING, TAG, "OUT IsValidCredential : Invalid Credential detected.");
244     return false;
245 }
246
247 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
248 static bool IsEmptyCred(const OicSecCred_t* cred)
249 {
250     OicUuid_t emptyUuid = {.id={0}};
251
252     VERIFY_SUCCESS(TAG, (0 == memcmp(cred->subject.id, emptyUuid.id, sizeof(emptyUuid))), ERROR);
253     VERIFY_SUCCESS(TAG, !IsNonEmptyRole(&cred->roleId), ERROR);
254     VERIFY_SUCCESS(TAG, (0 == cred->credId), ERROR);
255     VERIFY_SUCCESS(TAG, (0 == cred->credType), ERROR);
256     VERIFY_SUCCESS(TAG, (NULL == cred->privateData.data), ERROR);
257     VERIFY_SUCCESS(TAG, (NULL == cred->publicData.data), ERROR);
258     VERIFY_SUCCESS(TAG, (NULL == cred->optionalData.data), ERROR);
259     VERIFY_SUCCESS(TAG, (NULL == cred->credUsage), ERROR);
260     return true;
261 exit:
262     return false;
263 }
264 #endif // __WITH_DTLS__ or __WITH_TLS__
265
266 /**
267  * This function frees OicSecCred_t object's fields and object itself.
268  */
269 void FreeCred(OicSecCred_t *cred)
270 {
271     if(NULL == cred)
272     {
273         OIC_LOG(ERROR, TAG, "Invalid Parameter");
274         return;
275     }
276     //Note: Need further clarification on roleID data type
277 #if 0
278     //Clean roleIds
279     OICFree(cred->roleIds);
280 #endif
281
282     //Clean PublicData/OptionalData/Credusage
283 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
284      // TODO: Need to check credUsage.
285     OICFree(cred->publicData.data);
286     OICFree(cred->optionalData.data);
287     OICFree(cred->credUsage);
288
289 #endif /* __WITH_DTLS__ ||  __WITH_TLS__*/
290
291     //Clean PrivateData
292     OICClearMemory(cred->privateData.data, cred->privateData.len);
293     OICFree(cred->privateData.data);
294
295     //Clean Period
296     OICFree(cred->period);
297
298 #ifdef MULTIPLE_OWNER
299     //Clean eowner
300     OICFree(cred->eownerID);
301 #endif
302
303     cred->next = NULL;
304
305     //Clean Cred node itself
306     OICFree(cred);
307 }
308
309 void DeleteCredList(OicSecCred_t* cred)
310 {
311     if (cred)
312     {
313         OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
314         LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
315         {
316             LL_DELETE(cred, credTmp1);
317             FreeCred(credTmp1);
318         }
319     }
320 }
321
322 size_t GetCredKeyDataSize(const OicSecCred_t* cred)
323 {
324     size_t size = 0;
325     if (cred)
326     {
327         OicSecCred_t *credPtr = NULL, *credTmp = NULL;
328         LL_FOREACH_SAFE((OicSecCred_t*)cred, credPtr, credTmp)
329         {
330             if (credPtr->privateData.data && 0 < credPtr->privateData.len)
331             {
332                 size += credPtr->privateData.len;
333             }
334 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
335             if (credPtr->publicData.data && 0 < credPtr->publicData.len)
336             {
337                 size += credPtr->publicData.len;
338             }
339             if (credPtr->optionalData.data && 0 < credPtr->optionalData.len)
340             {
341                 size += credPtr->optionalData.len;
342             }
343 #endif
344         }
345     }
346     OIC_LOG_V(DEBUG, TAG, "Cred Key Data Size : %u", (unsigned int) size);
347     return size;
348 }
349
350 static size_t OicSecCredCount(const OicSecCred_t *secCred)
351 {
352     size_t size = 0;
353     for (const OicSecCred_t *cred = secCred; cred; cred = cred->next)
354     {
355         size++;
356     }
357     return size;
358 }
359
360 static const char* EncodingValueToString(OicEncodingType_t encoding)
361 {
362     switch (encoding)
363     {
364         case OIC_ENCODING_RAW:    return OIC_SEC_ENCODING_RAW;
365         case OIC_ENCODING_BASE64: return OIC_SEC_ENCODING_BASE64;
366         case OIC_ENCODING_DER:    return OIC_SEC_ENCODING_DER;
367         case OIC_ENCODING_PEM:    return OIC_SEC_ENCODING_PEM;
368         default:                  return NULL;
369     }
370 }
371
372 static CborError SerializeEncodingToCborInternal(CborEncoder *map, const OicSecKey_t *value)
373 {
374     CborError cborEncoderResult = CborNoError;
375     const char *encoding = EncodingValueToString(value->encoding);
376     if (encoding)
377     {
378         cborEncoderResult = cbor_encode_text_string(map, OIC_JSON_ENCODING_NAME,
379             strlen(OIC_JSON_ENCODING_NAME));
380         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Encoding Tag.");
381         cborEncoderResult = cbor_encode_text_string(map, encoding,
382             strlen(encoding));
383         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Encoding Value.");
384
385         cborEncoderResult = cbor_encode_text_string(map, OIC_JSON_DATA_NAME,
386             strlen(OIC_JSON_DATA_NAME));
387         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Name Tag.");
388         if (OIC_ENCODING_DER == value->encoding ||
389             OIC_ENCODING_RAW == value->encoding)
390         {
391             cborEncoderResult = cbor_encode_byte_string(map,
392                     value->data, value->len);
393         }
394         else
395         {
396             cborEncoderResult = cbor_encode_text_string(map,
397                     (char*)value->data, value->len);
398         }
399         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Name Value.");
400     }
401     else
402     {
403         OIC_LOG_V(ERROR, TAG, "%s: Unknown encoding type: %u.", __func__, value->encoding);
404         return CborErrorUnknownType;
405     }
406     exit:
407     return cborEncoderResult;
408 }
409
410 CborError SerializeEncodingToCbor(CborEncoder *rootMap, const char* tag, const OicSecKey_t *value)
411 {
412     CborError cborEncoderResult = CborNoError;
413     CborEncoder map;
414     const size_t mapSize = 2;
415
416     cborEncoderResult = cbor_encode_text_string(rootMap, tag, strlen(tag));
417     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding PrivateData Tag.");
418
419     cborEncoderResult = cbor_encoder_create_map(rootMap, &map, mapSize);
420     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Map");
421
422     cborEncoderResult = SerializeEncodingToCborInternal(&map, value);
423     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed adding OicSecKey_t structure");
424
425     cborEncoderResult = cbor_encoder_close_container(rootMap, &map);
426     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Closing Map.");
427
428     exit:
429     return cborEncoderResult;
430 }
431
432 CborError SerializeSecOptToCbor(CborEncoder *rootMap, const char* tag, const OicSecOpt_t *value)
433 {
434     CborError cborEncoderResult = CborNoError;
435     CborEncoder map;
436     const size_t mapSize = 3;
437
438     cborEncoderResult = cbor_encode_text_string(rootMap, tag, strlen(tag));
439     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding PrivateData Tag.");
440
441     cborEncoderResult = cbor_encoder_create_map(rootMap, &map, mapSize);
442     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Map");
443
444     OicSecKey_t in;
445     in.data = value->data;
446     in.encoding = value->encoding;
447     in.len = value->len;
448
449     cborEncoderResult = SerializeEncodingToCborInternal(&map, &in);
450     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed adding OicSecKey_t structure");
451
452     cborEncoderResult = cbor_encode_text_string(&map, OIC_JSON_REVOCATION_STATUS_NAME,
453         strlen(OIC_JSON_REVOCATION_STATUS_NAME));
454     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding optional revstat Tag.");
455     cborEncoderResult = cbor_encode_boolean(&map, value->revstat);
456     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding optional revstat Value.");
457
458     cborEncoderResult = cbor_encoder_close_container(rootMap, &map);
459     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Closing Map.");
460
461     exit:
462     return cborEncoderResult;
463 }
464
465 static CborError DeserializeEncodingFromCborInternal(CborValue *map, char *name, OicSecKey_t *value)
466 {
467     size_t len = 0;
468     CborError cborFindResult = CborNoError;
469
470     // data -- Mandatory
471     if (strcmp(name, OIC_JSON_DATA_NAME) == 0)
472     {
473         if(cbor_value_is_byte_string(map))
474         {
475             cborFindResult = cbor_value_dup_byte_string(map, &value->data,
476                 &value->len, NULL);
477         }
478         else if(cbor_value_is_text_string(map))
479         {
480             cborFindResult = cbor_value_dup_text_string(map, (char**)(&value->data),
481                 &value->len, NULL);
482         }
483         else
484         {
485             cborFindResult = CborErrorUnknownType;
486             OIC_LOG(ERROR, TAG, "Unknown type for private data.");
487         }
488         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding PrivateData.");
489     }
490
491     // encoding -- Mandatory
492     if (strcmp(name, OIC_JSON_ENCODING_NAME) == 0)
493     {
494         char* strEncoding = NULL;
495         cborFindResult = cbor_value_dup_text_string(map, &strEncoding, &len, NULL);
496         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding EncodingType");
497
498         if(strcmp(strEncoding, OIC_SEC_ENCODING_RAW) == 0)
499         {
500             value->encoding = OIC_ENCODING_RAW;
501         }
502         else if(strcmp(strEncoding, OIC_SEC_ENCODING_BASE64) == 0)
503         {
504             value->encoding = OIC_ENCODING_BASE64;
505         }
506         else if(strcmp(strEncoding, OIC_SEC_ENCODING_DER) == 0)
507         {
508             value->encoding = OIC_ENCODING_DER;
509         }
510         else if(strcmp(strEncoding, OIC_SEC_ENCODING_PEM) == 0)
511         {
512             value->encoding = OIC_ENCODING_PEM;
513         }
514         else
515         {
516             //For unit test
517             value->encoding = OIC_ENCODING_RAW;
518             OIC_LOG_V(WARNING, TAG, "%s: Unknown encoding type detected.", __func__);
519         }
520         //Because cbor using malloc directly, it is required to use free() instead of OICFree
521         free(strEncoding);
522     }
523     exit:
524     return cborFindResult;
525 }
526
527 CborError DeserializeEncodingFromCbor(CborValue *rootMap, OicSecKey_t *value)
528 {
529     CborValue map = { .parser = NULL };
530     CborError cborFindResult = cbor_value_enter_container(rootMap, &map);
531     size_t len = 0;
532
533     while (cbor_value_is_valid(&map))
534     {
535         char* name = NULL;
536         CborType type = cbor_value_get_type(&map);
537         if (type == CborTextStringType && cbor_value_is_text_string(&map))
538         {
539             cborFindResult = cbor_value_dup_text_string(&map, &name, &len, NULL);
540             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to get text");
541             cborFindResult = cbor_value_advance(&map);
542             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to advance value");
543         }
544         if (name)
545         {
546             cborFindResult = DeserializeEncodingFromCborInternal(&map, name, value);
547             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to read OicSecKey_t value");
548         }
549         if (cbor_value_is_valid(&map))
550         {
551             cborFindResult = cbor_value_advance(&map);
552             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Advancing Map.");
553         }
554         //Because cbor using malloc directly, it is required to use free() instead of OICFree
555         free(name);
556     }
557     exit:
558     return cborFindResult;
559 }
560
561 CborError DeserializeSecOptFromCbor(CborValue *rootMap, OicSecOpt_t *value)
562 {
563     CborValue map = { .parser = NULL };
564     CborError cborFindResult = cbor_value_enter_container(rootMap, &map);
565     size_t len = 0;
566     value->revstat = false;
567
568     while (cbor_value_is_valid(&map))
569     {
570         char* name = NULL;
571         CborType type = cbor_value_get_type(&map);
572         if (type == CborTextStringType && cbor_value_is_text_string(&map))
573         {
574             cborFindResult = cbor_value_dup_text_string(&map, &name, &len, NULL);
575             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to get text");
576             cborFindResult = cbor_value_advance(&map);
577             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to advance value");
578         }
579         if (name)
580         {
581             // OptionalData::revstat -- Mandatory
582             if (strcmp(name, OIC_JSON_REVOCATION_STATUS_NAME) == 0)
583             {
584                 cborFindResult = cbor_value_get_boolean(&map, &value->revstat);
585                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding revstat Value.")
586             }
587             OicSecKey_t out;
588             cborFindResult = DeserializeEncodingFromCborInternal(&map, name, &out);
589             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to read OicSecKey_t value");
590
591             value->data = out.data;
592             value->encoding = out.encoding;
593             value->len = out.len;
594         }
595         if (cbor_value_is_valid(&map))
596         {
597             cborFindResult = cbor_value_advance(&map);
598             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Advancing Map.");
599         }
600         //Because cbor using malloc directly, it is required to use free() instead of OICFree
601         free(name);
602     }
603     exit:
604     return cborFindResult;
605 }
606
607 /* Produce debugging output for all credentials, output metadata. */
608 static void logCredMetadata()
609 {
610 #if defined(TB_LOG)
611     OicSecCred_t * temp = NULL;
612     size_t count = 0;
613     char uuidString[UUID_STRING_SIZE];
614     OicUuid_t ownUuid;
615
616     OIC_LOG_V(DEBUG, TAG, "IN %s:", __func__);
617
618     if (GetDoxmDeviceID(&ownUuid) == OC_STACK_OK && OCConvertUuidToString(ownUuid.id, uuidString))
619     {
620         OIC_LOG_V(DEBUG, TAG, "Own UUID: %s", uuidString);
621     }
622
623     LL_FOREACH(gCred, temp)
624     {
625         count++;
626         OIC_LOG(DEBUG, TAG, " ");
627         OIC_LOG_V(DEBUG, TAG, "Cred ID: %d", temp->credId);
628         if (OCConvertUuidToString(temp->subject.id, uuidString))
629         {
630             OIC_LOG_V(DEBUG, TAG, "Subject UUID: %s", uuidString);
631         }
632         if (IsNonEmptyRole(&temp->roleId))
633         {
634             OIC_LOG_V(DEBUG, TAG, "Role ID: %s", temp->roleId.id);
635             OIC_LOG_V(DEBUG, TAG, "Role authority: %s", temp->roleId.authority);
636         }
637         OIC_LOG_V(DEBUG, TAG, "Cred Type: %d", temp->credType);
638         OIC_LOG_V(DEBUG, TAG, "privateData length: %" PRIuPTR ", encoding: %d", temp->privateData.len, temp->privateData.encoding);
639
640 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
641         OIC_LOG_V(DEBUG, TAG, "publicData length: %" PRIuPTR ", encoding: %d", temp->publicData.len, temp->publicData.encoding);
642         if (temp->credUsage)
643         {
644             OIC_LOG_V(DEBUG, TAG, "credUsage: %s", temp->credUsage);
645         }
646
647         OIC_LOG_V(DEBUG, TAG, "optionalData length: %" PRIuPTR", encoding: %d" PRIuPTR, temp->optionalData.len, temp->optionalData.encoding);
648 #endif
649
650     }
651
652     OIC_LOG_V(DEBUG, TAG, "Found %" PRIuPTR " credentials.", count);
653
654     OIC_LOG_V(DEBUG, TAG, "OUT %s:", __func__);
655 #endif
656 }
657
658 OCStackResult CredToCBORPayload(const OicSecCred_t *credS, uint8_t **cborPayload,
659                                 size_t *cborSize, int secureFlag)
660 {
661     OIC_LOG_V(DEBUG, TAG, "IN %s:", __func__);
662     if (NULL == cborPayload || NULL != *cborPayload || NULL == cborSize)
663     {
664         return OC_STACK_INVALID_PARAM;
665     }
666
667     OCStackResult ret = OC_STACK_ERROR;
668
669     CborError cborEncoderResult = CborNoError;
670     uint8_t *outPayload = NULL;
671     size_t cborLen = *cborSize;
672     *cborSize = 0;
673     *cborPayload = NULL;
674     const OicSecCred_t *cred = credS;
675     CborEncoder encoder;
676     CborEncoder credArray;
677     CborEncoder credRootMap;
678     CborEncoder roleIdMap;
679
680     if (0 == cborLen)
681     {
682         cborLen = CBOR_SIZE;
683     }
684
685     outPayload = (uint8_t *)OICCalloc(1, cborLen);
686     VERIFY_NOT_NULL_RETURN(TAG, outPayload, ERROR, OC_STACK_ERROR);
687
688     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
689
690     size_t credRootMapSize = CRED_ROOT_MAP_SIZE;
691
692     // Create CRED Root Map (creds, rownerid)
693     cborEncoderResult = cbor_encoder_create_map(&encoder, &credRootMap, credRootMapSize);
694     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Cred Root Map");
695
696     // creds
697     cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_CREDS_NAME,
698         strlen(OIC_JSON_CREDS_NAME));
699     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding creds Name Tag.");
700
701     // creds array
702     cborEncoderResult = cbor_encoder_create_array(&credRootMap, &credArray, OicSecCredCount(cred));
703     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Cred Array.");
704
705     while (cred)
706     {
707         CborEncoder credMap;
708         size_t mapSize = CRED_MAP_SIZE;
709         size_t inLen = 0;
710         if (cred->period)
711         {
712             mapSize++;
713         }
714
715 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
716 #ifdef MULTIPLE_OWNER
717         if(cred->eownerID)
718         {
719             mapSize++;
720         }
721 #endif //MULTIPLE_OWNER
722
723         if ((SIGNED_ASYMMETRIC_KEY == cred->credType || ASYMMETRIC_KEY == cred->credType)
724             && cred->publicData.data)
725         {
726             mapSize++;
727         }
728         if (SIGNED_ASYMMETRIC_KEY == cred->credType && cred->optionalData.data)
729         {
730             mapSize++;
731         }
732         if (cred->credUsage)
733         {
734             mapSize++;
735         }
736         if (IsNonEmptyRole(&cred->roleId))
737         {
738             mapSize++;
739         }
740 #endif /* __WITH_DTLS__ ||  __WITH_TLS__*/
741         if (!secureFlag && cred->privateData.data)
742         {
743             mapSize++;
744         }
745         cborEncoderResult = cbor_encoder_create_map(&credArray, &credMap, mapSize);
746         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Cred Map");
747
748         //CredID -- Mandatory
749         cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDID_NAME,
750             strlen(OIC_JSON_CREDID_NAME));
751         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Cred Id Tag. ");
752         cborEncoderResult = cbor_encode_int(&credMap, cred->credId);
753         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Cred Id Value.");
754
755         //Subject -- Mandatory
756         cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_SUBJECTID_NAME,
757             strlen(OIC_JSON_SUBJECTID_NAME));
758         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Subject Tag.");
759         inLen = (memcmp(&(cred->subject), &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0) ?
760             WILDCARD_SUBJECT_ID_LEN : sizeof(OicUuid_t);
761         if(inLen == WILDCARD_SUBJECT_ID_LEN)
762         {
763             cborEncoderResult = cbor_encode_text_string(&credMap, WILDCARD_RESOURCE_URI,
764                 strlen(WILDCARD_RESOURCE_URI));
765             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Addding Subject Id wildcard Value.");
766         }
767         else
768         {
769             char *subject = NULL;
770             ret = ConvertUuidToStr(&cred->subject, &subject);
771             VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
772             cborEncoderResult = cbor_encode_text_string(&credMap, subject, strlen(subject));
773             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Addding Subject Id Value.");
774             OICFree(subject);
775         }
776
777         //Role ID -- optional
778         if (IsNonEmptyRole(&cred->roleId))
779         {
780             cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_ROLEID_NAME,
781                 strlen(OIC_JSON_ROLEID_NAME));
782             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed adding role ID map tag");
783
784             bool includeAuthority = (0 != memcmp(&cred->roleId.authority, &EMPTY_ROLE.authority, sizeof(EMPTY_ROLE.authority)));
785
786             cborEncoderResult = cbor_encoder_create_map(&credMap, &roleIdMap, ROLEID_MAP_SIZE + (includeAuthority ? 1 : 0));
787             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed adding role ID map");
788
789             cborEncoderResult = cbor_encode_text_string(&roleIdMap, OIC_JSON_ROLE_NAME, strlen(OIC_JSON_ROLE_NAME));
790             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed adding role tag");
791
792             cborEncoderResult = cbor_encode_text_string(&roleIdMap, cred->roleId.id, strlen(cred->roleId.id));
793             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed adding role value");
794
795             if (includeAuthority)
796             {
797                 cborEncoderResult = cbor_encode_text_string(&roleIdMap, OIC_JSON_AUTHORITY_NAME, strlen(OIC_JSON_AUTHORITY_NAME));
798                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed adding authority tag");
799
800                 cborEncoderResult = cbor_encode_text_string(&roleIdMap, cred->roleId.authority, strlen(cred->roleId.authority));
801                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed adding authority value");
802             }
803
804             cborEncoderResult = cbor_encoder_close_container(&credMap, &roleIdMap);
805             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed closing role ID map");
806         }
807
808         //CredType -- Mandatory
809         cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDTYPE_NAME,
810             strlen(OIC_JSON_CREDTYPE_NAME));
811         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Cred Type Tag.");
812         cborEncoderResult = cbor_encode_int(&credMap, cred->credType);
813         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
814
815 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
816         //PublicData -- Not Mandatory
817         if ((SIGNED_ASYMMETRIC_KEY == cred->credType || ASYMMETRIC_KEY == cred->credType)
818             && cred->publicData.data)
819         {
820             cborEncoderResult = SerializeEncodingToCbor(&credMap,
821                                          OIC_JSON_PUBLICDATA_NAME, &cred->publicData);
822             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding PublicData Tag.");
823         }
824         //OptionalData -- Not Mandatory
825         if (SIGNED_ASYMMETRIC_KEY == cred->credType && cred->optionalData.data)
826         {
827             cborEncoderResult = SerializeSecOptToCbor(&credMap,
828                                          OIC_JSON_OPTDATA_NAME, &cred->optionalData);
829             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding OptionalData Tag.");
830         }
831         //CredUsage -- Not Mandatory
832         if(cred->credUsage)
833         {
834             cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDUSAGE_NAME,
835                 strlen(OIC_JSON_CREDUSAGE_NAME));
836             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Credusage Name Tag.");
837             cborEncoderResult = cbor_encode_text_string(&credMap, cred->credUsage,
838                 strlen(cred->credUsage));
839             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Credusage Name Value.");
840         }
841 #endif /* __WITH_DTLS__ ||  __WITH_TLS__*/
842         //PrivateData -- Not Mandatory
843         if(!secureFlag && cred->privateData.data)
844         {
845             cborEncoderResult = SerializeEncodingToCbor(&credMap,
846                                          OIC_JSON_PRIVATEDATA_NAME, &cred->privateData);
847             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding PrivateData Tag.");
848         }
849
850         //Period -- Not Mandatory
851         if(cred->period)
852         {
853             cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_PERIOD_NAME,
854                 strlen(OIC_JSON_PERIOD_NAME));
855             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Period Name Tag.");
856             cborEncoderResult = cbor_encode_text_string(&credMap, cred->period,
857                 strlen(cred->period));
858             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding Period Name Value.");
859         }
860
861 #ifdef MULTIPLE_OWNER
862         // Eownerid -- Not Mandatory
863         if(cred->eownerID)
864         {
865             char *eowner = NULL;
866             cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_EOWNERID_NAME,
867                 strlen(OIC_JSON_EOWNERID_NAME));
868             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding eownerId Name Tag.");
869             ret = ConvertUuidToStr(cred->eownerID, &eowner);
870             VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
871             cborEncoderResult = cbor_encode_text_string(&credMap, eowner, strlen(eowner));
872             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Addding eownerId Value.");
873             OICFree(eowner);
874         }
875 #endif //MULTIPLE_OWNER
876
877         cborEncoderResult = cbor_encoder_close_container(&credArray, &credMap);
878         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Closing Cred Map.");
879
880         cred = cred->next;
881     }
882     cborEncoderResult = cbor_encoder_close_container(&credRootMap, &credArray);
883     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Closing Cred Array.");
884
885     cred = credS;
886
887     // Rownerid
888     {
889         char *rowner = NULL;
890         cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_ROWNERID_NAME,
891             strlen(OIC_JSON_ROWNERID_NAME));
892         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding rownerid Name.");
893         ret = ConvertUuidToStr(&gRownerId, &rowner);
894         VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
895         cborEncoderResult = cbor_encode_text_string(&credRootMap, rowner, strlen(rowner));
896         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Addding rownerid Value.");
897         OICFree(rowner);
898     }
899
900     {
901         //RT -- Mandatory
902         CborEncoder rtArray;
903         cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_RT_NAME,
904                 strlen(OIC_JSON_RT_NAME));
905         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Addding RT Name Tag.");
906         cborEncoderResult = cbor_encoder_create_array(&credRootMap, &rtArray, 1);
907         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Addding RT Value.");
908         for (size_t i = 0; i < 1; i++)
909         {
910             cborEncoderResult = cbor_encode_text_string(&rtArray, OIC_RSRC_TYPE_SEC_CRED,
911                     strlen(OIC_RSRC_TYPE_SEC_CRED));
912             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding RT Value.");
913         }
914         cborEncoderResult = cbor_encoder_close_container(&credRootMap, &rtArray);
915         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Closing RT.");
916
917         //IF-- Mandatory
918         CborEncoder ifArray;
919         cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_IF_NAME,
920                  strlen(OIC_JSON_IF_NAME));
921         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Addding IF Name Tag.");
922         cborEncoderResult = cbor_encoder_create_array(&credRootMap, &ifArray, 1);
923         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Addding IF Value.");
924         for (size_t i = 0; i < 1; i++)
925         {
926             cborEncoderResult = cbor_encode_text_string(&ifArray, OC_RSRVD_INTERFACE_DEFAULT,
927                     strlen(OC_RSRVD_INTERFACE_DEFAULT));
928             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Adding IF Value.");
929         }
930         cborEncoderResult = cbor_encoder_close_container(&credRootMap, &ifArray);
931         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Closing IF.");
932     }
933
934     // Close CRED Root Map
935     cborEncoderResult = cbor_encoder_close_container(&encoder, &credRootMap);
936     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborEncoderResult, "Failed Closing CRED Root Map.");
937
938     if (CborNoError == cborEncoderResult)
939     {
940         OIC_LOG(DEBUG, TAG, "CredToCBORPayload Successed");
941         *cborPayload = outPayload;
942         *cborSize = cbor_encoder_get_buffer_size(&encoder, outPayload);
943         ret = OC_STACK_OK;
944     }
945     OIC_LOG(DEBUG, TAG, "CredToCBORPayload OUT");
946 exit:
947     if (CborErrorOutOfMemory == cborEncoderResult)
948     {
949         OIC_LOG(DEBUG, TAG, "CredToCBORPayload:CborErrorOutOfMemory : retry with more memory");
950         // reallocate and try again!
951         OICFree(outPayload);
952         // Since the allocated initial memory failed, double the memory.
953         cborLen += cbor_encoder_get_buffer_size(&encoder, encoder.end);
954         cborEncoderResult = CborNoError;
955         ret = CredToCBORPayload(credS, cborPayload, &cborLen, secureFlag);
956         *cborSize = cborLen;
957     }
958
959     if (CborNoError != cborEncoderResult)
960     {
961         OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
962         OICFree(outPayload);
963         outPayload = NULL;
964         *cborSize = 0;
965         *cborPayload = NULL;
966         ret = OC_STACK_ERROR;
967     }
968
969     OIC_LOG_V(DEBUG, TAG, "OUT %s:", __func__);
970
971     return ret;
972 }
973
974 OCStackResult CBORPayloadToCred(const uint8_t *cborPayload, size_t size,
975                                 OicSecCred_t **secCred, OicUuid_t **rownerid)
976 {
977     if (NULL == cborPayload || NULL == secCred || NULL != *secCred || 0 == size)
978     {
979         return OC_STACK_INVALID_PARAM;
980     }
981
982     char* tagName = NULL;
983     char* roleIdTagName = NULL;
984     char* name = NULL;
985     OCStackResult ret = OC_STACK_ERROR;
986     CborValue credCbor = { .parser = NULL };
987     CborParser parser = { .end = NULL };
988     CborError cborFindResult = CborNoError;
989     cbor_parser_init(cborPayload, size, 0, &parser, &credCbor);
990
991     if (!cbor_value_is_container(&credCbor))
992     {
993         return OC_STACK_ERROR;
994     }
995
996     OicSecCred_t *headCred = NULL;
997
998     // Enter CRED Root Map
999     CborValue CredRootMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
1000     cborFindResult = cbor_value_enter_container(&credCbor, &CredRootMap);
1001     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Entering CRED Root Map.");
1002
1003     headCred = (OicSecCred_t *) OICCalloc(1, sizeof(OicSecCred_t));
1004     VERIFY_NOT_NULL(TAG, headCred, ERROR);
1005
1006     while (cbor_value_is_valid(&CredRootMap))
1007     {
1008         size_t len = 0;
1009         CborType type = cbor_value_get_type(&CredRootMap);
1010         if (type == CborTextStringType && cbor_value_is_text_string(&CredRootMap))
1011         {
1012             cborFindResult = cbor_value_dup_text_string(&CredRootMap, &tagName, &len, NULL);
1013             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding Name in CRED Root Map.");
1014             cborFindResult = cbor_value_advance(&CredRootMap);
1015             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Advancing Value in CRED Root Map.");
1016         }
1017         if(tagName)
1018         {
1019             if (strcmp(tagName, OIC_JSON_CREDS_NAME)  == 0)
1020             {
1021                 // Enter CREDS Array
1022                 size_t tempLen = 0;
1023                 int credCount = 0;
1024                 CborValue credArray = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
1025                 cborFindResult = cbor_value_enter_container(&CredRootMap, &credArray);
1026                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding Cred Array.");
1027
1028                 while (cbor_value_is_valid(&credArray))
1029                 {
1030                     credCount++;
1031                     //CredId -- Mandatory
1032                     CborValue credMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
1033                     cborFindResult = cbor_value_enter_container(&credArray, &credMap);
1034                     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding Cred Map.");
1035                     OicSecCred_t *cred = NULL;
1036
1037                     if(1 == credCount)
1038                     {
1039                         cred = headCred;
1040                     }
1041                     else
1042                     {
1043                         cred = (OicSecCred_t *) OICCalloc(1, sizeof(OicSecCred_t));
1044                         VERIFY_NOT_NULL(TAG, cred, ERROR);
1045                         OicSecCred_t *temp = headCred;
1046                         while (temp->next)
1047                         {
1048                             temp = temp->next;
1049                         }
1050                         temp->next = cred;
1051                     }
1052
1053                     while(cbor_value_is_valid(&credMap) && cbor_value_is_text_string(&credMap))
1054                     {
1055                         CborType cmType = cbor_value_get_type(&credMap);
1056                         if (cmType == CborTextStringType)
1057                         {
1058                             cborFindResult = cbor_value_dup_text_string(&credMap, &name, &tempLen, NULL);
1059                             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding Name in CRED Map.");
1060                             cborFindResult = cbor_value_advance(&credMap);
1061                             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Advancing Value in CRED Map.");
1062                         }
1063                         if(name)
1064                         {
1065                             //credid
1066                             if (strcmp(name, OIC_JSON_CREDID_NAME)  == 0)
1067                             {
1068                                 uint64_t credId = 0;
1069                                 cborFindResult = cbor_value_get_uint64(&credMap, &credId);
1070                                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding CredId.");
1071                                 cred->credId = (uint16_t)credId;
1072                             }
1073                             // subjectid
1074                             if (strcmp(name, OIC_JSON_SUBJECTID_NAME)  == 0)
1075                             {
1076                                 char *subjectid = NULL;
1077                                 cborFindResult = cbor_value_dup_text_string(&credMap, &subjectid, &tempLen, NULL);
1078                                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding subjectid Value.");
1079                                 if(strcmp(subjectid, WILDCARD_RESOURCE_URI) == 0)
1080                                 {
1081                                     cred->subject.id[0] = '*';
1082                                 }
1083                                 else
1084                                 {
1085                                     ret = ConvertStrToUuid(subjectid, &cred->subject);
1086                                     VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
1087                                 }
1088                                 //Because cbor using malloc directly
1089                                 //It is required to use free() instead of OICFree
1090                                 free(subjectid);
1091                             }
1092                             // roleid
1093                             if (strcmp(name, OIC_JSON_ROLEID_NAME) == 0)
1094                             {
1095                                 /* Role subject */
1096                                 size_t unusedLen = 0;
1097                                 CborValue roleIdMap;
1098                                 memset(&roleIdMap, 0, sizeof(roleIdMap));
1099
1100                                 cborFindResult = cbor_value_enter_container(&credMap, &roleIdMap);
1101                                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed entering role ID map");
1102
1103                                 while (cbor_value_is_valid(&roleIdMap) && cbor_value_is_text_string(&roleIdMap))
1104                                 {
1105                                     cborFindResult = cbor_value_dup_text_string(&roleIdMap, &roleIdTagName, &unusedLen, NULL);
1106                                     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed getting role ID map tag name");
1107                                     cborFindResult = cbor_value_advance(&roleIdMap);
1108                                     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed advancing role ID map");
1109
1110                                     if (NULL != roleIdTagName)
1111                                     {
1112                                         if (strcmp(roleIdTagName, OIC_JSON_ROLE_NAME) == 0)
1113                                         {
1114                                             char *roleId = NULL;
1115                                             cborFindResult = cbor_value_dup_text_string(&roleIdMap, &roleId, &unusedLen, NULL);
1116                                             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed getting role id value");
1117                                             if (strlen(roleId) >= sizeof(cred->roleId.id))
1118                                             {
1119                                                 cborFindResult = CborUnknownError;
1120                                                 free(roleId);
1121                                                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Role ID is too long");
1122                                             }
1123                                             OICStrcpy(cred->roleId.id, sizeof(cred->roleId.id), roleId);
1124                                             free(roleId);
1125                                         }
1126                                         else if (strcmp(roleIdTagName, OIC_JSON_AUTHORITY_NAME) == 0)
1127                                         {
1128                                             char *authorityName = NULL;
1129                                             cborFindResult = cbor_value_dup_text_string(&roleIdMap, &authorityName, &unusedLen, NULL);
1130                                             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed getting role authority value");
1131                                             if (strlen(authorityName) >= sizeof(cred->roleId.authority))
1132                                             {
1133                                                 cborFindResult = CborUnknownError;
1134                                                 free(authorityName);
1135                                                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Authority name is too long");
1136                                             }
1137                                             OICStrcpy(cred->roleId.authority, sizeof(cred->roleId.authority), authorityName);
1138                                             free(authorityName);
1139                                         }
1140                                         else
1141                                         {
1142                                             OIC_LOG_V(WARNING, TAG, "Unknown tag name in role ID map: %s", roleIdTagName);
1143                                         }
1144
1145                                         free(roleIdTagName);
1146                                         roleIdTagName = NULL;
1147                                     }
1148
1149                                     if (cbor_value_is_valid(&roleIdMap))
1150                                     {
1151                                         cborFindResult = cbor_value_advance(&roleIdMap);
1152                                         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed advancing role map");
1153                                     }
1154                                 }
1155
1156                                 /* Make sure at least the id is present. */
1157                                 if ('\0' == cred->roleId.id[0])
1158                                 {
1159                                     cborFindResult = CborUnknownError;
1160                                     VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "ID for role was not present in role map");
1161                                 }
1162                             }
1163                             // credtype
1164                             if (strcmp(name, OIC_JSON_CREDTYPE_NAME)  == 0)
1165                             {
1166                                 uint64_t credType = 0;
1167                                 cborFindResult = cbor_value_get_uint64(&credMap, &credType);
1168                                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding CredType.");
1169                                 cred->credType = (OicSecCredType_t)credType;
1170                             }
1171                             // privatedata
1172                             if (strcmp(name, OIC_JSON_PRIVATEDATA_NAME)  == 0)
1173                             {
1174                                 cborFindResult = DeserializeEncodingFromCbor(&credMap, &cred->privateData);
1175                                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to read privateData structure");
1176                             }
1177 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1178                             //PublicData -- Not Mandatory
1179                             if (strcmp(name, OIC_JSON_PUBLICDATA_NAME)  == 0)
1180                             {
1181                                 cborFindResult = DeserializeEncodingFromCbor(&credMap, &cred->publicData);
1182                                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to read publicData structure");
1183                             }
1184                             //OptionalData -- Not Mandatory
1185                             if (strcmp(name, OIC_JSON_OPTDATA_NAME)  == 0)
1186                             {
1187                                 cborFindResult = DeserializeSecOptFromCbor(&credMap, &cred->optionalData);
1188                                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed to read optionalData structure");
1189                             }
1190                             //Credusage -- Not Mandatory
1191                             if (0 == strcmp(OIC_JSON_CREDUSAGE_NAME, name))
1192                             {
1193                                 cborFindResult = cbor_value_dup_text_string(&credMap, &cred->credUsage, &tempLen, NULL);
1194                                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding Period.");
1195                             }
1196 #endif  //__WITH_DTLS__ ||  __WITH_TLS__
1197
1198                             if (0 == strcmp(OIC_JSON_PERIOD_NAME, name))
1199                             {
1200                                 cborFindResult = cbor_value_dup_text_string(&credMap, &cred->period, &tempLen, NULL);
1201                                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding Period.");
1202                             }
1203
1204 #ifdef MULTIPLE_OWNER
1205                             // Eowner uuid -- Not Mandatory
1206                             if (strcmp(OIC_JSON_EOWNERID_NAME, name)  == 0 && cbor_value_is_text_string(&credMap))
1207                             {
1208                                 char *eowner = NULL;
1209                                 cborFindResult = cbor_value_dup_text_string(&credMap, &eowner, &tempLen, NULL);
1210                                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding eownerId Value.");
1211                                 if(NULL == cred->eownerID)
1212                                 {
1213                                     cred->eownerID = (OicUuid_t*)OICCalloc(1, sizeof(OicUuid_t));
1214                                     VERIFY_NOT_NULL(TAG, cred->eownerID, ERROR);
1215                                 }
1216                                 ret = ConvertStrToUuid(eowner, cred->eownerID);
1217                                 //Because cbor using malloc directly
1218                                 //It is required to use free() instead of OICFree
1219                                 free(eowner);
1220                                 VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
1221                             }
1222 #endif //MULTIPLE_OWNER
1223
1224                             if (cbor_value_is_valid(&credMap))
1225                             {
1226                                 cborFindResult = cbor_value_advance(&credMap);
1227                                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Advancing CRED Map.");
1228                             }
1229                             //Because cbor using malloc directly
1230                             //It is required to use free() instead of OICFree
1231                             free(name);
1232                             name = NULL;
1233                         }
1234                     }
1235                     cred->next = NULL;
1236                     if (cbor_value_is_valid(&credArray))
1237                     {
1238                         cborFindResult = cbor_value_advance(&credArray);
1239                         VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Advancing CRED Array.");
1240                     }
1241                 }
1242             }
1243
1244             //ROwner -- Mandatory
1245             if (strcmp(tagName, OIC_JSON_ROWNERID_NAME)  == 0 && cbor_value_is_text_string(&CredRootMap))
1246             {
1247                 char *stRowner = NULL;
1248                 cborFindResult = cbor_value_dup_text_string(&CredRootMap, &stRowner, &len, NULL);
1249                 VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Finding Rownerid Value.");
1250                 *rownerid = (OicUuid_t *) OICCalloc(1, sizeof(OicUuid_t));
1251                 VERIFY_NOT_NULL(TAG, *rownerid, ERROR);
1252                 ret = ConvertStrToUuid(stRowner, *rownerid);
1253                 //Because cbor using malloc directly
1254                 //It is required to use free() instead of OICFree
1255                 free(stRowner);
1256                 VERIFY_SUCCESS(TAG, (ret == OC_STACK_OK), ERROR);
1257             }
1258             //Because cbor using malloc directly
1259             //It is required to use free() instead of OICFree
1260             free(tagName);
1261             tagName = NULL;
1262         }
1263         if (cbor_value_is_valid(&CredRootMap))
1264         {
1265             cborFindResult = cbor_value_advance(&CredRootMap);
1266             VERIFY_CBOR_SUCCESS_OR_OUT_OF_MEMORY(TAG, cborFindResult, "Failed Advancing CRED Root Map.");
1267         }
1268     }
1269
1270     *secCred = headCred;
1271     ret = OC_STACK_OK;
1272
1273 exit:
1274     if (CborNoError != cborFindResult)
1275     {
1276         DeleteCredList(headCred);
1277         headCred = NULL;
1278         *secCred = NULL;
1279         ret = OC_STACK_ERROR;
1280     }
1281
1282     free(tagName);
1283     free(roleIdTagName);
1284     free(name);
1285
1286     return ret;
1287 }
1288
1289 #ifdef MULTIPLE_OWNER
1290 bool IsValidCredentialAccessForSubOwner(const OicUuid_t* uuid, const uint8_t *cborPayload, size_t size)
1291 {
1292     OicSecCred_t* cred = NULL;
1293     bool isValidCred = false;
1294     OicUuid_t *rownerId = NULL;
1295
1296     OIC_LOG_BUFFER(DEBUG, TAG, cborPayload, size);
1297
1298     VERIFY_NOT_NULL(TAG, uuid, ERROR);
1299     VERIFY_NOT_NULL(TAG, cborPayload, ERROR);
1300     VERIFY_SUCCESS(TAG, 0 != size, ERROR);
1301     VERIFY_SUCCESS(TAG, OC_STACK_OK == CBORPayloadToCred(cborPayload, size, &cred, &rownerId), ERROR);
1302     VERIFY_NOT_NULL(TAG, cred, ERROR);
1303     VERIFY_NOT_NULL(TAG, cred->eownerID, ERROR);
1304     VERIFY_NOT_NULL(TAG, rownerId, ERROR);
1305     VERIFY_SUCCESS(TAG, (memcmp(cred->eownerID->id, uuid->id, sizeof(uuid->id)) == 0), ERROR);
1306
1307     isValidCred = true;
1308
1309 exit:
1310     OICFree(rownerId);
1311     DeleteCredList(cred);
1312
1313     return isValidCred;
1314
1315 }
1316 #endif //MULTIPLE_OWNER
1317
1318 OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t credType,
1319                                   const OicSecKey_t * publicData, const OicSecKey_t* privateData,
1320                                   const OicUuid_t * eownerID)
1321 {
1322     OIC_LOG(DEBUG, TAG, "IN GenerateCredential");
1323
1324     (void)publicData;
1325     OCStackResult ret = OC_STACK_ERROR;
1326
1327     OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
1328     VERIFY_NOT_NULL(TAG, cred, ERROR);
1329     cred->next = NULL;
1330
1331     //CredId is assigned before appending new cred to the existing
1332     //credential list and updating svr database in AddCredential().
1333     cred->credId = 0;
1334
1335     VERIFY_NOT_NULL(TAG, subject, ERROR);
1336     memcpy(cred->subject.id, subject->id , sizeof(cred->subject.id));
1337
1338     VERIFY_SUCCESS(TAG, credType < (NO_SECURITY_MODE | SYMMETRIC_PAIR_WISE_KEY |
1339             SYMMETRIC_GROUP_KEY | ASYMMETRIC_KEY | SIGNED_ASYMMETRIC_KEY | PIN_PASSWORD), ERROR);
1340     cred->credType = credType;
1341
1342 #ifdef __WITH_DTLS__
1343     if (publicData && publicData->data)
1344     {
1345         cred->publicData.data = (uint8_t *)OICCalloc(1, publicData->len);
1346         VERIFY_NOT_NULL(TAG, cred->publicData.data, ERROR);
1347         memcpy(cred->publicData.data, publicData->data, publicData->len);
1348         cred->publicData.len = publicData->len;
1349         cred->publicData.encoding = publicData->encoding;
1350     }
1351 #endif // __WITH_DTLS__
1352
1353     if (privateData && privateData->data)
1354     {
1355         cred->privateData.data = (uint8_t *)OICCalloc(1, privateData->len);
1356         VERIFY_NOT_NULL(TAG, cred->privateData.data, ERROR);
1357         memcpy(cred->privateData.data, privateData->data, privateData->len);
1358         cred->privateData.len = privateData->len;
1359         cred->privateData.encoding = privateData->encoding;
1360     }
1361
1362 #ifdef MULTIPLE_OWNER
1363     if(eownerID)
1364     {
1365         cred->eownerID = (OicUuid_t*)OICCalloc(1, sizeof(OicUuid_t));
1366         VERIFY_NOT_NULL(TAG, cred->eownerID, ERROR);
1367         memcpy(cred->eownerID->id, eownerID->id, sizeof(eownerID->id));
1368     }
1369 #else
1370     (void)(eownerID);
1371 #endif //MULTIPLE_OWNER_
1372
1373     ret = OC_STACK_OK;
1374
1375     OIC_LOG_V(DEBUG, TAG, "GenerateCredential : result: %d", ret);
1376     OIC_LOG_V(DEBUG, TAG, "GenerateCredential : credId: %d", cred->credId);
1377     OIC_LOG_V(DEBUG, TAG, "GenerateCredential : credType: %d", cred->credType);
1378     OIC_LOG_BUFFER(DEBUG, TAG, cred->subject.id, sizeof(cred->subject.id));
1379     if (cred->privateData.data)
1380     {
1381         OIC_LOG_V(DEBUG, TAG, "GenerateCredential : privateData len: %"PRIuPTR, cred->privateData.len);
1382         OIC_LOG_BUFFER(DEBUG, TAG, cred->privateData.data, cred->privateData.len);
1383     }
1384 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1385     if(cred->credUsage)
1386     {
1387         OIC_LOG_V(DEBUG, TAG, "GenerateCredential : credUsage: %s", cred->credUsage);
1388     }
1389     if (cred->publicData.data)
1390     {
1391         OIC_LOG_V(DEBUG, TAG, "GenerateCredential : publicData len: %" PRIuPTR, cred->publicData.len);
1392         OIC_LOG_BUFFER(DEBUG, TAG, cred->publicData.data, cred->publicData.len);
1393
1394     }
1395     if (cred->optionalData.data)
1396     {
1397         OIC_LOG_V(DEBUG, TAG, "GenerateCredential : optionalData len: %" PRIuPTR, cred->optionalData.len);
1398         OIC_LOG_BUFFER(DEBUG, TAG, cred->optionalData.data, cred->optionalData.len);
1399         OIC_LOG_V(DEBUG, TAG, "GenerateCredential : optionalData revstat: %d", cred->optionalData.revstat);
1400     }
1401 #endif //defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1402
1403 exit:
1404     if (OC_STACK_OK != ret)
1405     {
1406         DeleteCredList(cred);
1407         cred = NULL;
1408     }
1409     OIC_LOG(DEBUG, TAG, "OUT GenerateCredential");
1410     return cred;
1411 }
1412
1413 #ifdef HAVE_WINDOWS_H
1414 /* Helper for UpdatePersistentStorage. */
1415 static OCStackResult CopyPayload(uint8_t **payload, size_t *payloadSize, const DATA_BLOB *source)
1416 {
1417     OCStackResult res = OC_STACK_OK;
1418
1419     if (source->cbData > *payloadSize)
1420     {
1421         /* Need more memory to copy encrypted payload out. */
1422         OICClearMemory(*payload, *payloadSize);
1423         OICFree(*payload);
1424         *payload = OICMalloc(source->cbData);
1425
1426         if (NULL == *payload)
1427         {
1428             OIC_LOG_V(ERROR, TAG, "Failed to OICMalloc for encrypted payload: %u", GetLastError());
1429             res = OC_STACK_NO_MEMORY;
1430         }
1431     }
1432     else if (source->cbData < *payloadSize)
1433     {
1434         /* Zero portion of payload we won't overwrite with the encrypted version. The
1435          * later call to OICClearMemory won't cover this part of the buffer.
1436          */
1437         OICClearMemory(*payload + source->cbData, *payloadSize - source->cbData);
1438     }
1439
1440     if (OC_STACK_OK == res)
1441     {
1442         memcpy(*payload, source->pbData, source->cbData);
1443         *payloadSize = source->cbData;
1444     }
1445
1446     return res;
1447 }
1448 #endif
1449
1450 static bool UpdatePersistentStorage(const OicSecCred_t *cred)
1451 {
1452     bool ret = false;
1453     OIC_LOG(DEBUG, TAG, "IN Cred UpdatePersistentStorage");
1454
1455     // Convert Cred data into JSON for update to persistent storage
1456     if (cred)
1457     {
1458         uint8_t *payload = NULL;
1459         // This added '512' is arbitrary value that is added to cover the name of the resource, map addition and ending
1460         size_t size = GetCredKeyDataSize(cred);
1461         size += (512 * OicSecCredCount(cred));
1462         OIC_LOG_V(DEBUG, TAG, "cred size: %zu", size);
1463
1464         int secureFlag = 0;
1465         OCStackResult res = CredToCBORPayload(cred, &payload, &size, secureFlag);
1466 #ifdef HAVE_WINDOWS_H
1467         /* On Windows, keep the credential resource encrypted on disk to protect symmetric and private keys. Only the
1468          * current user on this system will be able to decrypt it later, to help prevent credential theft.
1469          */
1470         DWORD dwordSize;
1471
1472         if (FAILED(SizeTToDWord(size, &dwordSize)))
1473         {
1474             OIC_LOG(DEBUG, TAG, "Cred size too large.");
1475             res = OC_STACK_ERROR;
1476             ret = false;
1477         }
1478
1479         if ((OC_STACK_OK == res) && payload)
1480         {
1481             DATA_BLOB decryptedPayload;
1482             DATA_BLOB encryptedPayload;
1483             memset(&decryptedPayload, 0, sizeof(decryptedPayload));
1484             memset(&encryptedPayload, 0, sizeof(encryptedPayload));
1485             decryptedPayload.cbData = dwordSize;
1486             decryptedPayload.pbData = payload;
1487
1488             if (CryptProtectData(
1489                 &decryptedPayload,
1490                 NULL,
1491                 NULL,
1492                 NULL,
1493                 NULL,
1494                 CRYPTPROTECT_UI_FORBIDDEN,
1495                 &encryptedPayload))
1496             {
1497                 res = CopyPayload(&payload, &size, &encryptedPayload);
1498                 ret = (OC_STACK_OK == res);
1499
1500                 /* For the returned data from CryptProtectData, LocalFree must be used to free. Don't use OICFree. */
1501                 if (NULL != LocalFree(encryptedPayload.pbData))
1502                 {
1503                     OIC_LOG_V(ERROR, TAG, "LocalFree failed on output from CryptProtectData; memory may be corrupted or leaked. Last error: %u.", GetLastError());
1504                     assert(!"LocalFree failed");
1505                 }
1506             }
1507             else
1508             {
1509                 OIC_LOG_V(ERROR, TAG, "Failed to CryptProtectData cred resource: %u", GetLastError());
1510                 res = OC_STACK_ERROR;
1511                 ret = false;
1512             }
1513         }
1514 #endif
1515
1516         if ((OC_STACK_OK == res) && payload)
1517         {
1518             if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, payload, size))
1519             {
1520                 ret = true;
1521             }
1522         }
1523
1524         OICClearMemory(payload, size);
1525         OICFree(payload);
1526     }
1527     else //Empty cred list
1528     {
1529         if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, NULL, 0))
1530         {
1531             ret = true;
1532         }
1533     }
1534
1535     OIC_LOG(DEBUG, TAG, "OUT Cred UpdatePersistentStorage");
1536
1537     logCredMetadata();
1538
1539     return ret;
1540 }
1541
1542 /**
1543  * Compare function used LL_SORT for sorting credentials.
1544  *
1545  * @param first pointer to OicSecCred_t struct.
1546  * @param second  pointer to OicSecCred_t struct.
1547  *
1548  *@return -1, if credId of first is less than credId of second.
1549  * 0, if credId of first is equal to credId of second.
1550  * 1, if credId of first is greater than credId of second.
1551  */
1552 static int CmpCredId(const OicSecCred_t * first, const OicSecCred_t *second)
1553 {
1554     if (first->credId < second->credId)
1555     {
1556         return -1;
1557     }
1558     else if (first->credId > second->credId)
1559     {
1560         return 1;
1561     }
1562     else
1563         return 0;
1564 }
1565
1566 /**
1567  * GetCredId goes through the cred list and returns the next
1568  * available credId. The next credId could be the credId that is
1569  * available due deletion of OicSecCred_t object or one more than
1570  * credId of last credential in the list.
1571  *
1572  * @return next available credId if successful, else 0 for error.
1573  */
1574 static uint16_t GetCredId()
1575 {
1576     //Sorts credential list in incremental order of credId
1577     /** @todo: Remove pragma for VS2013 warning; Investigate fixing LL_SORT macro */
1578 #ifdef _MSC_VER
1579 #pragma warning(suppress:4133)
1580     LL_SORT(gCred, CmpCredId);
1581 #else
1582     LL_SORT(gCred, CmpCredId);
1583 #endif
1584
1585     OicSecCred_t *currentCred = NULL, *credTmp = NULL;
1586     uint16_t nextCredId = 1;
1587
1588     LL_FOREACH_SAFE(gCred, currentCred, credTmp)
1589     {
1590         if (currentCred->credId == nextCredId)
1591         {
1592             nextCredId += 1;
1593         }
1594         else
1595         {
1596             break;
1597         }
1598     }
1599
1600     VERIFY_SUCCESS(TAG, nextCredId < UINT16_MAX, ERROR);
1601     return nextCredId;
1602
1603 exit:
1604     return 0;
1605 }
1606
1607 /**
1608  * Get the default value.
1609  *
1610  * @return  NULL for now.
1611  */
1612 static OicSecCred_t* GetCredDefault()
1613 {
1614     // TODO:Update it when we finalize the default info.
1615     return NULL;
1616 }
1617
1618 bool IsSameSecOpt(const OicSecOpt_t* sk1, const OicSecOpt_t* sk2)
1619 {
1620     VERIFY_NOT_NULL(TAG, sk1, WARNING);
1621     VERIFY_NOT_NULL(TAG, sk2, WARNING);
1622
1623     VERIFY_SUCCESS(TAG, (sk1->len == sk2->len), INFO);
1624     VERIFY_SUCCESS(TAG, (sk1->encoding == sk2->encoding), INFO);
1625     VERIFY_SUCCESS(TAG, (0 == memcmp(sk1->data, sk2->data, sk1->len)), INFO);
1626     return true;
1627 exit:
1628     return false;
1629 }
1630
1631 bool IsSameSecKey(const OicSecKey_t* sk1, const OicSecKey_t* sk2)
1632 {
1633     VERIFY_NOT_NULL(TAG, sk1, WARNING);
1634     VERIFY_NOT_NULL(TAG, sk2, WARNING);
1635
1636     VERIFY_SUCCESS(TAG, (sk1->len == sk2->len), INFO);
1637     VERIFY_SUCCESS(TAG, (sk1->encoding == sk2->encoding), INFO);
1638     VERIFY_SUCCESS(TAG, (0 == memcmp(sk1->data, sk2->data, sk1->len)), INFO);
1639     return true;
1640 exit:
1641     return false;
1642 }
1643
1644 #if ((defined(__WITH_DTLS__) || defined(__WITH_TLS__)) && defined(MULTIPLE_OWNER))
1645 static bool IsNewPreconfigPinCredential(OicSecCred_t * oldCred, OicSecCred_t * newCred)
1646 {
1647     if (oldCred->credUsage &&
1648         newCred->credUsage &&
1649         (0 == strcmp(PRECONFIG_PIN_CRED, oldCred->credUsage)) &&
1650         (0 == strcmp(PRECONFIG_PIN_CRED, newCred->credUsage)))
1651     {
1652         return true;
1653     }
1654
1655     return false;
1656 }
1657 #endif //(__WITH_DTLS__ or __WITH_TLS__) and MULTIPLE_OWNER
1658
1659 OCStackResult AddCredential(OicSecCred_t * newCred)
1660 {
1661     OCStackResult result = OC_STACK_ERROR;
1662
1663     OicSecCred_t* cred = NULL;
1664     OicSecCred_t* tempCred = NULL;
1665
1666     bool found = false;
1667
1668     OicSecDostype_t dos;
1669
1670     VERIFY_SUCCESS(TAG, OC_STACK_OK == GetDos(&dos), ERROR);
1671     if ((DOS_RESET == dos.state) ||
1672         (DOS_RFNOP == dos.state))
1673     {
1674         OIC_LOG_V(WARNING, TAG, "%s /cred resource is read-only in RESET and RFNOP.", __func__);
1675     }
1676
1677     //leave IOT-1936 fix for preconfig pin
1678 #if ((defined(__WITH_DTLS__) || defined(__WITH_TLS__)) && defined(MULTIPLE_OWNER))
1679     LL_FOREACH_SAFE(gCred, cred, tempCred)
1680     {
1681         if (IsNewPreconfigPinCredential(cred, newCred))
1682         {
1683             //devices can only have one Preconfigured Pin credential at any given time. Check
1684             //if the new credential is an update to an existing Preconfigured Pin credential
1685             //if so, just update existing one.
1686
1687             //save old credid so act like an update
1688             newCred->credId = cred->credId;
1689
1690             LL_DELETE(gCred, cred);
1691             LL_PREPEND(gCred, newCred);
1692
1693             FreeCred(cred);
1694             found = true;
1695             break;
1696         }
1697     }
1698 #endif //(__WITH_DTLS__ or __WITH_TLS__) and MULTIPLE_OWNER
1699
1700     if (found)
1701     {
1702         goto saveToDB;
1703     }
1704
1705     if (newCred->credId != 0)
1706     {
1707         //check if cred with such cred id exists
1708         LL_FOREACH_SAFE(gCred, cred, tempCred)
1709         {
1710             if (cred->credId == newCred->credId)
1711             {
1712                 //remove old cred with same cred id
1713                 LL_DELETE(gCred, cred);
1714                 FreeCred(cred);
1715                 break;
1716             }
1717         }
1718     }
1719     else
1720     {
1721         newCred->credId = GetCredId();
1722     }
1723
1724     OIC_LOG(DEBUG, TAG, "Adding New Cred");
1725     LL_APPEND(gCred, newCred);
1726
1727 saveToDB:
1728     if (UpdatePersistentStorage(gCred))
1729     {
1730         result = OC_STACK_OK;
1731     }
1732 exit:
1733     return result;
1734 }
1735
1736 OCStackResult RemoveCredential(const OicUuid_t *subject)
1737 {
1738     OCStackResult ret = OC_STACK_ERROR;
1739     OicSecCred_t *cred = NULL;
1740     OicSecCred_t *tempCred = NULL;
1741     bool deleteFlag = false;
1742
1743     LL_FOREACH_SAFE(gCred, cred, tempCred)
1744     {
1745         if (memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
1746         {
1747             LL_DELETE(gCred, cred);
1748             FreeCred(cred);
1749             deleteFlag = 1;
1750         }
1751     }
1752
1753     if (deleteFlag)
1754     {
1755         if (UpdatePersistentStorage(gCred))
1756         {
1757             ret = OC_STACK_RESOURCE_DELETED;
1758         }
1759     }
1760     return ret;
1761 }
1762
1763 OCStackResult RemoveCredentialByCredId(uint16_t credId)
1764 {
1765     OCStackResult ret = OC_STACK_ERROR;
1766     OicSecCred_t *cred = NULL;
1767     OicSecCred_t *tempCred = NULL;
1768     bool deleteFlag = false;
1769
1770     OIC_LOG(INFO, TAG, "IN RemoveCredentialByCredId");
1771
1772     if ( 0 == credId)
1773     {
1774         return OC_STACK_INVALID_PARAM;
1775     }
1776
1777
1778     LL_FOREACH_SAFE(gCred, cred, tempCred)
1779     {
1780         if (cred->credId == credId)
1781         {
1782             OIC_LOG_V(DEBUG, TAG, "Credential(ID=%d) will be removed.", credId);
1783
1784             LL_DELETE(gCred, cred);
1785             FreeCred(cred);
1786             deleteFlag = true;
1787         }
1788     }
1789
1790     if (deleteFlag)
1791     {
1792         if (UpdatePersistentStorage(gCred))
1793         {
1794             ret = OC_STACK_RESOURCE_DELETED;
1795         }
1796     }
1797     OIC_LOG(INFO, TAG, "OUT RemoveCredentialByCredId");
1798
1799     return ret;
1800 }
1801
1802 /**
1803  * This method removes cred's corresponding to given list of credid's from the Cred
1804  *
1805  * @param credid's of the Cred
1806  *
1807  * @return
1808  *     ::OC_STACK_RESOURCE_DELETED on success
1809  *     ::OC_STACK_NO_RESOURCE on failure to find the appropriate Cred
1810  *     ::OC_STACK_INVALID_PARAM on invalid parameter
1811  */
1812 static OCStackResult RemoveCredentialByCredIds(CredIdList_t *credIdList)
1813 {
1814     OCStackResult ret = OC_STACK_ERROR;
1815     OicSecCred_t *cred = NULL;
1816     OicSecCred_t *tempCred = NULL;
1817     CredIdList_t *credIdElem = NULL;
1818     bool deleteFlag = false;
1819
1820     OIC_LOG(INFO, TAG, "IN RemoveCredentialByCredIds");
1821
1822     LL_FOREACH(credIdList, credIdElem)
1823     {
1824         LL_FOREACH_SAFE(gCred, cred, tempCred)
1825         {
1826             if (cred->credId == credIdElem->credId)
1827             {
1828                 OIC_LOG_V(DEBUG, TAG, "Credential(ID=%d) will be removed.", cred->credId);
1829
1830                 LL_DELETE(gCred, cred);
1831                 FreeCred(cred);
1832                 deleteFlag = true;
1833                 //TODO: add break when cred's will have unique credid (during IOT-2464 fix)
1834             }
1835         }
1836     }
1837
1838     if (deleteFlag)
1839     {
1840         if (UpdatePersistentStorage(gCred))
1841         {
1842             ret = OC_STACK_RESOURCE_DELETED;
1843         }
1844     }
1845     OIC_LOG(INFO, TAG, "OUT RemoveCredentialByCredIds");
1846
1847     return ret;
1848 }
1849
1850 /**
1851  * This method parses the query string received for REST requests and
1852  * retrieves the 'credid' field.
1853  *
1854  * @param query querystring passed in REST request
1855  * @param credid cred id parsed from query string
1856  *
1857  * @return true if query parsed successfully and found 'credid', else false.
1858  */
1859 static bool GetCredIdsFromQueryString(const char *query, CredIdList_t **credid)
1860 {
1861     bool found = false;
1862     OicParseQueryIter_t parseIter = { .attrPos = NULL };
1863
1864     ParseQueryIterInit((unsigned char *) query, &parseIter);
1865
1866     while (GetNextQuery (&parseIter))
1867     {
1868         if (strncasecmp((char *) parseIter.attrPos, OIC_JSON_CREDID_NAME, parseIter.attrLen) == 0)
1869         {
1870             VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
1871
1872             //parse credid array value in format "1,2,3"
1873             unsigned char *str = parseIter.valPos;
1874
1875             //remember last symbol (may be '\0' or '&')
1876             unsigned char tmp = str[parseIter.valLen];
1877             //set last symbol to '\0' to use strtok_r
1878             str[parseIter.valLen] = '\0';
1879
1880             char *saveptr = NULL;
1881
1882             for (; ; str = NULL)
1883             {
1884                 char *token = strtok_r((char *)str, ",", &saveptr);
1885                 if (NULL == token)
1886                 {
1887                     break;
1888                 }
1889
1890                 CredIdList_t *newCredIdElem = (CredIdList_t *) OICCalloc(1, sizeof(CredIdList_t));
1891                 if (NULL == newCredIdElem)
1892                 {
1893                     OIC_LOG(ERROR, TAG, "Failed to allocate CredIdList_t element");
1894                     break;
1895                 }
1896                 newCredIdElem->credId = (uint16_t)atoi(token);
1897
1898                 LL_PREPEND(*credid, newCredIdElem);
1899                 found = true;
1900             }
1901
1902             //restore last symbol
1903             parseIter.valPos[parseIter.valLen] = tmp;
1904         }
1905     }
1906
1907 exit:
1908     return found;
1909 }
1910
1911 /**
1912  * Remove all credential data on credential resource and persistent storage
1913  *
1914  * @retval
1915  *     OC_STACK_OK              - no errors
1916  *     OC_STACK_ERROR           - stack process error
1917  */
1918 static OCStackResult RemoveAllCredentials()
1919 {
1920     DeleteCredList(gCred);
1921     gCred = GetCredDefault();
1922
1923     if (!UpdatePersistentStorage(gCred))
1924     {
1925         return OC_STACK_ERROR;
1926     }
1927     return OC_STACK_OK;
1928 }
1929
1930 /**
1931  * This method parses the query string received for REST requests and
1932  * retrieves the 'subjectuuid' field.
1933  *
1934  * @param query querystring passed in REST request
1935  * @param subject subject UUID parsed from query string
1936  *
1937  * @return true if query parsed successfully and found 'subject', else false.
1938  */
1939 static bool GetSubjectFromQueryString(const char *query, OicUuid_t *subject)
1940 {
1941     OicParseQueryIter_t parseIter = { .attrPos = NULL };
1942
1943     ParseQueryIterInit((unsigned char *) query, &parseIter);
1944
1945     while (GetNextQuery (&parseIter))
1946     {
1947         if (strncasecmp((char *) parseIter.attrPos, OIC_JSON_SUBJECTID_NAME, parseIter.attrLen) == 0)
1948         {
1949             VERIFY_SUCCESS(TAG, 0 != parseIter.valLen, ERROR);
1950             //temporary set '\0' symbol instead of copy string
1951             char tmp = parseIter.valPos[parseIter.valLen];
1952             parseIter.valPos[parseIter.valLen] = '\0';
1953
1954             OCStackResult res = ConvertStrToUuid((const char*)parseIter.valPos, subject);
1955             parseIter.valPos[parseIter.valLen] = tmp;
1956             VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
1957             return true;
1958         }
1959     }
1960
1961 exit:
1962     return false;
1963 }
1964
1965 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
1966 /**
1967  * Internal function to fill private data of owner PSK.
1968  *
1969  * @param receviedCred recevied owner credential from OBT(PT)
1970  * @param ownerAdd address of OBT(PT)
1971  * @param doxm current device's doxm resource
1972  *
1973  * @return
1974  *     true successfully done and valid ower psk information
1975  *     false Invalid owner psk information or failed to owner psk generation
1976  */
1977 static bool FillPrivateDataOfOwnerPSK(OicSecCred_t* receviedCred, const CAEndpoint_t* ownerAddr,
1978                            const OicSecDoxm_t* doxm)
1979 {
1980     //Derive OwnerPSK locally
1981     const char* oxmLabel = GetOxmString(doxm->oxmSel);
1982     char* b64Buf = NULL;
1983     size_t b64BufSize = 0;
1984     VERIFY_NOT_NULL(TAG, oxmLabel, ERROR);
1985
1986     uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
1987     CAResult_t pskRet = CAGenerateOwnerPSK(ownerAddr,
1988         (uint8_t*)oxmLabel, strlen(oxmLabel),
1989         doxm->owner.id, sizeof(doxm->owner.id),
1990         doxm->deviceID.id, sizeof(doxm->deviceID.id),
1991         ownerPSK, OWNER_PSK_LENGTH_128);
1992     VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
1993
1994     OIC_LOG(DEBUG, TAG, "OwnerPSK dump :");
1995     OIC_LOG_BUFFER(DEBUG, TAG, ownerPSK, OWNER_PSK_LENGTH_128);
1996
1997     //Generate owner credential based on recevied credential information
1998
1999     // TODO: Added as workaround, will be replaced soon.
2000     if(OIC_ENCODING_RAW == receviedCred->privateData.encoding)
2001     {
2002         receviedCred->privateData.data = (uint8_t *)OICCalloc(1, OWNER_PSK_LENGTH_128);
2003         VERIFY_NOT_NULL(TAG, receviedCred->privateData.data, ERROR);
2004         receviedCred->privateData.len = OWNER_PSK_LENGTH_128;
2005         memcpy(receviedCred->privateData.data, ownerPSK, OWNER_PSK_LENGTH_128);
2006     }
2007     else if(OIC_ENCODING_BASE64 == receviedCred->privateData.encoding)
2008     {
2009         B64Result b64res = B64_OK;
2010         size_t b64OutSize = 0;
2011         b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
2012         b64Buf = OICCalloc(1, b64BufSize);
2013         VERIFY_NOT_NULL(TAG, b64Buf, ERROR);
2014
2015         b64res = b64Encode(ownerPSK, OWNER_PSK_LENGTH_128, b64Buf, b64BufSize, &b64OutSize);
2016         VERIFY_SUCCESS(TAG, B64_OK == b64res, ERROR);
2017
2018         receviedCred->privateData.data = (uint8_t *)OICCalloc(1, b64OutSize + 1);
2019         VERIFY_NOT_NULL(TAG, receviedCred->privateData.data, ERROR);
2020         receviedCred->privateData.len = b64OutSize;
2021         strncpy((char*)receviedCred->privateData.data, b64Buf, b64OutSize);
2022         receviedCred->privateData.data[b64OutSize] = '\0';
2023         OICClearMemory(b64Buf, b64BufSize);
2024         OICFree(b64Buf);
2025         b64Buf = NULL;
2026     }
2027     else
2028     {
2029         OIC_LOG_V(ERROR, TAG, "Unknown credential encoding type: %u.", receviedCred->privateData.encoding);
2030         goto exit;
2031     }
2032
2033     OIC_LOG(INFO, TAG, "PrivateData of OwnerPSK was calculated successfully");
2034
2035     OICClearMemory(ownerPSK, sizeof(ownerPSK));
2036
2037     //Verify OwnerPSK information
2038     return (memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0 &&
2039             receviedCred->credType == SYMMETRIC_PAIR_WISE_KEY);
2040 exit:
2041     //receviedCred->privateData.data will be deallocated when deleting credential.
2042     OICClearMemory(ownerPSK, sizeof(ownerPSK));
2043     OICClearMemory(b64Buf, b64BufSize);
2044     OICFree(b64Buf);
2045     return false;
2046 }
2047
2048
2049 #ifdef MULTIPLE_OWNER
2050 /**
2051  * Internal function to fill private data of SubOwner PSK.
2052  *
2053  * @param receviedCred recevied owner credential from SubOwner
2054  * @param ownerAdd address of SubOwner
2055  * @param doxm current device's doxm resource
2056  *
2057  * @return
2058  *     true successfully done and valid subower psk information
2059  *     false Invalid subowner psk information or failed to subowner psk generation
2060  */
2061 static bool FillPrivateDataOfSubOwnerPSK(OicSecCred_t* receivedCred, const CAEndpoint_t* ownerAddr,
2062                            const OicSecDoxm_t* doxm, const OicUuid_t* subOwner)
2063 {
2064     char* b64Buf = NULL;
2065     //Derive OwnerPSK locally
2066     const char* oxmLabel = GetOxmString(doxm->oxmSel);
2067     VERIFY_NOT_NULL(TAG, oxmLabel, ERROR);
2068
2069     uint8_t subOwnerPSK[OWNER_PSK_LENGTH_128] = {0};
2070     CAResult_t pskRet = CAGenerateOwnerPSK(ownerAddr,
2071         (uint8_t*)oxmLabel, strlen(oxmLabel),
2072         subOwner->id, sizeof(subOwner->id),
2073         doxm->deviceID.id, sizeof(doxm->deviceID.id),
2074         subOwnerPSK, OWNER_PSK_LENGTH_128);
2075     VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
2076
2077     OIC_LOG(DEBUG, TAG, "SubOwnerPSK dump :");
2078     OIC_LOG_BUFFER(DEBUG, TAG, subOwnerPSK, OWNER_PSK_LENGTH_128);
2079
2080     //Generate owner credential based on received credential information
2081
2082     if(OIC_ENCODING_RAW == receivedCred->privateData.encoding)
2083     {
2084         receivedCred->privateData.data = (uint8_t *)OICCalloc(1, OWNER_PSK_LENGTH_128);
2085         VERIFY_NOT_NULL(TAG, receivedCred->privateData.data, ERROR);
2086         receivedCred->privateData.len = OWNER_PSK_LENGTH_128;
2087         memcpy(receivedCred->privateData.data, subOwnerPSK, OWNER_PSK_LENGTH_128);
2088     }
2089     else if(OIC_ENCODING_BASE64 == receivedCred->privateData.encoding)
2090     {
2091         size_t b64OutSize = 0;
2092         size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
2093         b64Buf = OICCalloc(1, b64BufSize);
2094         VERIFY_NOT_NULL(TAG, b64Buf, ERROR);
2095
2096         VERIFY_SUCCESS(TAG, \
2097                        B64_OK == b64Encode(subOwnerPSK, OWNER_PSK_LENGTH_128, b64Buf, b64BufSize, &b64OutSize), \
2098                        ERROR);
2099
2100         receivedCred->privateData.data = (uint8_t *)OICCalloc(1, b64OutSize + 1);
2101         VERIFY_NOT_NULL(TAG, receivedCred->privateData.data, ERROR);
2102         receivedCred->privateData.len = b64OutSize;
2103         strncpy((char*)receivedCred->privateData.data, b64Buf, b64OutSize);
2104         receivedCred->privateData.data[b64OutSize] = '\0';
2105     }
2106     else
2107     {
2108         OIC_LOG_V(ERROR, TAG, "Unknown credential encoding type: %u.", receivedCred->privateData.encoding);
2109         goto exit;
2110     }
2111
2112     OIC_LOG(INFO, TAG, "PrivateData of SubOwnerPSK was calculated successfully");
2113     OICFree(b64Buf);
2114     return true;
2115 exit:
2116     //receivedCred->privateData.data will be deallocated when deleting credential.
2117     OICFree(b64Buf);
2118     return false;
2119 }
2120 #endif //MULTIPLE_OWNER
2121 #endif // __WITH_DTLS__ or __WITH_TLS__
2122
2123
2124 static OCEntityHandlerResult HandleNewCredential(OCEntityHandlerRequest *ehRequest, OicSecCred_t *cred, uint16_t previousMsgId)
2125 {
2126     OCEntityHandlerResult ret = OC_EH_INTERNAL_SERVER_ERROR;
2127
2128 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
2129     OicUuid_t emptyUuid = {.id={0}};
2130     const OicSecDoxm_t *doxm = GetDoxmResourceData();
2131     if( NO_SECURITY_MODE != cred->credType
2132         && doxm
2133         && false == doxm->owned
2134         && memcmp(&(doxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0
2135         && memcmp(&(doxm->owner), &cred->subject, sizeof(OicUuid_t)) == 0 )
2136     {
2137         //in case of owner PSK
2138         switch(cred->credType)
2139         {
2140             case SYMMETRIC_PAIR_WISE_KEY:
2141             {
2142                 OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
2143                 if(FillPrivateDataOfOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm))
2144                 {
2145                     if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&cred->subject))
2146                     {
2147                         OIC_LOG(WARNING, TAG, "The credential with the same subject ID was detected!");
2148                     }
2149
2150                     OIC_LOG(INFO, TAG, "OwnerPSK was generated successfully.");
2151                     if(OC_STACK_OK == AddCredential(cred))
2152                     {
2153                         ret = OC_EH_CHANGED;
2154                     }
2155                     else
2156                     {
2157                         OIC_LOG(ERROR, TAG, "Failed to save the OwnerPSK as cred resource");
2158                         ret = OC_EH_ERROR;
2159                     }
2160                 }
2161                 else
2162                 {
2163                     OIC_LOG(ERROR, TAG, "Failed to verify receviced OwnerPSK.");
2164                     ret = OC_EH_ERROR;
2165                 }
2166
2167                 if(OC_EH_CHANGED == ret)
2168                 {
2169                     /**
2170                         * in case of random PIN based OxM,
2171                         * revert get_psk_info callback of tinyDTLS to use owner credential.
2172                         */
2173                     if(OIC_RANDOM_DEVICE_PIN == doxm->oxmSel)
2174                     {
2175                         SetUuidForPinBasedOxm(&emptyUuid);
2176
2177 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
2178                         if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
2179                         {
2180                             OIC_LOG(ERROR, TAG, "Failed to revert TLS credential handler.");
2181                             ret = OC_EH_ERROR;
2182                             break;
2183                         }
2184 #endif // __WITH_DTLS__ or __WITH_TLS__
2185                     }
2186
2187                     //Select cipher suite to use owner PSK
2188                     if(CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false))
2189                     {
2190                         OIC_LOG(ERROR, TAG, "Failed to disable anonymous cipher suite");
2191                         ret = OC_EH_ERROR;
2192                     }
2193                     else
2194                     {
2195                         OIC_LOG(INFO, TAG, "Anonymous cipher suite is DISABLED");
2196                     }
2197
2198 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
2199                     if(CA_STATUS_OK != CASelectCipherSuite(
2200                                 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, CA_ADAPTER_IP))
2201                     {
2202                         OIC_LOG(ERROR, TAG, "Failed to enable PSK cipher suite");
2203                         ret = OC_EH_ERROR;
2204                     }
2205                     else
2206                     {
2207                         OIC_LOG(INFO, TAG, "PSK cipher suite is ENABLED");
2208                     }
2209 #endif // __WITH_DTLS__ or __WITH_TLS__
2210                 }
2211
2212                 break;
2213             }
2214             case SYMMETRIC_GROUP_KEY:
2215             case ASYMMETRIC_KEY:
2216             case SIGNED_ASYMMETRIC_KEY:
2217             case PIN_PASSWORD:
2218             case ASYMMETRIC_ENCRYPTION_KEY:
2219             {
2220                 OIC_LOG(WARNING, TAG, "Unsupported credential type for owner credential.");
2221                 ret = OC_EH_ERROR;
2222                 break;
2223             }
2224             default:
2225             {
2226                 OIC_LOG(WARNING, TAG, "Unknown credential type for owner credential.");
2227                 ret = OC_EH_ERROR;
2228                 break;
2229             }
2230         }
2231
2232         if(OC_EH_CHANGED != ret)
2233         {
2234             /*
2235                 * If some error is occured while ownership transfer,
2236                 * ownership transfer related resource should be revert back to initial status.
2237                 */
2238             const OicSecDoxm_t *ownershipDoxm =  GetDoxmResourceData();
2239             if(ownershipDoxm)
2240             {
2241                 if(!ownershipDoxm->owned)
2242                 {
2243                     OIC_LOG(WARNING, TAG, "The operation failed during handle DOXM request");
2244
2245                     if((OC_ADAPTER_IP == ehRequest->devAddr.adapter && previousMsgId != ehRequest->messageID)
2246                         || OC_ADAPTER_TCP == ehRequest->devAddr.adapter)
2247                     {
2248                         RestoreDoxmToInitState();
2249                         RestorePstatToInitState();
2250                         OIC_LOG(WARNING, TAG, "DOXM will be reverted.");
2251                     }
2252                 }
2253             }
2254             else
2255             {
2256                 OIC_LOG(ERROR, TAG, "Invalid DOXM resource");
2257             }
2258         }
2259     }
2260 #ifdef MULTIPLE_OWNER
2261     // In case SubOwner Credential
2262     else if(doxm && doxm->owned && doxm->mom &&
2263             OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode &&
2264             0 == cred->privateData.len &&
2265             0 == cred->optionalData.len &&
2266             0 == cred->publicData.len )
2267     {
2268         switch(cred->credType)
2269         {
2270             case SYMMETRIC_PAIR_WISE_KEY:
2271             {
2272                 OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
2273                 if(FillPrivateDataOfSubOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm, &cred->subject))
2274                 {
2275                     if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&cred->subject))
2276                     {
2277                         OIC_LOG(WARNING, TAG, "The credential with the same subject ID was detected!");
2278                     }
2279
2280                     OIC_LOG(ERROR, TAG, "SubOwnerPSK was generated successfully.");
2281                     if(OC_STACK_OK == AddCredential(cred))
2282                     {
2283                         ret = OC_EH_CHANGED;
2284                     }
2285                     else
2286                     {
2287                         OIC_LOG(ERROR, TAG, "Failed to save the SubOwnerPSK as cred resource");
2288                         ret = OC_EH_ERROR;
2289                     }
2290                 }
2291                 else
2292                 {
2293                     OIC_LOG(ERROR, TAG, "Failed to verify receviced SubOwner PSK.");
2294                     ret = OC_EH_ERROR;
2295                 }
2296             }
2297             break;
2298
2299             case SYMMETRIC_GROUP_KEY:
2300             case ASYMMETRIC_KEY:
2301             case SIGNED_ASYMMETRIC_KEY:
2302             case PIN_PASSWORD:
2303             case ASYMMETRIC_ENCRYPTION_KEY:
2304             {
2305                 OIC_LOG(WARNING, TAG, "Unsupported credential type for SubOwner credential.");
2306                 ret = OC_EH_ERROR;
2307                 break;
2308             }
2309             default:
2310             {
2311                 OIC_LOG(WARNING, TAG, "Unknown credential type for SubOwner credential.");
2312                 ret = OC_EH_ERROR;
2313                 break;
2314             }
2315         }
2316     }
2317 #endif //MULTIPLE_OWNER
2318     else
2319     {
2320         if(IsEmptyCred(cred))
2321         {
2322                     if (UpdatePersistentStorage(gCred))
2323                     {
2324                         ret = OC_EH_CHANGED;
2325                     }
2326                     else
2327                     {
2328                         ret = OC_EH_ERROR;
2329                     }
2330         }
2331         else
2332         {
2333             /*
2334                 * If the post request credential has credId, it will be
2335                 * discarded and the next available credId will be assigned
2336                 * to it before getting appended to the existing credential
2337                 * list and updating svr database.
2338                 */
2339             ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_CHANGED : OC_EH_ERROR;
2340         }
2341     }
2342 #else //not __WITH_DTLS__ or __WITH_TLS__
2343     /*
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.
2348         */
2349     ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_CHANGED : OC_EH_ERROR;
2350     OC_UNUSED(previousMsgId);
2351     OC_UNUSED(ehRequest);
2352 #endif//__WITH_DTLS__ or __WITH_TLS__
2353
2354     return ret;
2355 }
2356
2357 static OCEntityHandlerResult HandlePostRequest(OCEntityHandlerRequest* ehRequest)
2358 {
2359     OCEntityHandlerResult ret = OC_EH_INTERNAL_SERVER_ERROR;
2360     OIC_LOG(DEBUG, TAG, "HandleCREDPostRequest IN");
2361
2362     OicSecDostype_t dos;
2363     static uint16_t previousMsgId = 0;
2364     // Get binary representation of cbor
2365     OicSecCred_t *cred = NULL;
2366     OicUuid_t     *rownerId = NULL;
2367     uint8_t *payload = (((OCSecurityPayload*)ehRequest->payload)->securityData);
2368     size_t size = (((OCSecurityPayload*)ehRequest->payload)->payloadSize);
2369
2370     OCStackResult res = OC_STACK_OK;
2371
2372     VERIFY_SUCCESS(TAG, OC_STACK_OK == GetDos(&dos), ERROR);
2373     if ((DOS_RESET == dos.state) ||
2374         (DOS_RFNOP == dos.state))
2375     {
2376         OIC_LOG_V(WARNING, TAG, "%s /cred resource is read-only in RESET and RFNOP.", __func__);
2377         ret = OC_EH_NOT_ACCEPTABLE;
2378         goto exit;
2379     }
2380
2381     res = CBORPayloadToCred(payload, size, &cred, &rownerId);
2382
2383     if (OC_STACK_OK == res)
2384     {
2385         OicSecCred_t *newCred = NULL;
2386         OicSecCred_t *newCredTemp = NULL;
2387
2388         LL_FOREACH_SAFE(cred, newCred, newCredTemp)
2389         {
2390             ret = HandleNewCredential(ehRequest, newCred, previousMsgId);
2391
2392             if (OC_EH_CHANGED != ret)
2393             {
2394                 // Remove the credentials added so far.
2395                 OicSecCred_t *removedCred = NULL;
2396                 OicSecCred_t *removedCredTemp = NULL;
2397                 LL_FOREACH_SAFE(cred, removedCred, removedCredTemp)
2398                 {
2399                     if (removedCred == newCred)
2400                     {
2401                         break;
2402                     }
2403
2404                     if (RemoveCredential(&cred->subject) != OC_STACK_OK)
2405                     {
2406                         OIC_LOG(WARNING, TAG, "Failed to remove credential");
2407                     }
2408                 }
2409
2410                 break;
2411             }
2412         }
2413         if (OC_EH_CHANGED == ret && NULL != rownerId)
2414         {
2415             memcpy(&gRownerId, rownerId, sizeof(OicUuid_t));
2416         }
2417     }
2418
2419 exit:
2420     OICFree(rownerId);
2421     if (OC_EH_CHANGED != ret)
2422     {
2423         if (NULL != cred)
2424         {
2425             DeleteCredList(cred);
2426         }
2427     }
2428     else
2429     {
2430         if (OC_ADAPTER_IP == ehRequest->devAddr.adapter)
2431         {
2432             previousMsgId = ehRequest->messageID++;
2433         }
2434     }
2435
2436     // Send response to request originator
2437     ret = ((SendSRMResponse(ehRequest, ret, NULL, 0)) == OC_STACK_OK) ?
2438                    OC_EH_OK : OC_EH_ERROR;
2439
2440     OIC_LOG(DEBUG, TAG, "HandleCREDPostRequest OUT");
2441     return ret;
2442 }
2443
2444 /**
2445  * The entity handler determines how to process a GET request.
2446  */
2447 static OCEntityHandlerResult HandleGetRequest (const OCEntityHandlerRequest * ehRequest)
2448 {
2449     OIC_LOG(INFO, TAG, "HandleGetRequest  processing GET request");
2450
2451     // Convert Cred data into CBOR for transmission
2452     size_t size = 0;
2453     uint8_t *payload = NULL;
2454     int secureFlag = 1;
2455
2456     const OicSecCred_t *cred = gCred;
2457
2458     // This added '256' is arbitrary value that is added to cover the name of the resource, map addition and ending
2459     size = GetCredKeyDataSize(cred);
2460     size += (256 * OicSecCredCount(cred));
2461     OCStackResult res = CredToCBORPayload(cred, &payload, &size, secureFlag);
2462
2463     // A device should always have a default cred. Therefore, payload should never be NULL.
2464     OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
2465
2466     //Send payload to request originator
2467     ehRet = ((SendSRMResponse(ehRequest, ehRet, payload, size)) == OC_STACK_OK) ?
2468                        OC_EH_OK : OC_EH_ERROR;
2469     OICClearMemory(payload, size);
2470     OICFree(payload);
2471     return ehRet;
2472 }
2473
2474 static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
2475 {
2476     OIC_LOG(DEBUG, TAG, "Processing CredDeleteRequest");
2477
2478     OCEntityHandlerResult ehRet = OC_EH_ERROR;
2479     CredIdList_t *credIdList = NULL;
2480     OicUuid_t subject = { .id= { 0 } };
2481
2482     if (NULL == ehRequest->query)
2483     {
2484         return ehRet;
2485     }
2486
2487     if (GetCredIdsFromQueryString(ehRequest->query, &credIdList))
2488     {
2489         if (OC_STACK_RESOURCE_DELETED == RemoveCredentialByCredIds(credIdList))
2490         {
2491             ehRet = OC_EH_RESOURCE_DELETED;
2492         }
2493         DeleteCredIdList(&credIdList);
2494     }
2495     else if (GetSubjectFromQueryString(ehRequest->query, &subject))
2496     {
2497         if (OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
2498         {
2499             ehRet = OC_EH_RESOURCE_DELETED;
2500         }
2501     }
2502     else
2503     {
2504         if (OC_STACK_OK == RemoveAllCredentials())
2505         {
2506             ehRet = OC_EH_RESOURCE_DELETED;
2507         }
2508     }
2509
2510     //Send response to request originator
2511     ehRet = ((SendSRMResponse(ehRequest, ehRet, NULL, 0)) == OC_STACK_OK) ?
2512                    OC_EH_OK : OC_EH_ERROR;
2513     return ehRet;
2514 }
2515
2516 OCEntityHandlerResult CredEntityHandler(OCEntityHandlerFlag flag,
2517                                         OCEntityHandlerRequest * ehRequest,
2518                                         void* callbackParameter)
2519 {
2520     (void)callbackParameter;
2521     OCEntityHandlerResult ret = OC_EH_ERROR;
2522
2523     if (!ehRequest)
2524     {
2525         return OC_EH_ERROR;
2526     }
2527     if (flag & OC_REQUEST_FLAG)
2528     {
2529         OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
2530         //TODO :  Remove Handle PUT methods once CTT have changed to POST on OTM
2531         switch (ehRequest->method)
2532         {
2533             case OC_REST_GET:
2534                 ret = HandleGetRequest(ehRequest);
2535                 break;
2536             case OC_REST_PUT:
2537             case OC_REST_POST:
2538                 ret = HandlePostRequest(ehRequest);
2539                 break;
2540             case OC_REST_DELETE:
2541                 ret = HandleDeleteRequest(ehRequest);
2542                 break;
2543             default:
2544                 ret = ((SendSRMResponse(ehRequest, ret, NULL, 0)) == OC_STACK_OK) ?
2545                                OC_EH_OK : OC_EH_ERROR;
2546                 break;
2547         }
2548     }
2549     return ret;
2550 }
2551
2552 OCStackResult CreateCredResource()
2553 {
2554     OCStackResult ret = OCCreateResource(&gCredHandle,
2555                                          OIC_RSRC_TYPE_SEC_CRED,
2556                                          OC_RSRVD_INTERFACE_DEFAULT,
2557                                          OIC_RSRC_CRED_URI,
2558                                          CredEntityHandler,
2559                                          NULL,
2560                                          OC_SECURE |
2561                                          OC_DISCOVERABLE);
2562
2563     if (OC_STACK_OK != ret)
2564     {
2565         OIC_LOG (FATAL, TAG, "Unable to instantiate Cred resource");
2566         DeInitCredResource();
2567     }
2568     return ret;
2569 }
2570
2571 OCStackResult InitCredResource()
2572 {
2573     OCStackResult ret = OC_STACK_ERROR;
2574     OicSecCred_t* cred = NULL;
2575     OicUuid_t   *rownerId = NULL;
2576
2577     //Read Cred resource from PS
2578     uint8_t *data = NULL;
2579     size_t size = 0;
2580     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_CRED_NAME, &data, &size);
2581     // If database read failed
2582     if (ret != OC_STACK_OK)
2583     {
2584         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
2585     }
2586
2587     if ((ret == OC_STACK_OK) && data)
2588     {
2589         // Read Cred resource from PS
2590         ret = CBORPayloadToCred(data, size, &gCred, &rownerId);
2591
2592 #ifdef HAVE_WINDOWS_H
2593         /* On Windows, if the credential payload isn't cleartext CBOR, it is encrypted. Decrypt and retry. */
2594         DWORD dwordSize;
2595
2596         if (FAILED(SizeTToDWord(size, &dwordSize)))
2597         {
2598             OIC_LOG(DEBUG, TAG, "Cred size too large.");
2599             ret = OC_STACK_ERROR;
2600         }
2601
2602         if (ret != OC_STACK_OK)
2603         {
2604             DATA_BLOB decryptedPayload;
2605             DATA_BLOB encryptedPayload;
2606             memset(&decryptedPayload, 0, sizeof(decryptedPayload));
2607             memset(&encryptedPayload, 0, sizeof(encryptedPayload));
2608             encryptedPayload.cbData = dwordSize;
2609             encryptedPayload.pbData = data;
2610
2611             if (CryptUnprotectData(
2612                 &encryptedPayload,
2613                 NULL,
2614                 NULL,
2615                 NULL,
2616                 NULL,
2617                 CRYPTPROTECT_UI_FORBIDDEN,
2618                 &decryptedPayload))
2619             {
2620                 ret = CBORPayloadToCred(decryptedPayload.pbData, decryptedPayload.cbData, &gCred, &rownerId);
2621
2622                 /* For the returned data from CryptUnprotectData, LocalFree must be used to free. Don't use OICFree. */
2623                 OICClearMemory(decryptedPayload.pbData, decryptedPayload.cbData);
2624                 if (NULL != LocalFree(decryptedPayload.pbData))
2625                 {
2626                     OIC_LOG_V(ERROR, TAG, "LocalFree failed on output from CryptUnprotectData; memory may be corrupted or leaked. Last error: %u.", GetLastError());
2627                     assert(!"LocalFree failed");
2628                 }
2629             }
2630             else
2631             {
2632                 /* Credential resource is corrupted, or we no longer have access to the encryption key to decrypt it. */
2633                 OIC_LOG_V(ERROR, TAG, "Failed to CryptUnprotectData cred resource: %u", GetLastError());
2634                 ret = OC_STACK_ERROR;
2635             }
2636         }
2637 #endif
2638     }
2639
2640     /*
2641      * If SVR database in persistent storage got corrupted or
2642      * is not available for some reason, a default Cred is created
2643      * which allows user to initiate Cred provisioning again.
2644      */
2645     if (ret != OC_STACK_OK || !data || !gCred)
2646     {
2647         gCred = GetCredDefault();
2648     }
2649
2650     if (gCred)
2651     {
2652         OicUuid_t deviceID;
2653         OicUuid_t emptyUuid = {.id={0}};
2654
2655         ret = GetDoxmDeviceID(&deviceID);
2656         if (ret != OC_STACK_OK)
2657         {
2658             OIC_LOG_V(WARNING, TAG, "%s: GetDoxmDeviceID failed, error %d", __func__, ret);
2659             //Unit tests expect error code OC_STACK_INVALID_PARAM.
2660             ret = OC_STACK_INVALID_PARAM;
2661             goto exit;
2662         }
2663
2664         //Add a log to track the invalid credential.
2665         LL_FOREACH(gCred, cred)
2666         {
2667             if (false == CheckSubjectOfCertificate(cred, deviceID))
2668             {
2669                 OIC_LOG(WARNING, TAG, "Check subject of Certificate was failed while InitCredResource");
2670             }
2671             if (false == IsValidCredential(cred))
2672             {
2673                 OIC_LOG(WARNING, TAG, "Invalid credential data was dectected while InitCredResource");
2674                 OIC_LOG_V(WARNING, TAG, "Invalid credential ID = %d", cred->credId);
2675             }
2676         }
2677
2678         if (NULL == rownerId || 0 == memcmp(rownerId, &emptyUuid, sizeof(OicUuid_t)))
2679         {
2680             memcpy(&gRownerId, &deviceID, sizeof(OicUuid_t));
2681         }
2682         else
2683         {
2684             memcpy(&gRownerId, rownerId, sizeof(OicUuid_t));
2685         }
2686
2687         if (!UpdatePersistentStorage(gCred))
2688         {
2689             OIC_LOG(FATAL, TAG, "UpdatePersistentStorage failed!");
2690         }
2691     }
2692     //Instantiate 'oic.sec.cred'
2693     ret = CreateCredResource();
2694
2695 exit:
2696     OIC_LOG(DEBUG, TAG, "OUT InitCredResource.");
2697     OICClearMemory(data, size);
2698     OICFree(data);
2699     OICFree(rownerId);
2700     return ret;
2701 }
2702
2703 OCStackResult DeInitCredResource()
2704 {
2705     OCStackResult result = OCDeleteResource(gCredHandle);
2706     DeleteCredList(gCred);
2707     gCred = NULL;
2708     return result;
2709 }
2710
2711 OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
2712 {
2713     OicSecCred_t *cred = NULL;
2714
2715    if ( NULL == subject)
2716     {
2717        return NULL;
2718     }
2719
2720     LL_FOREACH(gCred, cred)
2721     {
2722         if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
2723         {
2724             return cred;
2725         }
2726     }
2727     return NULL;
2728 }
2729
2730 const OicSecCred_t* GetCredList()
2731 {
2732     return gCred;
2733 }
2734
2735 OicSecCred_t* GetCredEntryByCredId(const uint16_t credId)
2736 {
2737     OicSecCred_t *cred = NULL;
2738     OicSecCred_t *tmpCred = NULL;
2739
2740    if ( 1 > credId)
2741     {
2742        return NULL;
2743     }
2744
2745     LL_FOREACH(gCred, tmpCred)
2746     {
2747         if(tmpCred->credId == credId)
2748         {
2749             cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
2750             VERIFY_NOT_NULL(TAG, cred, ERROR);
2751
2752             // common
2753             cred->next = NULL;
2754             cred->credId = tmpCred->credId;
2755             cred->credType = tmpCred->credType;
2756             memcpy(cred->subject.id, tmpCred->subject.id , sizeof(cred->subject.id));
2757             if (tmpCred->period)
2758             {
2759                 cred->period = OICStrdup(tmpCred->period);
2760             }
2761
2762             // key data
2763             if (tmpCred->privateData.data)
2764             {
2765                 cred->privateData.data = (uint8_t *)OICCalloc(1, tmpCred->privateData.len);
2766                 VERIFY_NOT_NULL(TAG, cred->privateData.data, ERROR);
2767
2768                 memcpy(cred->privateData.data, tmpCred->privateData.data, tmpCred->privateData.len);
2769                 cred->privateData.len = tmpCred->privateData.len;
2770                 cred->privateData.encoding = tmpCred->privateData.encoding;
2771             }
2772 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
2773             if (tmpCred->publicData.data)
2774             {
2775                 cred->publicData.data = (uint8_t *)OICCalloc(1, tmpCred->publicData.len);
2776                 VERIFY_NOT_NULL(TAG, cred->publicData.data, ERROR);
2777
2778                 memcpy(cred->publicData.data, tmpCred->publicData.data, tmpCred->publicData.len);
2779                 cred->publicData.len = tmpCred->publicData.len;
2780                 cred->publicData.encoding = tmpCred->publicData.encoding;
2781             }
2782             if (tmpCred->optionalData.data)
2783             {
2784                 cred->optionalData.data = (uint8_t *)OICCalloc(1, tmpCred->optionalData.len);
2785                 VERIFY_NOT_NULL(TAG, cred->optionalData.data, ERROR);
2786
2787                 memcpy(cred->optionalData.data, tmpCred->optionalData.data, tmpCred->optionalData.len);
2788                 cred->optionalData.len = tmpCred->optionalData.len;
2789                 cred->optionalData.encoding = tmpCred->optionalData.encoding;
2790                 cred->optionalData.revstat= tmpCred->optionalData.revstat;
2791             }
2792             if (tmpCred->credUsage)
2793             {
2794                 cred->credUsage = OICStrdup(tmpCred->credUsage);
2795             }
2796 #endif /* __WITH_DTLS__  or __WITH_TLS__*/
2797
2798             return cred;
2799         }
2800     }
2801
2802 exit:
2803     FreeCred(cred);
2804     return NULL;
2805 }
2806
2807 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
2808 static bool ValueWithinBounds(uint64_t value, uint64_t maxValue)
2809 {
2810     if (value > maxValue)
2811     {
2812         OIC_LOG_V(ERROR, TAG, "The value (%" PRId64 ") is greater than allowed maximum of %" PRId64 ".", value, maxValue);
2813         return false;
2814     }
2815
2816     return true;
2817 }
2818
2819 int32_t GetDtlsPskCredentials(CADtlsPskCredType_t type,
2820               const uint8_t *desc, size_t desc_len,
2821               uint8_t *result, size_t result_length)
2822 {
2823     int32_t ret = -1;
2824
2825     if (NULL == result)
2826     {
2827         return ret;
2828     }
2829
2830     switch (type)
2831     {
2832         case CA_DTLS_PSK_HINT:
2833         case CA_DTLS_PSK_IDENTITY:
2834             {
2835                 OicUuid_t deviceID = {.id={0}};
2836                 // Retrieve Device ID from doxm resource
2837                 if ( OC_STACK_OK != GetDoxmDeviceID(&deviceID) )
2838                 {
2839                     OIC_LOG (ERROR, TAG, "Unable to retrieve doxm Device ID");
2840                     return ret;
2841                 }
2842
2843                 if (result_length < sizeof(deviceID.id))
2844                 {
2845                     OIC_LOG (ERROR, TAG, "Wrong value for result_length");
2846                     return ret;
2847                 }
2848                 memcpy(result, deviceID.id, sizeof(deviceID.id));
2849                 return (sizeof(deviceID.id));
2850             }
2851             break;
2852
2853         case CA_DTLS_PSK_KEY:
2854             {
2855                 OicSecCred_t *cred = NULL;
2856                 LL_FOREACH(gCred, cred)
2857                 {
2858                     if (cred->credType != SYMMETRIC_PAIR_WISE_KEY)
2859                     {
2860                         continue;
2861                     }
2862
2863                     if ((desc_len == sizeof(cred->subject.id)) &&
2864                         (memcmp(desc, cred->subject.id, sizeof(cred->subject.id)) == 0))
2865                     {
2866                         /*
2867                          * If the credentials are valid for limited time,
2868                          * check their expiry.
2869                          */
2870                         if (cred->period)
2871                         {
2872                             if(IOTVTICAL_VALID_ACCESS != IsRequestWithinValidTime(cred->period, NULL))
2873                             {
2874                                 OIC_LOG (INFO, TAG, "Credentials are expired.");
2875                                 return ret;
2876                             }
2877                         }
2878
2879                         // Copy PSK.
2880                         // TODO: Added as workaround. Will be replaced soon.
2881                         if(OIC_ENCODING_RAW == cred->privateData.encoding)
2882                         {
2883                             if (ValueWithinBounds(cred->privateData.len, INT32_MAX))
2884                             {
2885                                 size_t len = cred->privateData.len;
2886                                 if (result_length < len)
2887                                 {
2888                                     OIC_LOG (ERROR, TAG, "Wrong value for result_length");
2889                                     return ret;
2890                                 }
2891                                 memcpy(result, cred->privateData.data, len);
2892                                 ret = (int32_t)len;
2893                             }
2894                         }
2895                         else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
2896                         {
2897                             size_t outBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
2898                             uint8_t* outKey = OICCalloc(1, outBufSize);
2899                             size_t outKeySize;
2900                             if(NULL == outKey)
2901                             {
2902                                 OIC_LOG (ERROR, TAG, "Failed to allocate memory.");
2903                                 return ret;
2904                             }
2905
2906                             if(B64_OK == b64Decode((char*)cred->privateData.data, cred->privateData.len, outKey, outBufSize, &outKeySize))
2907                             {
2908                                 if (ValueWithinBounds(outKeySize, INT32_MAX))
2909                                 {
2910                                     if (result_length < outKeySize)
2911                                     {
2912                                         OIC_LOG (ERROR, TAG, "Wrong value for result_length");
2913                                         return ret;
2914                                     }
2915                                     memcpy(result, outKey, outKeySize);
2916                                     ret = (int32_t)outKeySize;
2917                                 }
2918                             }
2919                             else
2920                             {
2921                                 OIC_LOG (ERROR, TAG, "Failed base64 decoding.");
2922                             }
2923
2924                             OICFree(outKey);
2925                         }
2926
2927                         if (OC_STACK_OK != RegisterSymmetricCredentialRole(cred))
2928                         {
2929                             OIC_LOG(WARNING, TAG, "Couldn't RegisterRoleForSubject");
2930                         }
2931
2932                         return ret;
2933                     }
2934                 }
2935                 OIC_LOG(DEBUG, TAG, "Can not find subject matched credential.");
2936
2937 #ifdef MULTIPLE_OWNER
2938                 const OicSecDoxm_t* doxm = GetDoxmResourceData();
2939                 if(doxm && doxm->mom && OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode)
2940                 {
2941                     // in case of multiple owner transfer authentication
2942                     if(OIC_PRECONFIG_PIN == doxm->oxmSel)
2943                     {
2944                         OicSecCred_t* wildCardCred = GetCredResourceData(&WILDCARD_SUBJECT_ID);
2945                         if(wildCardCred)
2946                         {
2947                             OIC_LOG(DEBUG, TAG, "Detected wildcard credential.");
2948                             if(PIN_PASSWORD == wildCardCred->credType)
2949                             {
2950                                 //Read PIN/PW
2951                                 char* pinBuffer = NULL;
2952                                 size_t pinLength = 0;
2953                                 if(OIC_ENCODING_RAW == wildCardCred->privateData.encoding)
2954                                 {
2955                                     pinBuffer = OICCalloc(1, wildCardCred->privateData.len + 1);
2956                                     if(NULL == pinBuffer)
2957                                     {
2958                                         OIC_LOG (ERROR, TAG, "Failed to allocate memory.");
2959                                         return ret;
2960                                     }
2961                                     pinLength = wildCardCred->privateData.len;
2962                                     memcpy(pinBuffer, wildCardCred->privateData.data, pinLength);
2963                                 }
2964                                 else if(OIC_ENCODING_BASE64 == wildCardCred->privateData.encoding)
2965                                 {
2966                                     size_t pinBufSize = B64DECODE_OUT_SAFESIZE((wildCardCred->privateData.len + 1));
2967                                     pinBuffer = OICCalloc(1, pinBufSize);
2968                                     if(NULL == pinBuffer)
2969                                     {
2970                                         OIC_LOG (ERROR, TAG, "Failed to allocate memory.");
2971                                         return ret;
2972                                     }
2973
2974                                     if(B64_OK != b64Decode((char*)wildCardCred->privateData.data, wildCardCred->privateData.len, (uint8_t*)pinBuffer, pinBufSize, &pinLength))
2975                                     {
2976                                         OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
2977                                         return ret;
2978                                     }
2979                                 }
2980                                 else
2981                                 {
2982                                     OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
2983                                     return ret;
2984                                 }
2985
2986                                 //Set the PIN/PW to derive PSK
2987                                 if (OC_STACK_OK != SetPreconfigPin(pinBuffer, pinLength))
2988                                 {
2989                                     OICFree(pinBuffer);
2990                                     OIC_LOG(ERROR, TAG, "Failed to load PIN data.");
2991                                     return ret;
2992                                 }
2993                                 OICFree(pinBuffer);
2994
2995                                 OicUuid_t myUuid;
2996                                 if(OC_STACK_OK != GetDoxmDeviceID(&myUuid))
2997                                 {
2998                                     OIC_LOG(ERROR, TAG, "Failed to read device ID");
2999                                     return ret;
3000                                 }
3001                                 SetUuidForPinBasedOxm(&myUuid);
3002
3003                                 //Calculate PSK using PIN/PW
3004                                 if(0 == DerivePSKUsingPIN((uint8_t*)result))
3005                                 {
3006                                     ret = OWNER_PSK_LENGTH_128;
3007                                 }
3008                                 else
3009                                 {
3010                                     OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN");
3011                                 }
3012
3013                                 if(CA_STATUS_OK != CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB))
3014                                 {
3015                                     OIC_LOG(WARNING, TAG, "Error while bind the DTLS Handshake Callback.");
3016                                 }
3017                             }
3018                         }
3019                     }
3020                     else if(OIC_RANDOM_DEVICE_PIN == doxm->oxmSel)
3021                     {
3022                         if(0 == DerivePSKUsingPIN((uint8_t*)result))
3023                         {
3024                             ret = OWNER_PSK_LENGTH_128;
3025                         }
3026                         else
3027                         {
3028                             OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
3029                             ret = -1;
3030                         }
3031                     }
3032                 }
3033 #endif //MULTIPLE_OWNER
3034             }
3035             break;
3036     }
3037
3038     return ret;
3039 }
3040
3041 /**
3042  * Add temporal PSK to PIN based OxM
3043  *
3044  * @param[in] tmpSubject UUID of target device
3045  * @param[in] credType Type of credential to be added
3046  * @param[in] pin numeric characters
3047  * @param[in] pinSize length of 'pin'
3048  * @param[in] rownerID Resource owner's UUID
3049  * @param[out] tmpCredSubject Generated credential's subject.
3050  *
3051  * @return OC_STACK_OK for success and errorcode otherwise.
3052  */
3053 OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
3054                             const char * pin, size_t pinSize,
3055                             const OicUuid_t * rownerID, OicUuid_t* tmpCredSubject)
3056 {
3057     OCStackResult ret = OC_STACK_ERROR;
3058     OIC_LOG(DEBUG, TAG, "AddTmpPskWithPIN IN");
3059
3060     if(NULL == tmpSubject || NULL == pin || 0 == pinSize || NULL == tmpCredSubject)
3061     {
3062         return OC_STACK_INVALID_PARAM;
3063     }
3064
3065     uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
3066     OicSecKey_t privKey;
3067     memset(&privKey, 0, sizeof(privKey));
3068     privKey.data = privData;
3069     privKey.len = OWNER_PSK_LENGTH_128;
3070     privKey.encoding = OIC_ENCODING_RAW;
3071
3072     OicSecCred_t* cred = NULL;
3073     int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, rownerID->id,
3074                                               UUID_LENGTH, PBKDF_ITERATIONS,
3075                                               OWNER_PSK_LENGTH_128, privData);
3076     VERIFY_SUCCESS(TAG, (0 == dtlsRes) , ERROR);
3077
3078     cred = GenerateCredential(tmpSubject, credType, NULL,
3079                               &privKey, NULL);
3080     OICClearMemory(privData, sizeof(privData));
3081     if(NULL == cred)
3082     {
3083         OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
3084         return OC_STACK_ERROR;
3085     }
3086
3087     memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
3088
3089     ret = AddCredential(cred);
3090     if( OC_STACK_OK != ret)
3091     {
3092         RemoveCredential(tmpSubject);
3093         OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
3094     }
3095     OIC_LOG(DEBUG, TAG, "AddTmpPskWithPIN OUT");
3096
3097 exit:
3098     return ret;
3099 }
3100
3101 #endif /* __WITH_DTLS__ */
3102
3103 OCStackResult SetCredRownerId(const OicUuid_t* newROwner)
3104 {
3105     OCStackResult ret = OC_STACK_ERROR;
3106     OicUuid_t prevId = {.id={0}};
3107
3108     if(NULL == newROwner)
3109     {
3110         ret = OC_STACK_INVALID_PARAM;
3111     }
3112
3113     if (newROwner)
3114     {
3115         memcpy(prevId.id, gRownerId.id, sizeof(prevId.id));
3116         memcpy(gRownerId.id, newROwner->id, sizeof(newROwner->id));
3117
3118         VERIFY_SUCCESS(TAG, UpdatePersistentStorage(gCred), ERROR);
3119
3120         ret = OC_STACK_OK;
3121     }
3122
3123     return ret;
3124
3125 exit:
3126     memcpy(gRownerId.id, prevId.id, sizeof(prevId.id));
3127     return ret;
3128 }
3129
3130 OCStackResult GetCredRownerId(OicUuid_t *rowneruuid)
3131 {
3132     if (rowneruuid)
3133     {
3134         memcpy(&(rowneruuid->id), &(gRownerId.id), sizeof(rowneruuid->id));
3135         return OC_STACK_OK;
3136     }
3137     return OC_STACK_ERROR;
3138 }
3139
3140 #if defined (__WITH_TLS__) || defined(__WITH_DTLS__)
3141 /* Caller must call OICFree on *der when finished. */
3142 static int ConvertPemCertToDer(const char *pem, size_t pemLen, uint8_t** der, size_t* derLen)
3143 {
3144     const char* pemHeader = "-----BEGIN CERTIFICATE-----"; /* no newlines allowed here */
3145     const char* pemFooter = "-----END CERTIFICATE-----";
3146
3147     mbedtls_pem_context ctx;
3148     int ret;
3149
3150     OC_UNUSED(pemLen);
3151
3152     mbedtls_pem_init(&ctx);
3153     size_t usedLen;
3154     ret = mbedtls_pem_read_buffer(&ctx, pemHeader, pemFooter, (const uint8_t*) pem, NULL, 0, &usedLen);
3155     if (ret != 0)
3156     {
3157         OIC_LOG_V(ERROR, TAG, "%s: failed reading PEM cert", __func__);
3158         goto exit;
3159     }
3160
3161     uint8_t *buf = OICCalloc(1, ctx.buflen);
3162     if (NULL == buf)
3163     {
3164         OIC_LOG(ERROR, TAG, "Failed to allocate memory");
3165         ret = -1;
3166         goto exit;
3167     }
3168
3169     memcpy(buf, ctx.buf, ctx.buflen);
3170
3171     *der = buf;
3172     *derLen = ctx.buflen;
3173
3174 exit:
3175     mbedtls_pem_free(&ctx);
3176
3177     return ret;
3178 }
3179
3180 /* Caller must call OICFree on *pem when finished. */
3181 static int ConvertDerCertToPem(const uint8_t* der, size_t derLen, uint8_t** pem)
3182 {
3183     const char* pemHeader = "-----BEGIN CERTIFICATE-----\n";
3184     const char* pemFooter = "-----END CERTIFICATE-----\n";
3185
3186     /* Get the length required for output */
3187     size_t pemLen;
3188     int ret = mbedtls_pem_write_buffer(pemHeader,
3189         pemFooter,
3190         der,
3191         derLen,
3192         NULL,
3193         0,
3194         &pemLen);
3195     if (ret != MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL)
3196     {
3197         OIC_LOG_V(ERROR, TAG, "Couldn't convert cert into PEM, failed getting required length: %d", ret);
3198         return ret;
3199     }
3200
3201     *pem = OICCalloc(1, pemLen + 1);
3202     if (*pem == NULL)
3203     {
3204         OIC_LOG(ERROR, TAG, "Failed to allocate memory for PEM cert");
3205         return ret;
3206     }
3207
3208     /* Try the conversion */
3209     ret = mbedtls_pem_write_buffer(pemHeader,
3210         pemFooter,
3211         der,
3212         derLen,
3213         *pem,
3214         pemLen,
3215         &pemLen);
3216     if (ret < 0)
3217     {
3218         OIC_LOG_V(ERROR, TAG, "Couldn't convert cert into PEM, failed writing PEM: %d", ret);
3219         OICFreeAndSetToNull((void **) pem);
3220         return ret;
3221     }
3222
3223     return 0;
3224 }
3225
3226 static OCStackResult GetCaCert(ByteArray_t * crt, const char * usage, OicEncodingType_t desiredEncoding)
3227 {
3228     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
3229     if (NULL == crt || NULL == usage)
3230     {
3231         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
3232         return OC_STACK_INVALID_PARAM;
3233     }
3234
3235     switch (desiredEncoding)
3236     {
3237     case OIC_ENCODING_PEM:
3238     case OIC_ENCODING_DER:
3239     case OIC_ENCODING_BASE64:
3240         break;
3241     default:
3242         OIC_LOG_V(ERROR, TAG, "%s: Unsupported encoding %d", __func__, desiredEncoding);
3243         return OC_STACK_INVALID_PARAM;
3244     }
3245
3246     crt->len = 0;
3247     OicSecCred_t* temp = NULL;
3248
3249     LL_FOREACH(gCred, temp)
3250     {
3251         if ((SIGNED_ASYMMETRIC_KEY == temp->credType) &&
3252             (temp->credUsage != NULL) &&
3253             (0 == strcmp(temp->credUsage, usage)) && (false == temp->optionalData.revstat))
3254         {
3255
3256             if ((OIC_ENCODING_BASE64 != temp->publicData.encoding) &&
3257                 (OIC_ENCODING_PEM != temp->publicData.encoding) &&
3258                 (OIC_ENCODING_DER != temp->publicData.encoding))
3259             {
3260                 OIC_LOG_V(WARNING, TAG, "%s: Unknown encoding type", __func__);
3261                 continue;
3262             }
3263
3264             if (OIC_ENCODING_DER == desiredEncoding)
3265             {
3266                 if ((OIC_ENCODING_BASE64 == temp->publicData.encoding) ||
3267                     (OIC_ENCODING_PEM == temp->publicData.encoding))
3268                 {
3269                     uint8_t* buf = NULL;
3270                     size_t outSize = 0;
3271                     int ret = ConvertPemCertToDer((const char*)temp->publicData.data, temp->publicData.len, &buf, &outSize);
3272                     if (0 > ret)
3273                     {
3274                         OIC_LOG(ERROR, TAG, "Could not convert PEM cert to DER");
3275                         return OC_STACK_ERROR;
3276                     }
3277
3278                     uint8_t *savePtr = crt->data;
3279                     crt->data = OICRealloc(crt->data, crt->len + outSize);
3280                     if (NULL == crt->data)
3281                     {
3282                         OIC_LOG(ERROR, TAG, "No memory reallocating crt->data");
3283                         OICFree(savePtr);
3284                         OICFree(buf);
3285                         return OC_STACK_NO_MEMORY;
3286                     }
3287                     memcpy(crt->data + crt->len, buf, outSize);
3288                     crt->len += outSize;
3289                     OICFree(buf);
3290                 }
3291                 else
3292                 {
3293                     uint8_t *savePtr = crt->data;
3294                     crt->data = OICRealloc(crt->data, crt->len + temp->publicData.len);
3295                     if (NULL == crt->data)
3296                     {
3297                         OIC_LOG(ERROR, TAG, "No memory reallocating crt->data");
3298                         OICFree(savePtr);
3299                         return OC_STACK_NO_MEMORY;
3300                     }
3301                     memcpy(crt->data + crt->len, temp->publicData.data, temp->publicData.len);
3302                     crt->len += temp->publicData.len;
3303                 }
3304                 OIC_LOG_V(DEBUG, TAG, "%s found", usage);
3305             }
3306             else
3307             {
3308                 /* PEM/Base64 */
3309                 uint8_t *pem = NULL;
3310                 size_t pemLen = 0;
3311                 if ((OIC_ENCODING_BASE64 == temp->publicData.encoding) ||
3312                     (OIC_ENCODING_PEM == temp->publicData.encoding))
3313                 {
3314                     pem = temp->publicData.data;
3315                     pemLen = temp->publicData.len;
3316                 }
3317                 else
3318                 {
3319                     int ret = ConvertDerCertToPem(temp->publicData.data, temp->publicData.len, &pem);
3320                     if (0 > ret)
3321                     {
3322                         OIC_LOG_V(ERROR, TAG, "Failed converting DER cert to PEM: %d", ret);
3323                         return OC_STACK_ERROR;
3324                     }
3325                     pemLen = strlen((char *)pem) + 1;
3326                 }
3327
3328                 uint8_t *oldData = crt->data;
3329                 crt->data = OICRealloc(crt->data, crt->len + pemLen);
3330                 if (NULL == crt->data)
3331                 {
3332                     OIC_LOG(ERROR, TAG, "No memory reallocating crt->data");
3333                     OICFree(oldData);
3334                     return OC_STACK_NO_MEMORY;
3335                 }
3336                 memcpy(crt->data + crt->len, pem, pemLen);
3337                 crt->len += pemLen;
3338             }
3339         }
3340     }
3341     if(0 == crt->len)
3342     {
3343         OIC_LOG_V(WARNING, TAG, "%s not found", usage);
3344         return OC_STACK_NO_RESOURCE;
3345     }
3346
3347     if (OIC_ENCODING_PEM == desiredEncoding)
3348     {
3349         /* mbedtls_x509_crt_parse requires a null terminator to determine that the format is PEM */
3350         size_t crtLength = crt->len;
3351         bool addNull = (crt->data[crtLength - 1] != 0);
3352
3353         if (addNull)
3354         {
3355             OIC_LOG_V(DEBUG, TAG, "%s: adding null terminator at the end of the cert", __func__);
3356             uint8_t *oldData = crt->data;
3357             crt->data = OICRealloc(crt->data, crtLength + 1);
3358             if (NULL == crt->data)
3359             {
3360                 OIC_LOG(ERROR, TAG, "No memory reallocating crt->data");
3361                 OICFree(oldData);
3362                 return OC_STACK_NO_MEMORY;
3363             }
3364             crt->data[crtLength] = 0;
3365             crt->len = crtLength + 1;
3366         }
3367     }
3368
3369     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
3370     return OC_STACK_OK;
3371 }
3372
3373 OCStackResult GetPemCaCert(ByteArray_t * crt, const char * usage)
3374 {
3375     return GetCaCert(crt, usage, OIC_ENCODING_PEM);
3376 }
3377
3378 static int cloneSecKey(OicSecKey_t * dst, OicSecKey_t * src)
3379 {
3380     if ((src == NULL) || (dst == NULL))
3381     {
3382         return -1;
3383     }
3384
3385     if (src->len > 0)
3386     {
3387         dst->data = OICCalloc(src->len, 1);
3388         if (dst->data == NULL)
3389         {
3390             OIC_LOG_V(ERROR, TAG, "%s memory allocation failed", __func__);
3391             return -1;
3392         }
3393         memcpy(dst->data, src->data, src->len);
3394     }
3395     else
3396     {
3397         dst->data = NULL;
3398     }
3399
3400     dst->len = src->len;
3401     dst->encoding = src->encoding;
3402
3403     return 0;
3404 }
3405
3406 /* Caller must call FreeRoleCertChainList on roleEntries when finished. */
3407 OCStackResult GetAllRoleCerts(RoleCertChain_t ** output)
3408 {
3409     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
3410
3411     *output = NULL;
3412
3413     OicSecCred_t * temp = NULL;
3414     LL_FOREACH(gCred, temp)
3415     {
3416         if ((SIGNED_ASYMMETRIC_KEY == temp->credType) &&
3417             (temp->credUsage != NULL) &&
3418             (0 == strcmp(temp->credUsage, ROLE_CERT)))
3419         {
3420             if (temp->publicData.data == NULL)
3421             {
3422                 OIC_LOG_V(WARNING, TAG, "%s missing certificate data in role certificate", __func__);
3423                 continue;
3424             }
3425
3426             RoleCertChain_t * add = (RoleCertChain_t *) OICCalloc(1, sizeof(RoleCertChain_t));
3427             if (add == NULL)
3428             {
3429                 OIC_LOG_V(ERROR, TAG, "%s Failed to allocate memory", __func__);
3430                 goto error;
3431             }
3432             LL_APPEND(*output, add);
3433             add->credId = temp->credId;
3434             if (cloneSecKey(&add->certificate, &temp->publicData) != 0)
3435             {
3436                 OIC_LOG_V(ERROR, TAG, "%s failed to copy certificate data", __func__);
3437                 goto error;
3438             }
3439         }
3440     }
3441
3442     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
3443     return OC_STACK_OK;
3444
3445 error:
3446     FreeRoleCertChainList(*output);
3447     *output = NULL;
3448     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
3449     return OC_STACK_ERROR;
3450 }
3451
3452 void GetPemOwnCert(ByteArray_t * crt, const char * usage)
3453 {
3454     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
3455     if (NULL == crt || NULL == usage)
3456     {
3457         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
3458         return;
3459     }
3460     crt->len = 0;
3461     OicSecCred_t * temp = NULL;
3462     LL_FOREACH(gCred, temp)
3463     {
3464         if (SIGNED_ASYMMETRIC_KEY == temp->credType &&
3465             temp->credUsage != NULL &&
3466             0 == strcmp(temp->credUsage, usage))
3467         {
3468             uint8_t *p = NULL;
3469             int mbedRet = 0;
3470             uint8_t *pem = NULL;
3471             size_t pemLen = 0;
3472             bool mustFreePem = false;
3473             bool mustAddNull = true;
3474
3475             switch (temp->publicData.encoding)
3476             {
3477             case OIC_ENCODING_DER:
3478             case OIC_ENCODING_RAW:
3479                 mbedRet = ConvertDerCertToPem(temp->publicData.data, temp->publicData.len, &pem);
3480                 if (0 > mbedRet)
3481                 {
3482                     OIC_LOG_V(ERROR, TAG, "Failed to ConvertDerCertToPem: %d", mbedRet);
3483                     return;
3484                 }
3485                 mustFreePem = true;
3486                 mustAddNull = false; /* mbedTLS always NULL-terminates. */
3487                 pemLen = strlen((char *)pem) + 1;
3488                 break;
3489
3490             case OIC_ENCODING_PEM:
3491             case OIC_ENCODING_BASE64:
3492                 pem = temp->publicData.data;
3493                 pemLen = temp->publicData.len;
3494
3495                 /* Make sure the buffer has a terminating NULL. If not, make sure we add one later. */
3496                 for (size_t i = pemLen - 1; i > 0; i--)
3497                 {
3498                     if ('\0' == (char)pem[i])
3499                     {
3500                         mustAddNull = false;
3501                         break;
3502                     }
3503                 }
3504                 break;
3505
3506             default:
3507                 OIC_LOG_V(ERROR, TAG, "Unsupported encoding %d", temp->publicData.encoding);
3508                 return;
3509             }
3510
3511             p = crt->data;
3512             crt->data = OICRealloc(crt->data, crt->len + pemLen + (mustAddNull ? 1 : 0));
3513             if (NULL == crt->data)
3514             {
3515                 OIC_LOG(ERROR, TAG, "No memory reallocating crt->data");
3516                 OICFree(p);
3517                 if (mustFreePem)
3518                 {
3519                     OICFree(pem);
3520                 }
3521                 return;
3522             }
3523
3524             /* If we're appending, subtract one from crt->len below so we overwrite the current terminating
3525              * NULL with the beginning of the new data.
3526              */
3527             if (0 < crt->len)
3528             {
3529                 assert(crt->data[crt->len - 1] == '\0');
3530                 memcpy(crt->data + crt->len - 1, pem, pemLen);
3531                 crt->len += pemLen - 1;
3532             }
3533             else
3534             {
3535                 memcpy(crt->data, pem, pemLen);
3536                 crt->len = pemLen;
3537             }
3538
3539             /* If pem doesn't contain a terminating NULL, add one. */
3540             if (mustAddNull)
3541             {
3542                 assert(crt->data[crt->len - 1] != '\0');
3543                 crt->data[crt->len] = '\0';
3544                 crt->len += 1;
3545             }
3546
3547             if (mustFreePem)
3548             {
3549                 OICFree(pem);
3550             }
3551
3552             OIC_LOG_V(DEBUG, TAG, "%s found", usage);
3553         }
3554     }
3555     if(0 == crt->len)
3556     {
3557         OIC_LOG_V(WARNING, TAG, "%s not found", usage);
3558     }
3559     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
3560     return;
3561 }
3562
3563 void GetDerKey(ByteArray_t * key, const char * usage)
3564 {
3565     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
3566     if (NULL == key || NULL == usage)
3567     {
3568         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
3569         return;
3570     }
3571
3572     OicSecCred_t * temp = NULL;
3573     key->len = 0;
3574     LL_FOREACH(gCred, temp)
3575     {
3576         if ((SIGNED_ASYMMETRIC_KEY == temp->credType || ASYMMETRIC_KEY == temp->credType) &&
3577             temp->privateData.len > 0 &&
3578             NULL != temp->credUsage &&
3579             0 == strcmp(temp->credUsage, usage))
3580         {
3581
3582             if (temp->privateData.encoding == OIC_ENCODING_PEM)
3583             {
3584                 /* Convert PEM to DER */
3585         &nbs