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