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