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