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