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