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