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