Security code comments which are doxygen compliant
[platform/upstream/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 <stdlib.h>
24 #ifdef WITH_ARDUINO
25 #include <string.h>
26 #else
27 #include <strings.h>
28 #endif
29 #include <stdint.h>
30
31 #include "cainterface.h"
32 #include "payload_logging.h"
33 #include "ocstack.h"
34 #include "ocrandom.h"
35 #include "ocserverrequest.h"
36 #include "oic_malloc.h"
37 #include "ocpayload.h"
38 #include "utlist.h"
39 #include "credresource.h"
40 #include "doxmresource.h"
41 #include "pstatresource.h"
42 #include "iotvticalendar.h"
43 #include "pbkdf2.h"
44 #include "resourcemanager.h"
45 #include "srmresourcestrings.h"
46 #include "srmutility.h"
47 #include "psinterface.h"
48 #include "pinoxmcommon.h"
49
50 #ifdef __WITH_DTLS__
51 #include "global.h"
52 #endif
53
54 #define TAG  "SRM-CREDL"
55
56 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
57  * The value of payload size is increased until reaching belox max cbor size. */
58 static const uint8_t CBOR_SIZE = 255;
59
60 /** Max cbor size payload. */
61 static const uint16_t CBOR_MAX_SIZE = 4400;
62
63 /** CRED Map size - Number of mandatory items. */
64 static const uint8_t CRED_MAP_SIZE = 4;
65
66 static OicSecCred_t        *gCred = NULL;
67 static OCResourceHandle    gCredHandle = NULL;
68
69 /**
70  * This function frees OicSecCred_t object's fields and object itself.
71  */
72 static void FreeCred(OicSecCred_t *cred)
73 {
74     if(NULL == cred)
75     {
76         OIC_LOG(ERROR, TAG, "Invalid Parameter");
77         return;
78     }
79     //Note: Need further clarification on roleID data type
80 #if 0
81     //Clean roleIds
82     OICFree(cred->roleIds);
83 #endif
84
85     //Clean PublicData
86     OICFree(cred->publicData.data);
87
88     //Clean PrivateData
89     OICFree(cred->privateData.data);
90
91     //Clean Period
92     OICFree(cred->period);
93
94     //Clean Owners
95     OICFree(cred->owners);
96
97     //Clean Cred node itself
98     OICFree(cred);
99 }
100
101 void DeleteCredList(OicSecCred_t* cred)
102 {
103     if (cred)
104     {
105         OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
106         LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
107         {
108             LL_DELETE(cred, credTmp1);
109             FreeCred(credTmp1);
110         }
111     }
112 }
113
114 static size_t OicSecCredCount(const OicSecCred_t *secCred)
115 {
116     size_t size = 0;
117     for (const OicSecCred_t *cred = secCred; cred; cred = cred->next)
118     {
119         size++;
120     }
121     return size;
122 }
123
124 OCStackResult CredToCBORPayload(const OicSecCred_t *credS, uint8_t **cborPayload,
125                                 size_t *cborSize)
126 {
127     if (NULL == credS || NULL == cborPayload || NULL != *cborPayload || NULL == cborSize)
128     {
129         return OC_STACK_INVALID_PARAM;
130     }
131
132     OCStackResult ret = OC_STACK_ERROR;
133     size_t cborLen = *cborSize;
134     if (0 == cborLen)
135     {
136         cborLen = CBOR_SIZE;
137     }
138
139     *cborSize = 0;
140     *cborPayload = NULL;
141
142     CborEncoder encoder = { {.ptr = NULL }, .end = 0 };
143     CborEncoder credArray = { {.ptr = NULL }, .end = 0 };
144     CborError cborEncoderResult = CborNoError;
145
146     const OicSecCred_t *cred = credS;
147     size_t mapSize = CRED_MAP_SIZE;
148     if (cred->period)
149     {
150         mapSize++;
151     }
152     if (cred->publicData.data)
153     {
154         mapSize++;
155     }
156     if (cred->privateData.data)
157     {
158         mapSize++;
159     }
160     if (cred->period)
161     {
162         mapSize++;
163     }
164     uint8_t *outPayload = (uint8_t *)OICCalloc(1, cborLen);
165     VERIFY_NON_NULL(TAG, outPayload, ERROR);
166     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
167
168     // Create CRED Array
169     cborEncoderResult = cbor_encoder_create_array(&encoder, &credArray, OicSecCredCount(cred));
170     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding0 Cred Array.");
171
172     while (cred)
173     {
174         CborEncoder credMap = { {.ptr = NULL }, .end = 0 };
175         cborEncoderResult = cbor_encoder_create_map(&credArray, &credMap, mapSize);
176         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Map");
177
178         //CredID -- Mandatory
179         cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDID_NAME,
180             strlen(OIC_JSON_CREDID_NAME));
181         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Id Tag. ");
182         cborEncoderResult = cbor_encode_int(&credMap, cred->credId);
183         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Id Value.");
184
185         //Subject -- Mandatory
186         cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_SUBJECT_NAME,
187             strlen(OIC_JSON_SUBJECT_NAME));
188         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Subject Tag.");
189         cborEncoderResult = cbor_encode_byte_string(&credMap, cred->subject.id,
190             sizeof(cred->subject.id));
191         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Subject Value.");
192
193         //CredType -- Mandatory
194         cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDTYPE_NAME,
195             strlen(OIC_JSON_CREDTYPE_NAME));
196         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Tag.");
197         cborEncoderResult = cbor_encode_int(&credMap, cred->credType);
198         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
199
200 #ifdef __WITH_X509__
201         //PublicData -- Not Mandatory
202         if (cred->publicData.data)
203         {
204             cborEncoderResult = cbor_encode_text_string(&credMap,
205                 OIC_JSON_PUBLICDATA_NAME, strlen(OIC_JSON_PUBLICDATA_NAME));
206             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Public Data Tag.");
207             cborEncoderResult = cbor_encode_byte_string(&credMap, cred->publicData.data,
208                     sizeof(cred->publicData.data));
209             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Public Tag Value.");
210         }
211 #endif /*__WITH_X509__*/
212         //PrivateData -- Not Mandatory
213         if(cred->privateData.data)
214         {
215             cborEncoderResult = cbor_encode_text_string(&credMap,
216                 OIC_JSON_PRIVATEDATA_NAME, strlen(OIC_JSON_PRIVATEDATA_NAME));
217             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Data Tag");
218             cborEncoderResult = cbor_encode_byte_string(&credMap, cred->privateData.data,
219                 sizeof(cred->privateData.data));
220             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Data Value.");
221         }
222
223         //Period -- Not Mandatory
224         if(cred->period)
225         {
226             cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_PERIOD_NAME,
227                 strlen(OIC_JSON_PERIOD_NAME));
228             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Name Tag.");
229             cborEncoderResult = cbor_encode_text_string(&credMap, cred->period,
230                 strlen(cred->period));
231             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Name Value.");
232         }
233
234         //Owners -- Mandatory
235         {
236             cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_OWNERS_NAME,
237                 strlen(OIC_JSON_OWNERS_NAME));
238             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owners Name Tag.");
239             CborEncoder owners = { {.ptr = NULL }, .end = 0 };
240             cborEncoderResult = cbor_encoder_create_array(&credMap, &owners, cred->ownersLen);
241             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owners Name Array.");
242             for (size_t i = 0; i < cred->ownersLen; i++)
243             {
244                 cborEncoderResult = cbor_encode_byte_string(&owners,
245                     (uint8_t *)cred->owners[i].id,
246                     sizeof(cred->owners[i].id));
247                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Owners Array Value.");
248             }
249             cborEncoderResult = cbor_encoder_close_container(&credMap, &owners);
250             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Owners Name Array.");
251         }
252         cborEncoderResult = cbor_encoder_close_container(&credArray, &credMap);
253         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Cred Map.");
254
255         cred = cred->next;
256    }
257    cborEncoderResult = cbor_encoder_close_container(&encoder, &credArray);
258    VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Cred Array.");
259
260    if (CborNoError == cborEncoderResult)
261    {
262        *cborPayload = outPayload;
263        *cborSize = encoder.ptr - outPayload;
264         ret = OC_STACK_OK;
265     }
266
267 exit:
268     if ((CborErrorOutOfMemory == cborEncoderResult) && (cborLen < CBOR_MAX_SIZE))
269     {
270        // reallocate and try again!
271        OICFree(outPayload);
272        outPayload = NULL;
273        // Since the allocated initial memory failed, double the memory.
274        cborLen += encoder.ptr - encoder.end;
275        cborEncoderResult = CborNoError;
276        ret = CredToCBORPayload(credS, cborPayload, &cborLen);
277        if (CborNoError == cborEncoderResult)
278        {
279            *cborSize = cborLen;
280             ret = OC_STACK_OK;
281         }
282     }
283
284     if (CborNoError != cborEncoderResult)
285     {
286        OICFree(outPayload);
287        outPayload = NULL;
288        *cborSize = 0;
289        *cborPayload = NULL;
290        ret = OC_STACK_ERROR;
291     }
292
293     return ret;
294 }
295
296 OCStackResult CBORPayloadToCred(const uint8_t *cborPayload, size_t size,
297                                 OicSecCred_t **secCred)
298 {
299     if (NULL == cborPayload || NULL == secCred || NULL != *secCred)
300     {
301         return OC_STACK_INVALID_PARAM;
302     }
303
304     *secCred = NULL;
305
306     OCStackResult ret = OC_STACK_ERROR;
307
308     CborValue credCbor = { .parser = NULL };
309     CborParser parser = { .end = NULL };
310     CborError cborFindResult = CborNoError;
311     OicSecCred_t *cred = NULL;
312     char *name = NULL;
313
314     int cborLen = size;
315     if (0 == size)
316     {
317         cborLen = CBOR_SIZE;
318     }
319     cbor_parser_init(cborPayload, cborLen, 0, &parser, &credCbor);
320
321     OicSecCred_t *headCred = NULL;
322
323     CborValue credArray = { .parser = NULL };
324     cborFindResult = cbor_value_enter_container(&credCbor, &credArray);
325     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Array.");
326
327     while (cbor_value_is_valid(&credArray))
328     {
329         CborValue credMap = { .parser = NULL };
330         cborFindResult = cbor_value_enter_container(&credArray, &credMap);
331         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Map.");
332
333         cred = (OicSecCred_t *) OICCalloc(1, sizeof(*cred));
334         VERIFY_NON_NULL(TAG, cred, ERROR);
335
336         while (cbor_value_is_valid(&credMap))
337         {
338             size_t len = 0;
339             cborFindResult = cbor_value_dup_text_string(&credMap, &name, &len, NULL);
340             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Name.");
341             cborFindResult = cbor_value_advance(&credMap);
342             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Cred Name. ");
343
344             CborType type = cbor_value_get_type(&credMap);
345
346             //CredId -- Mandatory
347             if (0 == strcmp(OIC_JSON_CREDID_NAME, name))
348             {
349                 cborFindResult = cbor_value_get_int(&credMap, (int *) &cred->credId);
350                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Id Value.");
351             }
352             //subject -- Mandatory
353             if (0 == strcmp(OIC_JSON_SUBJECT_NAME, name))
354             {
355                 uint8_t *id = NULL;
356                 cborFindResult = cbor_value_dup_byte_string(&credMap, &id, &len, NULL);
357                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Subject Name Value.");
358                 memcpy(cred->subject.id, id, len);
359                 OICFree(id);
360             }
361             //CredType -- Mandatory
362             if (0 == strcmp(OIC_JSON_CREDTYPE_NAME, name))
363             {
364                 cborFindResult = cbor_value_get_int(&credMap, (int *) &cred->credType);
365                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Type Value.");
366             }
367             //Owners -- Mandatory
368             if (0 == strcmp(OIC_JSON_OWNERS_NAME, name))
369             {
370                 CborValue owners = { .parser = NULL };
371                 cborFindResult = cbor_value_get_array_length(&credMap, &cred->ownersLen);
372                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owners Name Array Len.");
373                 cborFindResult = cbor_value_enter_container(&credMap, &owners);
374                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owners Name.");
375                 int i = 0;
376                 cred->owners = (OicUuid_t *)OICCalloc(cred->ownersLen, sizeof(*cred->owners));
377                 VERIFY_NON_NULL(TAG, cred->owners, ERROR);
378                 while (cbor_value_is_valid(&owners))
379                 {
380                     uint8_t *owner = NULL;
381                     cborFindResult = cbor_value_dup_byte_string(&owners, &owner, &len, NULL);
382                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Owner Value.");
383                     memcpy(cred->owners[i].id, owner, len);
384                     OICFree(owner);
385                     cborFindResult = cbor_value_advance(&owners);
386                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Owner Value.");
387                 }
388             }
389             //PrivateData is mandatory for some of the credential types listed below.
390             if (0 == strcmp(OIC_JSON_PRIVATEDATA_NAME, name))
391             {
392                 if ((cred->credType & SYMMETRIC_PAIR_WISE_KEY) ||
393                     (cred->credType & SYMMETRIC_GROUP_KEY) ||
394                     (cred->credType & PIN_PASSWORD))
395                 {
396                     cborFindResult = cbor_value_dup_byte_string(&credMap,
397                         &cred->privateData.data, &len, NULL);
398                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Private Data Value.");
399                 }
400             }
401             else
402             {
403                 cred->privateData.data = NULL;
404             }
405
406             //PublicData is mandatory only for SIGNED_ASYMMETRIC_KEY credentials type.
407             if (0 == strcmp(OIC_JSON_PUBLICDATA_NAME, name))
408             {
409                 if (cred->credType & SIGNED_ASYMMETRIC_KEY)
410                 {
411                     cborFindResult = cbor_value_dup_byte_string(&credMap,
412                         &cred->publicData.data, &len, NULL);
413                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding ");
414                 }
415             }
416             //Period -- Not Mandatory
417             if (0 == strcmp(OIC_JSON_PERIOD_NAME, name))
418             {
419                 cborFindResult = cbor_value_dup_text_string(&credMap,
420                     &cred->period, &len, NULL);
421                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Period Name Value.");
422             }
423             if (CborMapType != type && cbor_value_is_valid(&credMap))
424             {
425                 cborFindResult = cbor_value_advance(&credMap);
426                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Cred Map.");
427             }
428             OICFree(name);
429             name = NULL;
430         }
431
432         cred->next = NULL;
433         if (NULL == headCred)
434         {
435             headCred = cred;
436         }
437         else
438         {
439             OicSecCred_t *temp = headCred;
440             while (temp->next)
441             {
442                 temp = temp->next;
443             }
444             temp->next = cred;
445         }
446         if (cbor_value_is_valid(&credArray))
447         {
448             cborFindResult = cbor_value_advance(&credArray);
449             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Cred Array. ");
450         }
451     }
452     *secCred = headCred;
453     ret = OC_STACK_OK;
454 exit:
455     if (CborNoError != cborFindResult)
456     {
457         DeleteCredList(headCred);
458         headCred = NULL;
459         ret = OC_STACK_ERROR;
460     }
461     if (cred)
462     {
463         DeleteCredList(cred);
464     }
465     if (name)
466     {
467         OICFree(name);
468     }
469     return ret;
470 }
471
472 OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t credType,
473                                   const uint8_t * publicData, const uint8_t* privateData,
474                                   size_t ownersLen, const OicUuid_t * owners)
475 {
476     (void)publicData;
477     OCStackResult ret = OC_STACK_ERROR;
478
479     OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
480     VERIFY_NON_NULL(TAG, cred, ERROR);
481
482     //CredId is assigned before appending new cred to the existing
483     //credential list and updating svr database in AddCredential().
484     cred->credId = 0;
485
486     VERIFY_NON_NULL(TAG, subject, ERROR);
487     memcpy(cred->subject.id, subject->id , sizeof(cred->subject.id));
488
489     VERIFY_SUCCESS(TAG, credType < (NO_SECURITY_MODE | SYMMETRIC_PAIR_WISE_KEY |
490             SYMMETRIC_GROUP_KEY | ASYMMETRIC_KEY | SIGNED_ASYMMETRIC_KEY | PIN_PASSWORD), ERROR);
491     cred->credType = credType;
492
493 #ifdef __WITH_X509__
494     if (publicData)
495     {
496         cred->publicData.data = (uint8_t *)OICCalloc(1, PUBLIC_KEY_SIZE);
497         VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
498         memcpy(cred->publicData.data, publicData, PUBLIC_KEY_SIZE);
499     }
500 #endif // __WITH_X509__
501
502     if (privateData)
503     {
504 #ifdef __WITH_X509__
505         cred->privateData.data = (uint8_t *)OICCalloc(1, PRIVATE_KEY_SIZE);
506         VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
507         memcpy(cred->privateData.data, privateData, PRIVATE_KEY_SIZE);
508 #endif // __WITH_X509__
509     }
510
511     VERIFY_SUCCESS(TAG, ownersLen > 0, ERROR);
512     cred->ownersLen = ownersLen;
513
514     cred->owners = (OicUuid_t *)OICCalloc(cred->ownersLen, sizeof(*cred->owners));
515     VERIFY_NON_NULL(TAG, cred->owners, ERROR);
516     for (size_t i = 0; i < cred->ownersLen; i++)
517     {
518         memcpy(cred->owners[i].id, owners[i].id, sizeof(cred->owners[i].id));
519     }
520
521     ret = OC_STACK_OK;
522 exit:
523     if (OC_STACK_OK != ret)
524     {
525         DeleteCredList(cred);
526         cred = NULL;
527     }
528     return cred;
529 }
530
531 static bool UpdatePersistentStorage(const OicSecCred_t *cred)
532 {
533     bool ret = false;
534
535     // Convert Cred data into JSON for update to persistent storage
536     uint8_t *payload = NULL;
537     size_t size = 0;
538     OCStackResult res = CredToCBORPayload(cred, &payload, &size);
539     if ((OC_STACK_OK == res) && payload)
540     {
541         if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, payload, size))
542         {
543             ret = true;
544         }
545         OICFree(payload);
546     }
547     else //Empty cred list
548     {
549         if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, NULL, size))
550         {
551             ret = true;
552         }
553     }
554     return ret;
555 }
556
557 /**
558  * Compare function used LL_SORT for sorting credentials.
559  *
560  * @param first pointer to OicSecCred_t struct.
561  * @param second  pointer to OicSecCred_t struct.
562  *
563  *@return -1, if credId of first is less than credId of second.
564  * 0, if credId of first is equal to credId of second.
565  * 1, if credId of first is greater than credId of second.
566  */
567 static int CmpCredId(const OicSecCred_t * first, const OicSecCred_t *second)
568 {
569     if (first->credId < second->credId)
570     {
571         return -1;
572     }
573     else if (first->credId > second->credId)
574     {
575         return 1;
576     }
577     else
578         return 0;
579 }
580
581 /**
582  * GetCredId goes through the cred list and returns the next
583  * available credId. The next credId could be the credId that is
584  * available due deletion of OicSecCred_t object or one more than
585  * credId of last credential in the list.
586  *
587  * @return next available credId if successful, else 0 for error.
588  */
589 static uint16_t GetCredId()
590 {
591     //Sorts credential list in incremental order of credId
592     LL_SORT(gCred, CmpCredId);
593
594     OicSecCred_t *currentCred = NULL, *credTmp = NULL;
595     uint16_t nextCredId = 1;
596
597     LL_FOREACH_SAFE(gCred, currentCred, credTmp)
598     {
599         if (currentCred->credId == nextCredId)
600         {
601             nextCredId += 1;
602         }
603         else
604         {
605             break;
606         }
607     }
608
609     VERIFY_SUCCESS(TAG, nextCredId < UINT16_MAX, ERROR);
610     return nextCredId;
611
612 exit:
613     return 0;
614 }
615
616 /**
617  * Get the default value.
618  *
619  * @return  NULL for now.
620  */
621 static OicSecCred_t* GetCredDefault()
622 {
623     // TODO:Update it when we finalize the default info.
624     return NULL;
625 }
626
627 OCStackResult AddCredential(OicSecCred_t * newCred)
628 {
629     OCStackResult ret = OC_STACK_ERROR;
630     VERIFY_SUCCESS(TAG, NULL != newCred, ERROR);
631
632     //Assigning credId to the newCred
633     newCred->credId = GetCredId();
634     VERIFY_SUCCESS(TAG, newCred->credId != 0, ERROR);
635
636     //Append the new Cred to existing list
637     LL_APPEND(gCred, newCred);
638
639     if (UpdatePersistentStorage(gCred))
640     {
641         ret = OC_STACK_OK;
642     }
643
644 exit:
645     return ret;
646 }
647
648 OCStackResult RemoveCredential(const OicUuid_t *subject)
649 {
650     OCStackResult ret = OC_STACK_ERROR;
651     OicSecCred_t *cred = NULL;
652     OicSecCred_t *tempCred = NULL;
653     bool deleteFlag = false;
654
655     LL_FOREACH_SAFE(gCred, cred, tempCred)
656     {
657         if (memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
658         {
659             LL_DELETE(gCred, cred);
660             FreeCred(cred);
661             deleteFlag = 1;
662         }
663     }
664
665     if (deleteFlag)
666     {
667         if (UpdatePersistentStorage(gCred))
668         {
669             ret = OC_STACK_RESOURCE_DELETED;
670         }
671     }
672     return ret;
673
674 }
675
676 /**
677  * Remove all credential data on credential resource and persistent storage
678  *
679  * @retval
680  *     OC_STACK_OK              - no errors
681  *     OC_STACK_ERROR           - stack process error
682  */
683 OCStackResult RemoveAllCredentials(void)
684 {
685     DeleteCredList(gCred);
686     gCred = GetCredDefault();
687
688     if (!UpdatePersistentStorage(gCred))
689     {
690         return OC_STACK_ERROR;
691     }
692     return OC_STACK_OK;
693 }
694
695 #ifdef __WITH_DTLS__
696 /**
697  * Internal function to fill private data of owner PSK.
698  *
699  * @param receviedCred recevied owner credential from OBT(PT)
700  * @param ownerAdd address of OBT(PT)
701  * @param doxm current device's doxm resource
702  *
703  * @return
704  *     true successfully done and valid ower psk information
705  *     false Invalid owner psk information or failed to owner psk generation
706  */
707 static bool FillPrivateDataOfOwnerPSK(OicSecCred_t* receviedCred, const CAEndpoint_t* ownerAddr,
708                            const OicSecDoxm_t* doxm)
709 {
710     //Derive OwnerPSK locally
711     const char* oxmLabel = GetOxmString(doxm->oxmSel);
712     VERIFY_NON_NULL(TAG, oxmLabel, ERROR);
713
714     uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
715     CAResult_t pskRet = CAGenerateOwnerPSK(ownerAddr,
716         (uint8_t*)oxmLabel, strlen(oxmLabel),
717         doxm->owner.id, sizeof(doxm->owner.id),
718         doxm->deviceID.id, sizeof(doxm->deviceID.id),
719         ownerPSK, OWNER_PSK_LENGTH_128);
720     VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
721
722     OIC_LOG(DEBUG, TAG, "OwnerPSK dump :");
723     OIC_LOG_BUFFER(DEBUG, TAG, ownerPSK, OWNER_PSK_LENGTH_128);
724
725     //Generate owner credential based on recevied credential information
726     receviedCred->privateData.data = (uint8_t *)OICCalloc(1, OWNER_PSK_LENGTH_128);
727     VERIFY_NON_NULL(TAG, receviedCred->privateData.data, ERROR);
728     memcpy(receviedCred->privateData.data, ownerPSK, OWNER_PSK_LENGTH_128);
729
730     OIC_LOG(INFO, TAG, "PrivateData of OwnerPSK was calculated successfully");
731
732     //Verify OwnerPSK information
733     return (memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0 &&
734             receviedCred->credType == SYMMETRIC_PAIR_WISE_KEY);
735 exit:
736     //receviedCred->privateData.data will be deallocated when deleting credential.
737     return false;
738 }
739
740 #endif //__WITH_DTLS__
741
742 static OCEntityHandlerResult HandlePutRequest(const OCEntityHandlerRequest * ehRequest)
743 {
744     OCEntityHandlerResult ret = OC_EH_ERROR;
745
746     //Get binary representation of json
747     OicSecCred_t * cred  = NULL;
748     uint8_t *payload = (((OCSecurityPayload*)ehRequest->payload)->securityData1);
749     //size_t size = (((OCSecurityPayload*)ehRequest->payload)->payloadSize);
750     OCStackResult res = CBORPayloadToCred(payload, 0, &cred);
751     if (res == OC_STACK_OK)
752     {
753 #ifdef __WITH_DTLS__
754         OicUuid_t emptyUuid = {.id={0}};
755         const OicSecDoxm_t* doxm = GetDoxmResourceData();
756         if(false == doxm->owned && memcmp(&(doxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0)
757         {
758             //in case of owner PSK
759             switch(cred->credType)
760             {
761                 case SYMMETRIC_PAIR_WISE_KEY:
762                 {
763                     OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
764                     if(FillPrivateDataOfOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm))
765                     {
766                         if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&cred->subject))
767                         {
768                             OIC_LOG(WARNING, TAG, "The credential with the same subject ID was detected!");
769                         }
770
771                         OIC_LOG(ERROR, TAG, "OwnerPSK was generated successfully.");
772                         if(OC_STACK_OK == AddCredential(cred))
773                         {
774                             ret = OC_EH_RESOURCE_CREATED;
775                         }
776                         else
777                         {
778                             OIC_LOG(ERROR, TAG, "Failed to save the OwnerPSK as cred resource");
779                             ret = OC_EH_ERROR;
780                         }
781                     }
782                     else
783                     {
784                         OIC_LOG(ERROR, TAG, "Failed to verify receviced OwnerPKS.");
785                         ret = OC_EH_ERROR;
786                     }
787
788                     if(OC_EH_RESOURCE_CREATED == ret)
789                     {
790                         /**
791                          * in case of random PIN based OxM,
792                          * revert get_psk_info callback of tinyDTLS to use owner credential.
793                          */
794                         if(OIC_RANDOM_DEVICE_PIN == doxm->oxmSel)
795                         {
796                             OicUuid_t emptyUuid = { .id={0}};
797                             SetUuidForRandomPinOxm(&emptyUuid);
798
799                             if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
800                             {
801                                 OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
802                                 ret = OC_EH_ERROR;
803                                 break;
804                             }
805                         }
806
807                         //Select cipher suite to use owner PSK
808                         if(CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false))
809                         {
810                             OIC_LOG(ERROR, TAG, "Failed to disable anonymous cipher suite");
811                             ret = OC_EH_ERROR;
812                         }
813                         else
814                         {
815                             OIC_LOG(INFO, TAG, "Anonymous cipher suite is DISABLED");
816                         }
817
818                         if(CA_STATUS_OK !=
819                            CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256))
820                         {
821                             OIC_LOG(ERROR, TAG, "Failed to select cipher suite");
822                             ret = OC_EH_ERROR;
823                         }
824                     }
825
826                     break;
827                 }
828                 case SYMMETRIC_GROUP_KEY:
829                 case ASYMMETRIC_KEY:
830                 case SIGNED_ASYMMETRIC_KEY:
831                 case PIN_PASSWORD:
832                 case ASYMMETRIC_ENCRYPTION_KEY:
833                 {
834                     OIC_LOG(WARNING, TAG, "Unsupported credential type for owner credential.");
835                     ret = OC_EH_ERROR;
836                     break;
837                 }
838                 default:
839                 {
840                     OIC_LOG(WARNING, TAG, "Unknow credential type for owner credential.");
841                     ret = OC_EH_ERROR;
842                     break;
843                 }
844             }
845
846             if(OC_EH_RESOURCE_CREATED != ret)
847             {
848                 /*
849                   * If some error is occured while ownership transfer,
850                   * ownership transfer related resource should be revert back to initial status.
851                   */
852                 RestoreDoxmToInitState();
853                 RestorePstatToInitState();
854             }
855         }
856         else
857         {
858             /*
859              * If the post request credential has credId, it will be
860              * discarded and the next available credId will be assigned
861              * to it before getting appended to the existing credential
862              * list and updating svr database.
863              */
864             ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
865         }
866 #else //not __WITH_DTLS__
867         /*
868          * If the post request credential has credId, it will be
869          * discarded and the next available credId will be assigned
870          * to it before getting appended to the existing credential
871          * list and updating svr database.
872          */
873         ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
874 #endif//__WITH_DTLS__
875     }
876
877     if (OC_EH_RESOURCE_CREATED != ret)
878     {
879         if(OC_STACK_OK != RemoveCredential(&cred->subject))
880         {
881             OIC_LOG(WARNING, TAG, "Failed to remove the invalid credential");
882         }
883         FreeCred(cred);
884     }
885
886     return ret;
887 }
888
889 static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
890 {
891     OCEntityHandlerResult ret = OC_EH_ERROR;
892
893     //Get binary representation of CBOR
894     OicSecCred_t *cred  = NULL;
895     uint8_t *payload = ((OCSecurityPayload*)ehRequest->payload)->securityData1;
896     OCStackResult res = CBORPayloadToCred(payload, 0, &cred);
897     if ((OC_STACK_OK == res) && cred)
898     {
899         //If the Post request credential has credId, it will be
900         //discarded and the next available credId will be assigned
901         //to it before getting appended to the existing credential
902         //list and updating svr database.
903         ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
904     }
905
906     return ret;
907 }
908
909 static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
910 {
911     OIC_LOG(DEBUG, TAG, "Processing CredDeleteRequest");
912
913     OCEntityHandlerResult ehRet = OC_EH_ERROR;
914
915     if (NULL == ehRequest->query)
916    {
917        return ehRet;
918    }
919
920    OicParseQueryIter_t parseIter = { .attrPos=NULL };
921    OicUuid_t subject = {.id={0}};
922
923    //Parsing REST query to get the subject
924    ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
925    while (GetNextQuery(&parseIter))
926    {
927        if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME,
928                parseIter.attrLen) == 0)
929        {
930            memcpy(subject.id, parseIter.valPos, parseIter.valLen);
931        }
932    }
933
934    if (OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
935    {
936        ehRet = OC_EH_RESOURCE_DELETED;
937    }
938
939     return ehRet;
940 }
941
942 OCEntityHandlerResult CredEntityHandler(OCEntityHandlerFlag flag,
943                                         OCEntityHandlerRequest * ehRequest,
944                                         void* callbackParameter)
945 {
946     (void)callbackParameter;
947     OCEntityHandlerResult ret = OC_EH_ERROR;
948
949     if (!ehRequest)
950     {
951         return OC_EH_ERROR;
952     }
953     if (flag & OC_REQUEST_FLAG)
954     {
955         OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
956         //TODO :  Handle PUT/DEL methods
957         switch (ehRequest->method)
958         {
959             case OC_REST_GET:
960                 ret = OC_EH_FORBIDDEN;
961                 break;
962             case OC_REST_PUT:
963                 ret = HandlePutRequest(ehRequest);
964                 break;
965             case OC_REST_POST:
966                 ret = HandlePostRequest(ehRequest);
967                 break;
968             case OC_REST_DELETE:
969                 ret = HandleDeleteRequest(ehRequest);
970                 break;
971             default:
972                 ret = OC_EH_ERROR;
973                 break;
974         }
975     }
976
977     //Send payload to request originator
978     ret = (SendSRMCBORResponse(ehRequest, ret, NULL) == OC_STACK_OK) ?
979                        ret : OC_EH_ERROR;
980
981     return ret;
982 }
983
984 OCStackResult CreateCredResource()
985 {
986     OCStackResult ret = OCCreateResource(&gCredHandle,
987                                          OIC_RSRC_TYPE_SEC_CRED,
988                                          OIC_MI_DEF,
989                                          OIC_RSRC_CRED_URI,
990                                          CredEntityHandler,
991                                          NULL,
992                                          OC_RES_PROP_NONE);
993
994     if (OC_STACK_OK != ret)
995     {
996         OIC_LOG (FATAL, TAG, "Unable to instantiate Cred resource");
997         DeInitCredResource();
998     }
999     return ret;
1000 }
1001
1002 OCStackResult InitCredResource()
1003 {
1004     OCStackResult ret = OC_STACK_ERROR;
1005
1006     //Read Cred resource from PS
1007     uint8_t *data = NULL;
1008     size_t size = 0;
1009     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_CRED_NAME, &data, &size);
1010     // If database read failed
1011     if (ret != OC_STACK_OK)
1012     {
1013         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1014     }
1015     if (data)
1016     {
1017         // Read ACL resource from PS
1018         ret = CBORPayloadToCred(data, size, &gCred);
1019     }
1020
1021     /*
1022      * If SVR database in persistent storage got corrupted or
1023      * is not available for some reason, a default Cred is created
1024      * which allows user to initiate Cred provisioning again.
1025      */
1026     if (ret != OC_STACK_OK || !data || !gCred)
1027     {
1028         gCred = GetCredDefault();
1029     }
1030     //Instantiate 'oic.sec.cred'
1031     ret = CreateCredResource();
1032     OICFree(data);
1033     return ret;
1034 }
1035
1036 OCStackResult DeInitCredResource()
1037 {
1038     OCStackResult result = OCDeleteResource(gCredHandle);
1039     DeleteCredList(gCred);
1040     gCred = NULL;
1041     return result;
1042 }
1043
1044 const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
1045 {
1046     OicSecCred_t *cred = NULL;
1047
1048    if ( NULL == subject)
1049     {
1050        return NULL;
1051     }
1052
1053     LL_FOREACH(gCred, cred)
1054     {
1055         if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
1056         {
1057             return cred;
1058         }
1059     }
1060     return NULL;
1061 }
1062
1063
1064 #if defined(__WITH_DTLS__)
1065 int32_t GetDtlsPskCredentials(CADtlsPskCredType_t type,
1066               const uint8_t *desc, size_t desc_len,
1067               uint8_t *result, size_t result_length)
1068 {
1069     int32_t ret = -1;
1070
1071     if (NULL == result)
1072     {
1073         return ret;
1074     }
1075
1076     switch (type)
1077     {
1078         case CA_DTLS_PSK_HINT:
1079         case CA_DTLS_PSK_IDENTITY:
1080             {
1081                 OicUuid_t deviceID = {.id={}};
1082                 // Retrieve Device ID from doxm resource
1083                 if ( OC_STACK_OK != GetDoxmDeviceID(&deviceID) )
1084                 {
1085                     OIC_LOG (ERROR, TAG, "Unable to retrieve doxm Device ID");
1086                     return ret;
1087                 }
1088
1089                 if (result_length < sizeof(deviceID.id))
1090                 {
1091                     OIC_LOG (ERROR, TAG, "Wrong value for result_length");
1092                     return ret;
1093                 }
1094                 memcpy(result, deviceID.id, sizeof(deviceID.id));
1095                 return (sizeof(deviceID.id));
1096             }
1097             break;
1098
1099         case CA_DTLS_PSK_KEY:
1100             {
1101                 OicSecCred_t *cred = NULL;
1102                 LL_FOREACH(gCred, cred)
1103                 {
1104                     if (cred->credType != SYMMETRIC_PAIR_WISE_KEY)
1105                     {
1106                         continue;
1107                     }
1108
1109                     if ((desc_len == sizeof(cred->subject.id)) &&
1110                         (memcmp(desc, cred->subject.id, sizeof(cred->subject.id)) == 0))
1111                     {
1112                         /*
1113                          * If the credentials are valid for limited time,
1114                          * check their expiry.
1115                          */
1116                         if (cred->period)
1117                         {
1118                             if(IOTVTICAL_VALID_ACCESS != IsRequestWithinValidTime(cred->period, NULL))
1119                             {
1120                                 OIC_LOG (INFO, TAG, "Credentials are expired.");
1121                                 ret = -1;
1122                                 return ret;
1123                             }
1124                         }
1125
1126                         // Copy PSK.
1127                         result_length = sizeof(cred->privateData.data);
1128                         memcpy(result, cred->privateData.data, result_length);
1129                         return result_length;
1130                     }
1131                 }
1132             }
1133             break;
1134
1135         default:
1136             {
1137                 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
1138                 ret = -1;
1139             }
1140             break;
1141     }
1142
1143     return ret;
1144 }
1145
1146 /**
1147  * Add temporal PSK to PIN based OxM
1148  *
1149  * @param[in] tmpSubject UUID of target device
1150  * @param[in] credType Type of credential to be added
1151  * @param[in] pin numeric characters
1152  * @param[in] pinSize length of 'pin'
1153  * @param[in] ownersLen Number of owners
1154  * @param[in] owners Array of owners
1155  * @param[out] tmpCredSubject Generated credential's subject.
1156  *
1157  * @return OC_STACK_OK for success and errorcode otherwise.
1158  */
1159 OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
1160                             const char * pin, size_t pinSize,
1161                             size_t ownersLen, const OicUuid_t * owners, OicUuid_t* tmpCredSubject)
1162 {
1163     OCStackResult ret = OC_STACK_ERROR;
1164
1165     if(NULL == tmpSubject || NULL == pin || 0 == pinSize || NULL == tmpCredSubject)
1166     {
1167         return OC_STACK_INVALID_PARAM;
1168     }
1169
1170     uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
1171     OicSecCred_t* cred = NULL;
1172     int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, owners->id,
1173                                               UUID_LENGTH, PBKDF_ITERATIONS,
1174                                               OWNER_PSK_LENGTH_128, privData);
1175     VERIFY_SUCCESS(TAG, (0 == dtlsRes) , ERROR);
1176
1177     cred = GenerateCredential(tmpSubject, credType, NULL,
1178                               privData, ownersLen, owners);
1179     if(NULL == cred)
1180     {
1181         OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
1182         return OC_STACK_ERROR;
1183     }
1184
1185     memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
1186
1187     ret = AddCredential(cred);
1188     if( OC_STACK_OK != ret)
1189     {
1190         RemoveCredential(tmpSubject);
1191         OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
1192     }
1193
1194 exit:
1195     return ret;
1196 }
1197
1198 #endif /* __WITH_DTLS__ */
1199 #ifdef __WITH_X509__
1200 #define CERT_LEN_PREFIX (3)
1201 #define BYTE_SIZE (8) //bits
1202 #define PUB_KEY_X_COORD ("x")
1203 #define PUB_KEY_Y_COORD ("y")
1204 #define CERTIFICATE ("x5c")
1205 #define PRIVATE_KEY ("d")
1206
1207 static void WriteCertPrefix(uint8_t *prefix, uint32_t certLen)
1208 {
1209     for (size_t i = 0; i < CERT_LEN_PREFIX; ++i)
1210     {
1211         prefix[i] = (certLen >> (BYTE_SIZE * (CERT_LEN_PREFIX - 1 - i))) & 0xFF;
1212     }
1213 }
1214
1215 static uint32_t ParseCertPrefix(uint8_t *prefix)
1216 {
1217     uint32_t res = 0;
1218     if (NULL != prefix)
1219     {
1220         for (int i = 0; i < CERT_LEN_PREFIX; ++i)
1221         {
1222             res |= (((uint32_t) prefix[i]) << ((CERT_LEN_PREFIX - 1 -i) * BYTE_SIZE));
1223         }
1224     }
1225     return res;
1226 }
1227
1228 static uint32_t appendCert2Chain(uint8_t *appendPoint, uint8_t *cert, size_t len, uint32_t max_len)
1229 {
1230     uint32_t ret = 0;
1231     VERIFY_NON_NULL(TAG, appendPoint, ERROR);
1232     VERIFY_NON_NULL(TAG, cert, ERROR);
1233
1234     memcpy(appendPoint + CERT_LEN_PREFIX, cert, max_len - CERT_LEN_PREFIX);
1235     WriteCertPrefix(appendPoint, len);
1236
1237     ret = len + CERT_LEN_PREFIX;
1238 exit:
1239     return ret;
1240 }
1241
1242 static OCStackResult GetCAPublicKeyData(CADtlsX509Creds_t *credInfo)
1243 {
1244     OCStackResult ret = OC_STACK_ERROR;
1245     uint8_t *ccPtr = credInfo->certificateChain;
1246     for (uint8_t i = 0; i < credInfo->chainLen - 1; ++i)
1247     {
1248         ccPtr += CERT_LEN_PREFIX + ParseCertPrefix(ccPtr);
1249     }
1250
1251     ByteArray cert = { .data = ccPtr + CERT_LEN_PREFIX, .len = ParseCertPrefix(ccPtr) };
1252     CertificateX509 certStruct;
1253
1254     VERIFY_SUCCESS(TAG, PKI_SUCCESS == DecodeCertificate(cert, &certStruct), ERROR);
1255
1256     INC_BYTE_ARRAY(certStruct.pubKey, 2);
1257
1258     memcpy(credInfo->rootPublicKeyX, certStruct.pubKey.data, PUBLIC_KEY_SIZE / 2);
1259     memcpy(credInfo->rootPublicKeyY, certStruct.pubKey.data + PUBLIC_KEY_SIZE / 2, PUBLIC_KEY_SIZE / 2);
1260
1261     ret = OC_STACK_OK;
1262     exit:
1263     return ret;
1264 }
1265
1266 int GetDtlsX509Credentials(CADtlsX509Creds_t *credInfo)
1267 {
1268     int ret = 1;
1269     VERIFY_NON_NULL(TAG, credInfo, ERROR);
1270     if (NULL == gCred)
1271     {
1272         VERIFY_SUCCESS(TAG, OC_STACK_OK == InitCredResource(), ERROR);
1273     }
1274
1275     OicSecCred_t *cred = NULL;
1276     LL_SEARCH_SCALAR(gCred, cred, credType, SIGNED_ASYMMETRIC_KEY);
1277     VERIFY_NON_NULL(TAG, cred, ERROR);
1278
1279     CborValue credCbor = { .parser = NULL };
1280     CborParser parser = { .end = NULL };
1281     CborError cborFindResult = CborNoError;
1282     uint8_t *cborPayload = cred->publicData.data;
1283     int cborLen = cred->publicData.len;
1284     cbor_parser_init(cborPayload, cborLen, 0, &parser, &credCbor);
1285     CborValue certMap;
1286     cborFindResult = cbor_value_enter_container(&credCbor, &certMap);
1287     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Map.");
1288
1289     CborValue certs;
1290     cborFindResult = cbor_value_map_find_value(&certs, CERTIFICATE, &certs);
1291     if (cbor_value_is_array(&certs))
1292     {
1293         cborFindResult = cbor_value_get_array_length(&certs, (size_t *)&credInfo->chainLen);
1294         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Chain Len.");
1295         CborValue cert;
1296         cborFindResult = cbor_value_enter_container(&certs, &cert);
1297         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering Container.");
1298         size_t len = 0;
1299         size_t certLen = 0;
1300         uint8_t *val = NULL;
1301         while (cbor_value_is_byte_string(&cert))
1302         {
1303             cborFindResult = cbor_value_dup_byte_string(&cert, &val, &certLen, NULL);
1304             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding a Period Array Value.");
1305             cborFindResult = cbor_value_advance(&cert);
1306             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing a Period Array.");
1307             uint32_t appendedLen = appendCert2Chain(credInfo->certificateChain + len, val, certLen, MAX_CERT_MESSAGE_LEN - len);
1308             len += appendedLen;
1309         }
1310         credInfo->certificateChainLen = len;
1311         GetCAPublicKeyData(credInfo);
1312     }
1313     memcpy(credInfo->devicePrivateKey, cred->privateData.data, PRIVATE_KEY_SIZE);
1314
1315     ret = 0;
1316 exit:
1317
1318     return ret;
1319 }
1320 #undef CERT_LEN_PREFIX
1321 #endif /* __WITH_X509__ */