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