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
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
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_DATA_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_DATA_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     if (NULL == ehRequest->query)
1056     {
1057         return ehRet;
1058     }
1059
1060     OicParseQueryIter_t parseIter = { .attrPos=NULL };
1061     OicUuid_t subject = {.id={0}};
1062
1063     //Parsing REST query to get the subject
1064     ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
1065     while (GetNextQuery(&parseIter))
1066     {
1067         if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECTID_NAME,
1068                 parseIter.attrLen) == 0)
1069         {
1070             OCStackResult ret = ConvertStrToUuid((const char*)parseIter.valPos, &subject);
1071             VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1072         }
1073     }
1074
1075     if (OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
1076     {
1077         ehRet = OC_EH_RESOURCE_DELETED;
1078     }
1079
1080 exit:
1081     return ehRet;
1082 }
1083
1084 OCEntityHandlerResult CredEntityHandler(OCEntityHandlerFlag flag,
1085                                         OCEntityHandlerRequest * ehRequest,
1086                                         void* callbackParameter)
1087 {
1088     (void)callbackParameter;
1089     OCEntityHandlerResult ret = OC_EH_ERROR;
1090
1091     if (!ehRequest)
1092     {
1093         return OC_EH_ERROR;
1094     }
1095     if (flag & OC_REQUEST_FLAG)
1096     {
1097         OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1098         //TODO :  Handle PUT/DEL methods
1099         switch (ehRequest->method)
1100         {
1101             case OC_REST_GET:
1102                 ret = OC_EH_FORBIDDEN;
1103                 break;
1104             case OC_REST_PUT:
1105                 ret = HandlePutRequest(ehRequest);
1106                 break;
1107             case OC_REST_POST:
1108                 ret = HandlePostRequest(ehRequest);
1109                 break;
1110             case OC_REST_DELETE:
1111                 ret = HandleDeleteRequest(ehRequest);
1112                 break;
1113             default:
1114                 ret = OC_EH_ERROR;
1115                 break;
1116         }
1117     }
1118
1119     //Send payload to request originator
1120     ret = (SendSRMCBORResponse(ehRequest, ret, NULL, 0) == OC_STACK_OK) ?
1121                        ret : OC_EH_ERROR;
1122
1123     return ret;
1124 }
1125
1126 OCStackResult CreateCredResource()
1127 {
1128     OCStackResult ret = OCCreateResource(&gCredHandle,
1129                                          OIC_RSRC_TYPE_SEC_CRED,
1130                                          OIC_MI_DEF,
1131                                          OIC_RSRC_CRED_URI,
1132                                          CredEntityHandler,
1133                                          NULL,
1134                                          OC_RES_PROP_NONE);
1135
1136     if (OC_STACK_OK != ret)
1137     {
1138         OIC_LOG (FATAL, TAG, "Unable to instantiate Cred resource");
1139         DeInitCredResource();
1140     }
1141     return ret;
1142 }
1143
1144 OCStackResult InitCredResource()
1145 {
1146     OCStackResult ret = OC_STACK_ERROR;
1147
1148     //Read Cred resource from PS
1149     uint8_t *data = NULL;
1150     size_t size = 0;
1151     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_CRED_NAME, &data, &size);
1152     // If database read failed
1153     if (ret != OC_STACK_OK)
1154     {
1155         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1156     }
1157     if (data)
1158     {
1159         // Read ACL resource from PS
1160         ret = CBORPayloadToCred(data, size, &gCred);
1161     }
1162
1163     /*
1164      * If SVR database in persistent storage got corrupted or
1165      * is not available for some reason, a default Cred is created
1166      * which allows user to initiate Cred provisioning again.
1167      */
1168     if (ret != OC_STACK_OK || !data || !gCred)
1169     {
1170         gCred = GetCredDefault();
1171     }
1172     //Instantiate 'oic.sec.cred'
1173     ret = CreateCredResource();
1174     OICFree(data);
1175     return ret;
1176 }
1177
1178 OCStackResult DeInitCredResource()
1179 {
1180     OCStackResult result = OCDeleteResource(gCredHandle);
1181     DeleteCredList(gCred);
1182     gCred = NULL;
1183     return result;
1184 }
1185
1186 const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
1187 {
1188     OicSecCred_t *cred = NULL;
1189
1190    if ( NULL == subject)
1191     {
1192        return NULL;
1193     }
1194
1195     LL_FOREACH(gCred, cred)
1196     {
1197         if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
1198         {
1199             return cred;
1200         }
1201     }
1202     return NULL;
1203 }
1204
1205
1206 #if defined(__WITH_DTLS__)
1207 int32_t GetDtlsPskCredentials(CADtlsPskCredType_t type,
1208               const uint8_t *desc, size_t desc_len,
1209               uint8_t *result, size_t result_length)
1210 {
1211     int32_t ret = -1;
1212
1213     if (NULL == result)
1214     {
1215         return ret;
1216     }
1217
1218     switch (type)
1219     {
1220         case CA_DTLS_PSK_HINT:
1221         case CA_DTLS_PSK_IDENTITY:
1222             {
1223                 OicUuid_t deviceID = {.id={}};
1224                 // Retrieve Device ID from doxm resource
1225                 if ( OC_STACK_OK != GetDoxmDeviceID(&deviceID) )
1226                 {
1227                     OIC_LOG (ERROR, TAG, "Unable to retrieve doxm Device ID");
1228                     return ret;
1229                 }
1230
1231                 if (result_length < sizeof(deviceID.id))
1232                 {
1233                     OIC_LOG (ERROR, TAG, "Wrong value for result_length");
1234                     return ret;
1235                 }
1236                 memcpy(result, deviceID.id, sizeof(deviceID.id));
1237                 return (sizeof(deviceID.id));
1238             }
1239             break;
1240
1241         case CA_DTLS_PSK_KEY:
1242             {
1243                 OicSecCred_t *cred = NULL;
1244                 LL_FOREACH(gCred, cred)
1245                 {
1246                     if (cred->credType != SYMMETRIC_PAIR_WISE_KEY)
1247                     {
1248                         continue;
1249                     }
1250
1251                     if ((desc_len == sizeof(cred->subject.id)) &&
1252                         (memcmp(desc, cred->subject.id, sizeof(cred->subject.id)) == 0))
1253                     {
1254                         /*
1255                          * If the credentials are valid for limited time,
1256                          * check their expiry.
1257                          */
1258                         if (cred->period)
1259                         {
1260                             if(IOTVTICAL_VALID_ACCESS != IsRequestWithinValidTime(cred->period, NULL))
1261                             {
1262                                 OIC_LOG (INFO, TAG, "Credentials are expired.");
1263                                 ret = -1;
1264                                 return ret;
1265                             }
1266                         }
1267
1268                         // Copy PSK.
1269                         result_length = cred->privateData.len;
1270                         memcpy(result, cred->privateData.data, result_length);
1271                         return result_length;
1272                     }
1273                 }
1274             }
1275             break;
1276
1277         default:
1278             {
1279                 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
1280                 ret = -1;
1281             }
1282             break;
1283     }
1284
1285     return ret;
1286 }
1287
1288 /**
1289  * Add temporal PSK to PIN based OxM
1290  *
1291  * @param[in] tmpSubject UUID of target device
1292  * @param[in] credType Type of credential to be added
1293  * @param[in] pin numeric characters
1294  * @param[in] pinSize length of 'pin'
1295  * @param[in] ownersLen Number of owners
1296  * @param[in] owners Array of owners
1297  * @param[out] tmpCredSubject Generated credential's subject.
1298  *
1299  * @return OC_STACK_OK for success and errorcode otherwise.
1300  */
1301 OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
1302                             const char * pin, size_t pinSize,
1303                             size_t ownersLen, const OicUuid_t * owners, OicUuid_t* tmpCredSubject)
1304 {
1305     OCStackResult ret = OC_STACK_ERROR;
1306     OIC_LOG(DEBUG, TAG, "AddTmpPskWithPIN IN");
1307
1308     if(NULL == tmpSubject || NULL == pin || 0 == pinSize || NULL == tmpCredSubject)
1309     {
1310         return OC_STACK_INVALID_PARAM;
1311     }
1312
1313     uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
1314     OicSecKey_t privKey = {privData, OWNER_PSK_LENGTH_128};
1315     OicSecCred_t* cred = NULL;
1316     int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, owners->id,
1317                                               UUID_LENGTH, PBKDF_ITERATIONS,
1318                                               OWNER_PSK_LENGTH_128, privData);
1319     VERIFY_SUCCESS(TAG, (0 == dtlsRes) , ERROR);
1320
1321     cred = GenerateCredential(tmpSubject, credType, NULL,
1322                               &privKey, ownersLen, owners);
1323     if(NULL == cred)
1324     {
1325         OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
1326         return OC_STACK_ERROR;
1327     }
1328
1329     memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
1330
1331     ret = AddCredential(cred);
1332     if( OC_STACK_OK != ret)
1333     {
1334         RemoveCredential(tmpSubject);
1335         OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
1336     }
1337     OIC_LOG(DEBUG, TAG, "AddTmpPskWithPIN OUT");
1338
1339 exit:
1340     return ret;
1341 }
1342
1343 #endif /* __WITH_DTLS__ */
1344 #ifdef __WITH_X509__
1345 #define CERT_LEN_PREFIX (3)
1346 #define BYTE_SIZE (8) //bits
1347 #define PUB_KEY_X_COORD ("x")
1348 #define PUB_KEY_Y_COORD ("y")
1349 #define CERTIFICATE ("x5c")
1350 #define PRIVATE_KEY ("d")
1351
1352 static uint32_t parseCertPrefix(uint8_t *prefix)
1353 {
1354     uint32_t res = 0;
1355     if (NULL != prefix)
1356     {
1357         for (int i = 0; i < CERT_LEN_PREFIX; ++i)
1358         {
1359             res |= (((uint32_t) prefix[i]) << ((CERT_LEN_PREFIX - 1 -i) * BYTE_SIZE));
1360         }
1361     }
1362     return res;
1363 }
1364
1365 static OCStackResult GetCAPublicKeyData(CADtlsX509Creds_t *credInfo)
1366 {
1367     OCStackResult ret = OC_STACK_ERROR;
1368     uint8_t *ccPtr = credInfo->certificateChain;
1369     for (uint8_t i = 0; i < credInfo->chainLen - 1; ++i)
1370     {
1371         ccPtr += CERT_LEN_PREFIX + parseCertPrefix(ccPtr);
1372     }
1373
1374     ByteArray cert = { .data = ccPtr + CERT_LEN_PREFIX, .len = parseCertPrefix(ccPtr) };
1375     CertificateX509 certStruct;
1376
1377     VERIFY_SUCCESS(TAG, PKI_SUCCESS == DecodeCertificate(cert, &certStruct), ERROR);
1378
1379     INC_BYTE_ARRAY(certStruct.pubKey, 2);
1380
1381     memcpy(credInfo->rootPublicKeyX, certStruct.pubKey.data, PUBLIC_KEY_SIZE / 2);
1382     memcpy(credInfo->rootPublicKeyY, certStruct.pubKey.data + PUBLIC_KEY_SIZE / 2, PUBLIC_KEY_SIZE / 2);
1383
1384     ret = OC_STACK_OK;
1385     exit:
1386     return ret;
1387 }
1388
1389 int GetDtlsX509Credentials(CADtlsX509Creds_t *credInfo)
1390 {
1391     int ret = 1;
1392     VERIFY_NON_NULL(TAG, credInfo, ERROR);
1393     if (NULL == gCred)
1394     {
1395         VERIFY_SUCCESS(TAG, OC_STACK_OK == InitCredResource(), ERROR);
1396     }
1397
1398     OicSecCred_t *cred = NULL;
1399     LL_SEARCH_SCALAR(gCred, cred, credType, SIGNED_ASYMMETRIC_KEY);
1400     VERIFY_NON_NULL(TAG, cred, ERROR);
1401
1402     if (cred->publicData.len > MAX_CERT_MESSAGE_LEN || cred->privateData.len > PRIVATE_KEY_SIZE)
1403     {
1404         goto exit;
1405     }
1406     credInfo->chainLen = 2;
1407     memcpy(credInfo->certificateChain, cred->publicData.data, cred->publicData.len);
1408     memcpy(credInfo->devicePrivateKey, cred->privateData.data, cred->privateData.len);
1409     credInfo->certificateChainLen = cred->publicData.len;
1410     GetCAPublicKeyData(credInfo);
1411     ret = 0;
1412
1413 exit:
1414
1415     return ret;
1416 }
1417 #undef CERT_LEN_PREFIX
1418 #endif /* __WITH_X509__ */