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