replace : iotivity -> iotivity-sec
[platform/upstream/iotivity.git] / resource / csdk / security / tool / svrdbeditor_src / svrdbeditorcred.c
1 /* *****************************************************************
2  *
3  * Copyright 2017 Samsung Electronics 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 #ifndef _GNU_SOURCE
22 #define _GNU_SOURCE
23 #endif
24
25 #include <mbedtls/ssl.h>
26 #include <mbedtls/ctr_drbg.h>
27 #include <mbedtls/x509_crt.h>
28 #include <mbedtls/pkcs12.h>
29 #include <mbedtls/ssl_internal.h>
30 #include <string.h>
31 #include <stdbool.h>
32
33 #include "utlist.h"
34 #include "base64.h"
35 #include "octypes.h"
36 #include "oic_malloc.h"
37 #include "oic_string.h"
38 #include "logger.h"
39
40 #include "srmresourcestrings.h"
41 #include "pinoxmcommon.h"
42 #include "credresource.h"
43
44 #include "security_internals.h"
45 #include "psinterface.h"
46
47 #include "svrdbeditordoxm.h"
48 #include "svrdbeditorcred.h"
49
50 typedef enum CredModifyType
51 {
52     CRED_EDIT_SUBJECTUUID = 1,
53     CRED_EDIT_PSK,
54     CRED_EDIT_ROWNERUUID = 3,
55 } CredModifyType_t;
56
57 void RefreshCred()
58 {
59     OCStackResult ocResult = OC_STACK_ERROR;
60     uint8_t *secPayload = NULL;
61     size_t payloadSize = 0;
62
63     OicSecCred_t *credList = NULL;
64     OicSecCred_t *cred = NULL;
65     OicSecCred_t *tmpCred = NULL;
66     //Load security resouce data from SVR DB.
67     ocResult = GetSecureVirtualDatabaseFromPS(OIC_JSON_CRED_NAME, &secPayload, &payloadSize);
68     if (OC_STACK_OK != ocResult)
69     {
70         PRINT_WARN("GetSecureVirtualDatabaseFromPS : %d", ocResult);
71         return;
72     }
73     if (secPayload && 0 != payloadSize)
74     {
75         ocResult = CBORPayloadToCred(secPayload, payloadSize, &credList);
76         if (OC_STACK_OK != ocResult)
77         {
78             PRINT_ERR("CBORPayloadToCred : %d", ocResult);
79             OICFree(secPayload);
80             return;
81         }
82     }
83     OICFree(secPayload);
84     DeInitCredResource();
85
86     //Add the loaded credentials into gCred of CredResource module in order to use the credential management mechanism.
87     LL_FOREACH_SAFE(credList, cred, tmpCred)
88     {
89         ocResult = AddCredential(cred);
90         if (OC_STACK_OK != ocResult)
91         {
92             PRINT_ERR("AddCredential : %d", ocResult);
93             OICFree(credList);
94             return;
95         }
96     }
97 }
98
99 static void UpdateCred(void)
100 {
101     OCStackResult credResult = OC_STACK_ERROR;
102     uint8_t *credPayload = NULL;
103     size_t credPayloadSize = 0;
104     int secureFlag = 0;
105
106     credResult = CredToCBORPayload(GetCredList(), &credPayload, &credPayloadSize, secureFlag);
107     if (OC_STACK_OK != credResult)
108     {
109         PRINT_ERR("CredToCBORPayload error : %d", credResult);
110         return;
111     }
112     credResult = UpdateSecureResourceInPS(OIC_JSON_CRED_NAME, credPayload, credPayloadSize);
113     if (OC_STACK_OK != credResult)
114     {
115         PRINT_ERR("UpdateSecureResourceInPS error : %d", credResult);
116         OICFree(credPayload);
117         return;
118     }
119     OICFree(credPayload);
120 }
121
122 /**
123  * Parse chain of X.509 certificates.
124  *
125  * @param[out] crt     container for X.509 certificates
126  * @param[in]  buf     buffer with X.509 certificates. Certificates may be in either in PEM
127  or DER format in a jumble. Each PEM certificate must be NULL-terminated.
128  * @param[in]  bufLen  buffer length
129  *
130  * @return  0 on success, -1 on error
131  */
132 // TODO: Update to use credresource.c
133 static int ParseCertChain(mbedtls_x509_crt *crt, unsigned char *buf, size_t bufLen)
134 {
135     if (NULL == crt || NULL == buf || 0 == bufLen)
136     {
137         PRINT_ERR("ParseCertChain : Invalid param");
138         return -1;
139     }
140
141     /* byte encoded ASCII string '-----BEGIN CERTIFICATE-----' */
142     char pemCertHeader[] =
143     {
144         0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52,
145         0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d
146     };
147     // byte encoded ASCII string '-----END CERTIFICATE-----' */
148     char pemCertFooter[] =
149     {
150         0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49,
151         0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d
152     };
153     size_t pemCertHeaderLen = sizeof(pemCertHeader);
154     size_t pemCertFooterLen = sizeof(pemCertFooter);
155
156     size_t len = 0;
157     unsigned char *tmp = NULL;
158     int count = 0;
159     int ret = 0;
160     size_t pos = 0;
161
162     while (pos < bufLen)
163     {
164         if (0x30 == buf[pos] && 0x82 == buf[pos + 1])
165         {
166             tmp = (unsigned char *)buf + pos + 1;
167             ret = mbedtls_asn1_get_len(&tmp, buf + bufLen, &len);
168             if (0 != ret)
169             {
170                 PRINT_ERR("mbedtls_asn1_get_len failed: 0x%04x", ret);
171                 return -1;
172             }
173
174             if (pos + len < bufLen)
175             {
176                 ret = mbedtls_x509_crt_parse_der(crt, buf + pos, len + 4);
177                 if (0 == ret)
178                 {
179                     count++;
180                 }
181                 else
182                 {
183                     PRINT_ERR("mbedtls_x509_crt_parse_der failed: 0x%04x", ret);
184                 }
185             }
186             pos += len + 4;
187         }
188         else if ((buf + pos + pemCertHeaderLen < buf + bufLen) &&
189                  0 == memcmp(buf + pos, pemCertHeader, pemCertHeaderLen))
190         {
191             void *endPos = NULL;
192             endPos = memmem(&(buf[pos]), bufLen - pos, pemCertFooter, pemCertFooterLen);
193             if (NULL == endPos)
194             {
195                 PRINT_ERR("end of PEM certificate not found.");
196                 return -1;
197             }
198
199             len = (char *)endPos - ((char *)buf + pos) + pemCertFooterLen;
200             if (pos + len + 1 <= bufLen)
201             {
202                 char con = buf[pos + len];
203                 buf[pos + len] = 0x00;
204                 ret = mbedtls_x509_crt_parse(crt, buf + pos, len + 1);
205                 if (0 == ret)
206                 {
207                     count++;
208                 }
209                 else
210                 {
211                     PRINT_ERR("mbedtls_x509_crt_parse failed: 0x%04x", ret);
212                 }
213                 buf[pos + len] = con;
214             }
215             else
216             {
217                 unsigned char *lastCert = (unsigned char *)OICMalloc((len + 1) * sizeof(unsigned char));
218                 if (NULL == lastCert)
219                 {
220                     PRINT_ERR("Failed to allocate memory for certificate");
221                     return -1;
222                 }
223                 memcpy(lastCert, buf + pos, len);
224                 lastCert[len] = 0x00;
225                 ret = mbedtls_x509_crt_parse(crt, lastCert, len + 1);
226                 if (0 == ret)
227                 {
228                     count++;
229                 }
230                 else
231                 {
232                     PRINT_ERR("mbedtls_x509_crt_parse failed: 0x%04x", ret);
233                 }
234                 OICFree(lastCert);
235             }
236             pos += len;
237         }
238         else
239         {
240             pos++;
241         }
242     }
243
244     return 0;
245 }
246
247 // TODO: Update to use credresource.c
248 static void ParseDerCaCert(ByteArray_t *crt, const char *usage, uint16_t credId)
249 {
250     if (NULL == crt || NULL == usage)
251     {
252         PRINT_ERR("ParseDerCaCert : Invalid param");
253         return;
254     }
255     crt->len = 0;
256     OicSecCred_t *temp = NULL;
257
258     LL_FOREACH(((OicSecCred_t *)GetCredList()), temp)
259     {
260         if (SIGNED_ASYMMETRIC_KEY == temp->credType &&
261             0 == strcmp(temp->credUsage, usage) &&
262             temp->credId == credId)
263         {
264             if (OIC_ENCODING_BASE64 == temp->optionalData.encoding)
265             {
266                 size_t bufSize = B64DECODE_OUT_SAFESIZE((temp->optionalData.len + 1));
267                 uint8_t *buf = OICCalloc(1, bufSize);
268                 if (NULL == buf)
269                 {
270                     PRINT_ERR("ParseDerCaCert : Failed to allocate memory");
271                     return;
272                 }
273                 uint32_t outSize;
274                 if (B64_OK != b64Decode((char *)(temp->optionalData.data), temp->optionalData.len, buf, bufSize,
275                                         &outSize))
276                 {
277                     OICFree(buf);
278                     PRINT_ERR("ParseDerCaCert : Failed to decode base64 data");
279                     return;
280                 }
281                 crt->data = OICRealloc(crt->data, crt->len + outSize);
282                 memcpy(crt->data + crt->len, buf, outSize);
283                 crt->len += outSize;
284                 OICFree(buf);
285             }
286             else
287             {
288                 crt->data = OICRealloc(crt->data, crt->len + temp->optionalData.len);
289                 memcpy(crt->data + crt->len, temp->optionalData.data, temp->optionalData.len);
290                 crt->len += temp->optionalData.len;
291             }
292         }
293     }
294     if (0 == crt->len)
295     {
296         PRINT_INFO("ParseDerCaCert : %s not found", usage);
297     }
298     return;
299 }
300
301 // TODO: Update to use credresource.c
302 static void ParseDerOwnCert(ByteArray_t *crt, const char *usage, uint16_t credId)
303 {
304     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
305     if (NULL == crt || NULL == usage)
306     {
307         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
308         return;
309     }
310     crt->len = 0;
311     OicSecCred_t *temp = NULL;
312     LL_FOREACH(((OicSecCred_t *)GetCredList()), temp)
313     {
314         if (SIGNED_ASYMMETRIC_KEY == temp->credType &&
315             0 == strcmp(temp->credUsage, usage) &&
316             temp->credId == credId)
317         {
318             crt->data = OICRealloc(crt->data, crt->len + temp->publicData.len);
319             memcpy(crt->data + crt->len, temp->publicData.data, temp->publicData.len);
320             crt->len += temp->publicData.len;
321             OIC_LOG_V(DEBUG, TAG, "%s found", usage);
322         }
323     }
324     if (0 == crt->len)
325     {
326         OIC_LOG_V(WARNING, TAG, "%s not found", usage);
327     }
328     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
329     return;
330 }
331
332 inline void ParseDerKey(ByteArray_t *key, const char *usage, uint16_t credId)
333 {
334     OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
335     if (NULL == key || NULL == usage)
336     {
337         OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
338         return;
339     }
340
341     OicSecCred_t *temp = NULL;
342     key->len = 0;
343     LL_FOREACH(((OicSecCred_t *)GetCredList()), temp)
344     {
345         if (SIGNED_ASYMMETRIC_KEY == temp->credType &&
346             0 == strcmp(temp->credUsage, usage) &&
347             temp->credId == credId)
348         {
349             key->data = OICRealloc(key->data, key->len + temp->privateData.len);
350             memcpy(key->data + key->len, temp->privateData.data, temp->privateData.len);
351             key->len += temp->privateData.len;
352             OIC_LOG_V(DEBUG, TAG, "Key for %s found", usage);
353         }
354     }
355     if (0 == key->len)
356     {
357         OIC_LOG_V(WARNING, TAG, "Key for %s not found", usage);
358     }
359     OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
360 }
361
362 static void PrintCredType(OicSecCredType_t credType)
363 {
364     PRINT_DATA("%d", credType);
365     switch (credType)
366     {
367         case NO_SECURITY_MODE:
368             PRINT_DATA(" (NO_SECURITY_MODE)\n");
369             break;
370         case SYMMETRIC_PAIR_WISE_KEY:
371             PRINT_DATA(" (SYMMETRIC_PAIR_WISE_KEY)\n");
372             break;
373         case SYMMETRIC_GROUP_KEY:
374             PRINT_DATA(" (SYMMETRIC_GROUP_KEY)\n");
375             break;
376         case ASYMMETRIC_KEY:
377             PRINT_DATA(" (ASYMMETRIC_KEY)\n");
378             break;
379         case SIGNED_ASYMMETRIC_KEY:
380             PRINT_DATA(" (SIGNED_ASYMMETRIC_KEY)\n");
381             break;
382         case PIN_PASSWORD:
383             PRINT_DATA(" (PIN_PASSWORD)\n");
384             break;
385         case ASYMMETRIC_ENCRYPTION_KEY:
386             PRINT_DATA(" (ASYMMETRIC_ENCRYPTION_KEY)\n");
387             break;
388         default:
389             PRINT_ERR(" (Unknown Cred type)");
390             break;
391     }
392 }
393
394 static void PrintCredEncodingType(OicEncodingType_t encoding)
395 {
396     PRINT_DATA("%d", encoding);
397     switch (encoding)
398     {
399         case OIC_ENCODING_RAW:
400             PRINT_DATA(" (OIC_ENCODING_RAW)\n");
401             break;
402         case OIC_ENCODING_BASE64:
403             PRINT_DATA(" (OIC_ENCODING_BASE64)\n");
404             break;
405         case OIC_ENCODING_PEM:
406             PRINT_DATA(" (OIC_ENCODING_PEM)\n");
407             break;
408         case OIC_ENCODING_DER:
409             PRINT_DATA(" (OIC_ENCODING_DER)\n");
410             break;
411         default:
412             PRINT_ERR(" (Unknown Encoding type)");
413             break;
414     }
415
416 }
417
418 /**
419  * This API to print credential list.
420  * Also return the number of credential in credential list.
421  */
422 void PrintCredList(const OicSecCred_t *creds)
423 {
424     const OicSecCred_t *cred = NULL;
425     const OicSecCred_t *tempCred = NULL;
426     bool isEmptyList = true;
427     PRINT_INFO("\n\n********************* [%-20s] *********************",
428                "Credential Resource");
429     LL_FOREACH_SAFE(creds, cred, tempCred)
430     {
431         PRINT_PROG("%15s : ", OIC_JSON_CREDID_NAME);
432         PrintInt(cred->credId);
433
434         PRINT_PROG("%15s : ", OIC_JSON_SUBJECTID_NAME);
435         if (0 == memcmp(&(cred->subject), &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)))
436         {
437             PrintString((char *)WILDCARD_SUBJECT_ID.id);
438         }
439         else
440         {
441             PrintUuid(&(cred->subject));
442         }
443
444 #ifdef MULTIPLE_OWNER
445         if (creds->eownerID)
446         {
447             PRINT_PROG("%15s : ", OIC_JSON_EOWNERID_NAME);
448             PrintUuid(cred->eownerID);
449         }
450 #endif
451
452         PRINT_PROG("%15s : ", OIC_JSON_CREDTYPE_NAME);
453         PrintCredType(cred->credType);
454
455         switch (cred->credType)
456         {
457             case SYMMETRIC_PAIR_WISE_KEY:
458             case SYMMETRIC_GROUP_KEY:
459                 PRINT_PROG("%15s : \n", OIC_JSON_PRIVATEDATA_NAME);
460                 if (cred->privateData.data)
461                 {
462                     PRINT_DATA("%s : ", OIC_JSON_ENCODING_NAME);
463                     PrintCredEncodingType(cred->privateData.encoding);
464
465                     PRINT_DATA("%s : ", OIC_JSON_DATA_NAME);
466                     if (OIC_ENCODING_BASE64 == cred->privateData.encoding)
467                     {
468                         PrintString((char *)cred->privateData.data);
469                     }
470                     else
471                     {
472                         PrintBuffer(cred->privateData.data, cred->privateData.len);
473                     }
474                 }
475                 else
476                 {
477                     PRINT_ERR("Private data is null");
478                 }
479                 break;
480             case ASYMMETRIC_KEY:
481             case SIGNED_ASYMMETRIC_KEY:
482                 // TODO: Print certificate and asymmetric key in readable formats
483
484                 //cred usage
485                 if (cred->credUsage)
486                 {
487                     PRINT_PROG("%15s : ", OIC_JSON_CREDUSAGE_NAME);
488                     PRINT_DATA("%s\n", cred->credUsage);
489                 }
490
491                 //private data
492                 if (cred->privateData.data)
493                 {
494                     PRINT_PROG("%15s : \n", OIC_JSON_PRIVATEDATA_NAME);
495                     PrintBuffer(cred->privateData.data, cred->privateData.len);
496
497                     if (cred->credUsage &&
498                         (0 == strcmp(cred->credUsage, PRIMARY_CERT) ||
499                          0 == strcmp(cred->credUsage, MF_PRIMARY_CERT)))
500                     {
501                         // TODO: T.B.D
502                     }
503                     else
504                     {
505                         // TODO: T.B.D
506                     }
507                 }
508
509                 //public data
510                 if (cred->publicData.data)
511                 {
512                     PRINT_PROG("%15s : ", OIC_JSON_PUBLICDATA_NAME);
513                     PRINT_DATA("%-17s : ", OIC_JSON_ENCODING_NAME);
514                     PrintCredEncodingType(cred->publicData.encoding);
515
516                     if (cred->credUsage &&
517                         (0 == strcmp(cred->credUsage, PRIMARY_CERT) ||
518                          0 == strcmp(cred->credUsage, MF_PRIMARY_CERT)))
519                     {
520                         char buf[2048];
521                         mbedtls_x509_crt crt;
522                         mbedtls_x509_crt *tmpCrt = NULL;
523                         PkiInfo_t inf;
524                         int i = 0;
525
526                         memset(&inf, 0x00, sizeof(PkiInfo_t));
527                         mbedtls_x509_crt_init(&crt);
528
529                         ParseDerOwnCert(&inf.crt, cred->credUsage, cred->credId);
530                         ParseCertChain(&crt, inf.crt.data, inf.crt.len);
531
532                         for (i = 0, tmpCrt = &crt; NULL != tmpCrt; i++, tmpCrt = tmpCrt->next)
533                         {
534                             PRINT_INFO("[Cert #%d]", (i + 1));
535                             mbedtls_x509_crt_info( buf, sizeof(buf) - 1, "", tmpCrt );
536                             PRINT_DATA("%s", buf);
537                         }
538                         mbedtls_x509_crt_free(&crt);
539                     }
540                     else
541                     {
542                         PRINT_INFO("will be updated to print public data");
543                     }
544                 }
545
546                 //optional data
547                 if (cred->optionalData.data)
548                 {
549                     PRINT_PROG("%15s : \n", OIC_JSON_OPTDATA_NAME);
550
551                     //revocation status
552                     PRINT_DATA("%-17s : %s\n", OIC_JSON_REVOCATION_STATUS_NAME,
553                                (cred->optionalData.revstat ? "True" : "False"));
554
555                     PRINT_DATA("%-17s : ", OIC_JSON_ENCODING_NAME);
556                     PrintCredEncodingType(cred->optionalData.encoding);
557
558                     //CA chain
559                     if (cred->credUsage &&
560                         (0 == strcmp(cred->credUsage, TRUST_CA) ||
561                          0 == strcmp(cred->credUsage, MF_TRUST_CA)))
562                     {
563                         char buf[2048];
564                         mbedtls_x509_crt ca;
565                         mbedtls_x509_crt *tmpCa = NULL;
566                         PkiInfo_t inf;
567                         int i = 0;
568
569                         memset(&inf, 0x00, sizeof(PkiInfo_t));
570                         mbedtls_x509_crt_init(&ca);
571
572                         ParseDerCaCert(&inf.ca, cred->credUsage, cred->credId);
573                         ParseCertChain(&ca, inf.ca.data, inf.ca.len);
574
575                         for (i = 0, tmpCa = &ca; NULL != tmpCa; i++, tmpCa = tmpCa->next)
576                         {
577                             PRINT_INFO("[Cert #%d]", (i + 1));
578                             mbedtls_x509_crt_info( buf, sizeof(buf) - 1, "", tmpCa );
579                             PRINT_DATA("%s", buf);
580                         }
581                         mbedtls_x509_crt_free(&ca);
582                     }
583                     else
584                     {
585                         // TODO: T.B.D
586                         PRINT_INFO("will be updated to print optional data");
587                     }
588                 }
589                 break;
590             case PIN_PASSWORD:
591                 PRINT_PROG("%15s : ", OIC_JSON_PRIVATEDATA_NAME);
592                 if (cred->privateData.data)
593                 {
594                     PRINT_DATA("%s : ", OIC_JSON_ENCODING_NAME);
595                     PrintCredEncodingType(cred->privateData.encoding);
596
597                     PRINT_DATA("%s : ", OIC_JSON_DATA_NAME);
598                     PRINT_DATA("%s\n", cred->privateData.data);
599                 }
600                 else
601                 {
602                     PRINT_ERR("Private data is null");
603                 }
604                 break;
605             case ASYMMETRIC_ENCRYPTION_KEY:
606                 break;
607             default:
608                 PRINT_ERR(" (Unknown Cred type)");
609                 break;
610         }
611         PRINT_PROG("------------------------------------------------------------------\n");
612         isEmptyList = false;
613     }
614
615     if (!isEmptyList)
616     {
617         OicUuid_t uuid = {.id = {0}};
618         if (OC_STACK_OK != GetCredRownerId(&uuid))
619         {
620             PRINT_WARN("GetCredRownerId failed");
621         }
622         else
623         {
624             PRINT_PROG("%15s : ", OIC_JSON_ROWNERID_NAME);
625             PrintUuid(&uuid);
626         }
627     }
628     else
629     {
630         PRINT_PROG("Cred List is empty.\n");
631     }
632
633     PRINT_INFO("********************* [%-20s] *********************",
634                "Credential Resource");
635
636     return;
637 }
638
639 static int ReadDataFromFile(const char *infoTxt, uint8_t **buffer, size_t *bufferSize)
640 {
641     char filePath[512] = {0};
642     char tmpBuffer[SVR_DB_PATH_LENGTH] = {0};
643     FILE *fp = NULL;
644     size_t filePathLen = 0 ;
645     size_t fileSize = 0;
646
647     if (NULL == buffer || NULL != *buffer || NULL == bufferSize)
648     {
649         PRINT_ERR("ReadDataFromFile : Invaild param");
650         return -1;
651     }
652
653     PRINT_NORMAL("%s", infoTxt);
654     if (NULL == fgets(filePath, sizeof(filePath), stdin))
655     {
656         PRINT_ERR("Failed fgets");
657         return -1;
658     }
659     filePathLen = strlen(filePath);
660     if ('\n' == filePath[filePathLen - 1])
661     {
662         filePath[filePathLen - 1] = '\0';
663     }
664
665     //Get a file size
666     fp = fopen(filePath, "rb");
667     if (fp)
668     {
669         size_t bytesRead = 0;
670         do
671         {
672             bytesRead = fread(tmpBuffer, 1, 1023, fp);
673             fileSize += bytesRead;
674             if (ferror (fp))
675             {
676                 PRINT_ERR("Error fread\n");
677                 fclose (fp);
678                 return -1;
679             }
680         }
681         while (bytesRead);
682         fclose(fp);
683         fp = NULL;
684     }
685     else
686     {
687         PRINT_ERR("Failed to open %s" , filePath);
688         PRINT_ERR("Please make sure the file path and access permission.");
689         goto error;
690     }
691
692     if (0 == fileSize)
693     {
694         PRINT_ERR("%s is empty." , filePath);
695         goto error;
696     }
697
698     fp = fopen(filePath, "rb");
699     if (fp)
700     {
701         *buffer = (uint8_t *) OICCalloc(1, fileSize);
702         if ( NULL == *buffer)
703         {
704             PRINT_ERR("Failed to allocate memory.");
705             goto error;
706         }
707
708         if ( fread(*buffer, 1, fileSize, fp) == fileSize)
709         {
710             *bufferSize = fileSize;
711         }
712         fclose(fp);
713     }
714     else
715     {
716         PRINT_ERR("Failed to open %s" , filePath);
717         PRINT_ERR("Please make sure the file path and access permission.");
718         goto error;
719     }
720
721     return 0;
722
723 error:
724     if (fp)
725     {
726         fclose(fp);
727     }
728     if (*buffer)
729     {
730         OICFree(*buffer);
731     }
732     return -1;
733 }
734
735 static int InputCredUsage(char **credUsage)
736 {
737     char inputUsage[128] = {0};
738     int credUsageNum = 0;
739
740     if (NULL == credUsage || NULL != *credUsage)
741     {
742         PRINT_ERR("InputCredUsage error : invaild param");
743         return -1;
744     }
745
746     do
747     {
748         PRINT_NORMAL("\n\n");
749         PRINT_NORMAL("\t1. %s\n", TRUST_CA);
750         PRINT_NORMAL("\t2. %s\n", PRIMARY_CERT);
751         PRINT_NORMAL("\t3. %s\n", MF_TRUST_CA);
752         PRINT_NORMAL("\t4. %s\n", MF_PRIMARY_CERT);
753         PRINT_NORMAL("\t5. Input manually\n");
754         credUsageNum = InputNumber("\tSelect the credential usage : ");
755         switch (credUsageNum)
756         {
757             case 1:
758                 *credUsage = OICStrdup(TRUST_CA);
759                 break;
760             case 2:
761                 *credUsage = OICStrdup(PRIMARY_CERT);
762                 break;
763             case 3:
764                 *credUsage = OICStrdup(MF_TRUST_CA);
765                 break;
766             case 4:
767                 *credUsage = OICStrdup(MF_PRIMARY_CERT);
768                 break;
769             case 5:
770                 PRINT_NORMAL("\tInput the credential usage : ");
771                 for (int ret = 0; 1 != ret; )
772                 {
773                     ret = scanf("%128s", inputUsage);
774                     for ( ; 0x20 <= getchar(); ); // for removing overflow garbages
775                     // '0x20<=code' is character region
776                 }
777                 *credUsage = OICStrdup(inputUsage);
778                 break;
779             default:
780                 PRINT_ERR("Invaild credential usage");
781                 credUsageNum = 0;
782                 break;
783         }
784     }
785     while (0 == credUsageNum);
786
787     if (NULL == *credUsage)
788     {
789         PRINT_ERR("Failed OICStrdup");
790         return -1;
791     }
792
793     return 0;
794 }
795
796 static int InputCredEncodingType(const char *dataType, OicEncodingType_t *encoding)
797 {
798     int credEncType = 0;
799     char infoText[512] = {0};
800
801     if (NULL == dataType || NULL == encoding)
802     {
803         PRINT_ERR("InputCredEncodingType : Invaild param");
804         return -1;
805     }
806
807     snprintf(infoText, sizeof(infoText), "\tSelect the encoding type of %s : ", dataType);
808
809     do
810     {
811         PRINT_NORMAL("\n\n");
812         PRINT_NORMAL("\t%d. %s\n", OIC_ENCODING_RAW, "OIC_ENCODING_RAW");
813         PRINT_NORMAL("\t%d. %s\n", OIC_ENCODING_BASE64, "OIC_ENCODING_BASE64");
814         PRINT_NORMAL("\t%d. %s\n", OIC_ENCODING_PEM, "OIC_ENCODING_PEM");
815         PRINT_NORMAL("\t%d. %s\n", OIC_ENCODING_DER, "OIC_ENCODING_DER");
816         credEncType = InputNumber(infoText);
817         switch ( (OicEncodingType_t)credEncType )
818         {
819             case OIC_ENCODING_RAW:
820                 break;
821             case OIC_ENCODING_BASE64:
822                 break;
823             case OIC_ENCODING_PEM:
824                 break;
825             case OIC_ENCODING_DER:
826                 break;
827             default:
828                 PRINT_ERR("Invaild encoding type");
829                 credEncType = 0;
830                 break;
831         }
832     }
833     while (0 == credEncType);
834
835     *encoding = (OicEncodingType_t)credEncType;
836
837     return 0;
838 }
839
840 static int InputCredSubject(OicUuid_t *uuid)
841 {
842     int ret = 0;
843     OicUuid_t emptyUuid = {.id = {0}};
844     PRINT_PROG(
845         "\tInput the Subject UUID for this access (e.g. 61646D69-6E44-6576-6963-655575696430) : ");
846     ret = InputUuid(uuid);
847     if (0 != ret)
848     {
849         PRINT_ERR("InputUuid failed");
850         return ret;
851     }
852
853     if (0 == memcmp(emptyUuid.id, (*uuid).id, sizeof((*uuid).id) ) )
854     {
855         PRINT_ERR("Cred Subject UUID can't be empty uuid");
856         return -1;
857     }
858     return ret;
859 }
860
861 static int InputPSK(OicSecKey_t *secKey)
862 {
863     char *data = NULL;
864     size_t psklen = 0;
865     size_t bufSize = 0;
866     uint8_t *buf = NULL;
867     uint32_t outSize = 0;
868
869     data = InputString("\tInput encoded base64 psk (decoded psk 128 or 256 bits,\n"
870                        "\te.g. BxjJidB+u21QlEwMCYBoKA== ) : ");
871     if (NULL == data)
872     {
873         PRINT_ERR("Failed InputString");
874         return -1;
875     }
876
877     psklen = strlen(data);
878     bufSize = B64DECODE_OUT_SAFESIZE(psklen + 1);
879     buf = OICCalloc(1, bufSize);
880     if (NULL == buf)
881     {
882         PRINT_ERR("Failed to allocate memory");
883         OICFree(data);
884         return -1;
885     }
886     //validate base64 psk
887     if (B64_OK != b64Decode(data, psklen, buf, bufSize, &outSize))
888     {
889         PRINT_ERR("Failed to decode base64 data. Invalid base64 input");
890         OICFree(data);
891         OICFree(buf);
892         return -1;
893     }
894     if (!(OWNER_PSK_LENGTH_128 == outSize || OWNER_PSK_LENGTH_256 == outSize))
895     {
896         PRINT_ERR("Invalid key size");
897         OICFree(data);
898         OICFree(buf);
899         return -1;
900     }
901     secKey->data = (uint8_t *)data;
902     secKey->encoding = OIC_ENCODING_BASE64;
903     secKey->len = psklen;
904     OICFree(buf);
905     return 0;
906 }
907
908 static int InputCredentialData(OicSecCred_t *cred)
909 {
910     uint8_t *certChain = NULL;
911     uint8_t *privateKey = NULL;
912     uint8_t *publicKey = NULL;
913     size_t certChainSize = 0;
914     size_t privateKeySize = 0;
915     size_t publicKeySize = 0;
916
917     PRINT_PROG("\n\nPlease input the each entity of new credential.\n");
918
919     PRINT_NORMAL("\t%3d. Symmetric pair wise key\n", SYMMETRIC_PAIR_WISE_KEY);
920     PRINT_NORMAL("\t%3d. Symmetric group key\n", SYMMETRIC_GROUP_KEY);
921     PRINT_NORMAL("\t%3d. Asymmetric key\n", ASYMMETRIC_KEY);
922     PRINT_NORMAL("\t%3d. Signed asymmetric key\n", SIGNED_ASYMMETRIC_KEY);
923     PRINT_NORMAL("\t%3d. PIN/Password\n", PIN_PASSWORD);
924     PRINT_NORMAL("\t%3d. Asymmetric encryption key\n", ASYMMETRIC_ENCRYPTION_KEY);
925     cred->credType = (OicSecCredType_t)InputNumber("\tSelect the credential type : ");
926     if (SYMMETRIC_PAIR_WISE_KEY != cred->credType &&
927         SYMMETRIC_GROUP_KEY != cred->credType &&
928         SIGNED_ASYMMETRIC_KEY != cred->credType &&
929         PIN_PASSWORD != cred->credType &&
930         ASYMMETRIC_ENCRYPTION_KEY != cred->credType)
931     {
932         PRINT_ERR("Invaild credential type");
933         goto error;
934     }
935
936     //Input the key data according to credential type
937     switch (cred->credType)
938     {
939         case SYMMETRIC_PAIR_WISE_KEY:
940             {
941                 PRINT_PROG("\tSubject UUID (e.g. 61646D69-6E44-6576-6963-655575696430) : ");
942                 if (0 != InputCredSubject(&cred->subject))
943                 {
944                     PRINT_ERR("InputCredSubject failed");
945                     return -1;
946                 }
947                 if (0 != InputPSK(&cred->privateData))
948                 {
949                     PRINT_ERR("Failed InputPSK");
950                     return -1;
951                 }
952                 break;
953             }
954         case SYMMETRIC_GROUP_KEY:
955             // TODO: T.B.D
956             PRINT_INFO("Not supported yet.");
957             goto error;
958             break;
959         case ASYMMETRIC_KEY:
960             // TODO: T.B.D
961             PRINT_INFO("Not supported yet.");
962             goto error;
963             break;
964         case SIGNED_ASYMMETRIC_KEY:
965             //Credential usage
966             if ( 0 != InputCredUsage(&cred->credUsage))
967             {
968                 PRINT_ERR("Failed InputCredUsage");
969                 goto error;
970             }
971
972             //Input the other data according to credential usage.
973             if (0 == strcmp(cred->credUsage, TRUST_CA) ||
974                 0 == strcmp(cred->credUsage, MF_TRUST_CA))
975             {
976                 OicUuid_t doxmUuid;
977                 if (0 != GetDoxmDevID(&doxmUuid))
978                 {
979                     PRINT_ERR("Failed get doxm device id");
980                 }
981                 else
982                 {
983                     memcpy(cred->subject.id, doxmUuid.id, sizeof(doxmUuid.id));
984                 }
985
986                 //encoding type
987                 if ( 0 != InputCredEncodingType("certificate chain", &cred->optionalData.encoding))
988                 {
989                     PRINT_ERR("Failed InputCredEncodingType");
990                     goto error;
991                 }
992
993                 //Read chain data from file (readed data will be saved to optional data)
994                 if (0 != ReadDataFromFile("\tInput the certificate chain path : ", &certChain, &certChainSize))
995                 {
996                     PRINT_ERR("Failed ReadDataFromFile");
997                     goto error;
998                 }
999
1000                 //optional data
1001                 if (OIC_ENCODING_PEM == cred->optionalData.encoding)
1002                 {
1003                     cred->optionalData.data = (uint8_t *)OICCalloc(1, certChainSize + 1);
1004                     if (NULL == cred->optionalData.data)
1005                     {
1006                         PRINT_ERR("InputCredentialData : Failed to allocate memory.");
1007                         goto error;
1008                     }
1009                     cred->optionalData.len = certChainSize + 1;
1010                 }
1011                 else
1012                 {
1013                     cred->optionalData.data = (uint8_t *)OICCalloc(1, certChainSize);
1014                     if (NULL == cred->optionalData.data)
1015                     {
1016                         PRINT_ERR("InputCredentialData : Failed to allocate memory.");
1017                         goto error;
1018                     }
1019                     cred->optionalData.len = certChainSize;
1020                 }
1021                 memcpy(cred->optionalData.data, certChain, certChainSize);
1022                 cred->optionalData.revstat = false;
1023             }
1024             else if (0 == strcmp(cred->credUsage, PRIMARY_CERT) ||
1025                      0 == strcmp(cred->credUsage, MF_PRIMARY_CERT))
1026             {
1027                 OicUuid_t doxmUuid;
1028                 if (0 != GetDoxmDevID(&doxmUuid))
1029                 {
1030                     PRINT_ERR("Failed get doxm device id");
1031                 }
1032                 else
1033                 {
1034                     memcpy(cred->subject.id, doxmUuid.id, sizeof(doxmUuid.id));
1035                 }
1036
1037                 //private key
1038                 //encoding type
1039                 if ( 0 != InputCredEncodingType(YELLOW_BEGIN"Private key"COLOR_END, &cred->privateData.encoding))
1040                 {
1041                     PRINT_ERR("Failed InputCredEncodingType");
1042                     goto error;
1043                 }
1044
1045                 if (OIC_ENCODING_RAW != cred->privateData.encoding)
1046                 {
1047                     PRINT_ERR("Not supported encoding type for private key");
1048                     goto error;
1049                 }
1050
1051                 //Read private key data from file
1052                 if (0 != ReadDataFromFile("\tInput the private key's path : ", &privateKey, &privateKeySize))
1053                 {
1054                     PRINT_ERR("Failed ReadDataFromFile");
1055                     goto error;
1056                 }
1057
1058                 cred->privateData.data = OICCalloc(1, privateKeySize);
1059                 if (NULL == cred->privateData.data)
1060                 {
1061                     PRINT_ERR("InputCredentialData : Failed to allocate memory.");
1062                     goto error;
1063                 }
1064                 memcpy(cred->privateData.data, privateKey, privateKeySize);
1065                 cred->privateData.len = privateKeySize;
1066
1067                 //public key
1068                 //encoding type
1069                 if ( 0 != InputCredEncodingType(YELLOW_BEGIN"Certificate"COLOR_END, &cred->publicData.encoding))
1070                 {
1071                     PRINT_ERR("Failed InputCredEncodingType");
1072                     goto error;
1073                 }
1074
1075                 if (OIC_ENCODING_DER != cred->publicData.encoding &&
1076                     OIC_ENCODING_PEM != cred->publicData.encoding)
1077                 {
1078                     PRINT_ERR("Not supported encoding type for private key");
1079                     goto error;
1080                 }
1081
1082                 //Read certificate data from file
1083                 if (0 != ReadDataFromFile("\tInput the certificate's path : ", &publicKey, &publicKeySize))
1084                 {
1085                     PRINT_ERR("Failed ReadDataFromFile");
1086                     goto error;
1087                 }
1088
1089                 if (OIC_ENCODING_PEM == cred->publicData.encoding)
1090                 {
1091                     cred->publicData.data = OICCalloc(1, publicKeySize + 1);
1092                     if (NULL == cred->publicData.data)
1093                     {
1094                         PRINT_ERR("InputCredentialData : Failed to allocate memory.");
1095                         goto error;
1096                     }
1097                     cred->publicData.len = publicKeySize + 1;
1098                 }
1099                 else
1100                 {
1101                     cred->publicData.data = OICCalloc(1, publicKeySize);
1102                     if (NULL == cred->publicData.data)
1103                     {
1104                         PRINT_ERR("InputCredentialData : Failed to allocate memory.");
1105                         goto error;
1106                     }
1107                     cred->publicData.len = publicKeySize;
1108                 }
1109                 memcpy(cred->publicData.data, publicKey, publicKeySize);
1110             }
1111             else
1112             {
1113                 // TODO: T.B.D : Data type should be selected by user.
1114                 PRINT_ERR("Not supported yet.");
1115                 goto error;
1116             }
1117             break;
1118         case PIN_PASSWORD:
1119             {
1120                 char pinPass[OXM_RANDOM_PIN_MAX_SIZE + 1] = {0};
1121
1122                 PRINT_NORMAL("\tSubject UUID (e.g. 61646D69-6E44-6576-6963-655575696430) : ");
1123                 if (0 != InputCredSubject(&cred->subject))
1124                 {
1125                     PRINT_ERR("InputCredSubject failed");
1126                     goto error;
1127                 }
1128
1129                 PRINT_NORMAL("\tInput the PIN or Password : ");
1130                 for (int ret = 0; 1 != ret; )
1131                 {
1132                     ret = scanf("%32s", pinPass);
1133                     for ( ; 0x20 <= getchar(); ); // for removing overflow garbages
1134                     // '0x20<=code' is character region
1135                 }
1136                 cred->privateData.data = (uint8_t *)OICStrdup(pinPass);
1137                 if (NULL == cred->privateData.data)
1138                 {
1139                     PRINT_ERR("Failed OICStrdup");
1140                     goto error;
1141                 }
1142                 cred->privateData.len = strlen((char *)cred->privateData.data);
1143                 cred->privateData.encoding = OIC_ENCODING_RAW;
1144                 break;
1145             }
1146         case ASYMMETRIC_ENCRYPTION_KEY:
1147             // TODO: T.B.D
1148             PRINT_INFO("Not supported yet.");
1149             goto error;
1150             break;
1151         default:
1152             PRINT_ERR("Invalid credential type");
1153             goto error;
1154     }
1155
1156     OICFree(certChain);
1157     OICFree(privateKey);
1158     OICFree(publicKey);
1159     return 0;
1160
1161 error:
1162     OICFree(certChain);
1163     OICFree(privateKey);
1164     OICFree(publicKey);
1165     memset(cred, 0x00, sizeof(OicSecCred_t));
1166     return -1;
1167 }
1168
1169 static int ModifyCred(void)
1170 {
1171     OCStackResult credResult = OC_STACK_ERROR;
1172     int ret = 0;
1173     int modifyMenu = 0;
1174     OicSecCred_t *cred = NULL;
1175     uint16_t credId = 0;
1176     OicUuid_t uuid = {.id = {0}};
1177     OicSecKey_t key = {0};
1178
1179     PRINT_PROG("\n\nPlease select the menu you want to modify\n");
1180     PRINT_DATA("\t%2d. Edit subjectuuid\n", CRED_EDIT_SUBJECTUUID);
1181     PRINT_DATA("\t%2d. Edit psk of symmetric cred\n", CRED_EDIT_PSK);
1182     PRINT_DATA("\t%2d. Edit rowner uuid\n", CRED_EDIT_ROWNERUUID);
1183     PRINT_DATA("\t%2d. Back to the previous\n", BACK);
1184     modifyMenu = InputNumber("Select the menu : ");
1185     switch (modifyMenu)
1186     {
1187         case CRED_EDIT_SUBJECTUUID:
1188             PrintCredList(GetCredList());
1189             credId = (uint16_t)InputNumber("\tPlease input the credential ID : ");
1190             cred = GetCredEntryByCredId(credId);
1191             if (NULL == cred)
1192             {
1193                 PRINT_ERR("Invalid credId");
1194                 return -1;
1195             }
1196
1197             if (0 != InputCredSubject(&uuid))
1198             {
1199                 PRINT_ERR("InputCredSubject failed");
1200                 DeleteCredList(cred);
1201                 return ret;
1202             }
1203
1204             if (0 == memcmp(cred->subject.id, uuid.id, sizeof(cred->subject.id)))
1205             {
1206                 PRINT_ERR("Please input different uuid from the selected cred's uuid");
1207                 DeleteCredList(cred);
1208                 return -1;
1209             }
1210             memcpy(cred->subject.id, uuid.id , sizeof(cred->subject.id));
1211
1212             credResult = AddCredential(cred);
1213             if (OC_STACK_OK != credResult)
1214             {
1215                 PRINT_ERR("AddCredential : %d", credResult);
1216                 DeleteCredList(cred);
1217                 return -1;
1218             }
1219             credResult = RemoveCredentialByCredId(credId);
1220             if ( OC_STACK_RESOURCE_DELETED != credResult)
1221             {
1222                 PRINT_ERR("RemoveCredentialByCredId error : %d" , credResult);
1223                 return -1;
1224             }
1225
1226             break;
1227         case CRED_EDIT_PSK:
1228             PrintCredList(GetCredList());
1229             credId = (uint16_t)InputNumber("\tPlease input the credential ID : ");
1230             cred = GetCredEntryByCredId(credId);
1231             if (NULL == cred)
1232             {
1233                 PRINT_ERR("Invalid credId");
1234                 return -1;
1235             }
1236             if (SYMMETRIC_PAIR_WISE_KEY != cred->credType)
1237             {
1238                 PRINT_ERR("Selected cred is not SYMMETRIC_PAIR_WISE_KEY type\n");
1239                 DeleteCredList(cred);
1240                 return -1;
1241             }
1242             if (0 != InputPSK(&key))
1243             {
1244                 PRINT_ERR("Failed InputPSK");
1245                 DeleteCredList(cred);
1246                 return -1;
1247             }
1248             if (key.len == cred->privateData.len &&
1249                 key.encoding == cred->privateData.encoding &&
1250                 0 == memcmp(key.data, cred->privateData.data, key.len))
1251             {
1252                 PRINT_ERR("Please input different psk from the selected cred's psk");
1253                 OICFree(key.data);
1254                 DeleteCredList(cred);
1255                 return -1;
1256             }
1257             cred->privateData = key;
1258
1259             credResult = AddCredential(cred);
1260             if (OC_STACK_OK != credResult)
1261             {
1262                 PRINT_ERR("AddCredential : %d", credResult);
1263                 DeleteCredList(cred);
1264                 return -1;
1265             }
1266             credResult = RemoveCredentialByCredId(credId);
1267             if ( OC_STACK_RESOURCE_DELETED != credResult)
1268             {
1269                 PRINT_ERR("RemoveCredentialByCredId error : %d" , credResult);
1270                 return -1;
1271             }
1272
1273             break;
1274         case CRED_EDIT_ROWNERUUID:
1275             PRINT_PROG(
1276                 "\tInput the ROWNER UUID (e.g. 61646D69-6E44-6576-6963-655575696430) : ");
1277             ret = InputUuid(&uuid);
1278             if (0 != ret)
1279             {
1280                 PRINT_ERR("InputUuid failed");
1281                 return -1;
1282             }
1283             credResult = SetCredRownerId(&uuid);
1284             if (OC_STACK_OK != credResult)
1285             {
1286                 PRINT_ERR("SetCredRownerId failed");
1287                 return -1;
1288             }
1289             break;
1290         case BACK:
1291             PRINT_INFO("Back to the previous menu.");
1292             break;
1293         default:
1294             PRINT_ERR("Wrong type Number");
1295             ret = -1;
1296             break;
1297     }
1298     return ret;
1299 }
1300
1301 void HandleCredOperation(SubOperationType_t cmd)
1302 {
1303     uint16_t credId = 0;
1304     OCStackResult credResult = OC_STACK_ERROR;
1305
1306     if (SVR_EDIT_IDX_SIZE <= cmd)
1307     {
1308         PRINT_ERR("Invalid menu for credential");
1309         return;
1310     }
1311     switch (cmd)
1312     {
1313         case SVR_PRINT:
1314             PrintCredList(GetCredList());
1315             break;
1316         case SVR_ADD:
1317             {
1318                 OicSecCred_t *cred = (OicSecCred_t *)OICCalloc(1, sizeof(OicSecCred_t));
1319                 if (NULL == cred)
1320                 {
1321                     PRINT_ERR("Failed to allocate memory");
1322                     return;
1323                 }
1324
1325                 if (0 != InputCredentialData(cred))
1326                 {
1327                     PRINT_ERR("Failed to InputCredentialData");
1328                     DeleteCredList(cred);
1329                     return;
1330                 }
1331
1332                 credResult = AddCredential(cred);
1333                 if ( OC_STACK_OK != credResult)
1334                 {
1335                     PRINT_ERR("AddCredential error : %d" , credResult);
1336                     DeleteCredList(cred);
1337                     return;
1338                 }
1339                 break;
1340             }
1341         case SVR_REMOVE:
1342             PrintCredList(GetCredList());
1343             credId = (uint16_t)InputNumber("\tPlease input the credential ID : ");
1344
1345             credResult = RemoveCredentialByCredId(credId);
1346             if ( OC_STACK_RESOURCE_DELETED != credResult)
1347             {
1348                 PRINT_ERR("RemoveCredentialByCredId error : %d" , credResult);
1349                 return;
1350             }
1351             break;
1352         case SVR_MODIFY:
1353             if (0 != ModifyCred())
1354             {
1355                 PRINT_ERR("Failed Modification");
1356                 return;
1357             }
1358             PRINT_INFO("\n\nCred Modified");
1359             UpdateCred();
1360             break;
1361         default:
1362             break;
1363     }
1364 }