Fixed compiler warnings
[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 <stdlib.h>
37 #ifdef WITH_ARDUINO
38 #include <string.h>
39 #else
40 #include <strings.h>
41 #endif
42 #include <stdint.h>
43
44 #define TAG  PCF("SRM-CREDL")
45
46
47 static OicSecCred_t        *gCred = NULL;
48 static OCResourceHandle    gCredHandle = NULL;
49
50 /**
51  * This function frees OicSecCred_t object's fields and object itself.
52  */
53 static void FreeCred(OicSecCred_t *cred)
54 {
55     if(NULL == cred)
56     {
57         OC_LOG (INFO, TAG, PCF("Invalid Parameter"));
58         return;
59     }
60     //Note: Need further clarification on roleID data type
61 #if 0
62     //Clean roleIds
63     OICFree(cred->roleIds);
64 #endif
65
66     //Clean PublicData
67     OICFree(cred->publicData.data);
68
69     //Clean PrivateData
70     OICFree(cred->privateData.data);
71
72     //Clean Period
73     OICFree(cred->period);
74
75     //Clean Owners
76     OICFree(cred->owners);
77
78     //Clean Cred node itself
79     OICFree(cred);
80 }
81
82 void DeleteCredList(OicSecCred_t* cred)
83 {
84     if (cred)
85     {
86         OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
87         LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
88         {
89             LL_DELETE(cred, credTmp1);
90             FreeCred(credTmp1);
91         }
92     }
93 }
94
95 /**
96  * This function converts credential data into JSON format.
97  * Caller needs to invoke 'free' when done using
98  * returned string.
99  * @param cred  pointer to instance of OicSecCred_t structure.
100  *
101  * @retval
102  *      pointer to JSON credential representation - if credential for subjectId found
103  *      NULL                                      - if credential for subjectId not found
104  */
105 char * BinToCredJSON(const OicSecCred_t * cred)
106 {
107     cJSON *jsonRoot = NULL;
108     char *jsonStr = NULL;
109
110     if (cred)
111     {
112         char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
113         uint32_t outLen = 0;
114         B64Result b64Ret = B64_OK;
115
116         jsonRoot = cJSON_CreateObject();
117         VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
118
119         cJSON *jsonCredArray = NULL;
120         cJSON_AddItemToObject(jsonRoot, OIC_JSON_CRED_NAME,
121                 jsonCredArray = cJSON_CreateArray());
122         VERIFY_NON_NULL(TAG, jsonCredArray, ERROR);
123
124         while(cred)
125         {
126             cJSON *jsonCred = cJSON_CreateObject();
127             VERIFY_NON_NULL(TAG, jsonCred, ERROR);
128
129             //CredID -- Mandatory
130             cJSON_AddNumberToObject(jsonCred, OIC_JSON_CREDID_NAME, (int)cred->credId);
131
132             //Subject -- Mandatory
133             outLen = 0;
134             memset(base64Buff, 0, sizeof(base64Buff));
135             b64Ret = b64Encode(cred->subject.id, sizeof(cred->subject.id), base64Buff,
136                    sizeof(base64Buff), &outLen);
137             VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
138             cJSON_AddStringToObject(jsonCred, OIC_JSON_SUBJECT_NAME, base64Buff);
139
140             //Note: Need further clarification on roleID data type
141 #if 0
142             //RoleId -- Not Mandatory
143             if(cred->roleIdsLen > 0)
144             {
145                 cJSON *jsonRoleIdsArray = NULL;
146                 cJSON_AddItemToObject (jsonCred, OIC_JSON_ROLEIDS_NAME,
147                                          jsonRoleIdsArray = cJSON_CreateArray());
148                 VERIFY_NON_NULL(TAG, jsonRoleIdsArray, ERROR);
149                 for (size_t i = 0; i < cred->roleIdsLen; i++)
150                 {
151                     cJSON_AddItemToArray (jsonRoleIdsArray,
152                             cJSON_CreateString((char *)cred->roleIds[i].id));
153                 }
154             }
155 #endif
156
157             //CredType -- Mandatory
158             cJSON_AddNumberToObject(jsonCred, OIC_JSON_CREDTYPE_NAME,(int)cred->credType);
159
160 #if 0
161             //PublicData -- Not Mandatory
162             if(cred->publicData.data)
163             {
164                 cJSON_AddStringToObject(jsonCred, OIC_JSON_PUBLICDATA_NAME, cred->publicData.data);
165             }
166 #endif
167             //PrivateData -- Not Mandatory
168             if(cred->privateData.data)
169             {
170                 cJSON_AddStringToObject(jsonCred, OIC_JSON_PRIVATEDATA_NAME, cred->privateData.data);
171             }
172
173             //Period -- Not Mandatory
174             if(cred->period)
175             {
176                 cJSON_AddStringToObject(jsonCred, OIC_JSON_PERIOD_NAME,
177                                         cred->period);
178             }
179
180             //Owners -- Mandatory
181             cJSON *jsonOwnrArray = NULL;
182             cJSON_AddItemToObject (jsonCred, OIC_JSON_OWNERS_NAME,
183                                              jsonOwnrArray = cJSON_CreateArray());
184             VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
185             for (size_t i = 0; i < cred->ownersLen; i++)
186             {
187                 outLen = 0;
188                 memset(base64Buff, 0, sizeof(base64Buff));
189                 b64Ret = b64Encode(cred->owners[i].id, sizeof(cred->owners[i].id),
190                         base64Buff, sizeof(base64Buff), &outLen);
191                 VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
192                 cJSON_AddItemToArray (jsonOwnrArray,
193                                        cJSON_CreateString((char *)(base64Buff)));
194             }
195
196             /* Attach current cred node to cred Array */
197             cJSON_AddItemToArray(jsonCredArray, jsonCred);
198             cred = cred->next;
199         }
200
201         jsonStr = cJSON_PrintUnformatted(jsonRoot);
202     }
203
204 exit:
205     if (jsonRoot)
206     {
207         cJSON_Delete(jsonRoot);
208     }
209     return jsonStr;
210 }
211
212 /*
213  * This internal method converts JSON cred into binary cred.
214  */
215 OicSecCred_t * JSONToCredBin(const char * jsonStr)
216 {
217     OCStackResult ret = OC_STACK_ERROR;
218     OicSecCred_t * headCred = NULL;
219     OicSecCred_t * prevCred = NULL;
220     cJSON *jsonCredArray = NULL;
221
222     cJSON *jsonRoot = cJSON_Parse(jsonStr);
223     VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
224
225     jsonCredArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_CRED_NAME);
226     VERIFY_NON_NULL(TAG, jsonCredArray, ERROR);
227     if (cJSON_Array == jsonCredArray->type)
228     {
229         int numCred = cJSON_GetArraySize(jsonCredArray);
230         int idx = 0;
231
232         unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
233         uint32_t outLen = 0;
234         B64Result b64Ret = B64_OK;
235
236         VERIFY_SUCCESS(TAG, numCred > 0, ERROR);
237         do
238         {
239             cJSON *jsonCred = cJSON_GetArrayItem(jsonCredArray, idx);
240             VERIFY_NON_NULL(TAG, jsonCred, ERROR);
241
242             OicSecCred_t *cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
243             VERIFY_NON_NULL(TAG, cred, ERROR);
244
245             headCred = (headCred) ? headCred : cred;
246             if (prevCred)
247             {
248                 prevCred->next = cred;
249             }
250             size_t jsonObjLen = 0;
251             cJSON *jsonObj = NULL;
252
253             //CredId -- Mandatory
254             jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_CREDID_NAME);
255             if(jsonObj)
256             {
257                 VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
258                 cred->credId = jsonObj->valueint;
259             }
260
261             //subject -- Mandatory
262             jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_SUBJECT_NAME);
263             VERIFY_NON_NULL(TAG, jsonObj, ERROR);
264             VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
265             outLen = 0;
266             memset(base64Buff, 0, sizeof(base64Buff));
267             b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring),
268                     base64Buff, sizeof(base64Buff), &outLen);
269             VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(cred->subject.id)),
270                            ERROR);
271             memcpy(cred->subject.id, base64Buff, outLen);
272
273             //CredType -- Mandatory
274             jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_CREDTYPE_NAME);
275             VERIFY_NON_NULL(TAG, jsonObj, ERROR);
276             VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
277             cred->credType = jsonObj->valueint;
278
279             //PrivateData is mandatory for some of the credential types listed below.
280             jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PRIVATEDATA_NAME);
281             if ((cred->credType & SYMMETRIC_PAIR_WISE_KEY) ||
282                 (cred->credType & SYMMETRIC_GROUP_KEY) ||
283                 (cred->credType & PIN_PASSWORD))
284             {
285                 VERIFY_NON_NULL(TAG, jsonObj, ERROR);
286                 VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
287             }
288             if(jsonObj && cJSON_String == jsonObj->type)
289             {
290                 jsonObjLen = strlen(jsonObj->valuestring) + 1;
291                 cred->privateData.data = (char *)OICMalloc(jsonObjLen);
292                 VERIFY_NON_NULL(TAG, (cred->privateData.data), ERROR);
293                 strncpy((char *)cred->privateData.data, (char *)jsonObj->valuestring, jsonObjLen);
294             }
295
296             //Period -- Not Mandatory
297             jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PERIOD_NAME);
298             if(jsonObj && cJSON_String == jsonObj->type)
299             {
300                 jsonObjLen = strlen(jsonObj->valuestring) + 1;
301                 cred->period = (char *)OICMalloc(jsonObjLen);
302                 VERIFY_NON_NULL(TAG, cred->period, ERROR);
303                 strncpy(cred->period, jsonObj->valuestring, jsonObjLen);
304             }
305
306             //Owners -- Mandatory
307             jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_OWNERS_NAME);
308             VERIFY_NON_NULL(TAG, jsonObj, ERROR);
309             VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR)
310             cred->ownersLen = cJSON_GetArraySize(jsonObj);
311             VERIFY_SUCCESS(TAG, cred->ownersLen > 0, ERROR);
312             cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
313             VERIFY_NON_NULL(TAG, (cred->owners), ERROR);
314             for(size_t i = 0; i < cred->ownersLen; i++)
315             {
316                 cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, i);
317                 VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
318                 VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
319                 outLen = 0;
320                 memset(base64Buff, 0, sizeof(base64Buff));
321                 b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring),
322                          base64Buff, sizeof(base64Buff), &outLen);
323                 VERIFY_SUCCESS(TAG, (b64Ret == B64_OK &&
324                                outLen <= sizeof(cred->owners[i].id)), ERROR);
325                 memcpy(cred->owners[i].id, base64Buff, outLen);
326             }
327             prevCred = cred;
328         } while( ++idx < numCred);
329     }
330
331     ret = OC_STACK_OK;
332
333 exit:
334     cJSON_Delete(jsonRoot);
335     if (OC_STACK_OK != ret)
336     {
337         DeleteCredList(headCred);
338         headCred = NULL;
339     }
340     return headCred;
341 }
342
343 /**
344  * This function generates the bin credential data.
345  *
346  * @param subject pointer to subject of this credential.
347  * @param credType credential type.
348  * @param publicData public data such as public key.
349  * @param privateData private data such as private key.
350  *        The privateData is expected in base64 encoded format.
351  * @param ownersLen length of owners array
352  * @param owners array of owners.
353  *
354  * @retval
355  *      pointer to instance of OicSecCred_t  - success
356  *      NULL                                 - error
357  */
358 OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t credType,
359                                  const char * publicData, const char * privateData,
360                                  size_t ownersLen, const OicUuid_t * owners)
361 {
362     (void)publicData;
363     OCStackResult ret = OC_STACK_ERROR;
364
365     OicSecCred_t *cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
366     VERIFY_NON_NULL(TAG, cred, ERROR);
367
368     //CredId is assigned before appending new cred to the existing
369     //credential list and updating svr database in AddCredential().
370     cred->credId = 0;
371
372     VERIFY_NON_NULL(TAG, subject, ERROR);
373     memcpy(cred->subject.id, subject->id , sizeof(cred->subject.id));
374
375     VERIFY_SUCCESS(TAG, credType < (NO_SECURITY_MODE | SYMMETRIC_PAIR_WISE_KEY |
376             SYMMETRIC_GROUP_KEY | ASYMMETRIC_KEY | SIGNED_ASYMMETRIC_KEY | PIN_PASSWORD), ERROR);
377     cred->credType = credType;
378
379 #if 0
380     if(publicData)
381     {
382         cred->publicData.data = (char *)OICMalloc(strlen(publicData)+1);
383         VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
384         strncpy((char *)cred->publicData.data, publicData, strlen(publicData)+1);
385     }
386 #endif
387
388     if(privateData)
389     {
390         cred->privateData.data = (char *)OICMalloc(strlen(privateData)+1);
391         VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
392         strncpy((char *)cred->privateData.data, privateData, strlen(privateData)+1);
393     }
394
395     VERIFY_SUCCESS(TAG, ownersLen > 0, ERROR);
396     cred->ownersLen = ownersLen;
397
398     cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
399     VERIFY_NON_NULL(TAG, cred->owners, ERROR);
400     for(size_t i = 0; i < cred->ownersLen; i++)
401     {
402         memcpy(cred->owners[i].id, owners[i].id, sizeof(cred->owners[i].id));
403     }
404
405     ret = OC_STACK_OK;
406 exit:
407     if (OC_STACK_OK != ret)
408     {
409         DeleteCredList(cred);
410         cred = NULL;
411     }
412     return cred;
413 }
414
415 static bool UpdatePersistentStorage(const OicSecCred_t *cred)
416 {
417     bool ret = false;
418
419     // Convert Cred data into JSON for update to persistent storage
420     char *jsonStr = BinToCredJSON(cred);
421     if (jsonStr)
422     {
423         cJSON *jsonCred = cJSON_Parse(jsonStr);
424         OICFree(jsonStr);
425
426         if ((jsonCred) &&
427           (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, jsonCred)))
428         {
429             ret = true;
430         }
431         cJSON_Delete(jsonCred );
432     }
433     else //Empty cred list
434     {
435         if (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, NULL))
436         {
437             ret = true;
438         }
439     }
440     return ret;
441 }
442
443 /**
444  * Compare function used LL_SORT for sorting credentials
445  *
446  * @param first   pointer to OicSecCred_t struct
447  * @param second  pointer to OicSecCred_t struct
448  *
449  *@retval
450  *  -1    if credId of first is less than credId of second
451  *   0    if credId of first is equal to credId of second
452  *   1    if credId of first is greater than credId of second
453  */
454 static int CmpCredId(const OicSecCred_t * first, const OicSecCred_t *second)
455 {
456     if(first->credId < second->credId)
457     {
458         return -1;
459     }
460     else if(first->credId > second->credId)
461     {
462         return 1;
463     }
464     else
465         return 0;
466 }
467
468 /**
469  * GetCredId goes through the cred list and returns the next
470  * available credId. The next credId could be the credId that is
471  * available due deletion of OicSecCred_t object or one more than
472  * credId of last credential in the list.
473  *
474  * @retval
475  *      next available credId  - success
476  *      0                      - error
477  */
478
479 static uint16_t GetCredId()
480 {
481     //Sorts credential list in incremental order of credId
482     LL_SORT(gCred, CmpCredId);
483
484
485     OicSecCred_t *currentCred = NULL, *credTmp = NULL;
486     uint16_t nextCredId = 1;
487
488     LL_FOREACH_SAFE(gCred, currentCred, credTmp)
489     {
490         if(currentCred->credId == nextCredId)
491         {
492             nextCredId += 1;
493         }
494         else
495         {
496             break;
497         }
498     }
499
500     VERIFY_SUCCESS(TAG, nextCredId < UINT16_MAX, ERROR);
501     return nextCredId;
502
503 exit:
504     return 0;
505 }
506
507
508 /**
509  * This function adds the new cred to the credential list.
510  *
511  * @param cred pointer to new credential.
512  *
513  * @retval
514  *      OC_STACK_OK     - cred not NULL and persistent storage gets updated
515  *      OC_STACK_ERROR  - cred is NULL or fails to update persistent storage
516  */
517 OCStackResult AddCredential(OicSecCred_t * newCred)
518 {
519     OCStackResult ret = OC_STACK_ERROR;
520
521     VERIFY_SUCCESS(TAG, NULL != newCred, ERROR);
522
523     //Assigning credId to the newCred
524     newCred->credId = GetCredId();
525
526     VERIFY_SUCCESS(TAG, newCred->credId != 0, ERROR);
527
528     //Append the new Cred to existing list
529     LL_APPEND(gCred, newCred);
530
531     if(UpdatePersistentStorage(gCred))
532     {
533         ret = OC_STACK_OK;
534     }
535
536 exit:
537     return ret;
538 }
539
540 OCStackResult RemoveCredential(const OicUuid_t *subject)
541 {
542     OCStackResult ret = OC_STACK_ERROR;
543     OicSecCred_t *cred = NULL;
544     OicSecCred_t *tempCred = NULL;
545     bool deleteFlag = false;
546
547     LL_FOREACH_SAFE(gCred, cred, tempCred)
548     {
549         if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
550         {
551             LL_DELETE(gCred, cred);
552             FreeCred(cred);
553             deleteFlag = 1;
554         }
555     }
556
557     if(deleteFlag)
558     {
559         if(UpdatePersistentStorage(gCred))
560         {
561             ret = OC_STACK_RESOURCE_DELETED;
562         }
563     }
564     return ret;
565
566 }
567
568 static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
569 {
570     OCEntityHandlerResult ret = OC_EH_ERROR;
571
572     //Get binary representation of json
573     OicSecCred_t * cred  = JSONToCredBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
574
575     if(cred)
576     {
577         //If the Post request credential has credId, it will be
578         //discarded and the next available credId will be assigned
579         //to it before getting appended to the existing credential
580         //list and updating svr database.
581         ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
582     }
583
584     return ret;
585 }
586
587 static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
588 {
589     OC_LOG_V (INFO, TAG, PCF("Processing CredDeleteRequest"));
590
591     OCEntityHandlerResult ehRet = OC_EH_ERROR;
592
593     if(NULL == ehRequest->query)
594    {
595        return ehRet;
596    }
597
598    OicParseQueryIter_t parseIter = {.attrPos=NULL};
599    OicUuid_t subject = {.id={0}};
600
601    //Parsing REST query to get the subject
602    ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
603    while(GetNextQuery(&parseIter))
604    {
605        if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME,
606                parseIter.attrLen) == 0)
607        {
608            unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
609            uint32_t outLen = 0;
610            B64Result b64Ret = B64_OK;
611
612            b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen,
613                    base64Buff, sizeof(base64Buff), &outLen);
614
615            VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(subject.id)), ERROR);
616            memcpy(subject.id, base64Buff, outLen);
617        }
618    }
619
620    if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
621    {
622        ehRet = OC_EH_RESOURCE_DELETED;
623    }
624
625 exit:
626     return ehRet;
627 }
628
629
630 /*
631  * This internal method is the entity handler for Cred resources
632  * to handle REST request (PUT/POST/DEL)
633  */
634 OCEntityHandlerResult CredEntityHandler (OCEntityHandlerFlag flag,
635                                         OCEntityHandlerRequest * ehRequest,
636                                         void* callbackParameter)
637 {
638     (void)callbackParameter;
639     OCEntityHandlerResult ret = OC_EH_ERROR;
640
641     if(!ehRequest)
642     {
643         return OC_EH_ERROR;
644     }
645     if (flag & OC_REQUEST_FLAG)
646     {
647         OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
648         //TODO :  Handle PUT/DEL methods
649         switch(ehRequest->method)
650         {
651             case OC_REST_GET:
652                 ret = OC_EH_FORBIDDEN;
653                 break;
654             case OC_REST_POST:
655                 ret = HandlePostRequest(ehRequest);
656                 break;
657             case OC_REST_DELETE:
658                 ret = HandleDeleteRequest(ehRequest);
659                 break;
660             default:
661                 ret = OC_EH_ERROR;
662                 break;
663         }
664     }
665
666     //Send payload to request originator
667     ret = (SendSRMResponse(ehRequest, ret, NULL) == OC_STACK_OK ?
668                        ret : OC_EH_ERROR);
669
670     return ret;
671 }
672
673 /*
674  * This internal method is used to create '/oic/sec/Cred' resource.
675  */
676 OCStackResult CreateCredResource()
677 {
678     OCStackResult ret;
679
680     ret = OCCreateResource(&gCredHandle,
681                            OIC_RSRC_TYPE_SEC_CRED,
682                            OIC_MI_DEF,
683                            OIC_RSRC_CRED_URI,
684                            CredEntityHandler,
685                            NULL,
686                            OC_RES_PROP_NONE);
687
688     if (OC_STACK_OK != ret)
689     {
690         OC_LOG (FATAL, TAG, PCF("Unable to instantiate Cred resource"));
691         DeInitCredResource();
692     }
693     return ret;
694 }
695
696 /**
697  * Get the default value
698  * @retval  NULL for now. Update it when we finalize the default info.
699  */
700 static OicSecCred_t* GetCredDefault()
701 {
702     return NULL;
703 }
704
705 /**
706  * Initialize Cred resource by loading data from persistent storage.
707  *
708  * @retval
709  *     OC_STACK_OK    - no errors
710  *     OC_STACK_ERROR - stack process error
711  */
712 OCStackResult InitCredResource()
713 {
714     OCStackResult ret = OC_STACK_ERROR;
715
716     //Read Cred resource from PS
717     char* jsonSVRDatabase = GetSVRDatabase();
718
719     if (jsonSVRDatabase)
720     {
721         //Convert JSON Cred into binary format
722         gCred = JSONToCredBin(jsonSVRDatabase);
723     }
724     /*
725      * If SVR database in persistent storage got corrupted or
726      * is not available for some reason, a default Cred is created
727      * which allows user to initiate Cred provisioning again.
728      */
729     if (!jsonSVRDatabase || !gCred)
730     {
731         gCred = GetCredDefault();
732     }
733     //Instantiate 'oic.sec.cred'
734     ret = CreateCredResource();
735     OICFree(jsonSVRDatabase);
736     return ret;
737 }
738
739 /**
740  * Perform cleanup for Cred resources.
741  *
742  * @return
743  *     OC_STACK_OK              - no errors
744  *     OC_STACK_ERROR           - stack process error
745  *     OC_STACK_NO_RESOURCE     - resource not found
746  *     OC_STACK_INVALID_PARAM   - invalid param
747  */
748 OCStackResult DeInitCredResource()
749 {
750     OCStackResult result = OCDeleteResource(gCredHandle);
751     DeleteCredList(gCred);
752     gCred = NULL;
753     return result;
754 }
755
756 /**
757  * This method is used by tinydtls/SRM to retrieve credential for given Subject.
758  *
759  * @param subject - subject for which credential is required.
760  *
761  * @retval
762  *     reference to OicSecCred_t - if credential is found
763  *     NULL                      - if credential not found
764  */
765 const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
766 {
767     OicSecCred_t *cred = NULL;
768
769    if ( NULL == subject)
770     {
771        return NULL;
772     }
773
774     LL_FOREACH(gCred, cred)
775     {
776         if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
777         {
778             return cred;
779         }
780     }
781     return NULL;
782 }
783
784
785 #if defined(__WITH_DTLS__)
786 /**
787  * This internal callback is used by lower stack (i.e. CA layer) to
788  * retrieve PSK credentials from RI security layer.
789  *
790  * Note: When finished, caller should initialize memory to zeros and
791  * invoke OICFree to delete @p credInfo.
792  *
793  * @param credInfo
794  *     binary blob containing PSK credentials
795  *
796  * @retval none
797  */
798 void GetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo)
799 {
800     CADtlsPskCredsBlob_t * caBlob = NULL;
801     if(credInfo)
802     {
803         caBlob = (CADtlsPskCredsBlob_t *)OICCalloc(sizeof(CADtlsPskCredsBlob_t), 1);
804         if (caBlob)
805         {
806             OicUuid_t deviceID = {.id={}};
807
808             // Retrieve Device ID from doxm resource and copy in PSK creds blob
809             VERIFY_SUCCESS(TAG, GetDoxmDeviceID(&deviceID) == OC_STACK_OK, ERROR);
810             memcpy(caBlob->identity, deviceID.id, sizeof(caBlob->identity));
811
812             OicSecCred_t *cred = NULL;
813             size_t count = 0;
814             LL_FOREACH(gCred, cred)
815             {
816                 // Currently, Iotivity supports only symmetric pair wise key credentials
817                 if (cred->credType == SYMMETRIC_PAIR_WISE_KEY)
818                 {
819                     ++count;
820                 }
821             }
822             caBlob->num = count;
823             if (caBlob->num)
824             {
825                 caBlob->creds =
826                     (OCDtlsPskCreds*) OICMalloc(caBlob->num * sizeof(OCDtlsPskCreds));
827                 VERIFY_NON_NULL(TAG, caBlob->creds, ERROR);
828
829                 unsigned int i = 0;
830                 LL_FOREACH(gCred, cred)
831                 {
832                     if ((cred->credType == SYMMETRIC_PAIR_WISE_KEY) &&
833                             (i < count))
834
835                     {
836                         // Copy subject ID
837                         memcpy(caBlob->creds[i].id, cred->subject.id,
838                                 sizeof(caBlob->creds[i].id));
839
840                         // Convert PSK from JSON to binary before copying
841                         uint32_t outLen = 0;
842                         B64Result b64Ret = b64Decode(cred->privateData.data,
843                                 strlen(cred->privateData.data), caBlob->creds[i].psk,
844                                 sizeof(caBlob->creds[i].psk), &outLen);
845                         VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
846                         i++;
847                     }
848                 }
849             }
850         }
851         *credInfo = caBlob;
852         // Return from here after making the credential list
853         return;
854     }
855
856 exit:
857     if (caBlob)
858     {
859         memset(caBlob->creds, 0, caBlob->num * sizeof(OCDtlsPskCreds));
860         OICFree(caBlob->creds);
861     }
862     OICFree(caBlob);
863 }
864 #endif /* __WITH_DTLS__ */