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