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