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