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