Remove double checking type in credential data
[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         strcpy((char*)receviedCred->privateData.data, b64Buf);
954     }
955     else
956     {
957         // TODO: error
958         VERIFY_SUCCESS(TAG, OIC_ENCODING_UNKNOW, ERROR);
959     }
960
961     OIC_LOG(INFO, TAG, "PrivateData of OwnerPSK was calculated successfully");
962
963     //Verify OwnerPSK information
964     return (memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0 &&
965             receviedCred->credType == SYMMETRIC_PAIR_WISE_KEY);
966 exit:
967     //receviedCred->privateData.data will be deallocated when deleting credential.
968     return false;
969 }
970
971 #endif //__WITH_DTLS__
972
973 static OCEntityHandlerResult HandlePutRequest(const OCEntityHandlerRequest * ehRequest)
974 {
975     OCEntityHandlerResult ret = OC_EH_ERROR;
976     OIC_LOG(DEBUG, TAG, "HandleCREDPutRequest IN");
977
978     //Get binary representation of cbor
979     OicSecCred_t *cred  = NULL;
980     uint8_t *payload = (((OCSecurityPayload*)ehRequest->payload)->securityData);
981     size_t size = (((OCSecurityPayload*)ehRequest->payload)->payloadSize);
982
983     OCStackResult res = CBORPayloadToCred(payload, size, &cred);
984     if (res == OC_STACK_OK)
985     {
986 #ifdef __WITH_DTLS__
987         OicUuid_t emptyUuid = {.id={0}};
988         const OicSecDoxm_t* doxm = GetDoxmResourceData();
989         if(false == doxm->owned && memcmp(&(doxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0)
990         {
991             //in case of owner PSK
992             switch(cred->credType)
993             {
994                 case SYMMETRIC_PAIR_WISE_KEY:
995                 {
996                     OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
997                     if(FillPrivateDataOfOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm))
998                     {
999                         if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&cred->subject))
1000                         {
1001                             OIC_LOG(WARNING, TAG, "The credential with the same subject ID was detected!");
1002                         }
1003
1004                         OIC_LOG(ERROR, TAG, "OwnerPSK was generated successfully.");
1005                         if(OC_STACK_OK == AddCredential(cred))
1006                         {
1007                             ret = OC_EH_RESOURCE_CREATED;
1008                         }
1009                         else
1010                         {
1011                             OIC_LOG(ERROR, TAG, "Failed to save the OwnerPSK as cred resource");
1012                             ret = OC_EH_ERROR;
1013                         }
1014                     }
1015                     else
1016                     {
1017                         OIC_LOG(ERROR, TAG, "Failed to verify receviced OwnerPKS.");
1018                         ret = OC_EH_ERROR;
1019                     }
1020
1021                     if(OC_EH_RESOURCE_CREATED == ret)
1022                     {
1023                         /**
1024                          * in case of random PIN based OxM,
1025                          * revert get_psk_info callback of tinyDTLS to use owner credential.
1026                          */
1027                         if(OIC_RANDOM_DEVICE_PIN == doxm->oxmSel)
1028                         {
1029                             OicUuid_t emptyUuid = { .id={0}};
1030                             SetUuidForRandomPinOxm(&emptyUuid);
1031
1032                             if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
1033                             {
1034                                 OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
1035                                 ret = OC_EH_ERROR;
1036                                 break;
1037                             }
1038                         }
1039
1040                         //Select cipher suite to use owner PSK
1041                         if(CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false))
1042                         {
1043                             OIC_LOG(ERROR, TAG, "Failed to disable anonymous cipher suite");
1044                             ret = OC_EH_ERROR;
1045                         }
1046                         else
1047                         {
1048                             OIC_LOG(INFO, TAG, "Anonymous cipher suite is DISABLED");
1049                         }
1050
1051                         if(CA_STATUS_OK !=
1052                            CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256))
1053                         {
1054                             OIC_LOG(ERROR, TAG, "Failed to select cipher suite");
1055                             ret = OC_EH_ERROR;
1056                         }
1057                     }
1058
1059                     break;
1060                 }
1061                 case SYMMETRIC_GROUP_KEY:
1062                 case ASYMMETRIC_KEY:
1063                 case SIGNED_ASYMMETRIC_KEY:
1064                 case PIN_PASSWORD:
1065                 case ASYMMETRIC_ENCRYPTION_KEY:
1066                 {
1067                     OIC_LOG(WARNING, TAG, "Unsupported credential type for owner credential.");
1068                     ret = OC_EH_ERROR;
1069                     break;
1070                 }
1071                 default:
1072                 {
1073                     OIC_LOG(WARNING, TAG, "Unknow credential type for owner credential.");
1074                     ret = OC_EH_ERROR;
1075                     break;
1076                 }
1077             }
1078
1079             if(OC_EH_RESOURCE_CREATED != ret)
1080             {
1081                 /*
1082                   * If some error is occured while ownership transfer,
1083                   * ownership transfer related resource should be revert back to initial status.
1084                   */
1085                 RestoreDoxmToInitState();
1086                 RestorePstatToInitState();
1087             }
1088         }
1089         else
1090         {
1091             /*
1092              * If the post request credential has credId, it will be
1093              * discarded and the next available credId will be assigned
1094              * to it before getting appended to the existing credential
1095              * list and updating svr database.
1096              */
1097             ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
1098         }
1099 #else //not __WITH_DTLS__
1100         /*
1101          * If the post request credential has credId, it will be
1102          * discarded and the next available credId will be assigned
1103          * to it before getting appended to the existing credential
1104          * list and updating svr database.
1105          */
1106         ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
1107 #endif//__WITH_DTLS__
1108     }
1109
1110     if (OC_EH_RESOURCE_CREATED != ret)
1111     {
1112         if(OC_STACK_OK != RemoveCredential(&cred->subject))
1113         {
1114             OIC_LOG(WARNING, TAG, "Failed to remove the invalid credential");
1115         }
1116         FreeCred(cred);
1117     }
1118     OIC_LOG(DEBUG, TAG, "HandleCREDPutRequest OUT");
1119     return ret;
1120 }
1121
1122 /**
1123  * The entity handler determines how to process a GET request.
1124  */
1125 static OCEntityHandlerResult HandleGetRequest (const OCEntityHandlerRequest * ehRequest)
1126 {
1127     OIC_LOG(INFO, TAG, "HandleGetRequest  processing GET request");
1128
1129     // Convert Cred data into CBOR for transmission
1130     size_t size = 0;
1131     uint8_t *payload = NULL;
1132     int secureFlag = 1;
1133
1134     const OicSecCred_t *cred = gCred;
1135     OCStackResult res = CredToCBORPayload(cred, &payload, &size, secureFlag);
1136
1137     // A device should always have a default cred. Therefore, payload should never be NULL.
1138     OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
1139
1140     // Send response payload to request originator
1141     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, payload, size))
1142     {
1143         ehRet = OC_EH_ERROR;
1144         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandlePstatGetRequest");
1145     }
1146     OICFree(payload);
1147     return ehRet;
1148 }
1149
1150 static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
1151 {
1152     OCEntityHandlerResult ret = OC_EH_ERROR;
1153
1154     //Get binary representation of CBOR
1155     OicSecCred_t *cred  = NULL;
1156     uint8_t *payload = ((OCSecurityPayload*)ehRequest->payload)->securityData;
1157     size_t size = ((OCSecurityPayload*)ehRequest->payload)->payloadSize;
1158     OCStackResult res = CBORPayloadToCred(payload, size, &cred);
1159     if ((OC_STACK_OK == res) && cred)
1160     {
1161         //If the Post request credential has credId, it will be
1162         //discarded and the next available credId will be assigned
1163         //to it before getting appended to the existing credential
1164         //list and updating svr database.
1165         ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
1166     }
1167
1168     return ret;
1169 }
1170
1171 static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
1172 {
1173     OIC_LOG(DEBUG, TAG, "Processing CredDeleteRequest");
1174
1175     OCEntityHandlerResult ehRet = OC_EH_ERROR;
1176
1177     if (NULL == ehRequest->query)
1178     {
1179         return ehRet;
1180     }
1181
1182     OicParseQueryIter_t parseIter = { .attrPos=NULL };
1183     OicUuid_t subject = {.id={0}};
1184
1185     //Parsing REST query to get the subject
1186     ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
1187     while (GetNextQuery(&parseIter))
1188     {
1189         if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECTID_NAME,
1190                 parseIter.attrLen) == 0)
1191         {
1192             OCStackResult ret = ConvertStrToUuid((const char*)parseIter.valPos, &subject);
1193             VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1194         }
1195     }
1196
1197     if (OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
1198     {
1199         ehRet = OC_EH_RESOURCE_DELETED;
1200     }
1201
1202 exit:
1203     return ehRet;
1204 }
1205
1206 OCEntityHandlerResult CredEntityHandler(OCEntityHandlerFlag flag,
1207                                         OCEntityHandlerRequest * ehRequest,
1208                                         void* callbackParameter)
1209 {
1210     (void)callbackParameter;
1211     OCEntityHandlerResult ret = OC_EH_ERROR;
1212
1213     if (!ehRequest)
1214     {
1215         return OC_EH_ERROR;
1216     }
1217     if (flag & OC_REQUEST_FLAG)
1218     {
1219         OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1220         //TODO :  Handle PUT/DEL methods
1221         switch (ehRequest->method)
1222         {
1223             case OC_REST_GET:
1224                 ret = HandleGetRequest(ehRequest);;
1225                 break;
1226             case OC_REST_PUT:
1227                 ret = HandlePutRequest(ehRequest);
1228                 break;
1229             case OC_REST_POST:
1230                 ret = HandlePostRequest(ehRequest);
1231                 break;
1232             case OC_REST_DELETE:
1233                 ret = HandleDeleteRequest(ehRequest);
1234                 break;
1235             default:
1236                 ret = OC_EH_ERROR;
1237                 break;
1238         }
1239     }
1240
1241     //Send payload to request originator
1242     ret = (SendSRMResponse(ehRequest, ret, NULL, 0) == OC_STACK_OK) ?
1243                        ret : OC_EH_ERROR;
1244
1245     return ret;
1246 }
1247
1248 OCStackResult CreateCredResource()
1249 {
1250     OCStackResult ret = OCCreateResource(&gCredHandle,
1251                                          OIC_RSRC_TYPE_SEC_CRED,
1252                                          OIC_MI_DEF,
1253                                          OIC_RSRC_CRED_URI,
1254                                          CredEntityHandler,
1255                                          NULL,
1256                                          OC_RES_PROP_NONE);
1257
1258     if (OC_STACK_OK != ret)
1259     {
1260         OIC_LOG (FATAL, TAG, "Unable to instantiate Cred resource");
1261         DeInitCredResource();
1262     }
1263     return ret;
1264 }
1265
1266 OCStackResult InitCredResource()
1267 {
1268     OCStackResult ret = OC_STACK_ERROR;
1269
1270     //Read Cred resource from PS
1271     uint8_t *data = NULL;
1272     size_t size = 0;
1273     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_CRED_NAME, &data, &size);
1274     // If database read failed
1275     if (ret != OC_STACK_OK)
1276     {
1277         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1278     }
1279     if (data)
1280     {
1281         // Read ACL resource from PS
1282         ret = CBORPayloadToCred(data, size, &gCred);
1283     }
1284
1285     /*
1286      * If SVR database in persistent storage got corrupted or
1287      * is not available for some reason, a default Cred is created
1288      * which allows user to initiate Cred provisioning again.
1289      */
1290     if (ret != OC_STACK_OK || !data || !gCred)
1291     {
1292         gCred = GetCredDefault();
1293     }
1294     //Instantiate 'oic.sec.cred'
1295     ret = CreateCredResource();
1296     OICFree(data);
1297     return ret;
1298 }
1299
1300 OCStackResult DeInitCredResource()
1301 {
1302     OCStackResult result = OCDeleteResource(gCredHandle);
1303     DeleteCredList(gCred);
1304     gCred = NULL;
1305     return result;
1306 }
1307
1308 const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
1309 {
1310     OicSecCred_t *cred = NULL;
1311
1312    if ( NULL == subject)
1313     {
1314        return NULL;
1315     }
1316
1317     LL_FOREACH(gCred, cred)
1318     {
1319         if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
1320         {
1321             return cred;
1322         }
1323     }
1324     return NULL;
1325 }
1326
1327
1328 #if defined(__WITH_DTLS__)
1329 int32_t GetDtlsPskCredentials(CADtlsPskCredType_t type,
1330               const uint8_t *desc, size_t desc_len,
1331               uint8_t *result, size_t result_length)
1332 {
1333     int32_t ret = -1;
1334
1335     if (NULL == result)
1336     {
1337         return ret;
1338     }
1339
1340     switch (type)
1341     {
1342         case CA_DTLS_PSK_HINT:
1343         case CA_DTLS_PSK_IDENTITY:
1344             {
1345                 OicUuid_t deviceID = {.id={}};
1346                 // Retrieve Device ID from doxm resource
1347                 if ( OC_STACK_OK != GetDoxmDeviceID(&deviceID) )
1348                 {
1349                     OIC_LOG (ERROR, TAG, "Unable to retrieve doxm Device ID");
1350                     return ret;
1351                 }
1352
1353                 if (result_length < sizeof(deviceID.id))
1354                 {
1355                     OIC_LOG (ERROR, TAG, "Wrong value for result_length");
1356                     return ret;
1357                 }
1358                 memcpy(result, deviceID.id, sizeof(deviceID.id));
1359                 return (sizeof(deviceID.id));
1360             }
1361             break;
1362
1363         case CA_DTLS_PSK_KEY:
1364             {
1365                 OicSecCred_t *cred = NULL;
1366                 LL_FOREACH(gCred, cred)
1367                 {
1368                     if (cred->credType != SYMMETRIC_PAIR_WISE_KEY)
1369                     {
1370                         continue;
1371                     }
1372
1373                     if ((desc_len == sizeof(cred->subject.id)) &&
1374                         (memcmp(desc, cred->subject.id, sizeof(cred->subject.id)) == 0))
1375                     {
1376                         /*
1377                          * If the credentials are valid for limited time,
1378                          * check their expiry.
1379                          */
1380                         if (cred->period)
1381                         {
1382                             if(IOTVTICAL_VALID_ACCESS != IsRequestWithinValidTime(cred->period, NULL))
1383                             {
1384                                 OIC_LOG (INFO, TAG, "Credentials are expired.");
1385                                 ret = -1;
1386                                 return ret;
1387                             }
1388                         }
1389
1390                         // Copy PSK.
1391                         // TODO: Added as workaround. Will be replaced soon.
1392                         if(OIC_ENCODING_RAW == cred->privateData.encoding)
1393                         {
1394                             result_length = cred->privateData.len;
1395                             memcpy(result, cred->privateData.data, result_length);
1396                         }
1397                         else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
1398                         {
1399                             size_t outBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
1400                             uint8_t* outKey = OICCalloc(1, outBufSize);
1401                             uint32_t outKeySize;
1402                             if(NULL == outKey)
1403                             {
1404                                 result_length = -1;
1405                                 OIC_LOG (ERROR, TAG, "Failed to memoray allocation.");
1406                             }
1407
1408                             if(B64_OK == b64Decode((char*)cred->privateData.data, cred->privateData.len, outKey, outBufSize, &outKeySize))
1409                             {
1410                                 memcpy(result, outKey, outKeySize);
1411                                 result_length = outKeySize;
1412                             }
1413                             else
1414                             {
1415                                 result_length = -1;
1416                                 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
1417                             }
1418
1419                             OICFree(outKey);
1420                         }
1421
1422                         return result_length;
1423                     }
1424                 }
1425             }
1426             break;
1427
1428         default:
1429             {
1430                 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
1431                 ret = -1;
1432             }
1433             break;
1434     }
1435
1436     return ret;
1437 }
1438
1439 /**
1440  * Add temporal PSK to PIN based OxM
1441  *
1442  * @param[in] tmpSubject UUID of target device
1443  * @param[in] credType Type of credential to be added
1444  * @param[in] pin numeric characters
1445  * @param[in] pinSize length of 'pin'
1446  * @param[in] rownerID Resource owner's UUID
1447  * @param[out] tmpCredSubject Generated credential's subject.
1448  *
1449  * @return OC_STACK_OK for success and errorcode otherwise.
1450  */
1451 OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
1452                             const char * pin, size_t pinSize,
1453                             const OicUuid_t * rownerID, OicUuid_t* tmpCredSubject)
1454 {
1455     OCStackResult ret = OC_STACK_ERROR;
1456     OIC_LOG(DEBUG, TAG, "AddTmpPskWithPIN IN");
1457
1458     if(NULL == tmpSubject || NULL == pin || 0 == pinSize || NULL == tmpCredSubject)
1459     {
1460         return OC_STACK_INVALID_PARAM;
1461     }
1462
1463     uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
1464     OicSecKey_t privKey = {privData, OWNER_PSK_LENGTH_128, OIC_ENCODING_RAW};
1465     OicSecCred_t* cred = NULL;
1466     int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, rownerID->id,
1467                                               UUID_LENGTH, PBKDF_ITERATIONS,
1468                                               OWNER_PSK_LENGTH_128, privData);
1469     VERIFY_SUCCESS(TAG, (0 == dtlsRes) , ERROR);
1470
1471     cred = GenerateCredential(tmpSubject, credType, NULL,
1472                               &privKey, rownerID);
1473     if(NULL == cred)
1474     {
1475         OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
1476         return OC_STACK_ERROR;
1477     }
1478
1479     memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
1480
1481     ret = AddCredential(cred);
1482     if( OC_STACK_OK != ret)
1483     {
1484         RemoveCredential(tmpSubject);
1485         OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
1486     }
1487     OIC_LOG(DEBUG, TAG, "AddTmpPskWithPIN OUT");
1488
1489 exit:
1490     return ret;
1491 }
1492
1493 #endif /* __WITH_DTLS__ */
1494 #ifdef __WITH_X509__
1495 #define CERT_LEN_PREFIX (3)
1496 #define BYTE_SIZE (8) //bits
1497 #define PUB_KEY_X_COORD ("x")
1498 #define PUB_KEY_Y_COORD ("y")
1499 #define CERTIFICATE ("x5c")
1500 #define PRIVATE_KEY ("d")
1501
1502 static uint32_t parseCertPrefix(uint8_t *prefix)
1503 {
1504     uint32_t res = 0;
1505     if (NULL != prefix)
1506     {
1507         for (int i = 0; i < CERT_LEN_PREFIX; ++i)
1508         {
1509             res |= (((uint32_t) prefix[i]) << ((CERT_LEN_PREFIX - 1 -i) * BYTE_SIZE));
1510         }
1511     }
1512     return res;
1513 }
1514
1515 static OCStackResult GetCAPublicKeyData(CADtlsX509Creds_t *credInfo)
1516 {
1517     OCStackResult ret = OC_STACK_ERROR;
1518     uint8_t *ccPtr = credInfo->certificateChain;
1519     for (uint8_t i = 0; i < credInfo->chainLen - 1; ++i)
1520     {
1521         ccPtr += CERT_LEN_PREFIX + parseCertPrefix(ccPtr);
1522     }
1523
1524     ByteArray cert = { .data = ccPtr + CERT_LEN_PREFIX, .len = parseCertPrefix(ccPtr) };
1525     CertificateX509 certStruct;
1526
1527     VERIFY_SUCCESS(TAG, PKI_SUCCESS == DecodeCertificate(cert, &certStruct), ERROR);
1528
1529     INC_BYTE_ARRAY(certStruct.pubKey, 2);
1530
1531     memcpy(credInfo->rootPublicKeyX, certStruct.pubKey.data, PUBLIC_KEY_SIZE / 2);
1532     memcpy(credInfo->rootPublicKeyY, certStruct.pubKey.data + PUBLIC_KEY_SIZE / 2, PUBLIC_KEY_SIZE / 2);
1533
1534     ret = OC_STACK_OK;
1535     exit:
1536     return ret;
1537 }
1538
1539 int GetDtlsX509Credentials(CADtlsX509Creds_t *credInfo)
1540 {
1541     int ret = 1;
1542     VERIFY_NON_NULL(TAG, credInfo, ERROR);
1543     if (NULL == gCred)
1544     {
1545         VERIFY_SUCCESS(TAG, OC_STACK_OK == InitCredResource(), ERROR);
1546     }
1547
1548     OicSecCred_t *cred = NULL;
1549     LL_SEARCH_SCALAR(gCred, cred, credType, SIGNED_ASYMMETRIC_KEY);
1550     VERIFY_NON_NULL(TAG, cred, ERROR);
1551
1552     if (cred->publicData.len > MAX_CERT_MESSAGE_LEN || cred->privateData.len > PRIVATE_KEY_SIZE)
1553     {
1554         goto exit;
1555     }
1556     credInfo->chainLen = 2;
1557     memcpy(credInfo->certificateChain, cred->publicData.data, cred->publicData.len);
1558     memcpy(credInfo->devicePrivateKey, cred->privateData.data, cred->privateData.len);
1559     credInfo->certificateChainLen = cred->publicData.len;
1560     GetCAPublicKeyData(credInfo);
1561     ret = 0;
1562
1563 exit:
1564
1565     return ret;
1566 }
1567 #undef CERT_LEN_PREFIX
1568 #endif /* __WITH_X509__ */
1569
1570 OCStackResult SetCredRownerId(const OicUuid_t* newROwner)
1571 {
1572     OCStackResult ret = OC_STACK_ERROR;
1573     uint8_t *cborPayload = NULL;
1574     size_t size = 0;
1575     int secureFlag = 0;
1576     OicUuid_t prevId = {.id={0}};
1577
1578     if(NULL == newROwner)
1579     {
1580         ret = OC_STACK_INVALID_PARAM;
1581     }
1582     if(NULL == gCred)
1583     {
1584         ret = OC_STACK_NO_RESOURCE;
1585     }
1586
1587     if(newROwner && gCred)
1588     {
1589         memcpy(prevId.id, gCred->rownerID.id, sizeof(prevId.id));
1590         memcpy(gCred->rownerID.id, newROwner->id, sizeof(newROwner->id));
1591
1592         ret = CredToCBORPayload(gCred, &cborPayload, &size, secureFlag);
1593         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1594
1595         ret = UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, cborPayload, size);
1596         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1597
1598         OICFree(cborPayload);
1599     }
1600
1601     return ret;
1602
1603 exit:
1604     OICFree(cborPayload);
1605     memcpy(gCred->rownerID.id, prevId.id, sizeof(prevId.id));
1606     return ret;
1607 }
1608
1609 OCStackResult GetCredRownerId(OicUuid_t *rowneruuid)
1610 {
1611     OCStackResult retVal = OC_STACK_ERROR;
1612     if (gCred)
1613     {
1614         *rowneruuid = gCred->rownerID;
1615         retVal = OC_STACK_OK;
1616     }
1617     return retVal;
1618 }