Fixed svase-warnings for iotivity-product's SQA on |credresource|
[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, int secureFlag)
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 (!secureFlag && 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(!secureFlag && 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             // TODO: Need to data strucure modification for OicSecKey_t.
261             // TODO: Added as workaround, will be replaced soon.
262             if(OIC_ENCODING_RAW == cred->privateData.encoding)
263             {
264                 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_ENCODING_NAME,
265                     strlen(OIC_JSON_ENCODING_NAME));
266                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Tag.");
267                 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_SEC_ENCODING_RAW,
268                     strlen(OIC_SEC_ENCODING_RAW));
269                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Value.");
270
271                 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_DATA_NAME,
272                     strlen(OIC_JSON_DATA_NAME));
273                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Tag.");
274                 cborEncoderResult = cbor_encode_byte_string(&privateMap, cred->privateData.data,
275                     cred->privateData.len);
276                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Value.");
277             }
278             else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
279             {
280                 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_ENCODING_NAME,
281                     strlen(OIC_JSON_ENCODING_NAME));
282                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Tag.");
283                 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_SEC_ENCODING_BASE64,
284                     strlen(OIC_SEC_ENCODING_BASE64));
285                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Private Encoding Value.");
286
287                 cborEncoderResult = cbor_encode_text_string(&privateMap, OIC_JSON_DATA_NAME,
288                     strlen(OIC_JSON_DATA_NAME));
289                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Tag.");
290                 cborEncoderResult = cbor_encode_text_string(&privateMap, (char*)(cred->privateData.data),
291                     cred->privateData.len);
292                 VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Priv Value.");
293             }
294             else
295             {
296                 OIC_LOG(ERROR, TAG, "Unknow encoding type for private data.");
297                 VERIFY_CBOR_SUCCESS(TAG, CborErrorUnknownType, "Failed Adding Private Encoding Value.");
298             }
299
300             cborEncoderResult = cbor_encoder_close_container(&credMap, &privateMap);
301             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing PrivateData Map.");
302         }
303
304         //Period -- Not Mandatory
305         if(cred->period)
306         {
307             cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_PERIOD_NAME,
308                 strlen(OIC_JSON_PERIOD_NAME));
309             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Name Tag.");
310             cborEncoderResult = cbor_encode_text_string(&credMap, cred->period,
311                 strlen(cred->period));
312             VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Name Value.");
313         }
314
315
316         cborEncoderResult = cbor_encoder_close_container(&credArray, &credMap);
317         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Cred Map.");
318
319         cred = cred->next;
320     }
321     cborEncoderResult = cbor_encoder_close_container(&credRootMap, &credArray);
322     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Cred Array.");
323
324     cred = credS;
325
326     // Rownerid
327     {
328         char *rowner = NULL;
329         cborEncoderResult = cbor_encode_text_string(&credRootMap, OIC_JSON_ROWNERID_NAME,
330             strlen(OIC_JSON_ROWNERID_NAME));
331         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding rownerid Name.");
332         ret = ConvertUuidToStr(&cred->rownerID, &rowner);
333         VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
334         cborEncoderResult = cbor_encode_text_string(&credRootMap, rowner, strlen(rowner));
335         VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding rownerid Value.");
336         OICFree(rowner);
337     }
338
339     // Close CRED Root Map
340     cborEncoderResult = cbor_encoder_close_container(&encoder, &credRootMap);
341     VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing CRED Root Map.");
342
343     if (CborNoError == cborEncoderResult)
344     {
345         OIC_LOG(DEBUG, TAG, "CredToCBORPayload Successed");
346         *cborPayload = outPayload;
347         *cborSize = encoder.ptr - outPayload;
348         ret = OC_STACK_OK;
349     }
350     OIC_LOG(DEBUG, TAG, "CredToCBORPayload OUT");
351 exit:
352     if (CborErrorOutOfMemory == cborEncoderResult)
353     {
354         OIC_LOG(DEBUG, TAG, "CredToCBORPayload:CborErrorOutOfMemory : retry with more memory");
355         // reallocate and try again!
356         OICFree(outPayload);
357         // Since the allocated initial memory failed, double the memory.
358         cborLen += encoder.ptr - encoder.end;
359         cborEncoderResult = CborNoError;
360         ret = CredToCBORPayload(credS, cborPayload, &cborLen, secureFlag);
361         *cborSize = cborLen;
362     }
363
364     if (CborNoError != cborEncoderResult)
365     {
366         OIC_LOG(ERROR, TAG, "Failed to CredToCBORPayload");
367         OICFree(outPayload);
368         outPayload = NULL;
369         *cborSize = 0;
370         *cborPayload = NULL;
371         ret = OC_STACK_ERROR;
372     }
373
374     return ret;
375 }
376
377 OCStackResult CBORPayloadToCred(const uint8_t *cborPayload, size_t size,
378                                 OicSecCred_t **secCred)
379 {
380     if (NULL == cborPayload || NULL == secCred || NULL != *secCred || 0 == size)
381     {
382         return OC_STACK_INVALID_PARAM;
383     }
384
385     OCStackResult ret = OC_STACK_ERROR;
386     CborValue credCbor = { .parser = NULL };
387     CborParser parser = { .end = NULL };
388     CborError cborFindResult = CborNoError;
389     cbor_parser_init(cborPayload, size, 0, &parser, &credCbor);
390
391     OicSecCred_t *headCred = (OicSecCred_t *) OICCalloc(1, sizeof(OicSecCred_t));
392
393     // Enter CRED Root Map
394     CborValue CredRootMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
395     cborFindResult = cbor_value_enter_container(&credCbor, &CredRootMap);
396     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering CRED Root Map.");
397
398     while (cbor_value_is_valid(&CredRootMap))
399     {
400         char* tagName = NULL;
401         size_t len = 0;
402         CborType type = cbor_value_get_type(&CredRootMap);
403         if (type == CborTextStringType && cbor_value_is_text_string(&CredRootMap))
404         {
405             cborFindResult = cbor_value_dup_text_string(&CredRootMap, &tagName, &len, NULL);
406             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in CRED Root Map.");
407             cborFindResult = cbor_value_advance(&CredRootMap);
408             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in CRED Root Map.");
409         }
410         if(tagName)
411         {
412             if (strcmp(tagName, OIC_JSON_CREDS_NAME)  == 0)
413             {
414                 // Enter CREDS Array
415                 size_t len = 0;
416                 int credCount = 0;
417                 CborValue credArray = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
418                 cborFindResult = cbor_value_enter_container(&CredRootMap, &credArray);
419                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Array.");
420
421                 while (cbor_value_is_valid(&credArray))
422                 {
423                     credCount++;
424                     //CredId -- Mandatory
425                     CborValue credMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
426                     cborFindResult = cbor_value_enter_container(&credArray, &credMap);
427                     VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Cred Map.");
428                     OicSecCred_t *cred = NULL;
429
430                     if(1 == credCount)
431                     {
432                         cred = headCred;
433                     }
434                     else
435                     {
436                         cred = (OicSecCred_t *) OICCalloc(1, sizeof(OicSecCred_t));
437                         OicSecCred_t *temp = headCred;
438                         while (temp->next)
439                         {
440                             temp = temp->next;
441                         }
442                         temp->next = cred;
443                     }
444
445                     VERIFY_NON_NULL(TAG, cred, ERROR);
446
447                     while(cbor_value_is_valid(&credMap) && cbor_value_is_text_string(&credMap))
448                     {
449                         char* name = NULL;
450                         CborType type = cbor_value_get_type(&credMap);
451                         if (type == CborTextStringType)
452                         {
453                             cborFindResult = cbor_value_dup_text_string(&credMap, &name, &len, NULL);
454                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Name in CRED Map.");
455                             cborFindResult = cbor_value_advance(&credMap);
456                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing Value in CRED Map.");
457                         }
458                         if(name)
459                         {
460                             //credid
461                             if (strcmp(name, OIC_JSON_CREDID_NAME)  == 0)
462                             {
463                                 uint64_t credId = 0;
464                                 cborFindResult = cbor_value_get_uint64(&credMap, &credId);
465                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CredId.");
466                                 cred->credId = (uint16_t)credId;
467                             }
468                             // subjectid
469                             if (strcmp(name, OIC_JSON_SUBJECTID_NAME)  == 0)
470                             {
471                                 char *subjectid = NULL;
472                                 cborFindResult = cbor_value_dup_text_string(&credMap, &subjectid, &len, NULL);
473                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding subjectid Value.");
474                                 ret = ConvertStrToUuid(subjectid, &cred->subject);
475                                 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
476                                 OICFree(subjectid);
477                             }
478                             // credtype
479                             if (strcmp(name, OIC_JSON_CREDTYPE_NAME)  == 0)
480                             {
481                                 uint64_t credType = 0;
482                                 cborFindResult = cbor_value_get_uint64(&credMap, &credType);
483                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding CredType.");
484                                 cred->credType = (OicSecCredType_t)credType;
485                             }
486                             // privatedata
487                             if (strcmp(name, OIC_JSON_PRIVATEDATA_NAME)  == 0)
488                             {
489                                 CborValue privateMap = { .parser = NULL };
490                                 cborFindResult = cbor_value_enter_container(&credMap, &privateMap);
491
492                                 while (cbor_value_is_valid(&privateMap))
493                                 {
494                                     char* privname = NULL;
495                                     CborType type = cbor_value_get_type(&privateMap);
496                                     if (type == CborTextStringType && cbor_value_is_text_string(&privateMap))
497                                     {
498                                         cborFindResult = cbor_value_dup_text_string(&privateMap, &privname,
499                                                 &len, NULL);
500                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
501                                         cborFindResult = cbor_value_advance(&privateMap);
502                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
503                                     }
504                                     if (privname)
505                                     {
506                                         // PrivateData::privdata -- Mandatory
507                                         if (strcmp(privname, OIC_JSON_DATA_NAME) == 0)
508                                         {
509                                             if(cbor_value_is_byte_string(&privateMap))
510                                             {
511                                                 cborFindResult = cbor_value_dup_byte_string(&privateMap, &cred->privateData.data,
512                                                     &cred->privateData.len, NULL);
513                                             }
514                                             else if(cbor_value_is_text_string(&privateMap))
515                                             {
516                                                 cborFindResult = cbor_value_dup_text_string(&privateMap, (char**)(&cred->privateData.data),
517                                                     &cred->privateData.len, NULL);
518                                             }
519                                             else
520                                             {
521                                                 cborFindResult = CborErrorUnknownType;
522                                                 OIC_LOG(ERROR, TAG, "Unknow type for private data.");
523                                             }
524                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PrivateData.");
525                                         }
526
527                                         // PrivateData::encoding -- Mandatory
528                                         if (strcmp(privname, OIC_JSON_ENCODING_NAME) == 0)
529                                         {
530                                             // TODO: Added as workaround. Will be replaced soon.
531                                             char* strEncoding = NULL;
532                                             cborFindResult = cbor_value_dup_text_string(&privateMap, &strEncoding, &len, NULL);
533                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding EncodingType");
534
535                                             if(strcmp(strEncoding, OIC_SEC_ENCODING_RAW) == 0)
536                                             {
537                                                 cred->privateData.encoding = OIC_ENCODING_RAW;
538                                             }
539                                             else if(strcmp(strEncoding, OIC_SEC_ENCODING_BASE64) == 0)
540                                             {
541                                                 cred->privateData.encoding = OIC_ENCODING_BASE64;
542                                             }
543                                             else
544                                             {
545                                                 //For unit test
546                                                 cred->privateData.encoding = OIC_ENCODING_RAW;
547                                                 OIC_LOG(WARNING, TAG, "Unknow encoding type dectected for private data.");
548                                             }
549
550                                             OICFree(strEncoding);
551                                         }
552                                     }
553                                     if (cbor_value_is_valid(&privateMap))
554                                     {
555                                         cborFindResult = cbor_value_advance(&privateMap);
556                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing privatedata Map.");
557                                     }
558                                     OICFree(privname);
559                                 }
560
561                             }
562 #ifdef __WITH_X509__
563                             if (strcmp(name, OIC_JSON_PUBLICDATA_NAME)  == 0)
564                             {
565                                 CborValue pubMap = { .parser = NULL };
566                                 cborFindResult = cbor_value_enter_container(&credMap, &pubMap);
567
568                                 while (cbor_value_is_valid(&pubMap))
569                                 {
570                                     char* pubname = NULL;
571                                     CborType type = cbor_value_get_type(&pubMap);
572                                     if (type == CborTextStringType && cbor_value_is_text_string(&pubMap))
573                                     {
574                                         cborFindResult = cbor_value_dup_text_string(&pubMap, &pubname,
575                                                 &len, NULL);
576                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to get text");
577                                         cborFindResult = cbor_value_advance(&pubMap);
578                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed to advance value");
579                                     }
580                                     if (pubname)
581                                     {
582                                         // PrivateData::privdata -- Mandatory
583                                         if (strcmp(pubname, OIC_JSON_DATA_NAME) == 0 && cbor_value_is_byte_string(&pubMap))
584                                         {
585                                             cborFindResult = cbor_value_dup_byte_string(&pubMap, &cred->publicData.data,
586                                                 &cred->publicData.len, NULL);
587                                             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PubData.");
588                                         }
589                                         // PublicData::encoding -- Mandatory
590                                         if (strcmp(pubname, OIC_JSON_ENCODING_NAME) == 0)
591                                         {
592                                             // TODO: Need to update data structure, just ignore encoding value now.
593                                         }
594                                     }
595                                     if (cbor_value_is_valid(&pubMap))
596                                     {
597                                         cborFindResult = cbor_value_advance(&pubMap);
598                                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing publicdata Map.");
599                                     }
600                                     OICFree(pubname);
601                                 }
602                             }
603 #endif  //__WITH_X509__
604
605                             if (0 == strcmp(OIC_JSON_PERIOD_NAME, name))
606                             {
607                                 cborFindResult = cbor_value_dup_text_string(&credMap, &cred->period, &len, NULL);
608                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Period.");
609                             }
610
611                             if (cbor_value_is_valid(&credMap))
612                             {
613                                 cborFindResult = cbor_value_advance(&credMap);
614                                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing CRED Map.");
615                             }
616                             OICFree(name);
617                         }
618                     }
619                     cred->next = NULL;
620                     if (cbor_value_is_valid(&credArray))
621                     {
622                         cborFindResult = cbor_value_advance(&credArray);
623                         VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing CRED Array.");
624                     }
625                 }
626             }
627
628             //ROwner -- Mandatory
629             if (strcmp(tagName, OIC_JSON_ROWNERID_NAME)  == 0 && cbor_value_is_text_string(&CredRootMap))
630             {
631                 char *stRowner = NULL;
632                 cborFindResult = cbor_value_dup_text_string(&CredRootMap, &stRowner, &len, NULL);
633                 VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Rownerid Value.");
634
635                 ret = ConvertStrToUuid(stRowner, &headCred->rownerID);
636                 VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
637                 OICFree(stRowner);
638             }
639             OICFree(tagName);
640         }
641         if (cbor_value_is_valid(&CredRootMap))
642         {
643             cborFindResult = cbor_value_advance(&CredRootMap);
644             VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing CRED Root Map.");
645         }
646     }
647
648     *secCred = headCred;
649     ret = OC_STACK_OK;
650
651 exit:
652     if (CborNoError != cborFindResult)
653     {
654         DeleteCredList(headCred);
655         headCred = NULL;
656         *secCred = NULL;
657         ret = OC_STACK_ERROR;
658     }
659
660     return ret;
661 }
662
663 OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t credType,
664                                   const OicSecCert_t * publicData, const OicSecKey_t* privateData,
665                                   const OicUuid_t * rownerID)
666 {
667     (void)publicData;
668     OCStackResult ret = OC_STACK_ERROR;
669
670     OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(*cred));
671     VERIFY_NON_NULL(TAG, cred, ERROR);
672
673     //CredId is assigned before appending new cred to the existing
674     //credential list and updating svr database in AddCredential().
675     cred->credId = 0;
676
677     VERIFY_NON_NULL(TAG, subject, ERROR);
678     memcpy(cred->subject.id, subject->id , sizeof(cred->subject.id));
679
680     VERIFY_SUCCESS(TAG, credType < (NO_SECURITY_MODE | SYMMETRIC_PAIR_WISE_KEY |
681             SYMMETRIC_GROUP_KEY | ASYMMETRIC_KEY | SIGNED_ASYMMETRIC_KEY | PIN_PASSWORD), ERROR);
682     cred->credType = credType;
683
684 #ifdef __WITH_X509__
685     if (publicData && publicData->data)
686     {
687         cred->publicData.data = (uint8_t *)OICCalloc(1, publicData->len);
688         VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
689         memcpy(cred->publicData.data, publicData->data, publicData->len);
690         cred->publicData.len = publicData->len;
691     }
692 #endif // __WITH_X509__
693
694     if (privateData && privateData->data)
695     {
696         cred->privateData.data = (uint8_t *)OICCalloc(1, privateData->len);
697         VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
698         memcpy(cred->privateData.data, privateData->data, privateData->len);
699         cred->privateData.len = privateData->len;
700
701         // TODO: Added as workaround. Will be replaced soon.
702         cred->privateData.encoding = OIC_ENCODING_RAW;
703
704 #if 0
705         // NOTE: Test codes to use base64 for credential.
706         uint32_t outSize = 0;
707         size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((privateData->len + 1));
708         char* b64Buf = (uint8_t *)OICCalloc(1, b64BufSize);
709         VERIFY_NON_NULL(TAG, b64Buf, ERROR);
710         b64Encode(privateData->data, privateData->len, b64Buf, b64BufSize, &outSize);
711
712         OICFree( cred->privateData.data );
713         cred->privateData.data = (uint8_t *)OICCalloc(1, outSize + 1);
714         VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
715
716         strcpy(cred->privateData.data, b64Buf);
717         cred->privateData.encoding = OIC_ENCODING_BASE64;
718         cred->privateData.len = outSize;
719         OICFree(b64Buf);
720 #endif //End of Test codes
721
722     }
723
724     VERIFY_NON_NULL(TAG, rownerID, ERROR);
725     memcpy(&cred->rownerID, rownerID, sizeof(OicUuid_t));
726
727     ret = OC_STACK_OK;
728 exit:
729     if (OC_STACK_OK != ret)
730     {
731         DeleteCredList(cred);
732         cred = NULL;
733     }
734     return cred;
735 }
736
737 static bool UpdatePersistentStorage(const OicSecCred_t *cred)
738 {
739     bool ret = false;
740
741     // Convert Cred data into JSON for update to persistent storage
742     if (cred)
743     {
744         uint8_t *payload = NULL;
745         size_t size = 0;
746         int secureFlag = 0;
747         OCStackResult res = CredToCBORPayload(cred, &payload, &size, secureFlag);
748         if ((OC_STACK_OK == res) && payload)
749         {
750             if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, payload, size))
751             {
752                 ret = true;
753             }
754             OICFree(payload);
755         }
756     }
757     else //Empty cred list
758     {
759         if (OC_STACK_OK == UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, NULL, 0))
760         {
761             ret = true;
762         }
763     }
764     return ret;
765 }
766
767 /**
768  * Compare function used LL_SORT for sorting credentials.
769  *
770  * @param first pointer to OicSecCred_t struct.
771  * @param second  pointer to OicSecCred_t struct.
772  *
773  *@return -1, if credId of first is less than credId of second.
774  * 0, if credId of first is equal to credId of second.
775  * 1, if credId of first is greater than credId of second.
776  */
777 static int CmpCredId(const OicSecCred_t * first, const OicSecCred_t *second)
778 {
779     if (first->credId < second->credId)
780     {
781         return -1;
782     }
783     else if (first->credId > second->credId)
784     {
785         return 1;
786     }
787     else
788         return 0;
789 }
790
791 /**
792  * GetCredId goes through the cred list and returns the next
793  * available credId. The next credId could be the credId that is
794  * available due deletion of OicSecCred_t object or one more than
795  * credId of last credential in the list.
796  *
797  * @return next available credId if successful, else 0 for error.
798  */
799 static uint16_t GetCredId()
800 {
801     //Sorts credential list in incremental order of credId
802     LL_SORT(gCred, CmpCredId);
803
804     OicSecCred_t *currentCred = NULL, *credTmp = NULL;
805     uint16_t nextCredId = 1;
806
807     LL_FOREACH_SAFE(gCred, currentCred, credTmp)
808     {
809         if (currentCred->credId == nextCredId)
810         {
811             nextCredId += 1;
812         }
813         else
814         {
815             break;
816         }
817     }
818
819     VERIFY_SUCCESS(TAG, nextCredId < UINT16_MAX, ERROR);
820     return nextCredId;
821
822 exit:
823     return 0;
824 }
825
826 /**
827  * Get the default value.
828  *
829  * @return  NULL for now.
830  */
831 static OicSecCred_t* GetCredDefault()
832 {
833     // TODO:Update it when we finalize the default info.
834     return NULL;
835 }
836
837 OCStackResult AddCredential(OicSecCred_t * newCred)
838 {
839     OCStackResult ret = OC_STACK_ERROR;
840     VERIFY_SUCCESS(TAG, NULL != newCred, ERROR);
841
842     //Assigning credId to the newCred
843     newCred->credId = GetCredId();
844     VERIFY_SUCCESS(TAG, newCred->credId != 0, ERROR);
845
846     //Append the new Cred to existing list
847     LL_APPEND(gCred, newCred);
848
849     if (UpdatePersistentStorage(gCred))
850     {
851         ret = OC_STACK_OK;
852     }
853
854 exit:
855     return ret;
856 }
857
858 OCStackResult RemoveCredential(const OicUuid_t *subject)
859 {
860     OCStackResult ret = OC_STACK_ERROR;
861     OicSecCred_t *cred = NULL;
862     OicSecCred_t *tempCred = NULL;
863     bool deleteFlag = false;
864
865     LL_FOREACH_SAFE(gCred, cred, tempCred)
866     {
867         if (memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
868         {
869             LL_DELETE(gCred, cred);
870             FreeCred(cred);
871             deleteFlag = 1;
872         }
873     }
874
875     if (deleteFlag)
876     {
877         if (UpdatePersistentStorage(gCred))
878         {
879             ret = OC_STACK_RESOURCE_DELETED;
880         }
881     }
882     return ret;
883
884 }
885
886 /**
887  * Remove all credential data on credential resource and persistent storage
888  *
889  * @retval
890  *     OC_STACK_OK              - no errors
891  *     OC_STACK_ERROR           - stack process error
892  */
893 OCStackResult RemoveAllCredentials(void)
894 {
895     DeleteCredList(gCred);
896     gCred = GetCredDefault();
897
898     if (!UpdatePersistentStorage(gCred))
899     {
900         return OC_STACK_ERROR;
901     }
902     return OC_STACK_OK;
903 }
904
905 #ifdef __WITH_DTLS__
906 /**
907  * Internal function to fill private data of owner PSK.
908  *
909  * @param receviedCred recevied owner credential from OBT(PT)
910  * @param ownerAdd address of OBT(PT)
911  * @param doxm current device's doxm resource
912  *
913  * @return
914  *     true successfully done and valid ower psk information
915  *     false Invalid owner psk information or failed to owner psk generation
916  */
917 static bool FillPrivateDataOfOwnerPSK(OicSecCred_t* receviedCred, const CAEndpoint_t* ownerAddr,
918                            const OicSecDoxm_t* doxm)
919 {
920     //Derive OwnerPSK locally
921     const char* oxmLabel = GetOxmString(doxm->oxmSel);
922     VERIFY_NON_NULL(TAG, oxmLabel, ERROR);
923
924     uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
925     CAResult_t pskRet = CAGenerateOwnerPSK(ownerAddr,
926         (uint8_t*)oxmLabel, strlen(oxmLabel),
927         doxm->owner.id, sizeof(doxm->owner.id),
928         doxm->deviceID.id, sizeof(doxm->deviceID.id),
929         ownerPSK, OWNER_PSK_LENGTH_128);
930     VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
931
932     OIC_LOG(DEBUG, TAG, "OwnerPSK dump :");
933     OIC_LOG_BUFFER(DEBUG, TAG, ownerPSK, OWNER_PSK_LENGTH_128);
934
935     //Generate owner credential based on recevied credential information
936
937     // TODO: Added as workaround, will be replaced soon.
938     if(OIC_ENCODING_RAW == receviedCred->privateData.encoding)
939     {
940         receviedCred->privateData.data = (uint8_t *)OICCalloc(1, OWNER_PSK_LENGTH_128);
941         VERIFY_NON_NULL(TAG, receviedCred->privateData.data, ERROR);
942         receviedCred->privateData.len = OWNER_PSK_LENGTH_128;
943         memcpy(receviedCred->privateData.data, ownerPSK, OWNER_PSK_LENGTH_128);
944     }
945     else if(OIC_ENCODING_BASE64 == receviedCred->privateData.encoding)
946     {
947         uint32_t b64OutSize = 0;
948         size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
949         char* b64Buf = OICCalloc(1, b64BufSize);
950         VERIFY_NON_NULL(TAG, b64Buf, ERROR);
951
952         b64Encode(ownerPSK, OWNER_PSK_LENGTH_128, b64Buf, b64BufSize, &b64OutSize);
953
954         receviedCred->privateData.data = (uint8_t *)OICCalloc(1, b64OutSize + 1);
955         VERIFY_NON_NULL(TAG, receviedCred->privateData.data, ERROR);
956         receviedCred->privateData.len = b64OutSize;
957         strncpy((char*)receviedCred->privateData.data, b64Buf, b64OutSize);
958         receviedCred->privateData.data[b64OutSize] = '\0';
959     }
960     else
961     {
962         // TODO: error
963         VERIFY_SUCCESS(TAG, OIC_ENCODING_UNKNOW, ERROR);
964     }
965
966     OIC_LOG(INFO, TAG, "PrivateData of OwnerPSK was calculated successfully");
967
968     //Verify OwnerPSK information
969     return (memcmp(&(receviedCred->subject), &(doxm->owner), sizeof(OicUuid_t)) == 0 &&
970             receviedCred->credType == SYMMETRIC_PAIR_WISE_KEY);
971 exit:
972     //receviedCred->privateData.data will be deallocated when deleting credential.
973     return false;
974 }
975
976 #endif //__WITH_DTLS__
977
978 static OCEntityHandlerResult HandlePutRequest(const OCEntityHandlerRequest * ehRequest)
979 {
980     OCEntityHandlerResult ret = OC_EH_ERROR;
981     OIC_LOG(DEBUG, TAG, "HandleCREDPutRequest IN");
982
983     //Get binary representation of cbor
984     OicSecCred_t *cred  = NULL;
985     uint8_t *payload = (((OCSecurityPayload*)ehRequest->payload)->securityData);
986     size_t size = (((OCSecurityPayload*)ehRequest->payload)->payloadSize);
987
988     OCStackResult res = CBORPayloadToCred(payload, size, &cred);
989     if (res == OC_STACK_OK)
990     {
991 #ifdef __WITH_DTLS__
992         OicUuid_t emptyUuid = {.id={0}};
993         const OicSecDoxm_t* doxm = GetDoxmResourceData();
994         if(false == doxm->owned && memcmp(&(doxm->owner), &emptyUuid, sizeof(OicUuid_t)) != 0)
995         {
996             //in case of owner PSK
997             switch(cred->credType)
998             {
999                 case SYMMETRIC_PAIR_WISE_KEY:
1000                 {
1001                     OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
1002                     if(FillPrivateDataOfOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm))
1003                     {
1004                         if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&cred->subject))
1005                         {
1006                             OIC_LOG(WARNING, TAG, "The credential with the same subject ID was detected!");
1007                         }
1008
1009                         OIC_LOG(ERROR, TAG, "OwnerPSK was generated successfully.");
1010                         if(OC_STACK_OK == AddCredential(cred))
1011                         {
1012                             ret = OC_EH_RESOURCE_CREATED;
1013                         }
1014                         else
1015                         {
1016                             OIC_LOG(ERROR, TAG, "Failed to save the OwnerPSK as cred resource");
1017                             ret = OC_EH_ERROR;
1018                         }
1019                     }
1020                     else
1021                     {
1022                         OIC_LOG(ERROR, TAG, "Failed to verify receviced OwnerPKS.");
1023                         ret = OC_EH_ERROR;
1024                     }
1025
1026                     if(OC_EH_RESOURCE_CREATED == ret)
1027                     {
1028                         /**
1029                          * in case of random PIN based OxM,
1030                          * revert get_psk_info callback of tinyDTLS to use owner credential.
1031                          */
1032                         if(OIC_RANDOM_DEVICE_PIN == doxm->oxmSel)
1033                         {
1034                             OicUuid_t emptyUuid = { .id={0}};
1035                             SetUuidForRandomPinOxm(&emptyUuid);
1036
1037                             if(CA_STATUS_OK != CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials))
1038                             {
1039                                 OIC_LOG(ERROR, TAG, "Failed to revert DTLS credential handler.");
1040                                 ret = OC_EH_ERROR;
1041                                 break;
1042                             }
1043                         }
1044
1045                         //Select cipher suite to use owner PSK
1046                         if(CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false))
1047                         {
1048                             OIC_LOG(ERROR, TAG, "Failed to disable anonymous cipher suite");
1049                             ret = OC_EH_ERROR;
1050                         }
1051                         else
1052                         {
1053                             OIC_LOG(INFO, TAG, "Anonymous cipher suite is DISABLED");
1054                         }
1055
1056                         if(CA_STATUS_OK !=
1057                            CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256))
1058                         {
1059                             OIC_LOG(ERROR, TAG, "Failed to select cipher suite");
1060                             ret = OC_EH_ERROR;
1061                         }
1062                     }
1063
1064                     break;
1065                 }
1066                 case SYMMETRIC_GROUP_KEY:
1067                 case ASYMMETRIC_KEY:
1068                 case SIGNED_ASYMMETRIC_KEY:
1069                 case PIN_PASSWORD:
1070                 case ASYMMETRIC_ENCRYPTION_KEY:
1071                 {
1072                     OIC_LOG(WARNING, TAG, "Unsupported credential type for owner credential.");
1073                     ret = OC_EH_ERROR;
1074                     break;
1075                 }
1076                 default:
1077                 {
1078                     OIC_LOG(WARNING, TAG, "Unknow credential type for owner credential.");
1079                     ret = OC_EH_ERROR;
1080                     break;
1081                 }
1082             }
1083
1084             if(OC_EH_RESOURCE_CREATED != ret)
1085             {
1086                 /*
1087                   * If some error is occured while ownership transfer,
1088                   * ownership transfer related resource should be revert back to initial status.
1089                   */
1090                 RestoreDoxmToInitState();
1091                 RestorePstatToInitState();
1092             }
1093         }
1094         else
1095         {
1096             /*
1097              * If the post request credential has credId, it will be
1098              * discarded and the next available credId will be assigned
1099              * to it before getting appended to the existing credential
1100              * list and updating svr database.
1101              */
1102             ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
1103         }
1104 #else //not __WITH_DTLS__
1105         /*
1106          * If the post request credential has credId, it will be
1107          * discarded and the next available credId will be assigned
1108          * to it before getting appended to the existing credential
1109          * list and updating svr database.
1110          */
1111         ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
1112 #endif//__WITH_DTLS__
1113     }
1114
1115     if (OC_EH_RESOURCE_CREATED != ret)
1116     {
1117         if(OC_STACK_OK != RemoveCredential(&cred->subject))
1118         {
1119             OIC_LOG(WARNING, TAG, "Failed to remove the invalid credential");
1120         }
1121         FreeCred(cred);
1122     }
1123     OIC_LOG(DEBUG, TAG, "HandleCREDPutRequest OUT");
1124     return ret;
1125 }
1126
1127 /**
1128  * The entity handler determines how to process a GET request.
1129  */
1130 static OCEntityHandlerResult HandleGetRequest (const OCEntityHandlerRequest * ehRequest)
1131 {
1132     OIC_LOG(INFO, TAG, "HandleGetRequest  processing GET request");
1133
1134     // Convert Cred data into CBOR for transmission
1135     size_t size = 0;
1136     uint8_t *payload = NULL;
1137     int secureFlag = 1;
1138
1139     const OicSecCred_t *cred = gCred;
1140     OCStackResult res = CredToCBORPayload(cred, &payload, &size, secureFlag);
1141
1142     // A device should always have a default cred. Therefore, payload should never be NULL.
1143     OCEntityHandlerResult ehRet = (res == OC_STACK_OK) ? OC_EH_OK : OC_EH_ERROR;
1144
1145     // Send response payload to request originator
1146     if (OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, payload, size))
1147     {
1148         ehRet = OC_EH_ERROR;
1149         OIC_LOG(ERROR, TAG, "SendSRMResponse failed in HandlePstatGetRequest");
1150     }
1151     OICFree(payload);
1152     return ehRet;
1153 }
1154
1155 static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
1156 {
1157     OCEntityHandlerResult ret = OC_EH_ERROR;
1158
1159     //Get binary representation of CBOR
1160     OicSecCred_t *cred  = NULL;
1161     uint8_t *payload = ((OCSecurityPayload*)ehRequest->payload)->securityData;
1162     size_t size = ((OCSecurityPayload*)ehRequest->payload)->payloadSize;
1163     OCStackResult res = CBORPayloadToCred(payload, size, &cred);
1164     if ((OC_STACK_OK == res) && cred)
1165     {
1166         //If the Post request credential has credId, it will be
1167         //discarded and the next available credId will be assigned
1168         //to it before getting appended to the existing credential
1169         //list and updating svr database.
1170         ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
1171     }
1172
1173     return ret;
1174 }
1175
1176 static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
1177 {
1178     OIC_LOG(DEBUG, TAG, "Processing CredDeleteRequest");
1179
1180     OCEntityHandlerResult ehRet = OC_EH_ERROR;
1181
1182     if (NULL == ehRequest->query)
1183     {
1184         return ehRet;
1185     }
1186
1187     OicParseQueryIter_t parseIter = { .attrPos=NULL };
1188     OicUuid_t subject = {.id={0}};
1189
1190     //Parsing REST query to get the subject
1191     ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
1192     while (GetNextQuery(&parseIter))
1193     {
1194         if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECTID_NAME,
1195                 parseIter.attrLen) == 0)
1196         {
1197             OCStackResult ret = ConvertStrToUuid((const char*)parseIter.valPos, &subject);
1198             VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1199         }
1200     }
1201
1202     if (OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
1203     {
1204         ehRet = OC_EH_RESOURCE_DELETED;
1205     }
1206
1207 exit:
1208     return ehRet;
1209 }
1210
1211 OCEntityHandlerResult CredEntityHandler(OCEntityHandlerFlag flag,
1212                                         OCEntityHandlerRequest * ehRequest,
1213                                         void* callbackParameter)
1214 {
1215     (void)callbackParameter;
1216     OCEntityHandlerResult ret = OC_EH_ERROR;
1217
1218     if (!ehRequest)
1219     {
1220         return OC_EH_ERROR;
1221     }
1222     if (flag & OC_REQUEST_FLAG)
1223     {
1224         OIC_LOG (DEBUG, TAG, "Flag includes OC_REQUEST_FLAG");
1225         //TODO :  Handle PUT/DEL methods
1226         switch (ehRequest->method)
1227         {
1228             case OC_REST_GET:
1229                 ret = HandleGetRequest(ehRequest);;
1230                 break;
1231             case OC_REST_PUT:
1232                 ret = HandlePutRequest(ehRequest);
1233                 break;
1234             case OC_REST_POST:
1235                 ret = HandlePostRequest(ehRequest);
1236                 break;
1237             case OC_REST_DELETE:
1238                 ret = HandleDeleteRequest(ehRequest);
1239                 break;
1240             default:
1241                 ret = OC_EH_ERROR;
1242                 break;
1243         }
1244     }
1245
1246     //Send payload to request originator
1247     ret = (SendSRMResponse(ehRequest, ret, NULL, 0) == OC_STACK_OK) ?
1248                        ret : OC_EH_ERROR;
1249
1250     return ret;
1251 }
1252
1253 OCStackResult CreateCredResource()
1254 {
1255     OCStackResult ret = OCCreateResource(&gCredHandle,
1256                                          OIC_RSRC_TYPE_SEC_CRED,
1257                                          OC_RSRVD_INTERFACE_DEFAULT,
1258                                          OIC_RSRC_CRED_URI,
1259                                          CredEntityHandler,
1260                                          NULL,
1261                                          OC_SECURE);
1262
1263     if (OC_STACK_OK != ret)
1264     {
1265         OIC_LOG (FATAL, TAG, "Unable to instantiate Cred resource");
1266         DeInitCredResource();
1267     }
1268     return ret;
1269 }
1270
1271 OCStackResult InitCredResource()
1272 {
1273     OCStackResult ret = OC_STACK_ERROR;
1274
1275     //Read Cred resource from PS
1276     uint8_t *data = NULL;
1277     size_t size = 0;
1278     ret = GetSecureVirtualDatabaseFromPS(OIC_JSON_CRED_NAME, &data, &size);
1279     // If database read failed
1280     if (ret != OC_STACK_OK)
1281     {
1282         OIC_LOG (DEBUG, TAG, "ReadSVDataFromPS failed");
1283     }
1284     if (data)
1285     {
1286         // Read ACL resource from PS
1287         ret = CBORPayloadToCred(data, size, &gCred);
1288     }
1289
1290     /*
1291      * If SVR database in persistent storage got corrupted or
1292      * is not available for some reason, a default Cred is created
1293      * which allows user to initiate Cred provisioning again.
1294      */
1295     if (ret != OC_STACK_OK || !data || !gCred)
1296     {
1297         gCred = GetCredDefault();
1298     }
1299     //Instantiate 'oic.sec.cred'
1300     ret = CreateCredResource();
1301     OICFree(data);
1302     return ret;
1303 }
1304
1305 OCStackResult DeInitCredResource()
1306 {
1307     OCStackResult result = OCDeleteResource(gCredHandle);
1308     DeleteCredList(gCred);
1309     gCred = NULL;
1310     return result;
1311 }
1312
1313 const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
1314 {
1315     OicSecCred_t *cred = NULL;
1316
1317    if ( NULL == subject)
1318     {
1319        return NULL;
1320     }
1321
1322     LL_FOREACH(gCred, cred)
1323     {
1324         if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
1325         {
1326             return cred;
1327         }
1328     }
1329     return NULL;
1330 }
1331
1332
1333 #if defined(__WITH_DTLS__)
1334 int32_t GetDtlsPskCredentials(CADtlsPskCredType_t type,
1335               const uint8_t *desc, size_t desc_len,
1336               uint8_t *result, size_t result_length)
1337 {
1338     int32_t ret = -1;
1339
1340     if (NULL == result)
1341     {
1342         return ret;
1343     }
1344
1345     switch (type)
1346     {
1347         case CA_DTLS_PSK_HINT:
1348         case CA_DTLS_PSK_IDENTITY:
1349             {
1350                 OicUuid_t deviceID = {.id={}};
1351                 // Retrieve Device ID from doxm resource
1352                 if ( OC_STACK_OK != GetDoxmDeviceID(&deviceID) )
1353                 {
1354                     OIC_LOG (ERROR, TAG, "Unable to retrieve doxm Device ID");
1355                     return ret;
1356                 }
1357
1358                 if (result_length < sizeof(deviceID.id))
1359                 {
1360                     OIC_LOG (ERROR, TAG, "Wrong value for result_length");
1361                     return ret;
1362                 }
1363                 memcpy(result, deviceID.id, sizeof(deviceID.id));
1364                 return (sizeof(deviceID.id));
1365             }
1366             break;
1367
1368         case CA_DTLS_PSK_KEY:
1369             {
1370                 OicSecCred_t *cred = NULL;
1371                 LL_FOREACH(gCred, cred)
1372                 {
1373                     if (cred->credType != SYMMETRIC_PAIR_WISE_KEY)
1374                     {
1375                         continue;
1376                     }
1377
1378                     if ((desc_len == sizeof(cred->subject.id)) &&
1379                         (memcmp(desc, cred->subject.id, sizeof(cred->subject.id)) == 0))
1380                     {
1381                         /*
1382                          * If the credentials are valid for limited time,
1383                          * check their expiry.
1384                          */
1385                         if (cred->period)
1386                         {
1387                             if(IOTVTICAL_VALID_ACCESS != IsRequestWithinValidTime(cred->period, NULL))
1388                             {
1389                                 OIC_LOG (INFO, TAG, "Credentials are expired.");
1390                                 return ret;
1391                             }
1392                         }
1393
1394                         // Copy PSK.
1395                         // TODO: Added as workaround. Will be replaced soon.
1396                         if(OIC_ENCODING_RAW == cred->privateData.encoding)
1397                         {
1398                             result_length = cred->privateData.len;
1399                             memcpy(result, cred->privateData.data, result_length);
1400                         }
1401                         else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
1402                         {
1403                             size_t outBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
1404                             uint8_t* outKey = OICCalloc(1, outBufSize);
1405                             uint32_t outKeySize;
1406                             if(NULL == outKey)
1407                             {
1408                                 OIC_LOG (ERROR, TAG, "Failed to memoray allocation.");
1409                                 return ret;
1410                             }
1411
1412                             if(B64_OK == b64Decode((char*)cred->privateData.data, cred->privateData.len, outKey, outBufSize, &outKeySize))
1413                             {
1414                                 memcpy(result, outKey, outKeySize);
1415                                 ret = outKeySize;
1416                             }
1417                             else
1418                             {
1419                                 OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
1420                             }
1421
1422                             OICFree(outKey);
1423                         }
1424
1425                         return ret;
1426                     }
1427                 }
1428             }
1429             break;
1430
1431         default:
1432             {
1433                 OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
1434             }
1435             break;
1436     }
1437
1438     return ret;
1439 }
1440
1441 /**
1442  * Add temporal PSK to PIN based OxM
1443  *
1444  * @param[in] tmpSubject UUID of target device
1445  * @param[in] credType Type of credential to be added
1446  * @param[in] pin numeric characters
1447  * @param[in] pinSize length of 'pin'
1448  * @param[in] rownerID Resource owner's UUID
1449  * @param[out] tmpCredSubject Generated credential's subject.
1450  *
1451  * @return OC_STACK_OK for success and errorcode otherwise.
1452  */
1453 OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
1454                             const char * pin, size_t pinSize,
1455                             const OicUuid_t * rownerID, OicUuid_t* tmpCredSubject)
1456 {
1457     OCStackResult ret = OC_STACK_ERROR;
1458     OIC_LOG(DEBUG, TAG, "AddTmpPskWithPIN IN");
1459
1460     if(NULL == tmpSubject || NULL == pin || 0 == pinSize || NULL == tmpCredSubject)
1461     {
1462         return OC_STACK_INVALID_PARAM;
1463     }
1464
1465     uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
1466     OicSecKey_t privKey = {privData, OWNER_PSK_LENGTH_128, OIC_ENCODING_RAW};
1467     OicSecCred_t* cred = NULL;
1468     int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, rownerID->id,
1469                                               UUID_LENGTH, PBKDF_ITERATIONS,
1470                                               OWNER_PSK_LENGTH_128, privData);
1471     VERIFY_SUCCESS(TAG, (0 == dtlsRes) , ERROR);
1472
1473     cred = GenerateCredential(tmpSubject, credType, NULL,
1474                               &privKey, rownerID);
1475     if(NULL == cred)
1476     {
1477         OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
1478         return OC_STACK_ERROR;
1479     }
1480
1481     memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
1482
1483     ret = AddCredential(cred);
1484     if( OC_STACK_OK != ret)
1485     {
1486         RemoveCredential(tmpSubject);
1487         OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
1488     }
1489     OIC_LOG(DEBUG, TAG, "AddTmpPskWithPIN OUT");
1490
1491 exit:
1492     return ret;
1493 }
1494
1495 #endif /* __WITH_DTLS__ */
1496 #ifdef __WITH_X509__
1497 #define CERT_LEN_PREFIX (3)
1498 #define BYTE_SIZE (8) //bits
1499 #define PUB_KEY_X_COORD ("x")
1500 #define PUB_KEY_Y_COORD ("y")
1501 #define CERTIFICATE ("x5c")
1502 #define PRIVATE_KEY ("d")
1503
1504 static uint32_t parseCertPrefix(uint8_t *prefix)
1505 {
1506     uint32_t res = 0;
1507     if (NULL != prefix)
1508     {
1509         for (int i = 0; i < CERT_LEN_PREFIX; ++i)
1510         {
1511             res |= (((uint32_t) prefix[i]) << ((CERT_LEN_PREFIX - 1 -i) * BYTE_SIZE));
1512         }
1513     }
1514     return res;
1515 }
1516
1517 static OCStackResult GetCAPublicKeyData(CADtlsX509Creds_t *credInfo)
1518 {
1519     OCStackResult ret = OC_STACK_ERROR;
1520     uint8_t *ccPtr = credInfo->certificateChain;
1521     for (uint8_t i = 0; i < credInfo->chainLen - 1; ++i)
1522     {
1523         ccPtr += CERT_LEN_PREFIX + parseCertPrefix(ccPtr);
1524     }
1525
1526     ByteArray cert = { .data = ccPtr + CERT_LEN_PREFIX, .len = parseCertPrefix(ccPtr) };
1527     CertificateX509 certStruct;
1528
1529     VERIFY_SUCCESS(TAG, PKI_SUCCESS == DecodeCertificate(cert, &certStruct), ERROR);
1530
1531     INC_BYTE_ARRAY(certStruct.pubKey, 2);
1532
1533     memcpy(credInfo->rootPublicKeyX, certStruct.pubKey.data, PUBLIC_KEY_SIZE / 2);
1534     memcpy(credInfo->rootPublicKeyY, certStruct.pubKey.data + PUBLIC_KEY_SIZE / 2, PUBLIC_KEY_SIZE / 2);
1535
1536     ret = OC_STACK_OK;
1537     exit:
1538     return ret;
1539 }
1540
1541 int GetDtlsX509Credentials(CADtlsX509Creds_t *credInfo)
1542 {
1543     int ret = 1;
1544     VERIFY_NON_NULL(TAG, credInfo, ERROR);
1545     if (NULL == gCred)
1546     {
1547         VERIFY_SUCCESS(TAG, OC_STACK_OK == InitCredResource(), ERROR);
1548     }
1549
1550     OicSecCred_t *cred = NULL;
1551     LL_SEARCH_SCALAR(gCred, cred, credType, SIGNED_ASYMMETRIC_KEY);
1552     VERIFY_NON_NULL(TAG, cred, ERROR);
1553
1554     if (cred->publicData.len > MAX_CERT_MESSAGE_LEN || cred->privateData.len > PRIVATE_KEY_SIZE)
1555     {
1556         goto exit;
1557     }
1558     credInfo->chainLen = 2;
1559     memcpy(credInfo->certificateChain, cred->publicData.data, cred->publicData.len);
1560     memcpy(credInfo->devicePrivateKey, cred->privateData.data, cred->privateData.len);
1561     credInfo->certificateChainLen = cred->publicData.len;
1562     GetCAPublicKeyData(credInfo);
1563     ret = 0;
1564
1565 exit:
1566
1567     return ret;
1568 }
1569 #undef CERT_LEN_PREFIX
1570 #endif /* __WITH_X509__ */
1571
1572 OCStackResult SetCredRownerId(const OicUuid_t* newROwner)
1573 {
1574     OCStackResult ret = OC_STACK_ERROR;
1575     uint8_t *cborPayload = NULL;
1576     size_t size = 0;
1577     int secureFlag = 0;
1578     OicUuid_t prevId = {.id={0}};
1579
1580     if(NULL == newROwner)
1581     {
1582         ret = OC_STACK_INVALID_PARAM;
1583     }
1584     if(NULL == gCred)
1585     {
1586         ret = OC_STACK_NO_RESOURCE;
1587     }
1588
1589     if(newROwner && gCred)
1590     {
1591         memcpy(prevId.id, gCred->rownerID.id, sizeof(prevId.id));
1592         memcpy(gCred->rownerID.id, newROwner->id, sizeof(newROwner->id));
1593
1594         ret = CredToCBORPayload(gCred, &cborPayload, &size, secureFlag);
1595         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1596
1597         ret = UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, cborPayload, size);
1598         VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, ERROR);
1599
1600         OICFree(cborPayload);
1601     }
1602
1603     return ret;
1604
1605 exit:
1606     OICFree(cborPayload);
1607     memcpy(gCred->rownerID.id, prevId.id, sizeof(prevId.id));
1608     return ret;
1609 }
1610
1611 OCStackResult GetCredRownerId(OicUuid_t *rowneruuid)
1612 {
1613     OCStackResult retVal = OC_STACK_ERROR;
1614     if (gCred)
1615     {
1616         *rowneruuid = gCred->rownerID;
1617         retVal = OC_STACK_OK;
1618     }
1619     return retVal;
1620 }