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