Svace Defects Fixes.
[platform/upstream/iotivity.git] / resource / csdk / security / src / credresource.c
1 //******************************************************************
2 //
3 // Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #define __STDC_LIMIT_MACROS
22
23 #include <stdlib.h>
24 #ifdef WITH_ARDUINO
25 #include <string.h>
26 #else
27 #include <strings.h>
28 #endif
29 #include <stdint.h>
30
31 #include "cainterface.h"
32 #include "payload_logging.h"
33 #include "ocstack.h"
34 #include "ocrandom.h"
35 #include "base64.h"
36 #include "ocserverrequest.h"
37 #include "oic_malloc.h"
38 #include "ocpayload.h"
39 #include "utlist.h"
40 #include "credresource.h"
41 #include "doxmresource.h"
42 #include "pstatresource.h"
43 #include "iotvticalendar.h"
44 #include "pbkdf2.h"
45 #include "resourcemanager.h"
46 #include "srmresourcestrings.h"
47 #include "srmutility.h"
48 #include "psinterface.h"
49 #include "pinoxmcommon.h"
50
51 #ifdef __WITH_DTLS__
52 #include "global.h"
53 #endif
54
55 #define TAG  "SRM-CREDL"
56
57 /** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
58  * The value of payload size is increased until reaching belox max cbor size. */
59 static const uint16_t CBOR_SIZE = 2048;
60
61 /** Max cbor size payload. */
62 static const uint16_t CBOR_MAX_SIZE = 4400;
63
64 /** CRED size - Number of mandatory items. */
65 static const uint8_t CRED_ROOT_MAP_SIZE = 2;
66 static const uint8_t CRED_MAP_SIZE = 3;
67
68
69 static OicSecCred_t        *gCred = NULL;
70 static OCResourceHandle    gCredHandle = NULL;
71
72 /**
73  * This function frees OicSecCred_t object's fields and object itself.
74  */
75 static void FreeCred(OicSecCred_t *cred)
76 {
77     if(NULL == cred)
78     {
79         OIC_LOG(ERROR, TAG, "Invalid Parameter");
80         return;
81     }
82     //Note: Need further clarification on roleID data type
83 #if 0
84     //Clean roleIds
85     OICFree(cred->roleIds);
86 #endif
87
88     //Clean PublicData
89 #ifdef __WITH_X509__
90     OICFree(cred->publicData.data);
91 #endif
92
93     //Clean PrivateData
94     OICFree(cred->privateData.data);
95
96     //Clean Period
97     OICFree(cred->period);
98
99     //Clean Cred node itself
100     OICFree(cred);
101 }
102
103 void DeleteCredList(OicSecCred_t* cred)
104 {
105     if (cred)
106     {
107         OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
108         LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
109         {
110             LL_DELETE(cred, credTmp1);
111             FreeCred(credTmp1);
112         }
113     }
114 }
115
116 static size_t OicSecCredCount(const OicSecCred_t *secCred)
117 {
118     size_t size = 0;
119     for (const OicSecCred_t *cred = secCred; cred; cred = cred->next)
120     {
121         size++;
122     }
123     return size;
124 }
125
126 OCStackResult CredToCBORPayload(const OicSecCred_t *credS, uint8_t **cborPayload,
127                                 size_t *cborSize, int secureFlag)
128 {
129     if (NULL == credS || NULL == cborPayload || NULL != *cborPayload || NULL == cborSize)
130     {
131         return OC_STACK_INVALID_PARAM;
132     }
133
134     OCStackResult ret = OC_STACK_ERROR;
135
136     CborError cborEncoderResult = CborNoError;
137     uint8_t *outPayload = NULL;
138     size_t cborLen = *cborSize;
139     *cborSize = 0;
140     *cborPayload = NULL;
141     const OicSecCred_t *cred = credS;
142     CborEncoder encoder;
143     CborEncoder credArray;
144     CborEncoder credRootMap;
145
146     if (0 == cborLen)
147     {
148         cborLen = CBOR_SIZE;
149     }
150
151     outPayload = (uint8_t *)OICCalloc(1, cborLen);
152     VERIFY_NON_NULL(TAG, outPayload, ERROR);
153     cbor_encoder_init(&encoder, outPayload, cborLen, 0);
154
155     // Create CRED Root Map (creds, rownerid)
156     cborEncoderResult = cbor_encoder_create_map(&encoder, &credRootMap, CRED_ROOT_MAP_SIZE);
157     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Root Map");
158
159     // creds
160     cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_CREDS_NAME,
161         strlen(OIC_JSON_CREDS_NAME));
162     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding creds Name Tag.");
163
164     // creds array
165     cborEncoderResult = cbor_encoder_create_array(&credRootMap, &credArray, OicSecCredCount(cred));
166     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Array.");
167
168     while (cred)
169     {
170         CborEncoder credMap;
171         size_t mapSize = CRED_MAP_SIZE;
172         char *subject = NULL;
173         if (cred->period)
174         {
175             mapSize++;
176         }
177 #ifdef __WITH_X509__
178         if (SIGNED_ASYMMETRIC_KEY == cred->credType && cred->publicData.data)
179         {
180             mapSize++;
181         }
182 #endif /* __WITH_X509__ */
183         if (!secureFlag && cred->privateData.data)
184         {
185             mapSize++;
186         }
187         cborEncoderResult = cbor_encoder_create_map(&credArray, &credMap, mapSize);
188         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Map");
189
190         //CredID -- Mandatory
191         cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDID_NAME,
192             strlen(OIC_JSON_CREDID_NAME));
193         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Id Tag. ");
194         cborEncoderResult = cbor_encode_int(&credMap, cred->credId);
195         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Id Value.");
196
197         //Subject -- Mandatory
198         cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_SUBJECTID_NAME,
199             strlen(OIC_JSON_SUBJECTID_NAME));
200         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Subject Tag.");
201         ret = ConvertUuidToStr(&cred->subject, &subject);
202         VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
203         cborEncoderResult = cbor_encode_text_string(&credMap, subject, strlen(subject));
204         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding Subject Id Value.");
205         OICFree(subject);
206
207         //CredType -- Mandatory
208         cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_CREDTYPE_NAME,
209             strlen(OIC_JSON_CREDTYPE_NAME));
210         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Tag.");
211         cborEncoderResult = cbor_encode_int(&credMap, cred->credType);
212         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Cred Type Value.");
213
214 #ifdef __WITH_X509__
215         //PublicData -- Not Mandatory
216         if (SIGNED_ASYMMETRIC_KEY == cred->credType && cred->publicData.data)
217         {
218             CborEncoder publicMap;
219             const size_t publicMapSize = 2;
220
221             cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_PUBLICDATA_NAME,
222                 strlen(OIC_JSON_PUBLICDATA_NAME));
223             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PublicData Tag.");
224
225             cborEncoderResult = cbor_encoder_create_map(&credMap, &publicMap, publicMapSize);
226             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PublicData Map");
227
228             cborEncoderResult = cbor_encode_text_string(&publicMap, OIC_JSON_DATA_NAME,
229                 strlen(OIC_JSON_DATA_NAME));
230             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pub Data Tag.");
231             cborEncoderResult = cbor_encode_byte_string(&publicMap, cred->publicData.data,
232                 cred->publicData.len);
233             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Pub Value.");
234
235             // TODO: Need to data strucure modification for OicSecCert_t.
236             cborEncoderResult = cbor_encode_text_string(&publicMap, OIC_JSON_ENCODING_NAME,
237                 strlen(OIC_JSON_ENCODING_NAME));
238             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Public Encoding Tag.");
239             cborEncoderResult = cbor_encode_text_string(&publicMap, OIC_SEC_ENCODING_RAW,
240                 strlen(OIC_SEC_ENCODING_RAW));
241             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Public Encoding Value.");
242
243             cborEncoderResult = cbor_encoder_close_container(&credMap, &publicMap);
244             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing PublicData Map.");
245         }
246 #endif /*__WITH_X509__*/
247         //PrivateData -- Not Mandatory
248         if(!secureFlag && cred->privateData.data)
249         {
250             CborEncoder privateMap;
251             const size_t privateMapSize = 2;
252
253             cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_PRIVATEDATA_NAME,
254                 strlen(OIC_JSON_PRIVATEDATA_NAME));
255             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PrivateData Tag.");
256
257             cborEncoderResult = cbor_encoder_create_map(&credMap, &privateMap, privateMapSize);
258             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding PrivateData Map");
259
260             // TODO: Need to data strucure modification for OicSecKey_t.
261             // TODO: Added as workaround, will be replaced soon.
262             if(OIC_ENCODING_RAW == cred->privateData.encoding)
263             {
264                 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_ENCODING_NAME,
265                     strlen(OIC_JSON_ENCODING_NAME));
266                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Tag.");
267                 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_SEC_ENCODING_RAW,
268                     strlen(OIC_SEC_ENCODING_RAW));
269                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Value.");
270
271                 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_DATA_NAME,
272                     strlen(OIC_JSON_DATA_NAME));
273                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Tag.");
274                 cborEncoderResult = cbor_encode_byte_string(&privateMap, cred->privateData.data,
275                     cred->privateData.len);
276                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Value.");
277             }
278             else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
279             {
280                 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_ENCODING_NAME,
281                     strlen(OIC_JSON_ENCODING_NAME));
282                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Tag.");
283                 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_SEC_ENCODING_BASE64,
284                     strlen(OIC_SEC_ENCODING_BASE64));
285                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Value.");
286
287                 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_DATA_NAME,
288                     strlen(OIC_JSON_DATA_NAME));
289                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Tag.");
290                 cborEncoderResult = cbor_encode_text_string(&privateMap, (char*)(cred->privateData.data),
291                     cred->privateData.len);
292                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Value.");
293             }
294             else
295             {
296                 OIC_LOG(ERROR, TAG, "Unknow encoding type for private data.");
297                 VERIFY_CBOR_SUCCESS(TAG, CborErrorUnknownType, "Failed Adding Private Encoding Value.");
298             }
299
300             cborEncoderResult = cbor_encoder_close_container(&credMap, &privateMap);
301             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing PrivateData Map.");
302         }
303
304         //Period -- Not Mandatory
305         if(cred->period)
306         {
307             cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_PERIOD_NAME,
308                 strlen(OIC_JSON_PERIOD_NAME));
309             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Name Tag.");
310             cborEncoderResult = cbor_encode_text_string(&credMap, cred->period,
311                 strlen(cred->period));
312             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Name Value.");
313         }
314
315
316         cborEncoderResult = cbor_encoder_close_container(&credArray, &credMap);
317         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Cred Map.");
318
319         cred = cred->next;
320     }
321     cborEncoderResult = cbor_encoder_close_container(&credRootMap, &credArray);
322     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Cred Array.");
323
324     cred = credS;
325
326     // Rownerid
327     {
328         char *rowner = NULL;
329         cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_ROWNERID_NAME,
330             strlen(OIC_JSON_ROWNERID_NAME));
331         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding rownerid Name.");
332         ret = ConvertUuidToStr(&cred->rownerID, &rowner);
333         VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
334         cborEncoderResult = cbor_encode_text_string(&credRootMap, rowner, strlen(rowner));
335         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding rownerid Value.");
336         OICFree(rowner);
337     }
338
339     // Close CRED Root Map
340     cborEncoderResult = cbor_encoder_close_container(&encoder, &credRootMap);
341     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing CRED Root Map.");
342
343     if (CborNoError == cborEncoderResult)
344     {
345         OIC_LOG(DEBUG, TAG, "CredToCBORPayload Successed");
346         *cborPayload = outPayload;
347         *cborSize = encoder.ptr - outPayload;
348         ret = OC_STACK_OK;
349     }
350     OIC_LOG(DEBUG, TAG, "CredToCBORPayload OUT");
351 exit:
352     if (CborErrorOutOfMemory == cborEncoderResult)
353     {
354         OIC_LOG(DEBUG, TAG, "CredToCBORPayload:CborErrorOutOfMemory : retry with more memory");
355         // reallocate and try again!
356         OICFree(outPayload);
357         // Since the allocated initial memory failed, double the memory.
358         cborLen += encoder.ptr - encoder.end;
359         cborEncoderResult = CborNoError;
360         ret = CredToCBORPayload(credS, cborPayload, &cborLen, secureFlag);
361         *cborSize = cborLen;
362     }
363
364     if (CborNoError != cborEncoderResult)
365     {
366         OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
367         OICFree(outPayload);
368         outPayload = NULL;
369         *cborSize = 0;
370         *cborPayload = NULL;
371         ret = OC_STACK_ERROR;
372     }
373
374     return ret;
375 }
376
377 OCStackResult CBORPayloadToCred(const uint8_t *cborPayload, size_t size,
378                                 OicSecCred_t **secCred)
379 {
380     if (NULL == cborPayload || NULL == secCred || NULL != *secCred || 0 == size)
381     {
382         return OC_STACK_INVALID_PARAM;
383     }
384
385     OCStackResult ret = OC_STACK_ERROR;
386     CborValue credCbor = { .parser = NULL };
387     CborParser parser = { .end = NULL };
388     CborError cborFindResult = CborNoError;
389     cbor_parser_init(cborPayload, size, 0, &parser, &credCbor);
390
391     OicSecCred_t *headCred = (OicSecCred_t *) OICCalloc(1, sizeof(OicSecCred_t));
392
393     // Enter CRED Root Map
394     CborValue CredRootMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
395     cborFindResult = cbor_value_enter_container(&credCbor, &CredRootMap);
396     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering CRED Root Map.");
397
398     while (cbor_value_is_valid(&CredRootMap))
399     {
400         char* tagName = NULL;
401         size_t len = 0;
402         CborType type = cbor_value_get_type(&CredRootMap);
403         if (type == CborTextStringType && cbor_value_is_text_string(&CredRootMap))
404         {
405             cborFindResult = cbor_value_dup_text_string(&CredRootMap, &tagName, &len, NULL);
406             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in CRED Root Map.");
407             cborFindResult = cbor_value_advance(&CredRootMap);
408             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in CRED Root Map.");
409         }
410         if(tagName)
411         {
412             if (strcmp(tagName, OIC_JSON_CREDS_NAME)  == 0)
413             {
414                 // Enter CREDS Array
415                 size_t len = 0;
416                 int credCount = 0;
417                 CborValue credArray = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
418                 cborFindResult = cbor_value_enter_container(&CredRootMap, &credArray);
419                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Array.");
420
421                 while (cbor_value_is_valid(&credArray))
422                 {
423                     credCount++;
424                     //CredId -- Mandatory
425                     CborValue credMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
426                     cborFindResult = cbor_value_enter_container(&credArray, &credMap);
427                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Map.");
428                     OicSecCred_t *cred = NULL;
429
430                     if(1 == credCount)
431                     {
432                         cred = headCred;
433                     }
434                     else
435                     {
436                         cred = (OicSecCred_t *) OICCalloc(1, sizeof(OicSecCred_t));
437                         OicSecCred_t *temp = headCred;
438                         while (temp->next)
439                         {
440                             temp = temp->next;
441                         }
442                         temp->next = cred;
443                     }
444
445                     VERIFY_NON_NULL(TAG, cred, ERROR);
446
447                     while(cbor_value_is_valid(&credMap) && cbor_value_is_text_string(&credMap))
448                     {
449                         char* name = NULL;
450                         CborType type = cbor_value_get_type(&credMap);
451                         if (type == CborTextStringType)
452                         {
453                             cborFindResult = cbor_value_dup_text_string(&credMap, &name, &len, NULL);
454                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in CRED Map.");
455                             cborFindResult = cbor_value_advance(&credMap);
456                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in CRED Map.");
457                         }
458                         if(name)
459                         {
460                             //credid
461                             if (strcmp(name, OIC_JSON_CREDID_NAME)  == 0)
462                             {
463                                 cborFindResult = cbor_value_get_uint64(&credMap, (uint64_t *) &cred->credId);
464                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CredId.");
465                             }
466                             // subjectid
467                             if (strcmp(name, OIC_JSON_SUBJECTID_NAME)  == 0)
468                             {
469                                 char *subjectid = NULL;
470                                 cborFindResult = cbor_value_dup_text_string(&credMap, &subjectid, &len, NULL);
471                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding subjectid Value.");
472                                 ret = ConvertStrToUuid(subjectid, &cred->subject);
473                                 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
474                                 OICFree(subjectid);
475                             }
476                             // credtype
477                             if (strcmp(name, OIC_JSON_CREDTYPE_NAME)  == 0)
478                             {
479                                 cborFindResult = cbor_value_get_uint64(&credMap, (uint64_t *) &cred->credType);
480                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CredType.");
481                             }
482                             // privatedata
483                             if (strcmp(name, OIC_JSON_PRIVATEDATA_NAME)  == 0)
484                             {
485                                 CborValue privateMap = { .parser = NULL };
486                                 cborFindResult = cbor_value_enter_container(&credMap, &privateMap);
487
488                                 while (cbor_value_is_valid(&privateMap))
489                                 {
490                                     char* privname = NULL;
491                                     CborType type = cbor_value_get_type(&privateMap);
492                                     if (type == CborTextStringType && cbor_value_is_text_string(&privateMap))
493                                     {
494                                         cborFindResult = cbor_value_dup_text_string(&privateMap, &privname,
495                                                 &len, NULL);
496                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
497                                         cborFindResult = cbor_value_advance(&privateMap);
498                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
499                                     }
500                                     if (privname)
501                                     {
502                                         // PrivateData::privdata -- Mandatory
503                                         if (strcmp(privname, OIC_JSON_DATA_NAME) == 0)
504                                         {
505                                             if(cbor_value_is_byte_string(&privateMap))
506                                             {
507                                                 cborFindResult = cbor_value_dup_byte_string(&privateMap, &cred->privateData.data,
508                                                     &cred->privateData.len, NULL);
509                                             }
510                                             else if(cbor_value_is_text_string(&privateMap))
511                                             {
512                                                 cborFindResult = cbor_value_dup_text_string(&privateMap, (char**)(&cred->privateData.data),
513                                                     &cred->privateData.len, NULL);
514                                             }
515                                             else
516                                             {
517                                                 cborFindResult = CborErrorUnknownType;
518                                                 OIC_LOG(ERROR, TAG, "Unknow type for private data.");
519                                             }
520                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PrivateData.");
521                                         }
522
523                                         // PrivateData::encoding -- Mandatory
524                                         if (strcmp(privname, OIC_JSON_ENCODING_NAME) == 0)
525                                         {
526                                             // TODO: Added as workaround. Will be replaced soon.
527                                             char* strEncoding = NULL;
528                                             cborFindResult = cbor_value_dup_text_string(&privateMap, &strEncoding, &len, NULL);
529                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding EncodingType");
530
531                                             if(strcmp(strEncoding, OIC_SEC_ENCODING_RAW) == 0)
532                                             {
533                                                 cred->privateData.encoding = OIC_ENCODING_RAW;
534                                             }
535                                             else if(strcmp(strEncoding, OIC_SEC_ENCODING_BASE64) == 0)
536                                             {
537                                                 cred->privateData.encoding = OIC_ENCODING_BASE64;
538                                             }
539                                             else
540                                             {
541                                                 //For unit test
542                                                 cred->privateData.encoding = OIC_ENCODING_RAW;
543                                                 OIC_LOG(WARNING, TAG, "Unknow encoding type dectected for private data.");
544                                             }
545
546                                             OICFree(strEncoding);
547                                         }
548                                     }
549                                     if (cbor_value_is_valid(&privateMap))
550                                     {
551                                         cborFindResult = cbor_value_advance(&privateMap);
552                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing privatedata Map.");
553                                     }
554                                     OICFree(privname);
555                                 }
556
557                             }
558 #ifdef __WITH_X509__
559                             if (strcmp(name, OIC_JSON_PUBLICDATA_NAME)  == 0)
560                             {
561                                 CborValue pubMap = { .parser = NULL };
562                                 cborFindResult = cbor_value_enter_container(&credMap, &pubMap);
563
564                                 while (cbor_value_is_valid(&pubMap))
565                                 {
566                                     char* pubname = NULL;
567                                     CborType type = cbor_value_get_type(&pubMap);
568                                     if (type == CborTextStringType && cbor_value_is_text_string(&pubMap))
569                                     {
570                                         cborFindResult = cbor_value_dup_text_string(&pubMap, &pubname,
571                                                 &len, NULL);
572                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
573                                         cborFindResult = cbor_value_advance(&pubMap);
574                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
575                                     }
576                                     if (pubname)
577                                     {
578                                         // PrivateData::privdata -- Mandatory
579                                         if (strcmp(pubname, OIC_JSON_DATA_NAME) == 0 && cbor_value_is_byte_string(&pubMap))
580                                         {
581                                             cborFindResult = cbor_value_dup_byte_string(&pubMap, &cred->publicData.data,
582                                                 &cred->publicData.len, NULL);
583                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PubData.");
584                                         }
585                                         // PublicData::encoding -- Mandatory
586                                         if (strcmp(pubname, OIC_JSON_ENCODING_NAME) == 0)
587                                         {
588                                             // TODO: Need to update data structure, just ignore encoding value now.
589                                         }
590                                     }
591                                     if (cbor_value_is_valid(&pubMap))
592                                     {
593                                         cborFindResult = cbor_value_advance(&pubMap);
594                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing publicdata Map.");
595                                     }
596                                     OICFree(pubname);
597                                 }
598                             }
599 #endif  //__WITH_X509__
600
601                             if (0 == strcmp(OIC_JSON_PERIOD_NAME, name))
602                             {
603                                 cborFindResult = cbor_value_dup_text_string(&credMap, &cred->period, &len, NULL);
604                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Period.");
605                             }
606
607                             if (cbor_value_is_valid(&credMap))
608                             {
609                                 cborFindResult = cbor_value_advance(&credMap);
610                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing CRED Map.");
611                             }
612                             OICFree(name);
613                         }
614                     }
615                     cred->next = NULL;
616                     if (cbor_value_is_valid(&credArray))
617                     {
618                         cborFindResult = cbor_value_advance(&credArray);
619                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing CRED Array.");
620                     }
621                 }
622             }
623
624             //ROwner -- Mandatory
625             if (strcmp(tagName, OIC_JSON_ROWNERID_NAME)  == 0 && cbor_value_is_text_string(&CredRootMap))
626             {
627                 char *stRowner = NULL;
628                 cborFindResult = cbor_value_dup_text_string(&CredRootMap, &stRowner, &len, NULL);
629                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Rownerid Value.");
630
631                 ret = ConvertStrToUuid(stRowner, &headCred->rownerID);
632                 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
633                 OICFree(stRowner);
634             }
635             OICFree(tagName);
636         }
637         if (cbor_value_is_valid(&CredRootMap))
638         {
639             cborFindResult = cbor_value_advance(&CredRootMap);
640             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing CRED Root Map.");
641         }
642     }
643
644     *secCred = headCred;
645     ret = OC_STACK_OK;
646
647 exit:
648     if (CborNoError != cborFindResult)
649     {
650         DeleteCredList(headCred);
651         headCred = NULL;
652         *secCred = NULL;
653         ret = OC_STACK_ERROR;
654     }
655
656     return ret;
657 }
658
659 OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t credType,
660                                   const OicSecCert_t * publicData, const OicSecKey_t* privateData,
661                                   const OicUuid_t * rownerID)
662 {
663     (void)publicData;
664     OCStackResult ret = OC_STACK_ERROR;
665
666     OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
667     VERIFY_NON_NULL(TAG, cred, ERROR);
668
669     //CredId is assigned before appending new cred to the existing
670     //credential list and updating svr database in AddCredential().
671     cred->credId = 0;
672
673     VERIFY_NON_NULL(TAG, subject, ERROR);
674     memcpy(cred->subject.id, subject->id , sizeof(cred->subject.id));
675
676     VERIFY_SUCCESS(TAG, credType < (NO_SECURITY_MODE | SYMMETRIC_PAIR_WISE_KEY |
677             SYMMETRIC_GROUP_KEY | ASYMMETRIC_KEY | SIGNED_ASYMMETRIC_KEY | PIN_PASSWORD), ERROR);
678     cred->credType = credType;
679
680 #ifdef __WITH_X509__
681     if (publicData && publicData->data)
682     {
683         cred->publicData.data = (uint8_t *)OICCalloc(1, publicData->len);
684         VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
685         memcpy(cred->publicData.data, publicData->data, publicData->len);
686         cred->publicData.len = publicData->len;
687     }
688 #endif // __WITH_X509__
689
690     if (privateData && privateData->data)
691     {
692         cred->privateData.data = (uint8_t *)OICCalloc(1, privateData->len);
693         VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
694         memcpy(cred->privateData.data, privateData->data, privateData->len);
695         cred->privateData.len = privateData->len;
696
697         // TODO: Added as workaround. Will be replaced soon.
698         cred->privateData.encoding = OIC_ENCODING_RAW;
699
700 #if 0
701         // NOTE: Test codes to use base64 for credential.
702         uint32_t outSize = 0;
703         size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((privateData->len + 1));
704         char* b64Buf = (uint8_t *)OICCalloc(1, b64BufSize);
705         VERIFY_NON_NULL(TAG, b64Buf, ERROR);
706         b64Encode(privateData->data, privateData->len, b64Buf, b64BufSize, &outSize);
707
708         OICFree( cred->privateData.data );
709         cred->privateData.data = (uint8_t *)OICCalloc(1, outSize + 1);
710         VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
711
712         strcpy(cred->privateData.data, b64Buf);
713         cred->privateData.encoding = OIC_ENCODING_BASE64;
714         cred->privateData.len = outSize;
715         OICFree(b64Buf);
716 #endif //End of Test codes
717
718     }
719
720     VERIFY_NON_NULL(TAG, rownerID, ERROR);
721     memcpy(&cred->rownerID, rownerID, sizeof(OicUuid_t));
722
723     ret = OC_STACK_OK;
724 exit:
725     if (OC_STACK_OK != ret)
726     {
727         DeleteCredList(cred);
728         cred = NULL;
729     }
730     return cred;
731 }
732
733 static bool UpdatePersistentStorage(const OicSecCred_t *cred)
734 {
735     bool ret = false;
736
737     // Convert Cred data into JSON for update to persistent storage
738     if (cred)
739     {
740         uint8_t *payload = NULL;
741         size_t size = 0;
742         int secureFlag = 0;
743         OCStackResult res = CredToCBORPayload(cred, &payload, &size, secureFlag);
744         if ((OC_STACK_OK == res) && payload)
745         {
746             if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, payload, size))
747             {
748                 ret = true;
749             }
750             OICFree(payload);
751         }
752     }
753     else //Empty cred list
754     {
755         if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, NULL, 0))
756         {
757             ret = true;
758         }
759     }
760     return ret;
761 }
762
763 /**
764  * Compare function used LL_SORT for sorting credentials.
765  *
766  * @param first pointer to OicSecCred_t struct.
767  * @param second  pointer to OicSecCred_t struct.
768  *
769  *@return -1, if credId of first is less than credId of second.
770  * 0, if credId of first is equal to credId of second.
771  * 1, if credId of first is greater than credId of second.
772  */
773 static int CmpCredId(const OicSecCred_t * first, const OicSecCred_t *second)
774 {
775     if (first->credId < second->credId)
776     {
777         return -1;
778     }
779     else if (first->credId > second->credId)
780     {
781         return 1;
782     }
783     else
784         return 0;
785 }
786
787 /**
788  * GetCredId goes through the cred list and returns the next
789  * available credId. The next credId could be the credId that is
790  * available due deletion of OicSecCred_t object or one more than
791  * credId of last credential in the list.
792  *
793  * @return next available credId if successful, else 0 for error.
794  */
795 static uint16_t GetCredId()
796 {
797     //Sorts credential list in incremental order of credId
798     LL_SORT(gCred, CmpCredId);
799
800     OicSecCred_t *currentCred = NULL, *credTmp = NULL;
801     uint16_t nextCredId = 1;
802
803     LL_FOREACH_SAFE(gCred, currentCred, credTmp)
804     {
805         if (currentCred->credId == nextCredId)
806         {
807             nextCredId += 1;
808         }
809         else
810         {
811             break;
812         }
813     }
814
815     VERIFY_SUCCESS(TAG, nextCredId < UINT16_MAX, ERROR);
816     return nextCredId;
817
818 exit:
819     return 0;
820 }
821
822 /**
823  * Get the default value.
824  *
825  * @return  NULL for now.
826  */
827 static OicSecCred_t* GetCredDefault()
828 {
829     // TODO:Update it when we finalize the default info.
830     return NULL;
831 }
832
833 OCStackResult AddCredential(OicSecCred_t * newCred)
834 {
835     OCStackResult ret = OC_STACK_ERROR;
836     VERIFY_SUCCESS(TAG, NULL != newCred, ERROR);
837
838     //Assigning credId to the newCred
839     newCred->credId = GetCredId();
840     VERIFY_SUCCESS(TAG, newCred->credId != 0, ERROR);
841
842     //Append the new Cred to existing list
843     LL_APPEND(gCred, newCred);
844
845     if (UpdatePersistentStorage(gCred))
846     {
847         ret = OC_STACK_OK;
848     }
849
850 exit:
851     return ret;
852 }
853
854 OCStackResult RemoveCredential(const OicUuid_t *subject)
855 {
856     OCStackResult ret = OC_STACK_ERROR;
857     OicSecCred_t *cred = NULL;
858     OicSecCred_t *tempCred = NULL;
859     bool deleteFlag = false;
860
861     LL_FOREACH_SAFE(gCred, cred, tempCred)
862     {
863         if (memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
864         {
865             LL_DELETE(gCred, cred);
866             FreeCred(cred);
867             deleteFlag = 1;
868         }
869     }
870
871     if (deleteFlag)
872     {
873         if (UpdatePersistentStorage(gCred))
874         {
875             ret = OC_STACK_RESOURCE_DELETED;
876         }
877     }
878     return ret;
879
880 }
881
882 /**
883  * Remove all credential data on credential resource and persistent storage
884  *
885  * @retval
886  *     OC_STACK_OK              - no errors
887  *     OC_STACK_ERROR           - stack process error
888  */
889 OCStackResult RemoveAllCredentials(void)
890 {
891     DeleteCredList(gCred);
892     gCred = GetCredDefault();
893
894     if (!UpdatePersistentStorage(gCred))
895     {
896         return OC_STACK_ERROR;
897     }
898     return OC_STACK_OK;
899 }
900
901 #ifdef __WITH_DTLS__
902 /**
903  * Internal function to fill private data of owner PSK.
904  *
905  * @param receviedCred recevied owner credential from OBT(PT)
906  * @param ownerAdd address of OBT(PT)
907  * @param doxm current device's doxm resource
908  *
909  * @return
910  *     true successfully done and valid ower psk information
911  *     false Invalid owner psk information or failed to owner psk generation
912  */
913 static bool FillPrivateDataOfOwnerPSK(OicSecCred_t* receviedCred, const CAEndpoint_t* ownerAddr,
914                            const OicSecDoxm_t* doxm)
915 {
916     //Derive OwnerPSK locally
917     const char* oxmLabel = GetOxmString(doxm->oxmSel);
918     VERIFY_NON_NULL(TAG, oxmLabel, ERROR);
919
920     uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
921     CAResult_t pskRet = CAGenerateOwnerPSK(ownerAddr,
922         (uint8_t*)oxmLabel, strlen(oxmLabel),
923         doxm->owner.id, sizeof(doxm->owner.id),
924         doxm->deviceID.id, sizeof(doxm->deviceID.id),
925         ownerPSK, OWNER_PSK_LENGTH_128);
926     VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
927
928     OIC_LOG(DEBUG, TAG, "OwnerPSK dump :");
929     OIC_LOG_BUFFER(DEBUG, TAG, ownerPSK, OWNER_PSK_LENGTH_128);
930
931     //Generate owner credential based on recevied credential information
932
933     // TODO: Added as workaround, will be replaced soon.
934     if(OIC_ENCODING_RAW == receviedCred->privateData.encoding)
935     {
936         receviedCred->privateData.data = (uint8_t *)OICCalloc(1, OWNER_PSK_LENGTH_128);
937         VERIFY_NON_NULL(TAG, receviedCred->privateData.data, ERROR);
938         receviedCred->privateData.len = OWNER_PSK_LENGTH_128;
939         memcpy(receviedCred->privateData.data, ownerPSK, OWNER_PSK_LENGTH_128);
940     }
941     else if(OIC_ENCODING_BASE64 == receviedCred->privateData.encoding)
942     {
943         uint32_t b64OutSize = 0;
944         size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
945         char* b64Buf = OICCalloc(1, b64BufSize);
946         VERIFY_NON_NULL(TAG, b64Buf, ERROR);
947
948         b64Encode(ownerPSK, OWNER_PSK_LENGTH_128, b64Buf, b64BufSize, &b64OutSize);
949
950         receviedCred->privateData.data = (uint8_t *)OICCalloc(1, b64OutSize + 1);
951         VERIFY_NON_NULL(TAG, receviedCred->privateData.data, ERROR);
952         receviedCred->privateData.len = b64OutSize;
953         strncpy((char*)receviedCred->privateData.data, b64Buf, b64OutSize);
954         receviedCred->privateData.data[b64OutSize] = '\0';
955     }
956     else
957     {
958         // TODO: error
959         VERIFY_SUCCESS(TAG, OIC_ENCODING_UNKNOW, ERROR);
960     }
961
962     OIC_LOG(INFO, TAG, "PrivateData of OwnerPSK was calculated successfully");
963
964     //Verify OwnerPSK information
965     return (memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0 &&
966             receviedCred->credType == SYMMETRIC_PAIR_WISE_KEY);
967 exit:
968     //receviedCred->privateData.data will be deallocated when deleting credential.
969     return false;
970 }
971
972 #endif //__WITH_DTLS__
973
974 static OCEntityHandlerResult HandlePutRequest(const OCEntityHandlerRequest * ehRequest)
975 {
976     OCEntityHandlerResult ret = OC_EH_ERROR;
977     OIC_LOG(DEBUG, TAG, "HandleCREDPutRequest IN");
978
979     //Get binary representation of cbor
980     OicSecCred_t *cred  = NULL;
981     uint8_t *payload = (((OCSecurityPayload*)ehRequest->payload)->securityData);
982     size_t size = (((OCSecurityPayload*)ehRequest->payload)->payloadSize);
983
984     OCStackResult res = CBORPayloadToCred(payload, size, &cred);
985     if (res == OC_STACK_OK)
986     {
987 #ifdef __WITH_DTLS__
988         OicUuid_t emptyUuid = {.id={0}};
989         const OicSecDoxm_t* doxm = GetDoxmResourceData();
990         if(false == doxm->owned && memcmp(&(doxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0)
991         {
992             //in case of owner PSK
993             switch(cred->credType)
994             {
995                 case SYMMETRIC_PAIR_WISE_KEY:
996                 {
997                     OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
998                     if(FillPrivateDataOfOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm))
999                     {
1000                         if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&cred->subject))
1001                         {
1002                             OIC_LOG(WARNING, TAG, "The credential with the same subject ID was detected!");
1003                         }
1004
1005                         OIC_LOG(ERROR, TAG, "OwnerPSK was generated successfully.");
1006                         if(OC_STACK_OK == AddCredential(cred))
1007                         {
1008                             ret = OC_EH_RESOURCE_CREATED;
1009                         }
1010                         else
1011                         {
1012                             OIC_LOG(ERROR, TAG, "Failed to save the OwnerPSK as cred resource");
1013                             ret = OC_EH_ERROR;
1014                         }
1015                     }
1016                     else
1017                     {
1018                         OIC_LOG(ERROR, TAG, "Failed to verify receviced OwnerPKS.");
1019                         ret = OC_EH_ERROR;
1020                     }
1021
1022                     if(OC_EH_RESOURCE_CREATED == ret)
1023                     {
1024                         /**
1025                          * in case of random PIN based OxM,
1026                          * revert get_psk_info callback of tinyDTLS to use owner credential.
1027                          */
1028                         if(OIC_RANDOM_DEVICE_PIN == doxm->oxmSel)
1029                         {
1030                             OicUuid_t emptyUuid = { .id={0}};
1031                             SetUuidForRandomPinOxm(&emptyUuid);
1032
1033                             if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
1034                             {
1035                                 OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
1036                                 ret = OC_EH_ERROR;
1037                                 break;
1038                             }
1039                         }
1040
1041                         //Select cipher suite to use owner PSK
1042                         if(CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false))
1043                         {
1044                             OIC_LOG(ERROR, TAG, "Failed to disable anonymous cipher suite");
1045                             ret = OC_EH_ERROR;
1046                         }
1047                         else
1048                         {
1049                             OIC_LOG(INFO, TAG, "Anonymous cipher suite is DISABLED");
1050                         }
1051
1052                         if(CA_STATUS_OK !=
1053                            CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256))
1054                         {
1055                             OIC_LOG(ERROR, TAG, "Failed to select cipher suite");
1056                             ret = OC_EH_ERROR;
1057                         }
1058                     }
1059
1060                     break;
1061                 }
1062                 case SYMMETRIC_GROUP_KEY:
1063                 case ASYMMETRIC_KEY:
1064                 case SIGNED_ASYMMETRIC_KEY:
1065                 case PIN_PASSWORD:
1066                 case ASYMMETRIC_ENCRYPTION_KEY:
1067                 {
1068                     OIC_LOG(WARNING, TAG, "Unsupported credential type for owner credential.");
1069                     ret = OC_EH_ERROR;
1070                     break;
1071                 }
1072                 default:
1073                 {
1074                     OIC_LOG(WARNING, TAG, "Unknow credential type for owner credential.");
1075                     ret = OC_EH_ERROR;
1076                     break;
1077                 }
1078             }
1079
1080             if(OC_EH_RESOURCE_CREATED != ret)
1081             {
1082                 /*
1083                   * If some error is occured while ownership transfer,
1084                   * ownership transfer related resource should be revert back to initial status.
1085                   */
1086                 RestoreDoxmToInitState();
1087                 RestorePstatToInitState();
1088             }
1089         }
1090         else
1091         {
1092             /*
1093              * If the post request credential has credId, it will be
1094              * discarded and the next available credId will be assigned
1095              * to it before getting appended to the existing credential
1096              * list and updating svr database.
1097              */
1098             ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
1099         }
1100 #else //not __WITH_DTLS__
1101         /*
1102          * If the post request credential has credId, it will be
1103          * discarded and the next available credId will be assigned
1104          * to it before getting appended to the existing credential
1105          * list and updating svr database.
1106          */
1107         ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
1108 #endif//__WITH_DTLS__
1109     }
1110
1111     if (OC_EH_RESOURCE_CREATED != ret)
1112     {
1113         if(OC_STACK_OK != RemoveCredential(&cred->subject))
1114         {
1115             OIC_LOG(WARNING, TAG, "Failed to remove the invalid credential");
1116         }
1117         FreeCred(cred);
1118     }
1119     OIC_LOG(DEBUG, TAG, "HandleCREDPutRequest OUT");
1120     return ret;
1121 }
1122
1123 /**
1124  * The entity handler determines how to process a GET request.
1125  */
1126 static OCEntityHandlerResult HandleGetRequest (const OCEntityHandlerRequest * ehRequest)
1127 {
1128     OIC_LOG(INFO, TAG, "HandleGetRequest  processing GET request");
1129
1130     // Convert Cred data into CBOR for transmission
1131     size_t size = 0;
1132     uint8_t *payload = NULL;
1133     int secureFlag = 1;
1134
1135     const OicSecCred_t *cred = gCred;
1136     OCStackResult res = CredToCBORPayload(cred, &payload, &size, secureFlag);
1137
1138     // A device should always have a default cred. Therefore, payload should never be NULL.
1139     OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
1140
1141     // Send response payload to request originator
1142     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, payload, size))
1143     {
1144         ehRet = OC_EH_ERROR;
1145         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandlePstatGetRequest");
1146     }
1147     OICFree(payload);
1148     return ehRet;
1149 }
1150
1151 static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
1152 {
1153     OCEntityHandlerResult ret = OC_EH_ERROR;
1154
1155     //Get binary representation of CBOR
1156     OicSecCred_t *cred  = NULL;
1157     uint8_t *payload = ((OCSecurityPayload*)ehRequest->payload)->securityData;
1158     size_t size = ((OCSecurityPayload*)ehRequest->payload)->payloadSize;
1159     OCStackResult res = CBORPayloadToCred(payload, size, &cred);
1160     if ((OC_STACK_OK == res) && cred)
1161     {
1162         //If the Post request credential has credId, it will be
1163         //discarded and the next available credId will be assigned
1164         //to it before getting appended to the existing credential
1165         //list and updating svr database.
1166         ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
1167     }
1168
1169     return ret;
1170 }
1171
1172 static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
1173 {
1174     OIC_LOG(DEBUG, TAG, "Processing CredDeleteRequest");
1175
1176     OCEntityHandlerResult ehRet = OC_EH_ERROR;
1177
1178     if (NULL == ehRequest->query)
1179     {
1180         return ehRet;
1181     }
1182
1183     OicParseQueryIter_t parseIter = { .attrPos=NULL };
1184     OicUuid_t subject = {.id={0}};
1185
1186     //Parsing REST query to get the subject
1187     ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
1188     while (GetNextQuery(&parseIter))
1189     {
1190         if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECTID_NAME,
1191                 parseIter.attrLen) == 0)
1192         {
1193             OCStackResult ret = ConvertStrToUuid((const char*)parseIter.valPos, &subject);
1194             VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1195         }
1196     }
1197
1198     if (OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
1199     {
1200         ehRet = OC_EH_RESOURCE_DELETED;
1201     }
1202
1203 exit:
1204     return ehRet;
1205 }
1206
1207 OCEntityHandlerResult CredEntityHandler(OCEntityHandlerFlag flag,
1208                                         OCEntityHandlerRequest * ehRequest,
1209                                         void* callbackParameter)
1210 {
1211     (void)callbackParameter;
1212     OCEntityHandlerResult ret = OC_EH_ERROR;
1213
1214     if (!ehRequest)
1215     {
1216         return OC_EH_ERROR;
1217     }
1218     if (flag & OC_REQUEST_FLAG)
1219     {
1220         OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1221         //TODO :  Handle PUT/DEL methods
1222         switch (ehRequest->method)
1223         {
1224             case OC_REST_GET:
1225                 ret = HandleGetRequest(ehRequest);;
1226                 break;
1227             case OC_REST_PUT:
1228                 ret = HandlePutRequest(ehRequest);
1229                 break;
1230             case OC_REST_POST:
1231                 ret = HandlePostRequest(ehRequest);
1232                 break;
1233             case OC_REST_DELETE:
1234                 ret = HandleDeleteRequest(ehRequest);
1235                 break;
1236             default:
1237                 ret = OC_EH_ERROR;
1238                 break;
1239         }
1240     }
1241
1242     //Send payload to request originator
1243     ret = (SendSRMResponse(ehRequest, ret, NULL, 0) == OC_STACK_OK) ?
1244                        ret : OC_EH_ERROR;
1245
1246     return ret;
1247 }
1248
1249 OCStackResult CreateCredResource()
1250 {
1251     OCStackResult ret = OCCreateResource(&gCredHandle,
1252                                          OIC_RSRC_TYPE_SEC_CRED,
1253                                          OIC_MI_DEF,
1254                                          OIC_RSRC_CRED_URI,
1255                                          CredEntityHandler,
1256                                          NULL,
1257                                          OC_RES_PROP_NONE);
1258
1259     if (OC_STACK_OK != ret)
1260     {
1261         OIC_LOG (FATAL, TAG, "Unable to instantiate Cred resource");
1262         DeInitCredResource();
1263     }
1264     return ret;
1265 }
1266
1267 OCStackResult InitCredResource()
1268 {
1269     OCStackResult ret = OC_STACK_ERROR;
1270
1271     //Read Cred resource from PS
1272     uint8_t *data = NULL;
1273     size_t size = 0;
1274     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_CRED_NAME, &data, &size);
1275     // If database read failed
1276     if (ret != OC_STACK_OK)
1277     {
1278         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1279     }
1280     if (data)
1281     {
1282         // Read ACL resource from PS
1283         ret = CBORPayloadToCred(data, size, &gCred);
1284     }
1285
1286     /*
1287      * If SVR database in persistent storage got corrupted or
1288      * is not available for some reason, a default Cred is created
1289      * which allows user to initiate Cred provisioning again.
1290      */
1291     if (ret != OC_STACK_OK || !data || !gCred)
1292     {
1293         gCred = GetCredDefault();
1294     }
1295     //Instantiate 'oic.sec.cred'
1296     ret = CreateCredResource();
1297     OICFree(data);
1298     return ret;
1299 }
1300
1301 OCStackResult DeInitCredResource()
1302 {
1303     OCStackResult result = OCDeleteResource(gCredHandle);
1304     DeleteCredList(gCred);
1305     gCred = NULL;
1306     return result;
1307 }
1308
1309 const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
1310 {
1311     OicSecCred_t *cred = NULL;
1312
1313    if ( NULL == subject)
1314     {
1315        return NULL;
1316     }
1317
1318     LL_FOREACH(gCred, cred)
1319     {
1320         if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
1321         {
1322             return cred;
1323         }
1324     }
1325     return NULL;
1326 }
1327
1328
1329 #if defined(__WITH_DTLS__)
1330 int32_t GetDtlsPskCredentials(CADtlsPskCredType_t type,
1331               const uint8_t *desc, size_t desc_len,
1332               uint8_t *result, size_t result_length)
1333 {
1334     int32_t ret = -1;
1335
1336     if (NULL == result)
1337     {
1338         return ret;
1339     }
1340
1341     switch (type)
1342     {
1343         case CA_DTLS_PSK_HINT:
1344         case CA_DTLS_PSK_IDENTITY:
1345             {
1346                 OicUuid_t deviceID = {.id={}};
1347                 // Retrieve Device ID from doxm resource
1348                 if ( OC_STACK_OK != GetDoxmDeviceID(&deviceID) )
1349                 {
1350                     OIC_LOG (ERROR, TAG, "Unable to retrieve doxm Device ID");
1351                     return ret;
1352                 }
1353
1354                 if (result_length < sizeof(deviceID.id))
1355                 {
1356                     OIC_LOG (ERROR, TAG, "Wrong value for result_length");
1357                     return ret;
1358                 }
1359                 memcpy(result, deviceID.id, sizeof(deviceID.id));
1360                 return (sizeof(deviceID.id));
1361             }
1362             break;
1363
1364         case CA_DTLS_PSK_KEY:
1365             {
1366                 OicSecCred_t *cred = NULL;
1367                 LL_FOREACH(gCred, cred)
1368                 {
1369                     if (cred->credType != SYMMETRIC_PAIR_WISE_KEY)
1370                     {
1371                         continue;
1372                     }
1373
1374                     if ((desc_len == sizeof(cred->subject.id)) &&
1375                         (memcmp(desc, cred->subject.id, sizeof(cred->subject.id)) == 0))
1376                     {
1377                         /*
1378                          * If the credentials are valid for limited time,
1379                          * check their expiry.
1380                          */
1381                         if (cred->period)
1382                         {
1383                             if(IOTVTICAL_VALID_ACCESS != IsRequestWithinValidTime(cred->period, NULL))
1384                             {
1385                                 OIC_LOG (INFO, TAG, "Credentials are expired.");
1386                                 ret = -1;
1387                                 return ret;
1388                             }
1389                         }
1390
1391                         // Copy PSK.
1392                         // TODO: Added as workaround. Will be replaced soon.
1393                         if(OIC_ENCODING_RAW == cred->privateData.encoding)
1394                         {
1395                             result_length = cred->privateData.len;
1396                             memcpy(result, cred->privateData.data, result_length);
1397                         }
1398                         else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
1399                         {
1400                             size_t outBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
1401                             uint8_t* outKey = OICCalloc(1, outBufSize);
1402                             uint32_t outKeySize;
1403                             if(NULL == outKey)
1404                             {
1405                                 result_length = -1;
1406                                 OIC_LOG (ERROR, TAG, "Failed to memoray allocation.");
1407                                 return ret;
1408                             }
1409
1410                             if(B64_OK == b64Decode((char*)cred->privateData.data, cred->privateData.len, outKey, outBufSize, &outKeySize))
1411                             {
1412                                 memcpy(result, outKey, outKeySize);
1413                                 result_length = outKeySize;
1414                             }
1415                             else
1416                             {
1417                                 result_length = -1;
1418                                 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
1419                             }
1420
1421                             OICFree(outKey);
1422                         }
1423
1424                         return result_length;
1425                     }
1426                 }
1427             }
1428             break;
1429
1430         default:
1431             {
1432                 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
1433                 ret = -1;
1434             }
1435             break;
1436     }
1437
1438     return ret;
1439 }
1440
1441 /**
1442  * Add temporal PSK to PIN based OxM
1443  *
1444  * @param[in] tmpSubject UUID of target device
1445  * @param[in] credType Type of credential to be added
1446  * @param[in] pin numeric characters
1447  * @param[in] pinSize length of 'pin'
1448  * @param[in] rownerID Resource owner's UUID
1449  * @param[out] tmpCredSubject Generated credential's subject.
1450  *
1451  * @return OC_STACK_OK for success and errorcode otherwise.
1452  */
1453 OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
1454                             const char * pin, size_t pinSize,
1455                             const OicUuid_t * rownerID, OicUuid_t* tmpCredSubject)
1456 {
1457     OCStackResult ret = OC_STACK_ERROR;
1458     OIC_LOG(DEBUG, TAG, "AddTmpPskWithPIN IN");
1459
1460     if(NULL == tmpSubject || NULL == pin || 0 == pinSize || NULL == tmpCredSubject)
1461     {
1462         return OC_STACK_INVALID_PARAM;
1463     }
1464
1465     uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
1466     OicSecKey_t privKey = {privData, OWNER_PSK_LENGTH_128, OIC_ENCODING_RAW};
1467     OicSecCred_t* cred = NULL;
1468     int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, rownerID->id,
1469                                               UUID_LENGTH, PBKDF_ITERATIONS,
1470                                               OWNER_PSK_LENGTH_128, privData);
1471     VERIFY_SUCCESS(TAG, (0 == dtlsRes) , ERROR);
1472
1473     cred = GenerateCredential(tmpSubject, credType, NULL,
1474                               &privKey, rownerID);
1475     if(NULL == cred)
1476     {
1477         OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
1478         return OC_STACK_ERROR;
1479     }
1480
1481     memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
1482
1483     ret = AddCredential(cred);
1484     if( OC_STACK_OK != ret)
1485     {
1486         RemoveCredential(tmpSubject);
1487         OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
1488     }
1489     OIC_LOG(DEBUG, TAG, "AddTmpPskWithPIN OUT");
1490
1491 exit:
1492     return ret;
1493 }
1494
1495 #endif /* __WITH_DTLS__ */
1496 #ifdef __WITH_X509__
1497 #define CERT_LEN_PREFIX (3)
1498 #define BYTE_SIZE (8) //bits
1499 #define PUB_KEY_X_COORD ("x")
1500 #define PUB_KEY_Y_COORD ("y")
1501 #define CERTIFICATE ("x5c")
1502 #define PRIVATE_KEY ("d")
1503
1504 static uint32_t parseCertPrefix(uint8_t *prefix)
1505 {
1506     uint32_t res = 0;
1507     if (NULL != prefix)
1508     {
1509         for (int i = 0; i < CERT_LEN_PREFIX; ++i)
1510         {
1511             res |= (((uint32_t) prefix[i]) << ((CERT_LEN_PREFIX - 1 -i) * BYTE_SIZE));
1512         }
1513     }
1514     return res;
1515 }
1516
1517 static OCStackResult GetCAPublicKeyData(CADtlsX509Creds_t *credInfo)
1518 {
1519     OCStackResult ret = OC_STACK_ERROR;
1520     uint8_t *ccPtr = credInfo->certificateChain;
1521     for (uint8_t i = 0; i < credInfo->chainLen - 1; ++i)
1522     {
1523         ccPtr += CERT_LEN_PREFIX + parseCertPrefix(ccPtr);
1524     }
1525
1526     ByteArray cert = { .data = ccPtr + CERT_LEN_PREFIX, .len = parseCertPrefix(ccPtr) };
1527     CertificateX509 certStruct;
1528
1529     VERIFY_SUCCESS(TAG, PKI_SUCCESS == DecodeCertificate(cert, &certStruct), ERROR);
1530
1531     INC_BYTE_ARRAY(certStruct.pubKey, 2);
1532
1533     memcpy(credInfo->rootPublicKeyX, certStruct.pubKey.data, PUBLIC_KEY_SIZE / 2);
1534     memcpy(credInfo->rootPublicKeyY, certStruct.pubKey.data + PUBLIC_KEY_SIZE / 2, PUBLIC_KEY_SIZE / 2);
1535
1536     ret = OC_STACK_OK;
1537     exit:
1538     return ret;
1539 }
1540
1541 int GetDtlsX509Credentials(CADtlsX509Creds_t *credInfo)
1542 {
1543     int ret = 1;
1544     VERIFY_NON_NULL(TAG, credInfo, ERROR);
1545     if (NULL == gCred)
1546     {
1547         VERIFY_SUCCESS(TAG, OC_STACK_OK == InitCredResource(), ERROR);
1548     }
1549
1550     OicSecCred_t *cred = NULL;
1551     LL_SEARCH_SCALAR(gCred, cred, credType, SIGNED_ASYMMETRIC_KEY);
1552     VERIFY_NON_NULL(TAG, cred, ERROR);
1553
1554     if (cred->publicData.len > MAX_CERT_MESSAGE_LEN || cred->privateData.len > PRIVATE_KEY_SIZE)
1555     {
1556         goto exit;
1557     }
1558     credInfo->chainLen = 2;
1559     memcpy(credInfo->certificateChain, cred->publicData.data, cred->publicData.len);
1560     memcpy(credInfo->devicePrivateKey, cred->privateData.data, cred->privateData.len);
1561     credInfo->certificateChainLen = cred->publicData.len;
1562     GetCAPublicKeyData(credInfo);
1563     ret = 0;
1564
1565 exit:
1566
1567     return ret;
1568 }
1569 #undef CERT_LEN_PREFIX
1570 #endif /* __WITH_X509__ */
1571
1572 OCStackResult SetCredRownerId(const OicUuid_t* newROwner)
1573 {
1574     OCStackResult ret = OC_STACK_ERROR;
1575     uint8_t *cborPayload = NULL;
1576     size_t size = 0;
1577     int secureFlag = 0;
1578     OicUuid_t prevId = {.id={0}};
1579
1580     if(NULL == newROwner)
1581     {
1582         ret = OC_STACK_INVALID_PARAM;
1583     }
1584     if(NULL == gCred)
1585     {
1586         ret = OC_STACK_NO_RESOURCE;
1587     }
1588
1589     if(newROwner && gCred)
1590     {
1591         memcpy(prevId.id, gCred->rownerID.id, sizeof(prevId.id));
1592         memcpy(gCred->rownerID.id, newROwner->id, sizeof(newROwner->id));
1593
1594         ret = CredToCBORPayload(gCred, &cborPayload, &size, secureFlag);
1595         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1596
1597         ret = UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, cborPayload, size);
1598         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1599
1600         OICFree(cborPayload);
1601     }
1602
1603     return ret;
1604
1605 exit:
1606     OICFree(cborPayload);
1607     memcpy(gCred->rownerID.id, prevId.id, sizeof(prevId.id));
1608     return ret;
1609 }
1610
1611 OCStackResult GetCredRownerId(OicUuid_t *rowneruuid)
1612 {
1613     OCStackResult retVal = OC_STACK_ERROR;
1614     if (gCred)
1615     {
1616         *rowneruuid = gCred->rownerID;
1617         retVal = OC_STACK_OK;
1618     }
1619     return retVal;
1620 }