Imported Upstream version 1.1.0
[platform/upstream/iotivity.git] / resource / csdk / security / provisioning / ck_manager / sample / provisioningclient.c
1 /******************************************************************
2 *
3 * Copyright 2015 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 #include <stdio.h>
22 #include <string.h>
23 #include <unistd.h>
24
25 #include "logger.h"
26 #include "oic_malloc.h"
27 #include "utlist.h"
28 #include "ocprovisioningmanager.h"
29 #include "secureresourceprovider.h"
30 #include "oxmjustworks.h"
31 #include "oic_string.h"
32 #include "securevirtualresourcetypes.h"
33 #include "cacommon.h"
34 #include "ck_manager.h"
35 #include "ckm_info.h"
36 #include "crlresource.h"
37
38 #define MAX_URI_LENGTH (64)
39 #define MAX_PERMISSION_LENGTH (5)
40 #define CREATE (1)
41 #define READ (2)
42 #define UPDATE (4)
43 #define DELETE (8)
44 #define NOTIFY (16)
45 #define DASH '-'
46 #define PREDEFINED_TIMEOUT (10)
47 #define MAX_OWNED_DEVICE (10)
48 #define DATE_LENGTH      (14)
49 #define TAG  "provisioningclient"
50
51 static OicSecAcl_t        *gAcl = NULL;
52 static OicSecCrl_t        *gCrl = NULL;
53 static char PROV_TOOL_DB_FILE[] = "oic_svr_db_pt.dat";
54 static const char* PRVN_DB_FILE_NAME = "oic_prvn_mng.db";
55 static int gOwnershipState = 0;
56
57 typedef enum
58 {
59     ownershipDone = 1 << 1,
60     finalizeDone = 1 << 2,
61     provisionAclDone = 1 << 3,
62     provisionCert1Done = 1 << 4,
63     provisionCert2Done = 1 << 5,
64     provisionCrlDone = 1 << 6
65 } StateManager;
66
67
68 /**
69  * Perform cleanup for ACL
70  * @param[in]    ACL
71  */
72 static void deleteACL(OicSecAcl_t *acl)
73 {
74     if (acl)
75     {
76         /* Clean Resources */
77         for (size_t i = 0; i < (acl)->resourcesLen; i++)
78         {
79             OICFree((acl)->resources[i]);
80         }
81         OICFree((acl)->resources);
82
83         /* Clean ACL node itself */
84         OICFree((acl));
85
86         acl = NULL;
87     }
88 }
89
90 void deleteCrl(OicSecCrl_t *crl)
91 {
92     if (crl)
93     {
94         //Clean ThisUpdate
95         OICFree(crl->ThisUpdate.data);
96
97         //clean CrlData
98         OICFree(crl->CrlData.data);
99
100         //Clean crl itself
101         OICFree(crl);
102     }
103 }
104
105 /**
106  * Calculate ACL permission from string to bit
107  *
108  * @param[in] temp_psm    Input data of ACL permission string
109  * @param[in,out] pms    The pointer of ACL permission value
110  * @return  0 on success otherwise -1.
111  */
112 static int CalculateAclPermission(const char *temp_pms, uint16_t *pms)
113 {
114     int i = 0;
115
116     if (NULL == temp_pms || NULL == pms)
117     {
118         return -1;
119     }
120     *pms = 0;
121     while (temp_pms[i] != '\0')
122     {
123         switch (temp_pms[i])
124         {
125             case 'C':
126                 {
127                     *pms += CREATE;
128                     i++;
129                     break;
130                 }
131             case 'R':
132                 {
133                     *pms += READ;
134                     i++;
135                     break;
136                 }
137             case 'U':
138                 {
139                     *pms += UPDATE;
140                     i++;
141                     break;
142                 }
143             case 'D':
144                 {
145                     *pms += DELETE;
146                     i++;
147                     break;
148                 }
149             case 'N':
150                 {
151                     *pms += NOTIFY;
152                     i++;
153                     break;
154                 }
155             case '_':
156                 {
157                     i++;
158                     break;
159                 }
160             default:
161                 {
162                     return -1;
163                 }
164         }
165     }
166     return 0;
167 }
168
169 /**
170  * Get the ACL property from user
171  *
172  * @param[in]    ACL Datastructure to save user inputs
173  * @return  0 on success otherwise -1.
174  */
175 static int InputACL(OicSecAcl_t *acl)
176 {
177     int ret;
178     char temp_id [UUID_LENGTH + 4] = {0,};
179     char temp_rsc[MAX_URI_LENGTH + 1] = {0,};
180     char temp_pms[MAX_PERMISSION_LENGTH + 1] = {0,};
181     printf("******************************************************************************\n");
182     printf("-Set ACL policy for target device\n");
183     printf("******************************************************************************\n");
184     //Set Subject.
185     printf("-URN identifying the subject\n");
186     printf("ex) doorDeviceUUID00 (16 Numbers except to '-')\n");
187     printf("Subject : ");
188     char *ptr = NULL;
189     ret = scanf("%19ms", &ptr);
190     if(1==ret)
191     {
192         OICStrcpy(temp_id, sizeof(temp_id), ptr);
193         OICFree(ptr);
194     }
195     else
196     {
197          printf("Error while input\n");
198          return -1;
199     }
200     int j = 0;
201     for (int i = 0; temp_id[i] != '\0'; i++)
202     {
203         if (DASH != temp_id[i])
204         {
205             if(j >= UUID_LENGTH)
206             {
207                 printf("Invalid input\n");
208                 return -1;
209             }
210             acl->subject.id[j++] = temp_id[i];
211         }
212     }
213
214     //Set Resource.
215     printf("Num. of Resource : \n");
216     ret = scanf("%zu", &acl->resourcesLen);
217     if(-1 == ret)
218     {
219         printf("Error while input\n");
220         return -1;
221     }
222     printf("-URI of resource\n");
223     printf("ex) /a/light (Max_URI_Length: 64 Byte )\n");
224     acl->resources = (char **)OICCalloc(acl->resourcesLen, sizeof(char *));
225     if (NULL == acl->resources)
226     {
227         OIC_LOG(ERROR, TAG, "Error while memory allocation");
228         return -1;
229     }
230     for (size_t i = 0; i < acl->resourcesLen; i++)
231     {
232         printf("[%zu]Resource : ", i + 1);
233         char *ptr_tempRsc = NULL;
234         ret = scanf("%64ms", &ptr_tempRsc);
235         if (1==ret)
236         {
237             OICStrcpy(temp_rsc, sizeof(temp_rsc), ptr_tempRsc);
238             OICFree(ptr_tempRsc);
239         }
240         else
241         {
242             printf("Error while input\n");
243             return -1;
244         }
245         acl->resources[i] = OICStrdup(temp_rsc);
246
247         if (NULL == acl->resources[i])
248         {
249             OIC_LOG(ERROR, TAG, "Error while memory allocation");
250             return -1;
251         }
252     }
253     // Set Permission
254     do
255     {
256         printf("-Set the permission(C,R,U,D,N)\n");
257         printf("ex) CRUDN, CRU_N,..(5 Charaters)\n");
258         printf("Permission : ");
259         char *ptr_temp_pms = NULL;
260         ret = scanf("%5ms", &ptr_temp_pms);
261         if(1 == ret)
262         {
263             OICStrcpy(temp_pms, sizeof(temp_pms), ptr_temp_pms);
264             OICFree(ptr_temp_pms);
265
266         }
267         else
268         {
269             printf("Error while input\n");
270             return -1;
271         }
272     }
273     while (0 != CalculateAclPermission(temp_pms, &(acl->permission)) );
274     // Set Rowner
275     printf("-URN identifying the rowner\n");
276     printf("ex) lightDeviceUUID0 (16 Numbers except to '-')\n");
277
278     printf("Rowner : ");
279     char *ptr_temp_id = NULL;
280     ret = scanf("%19ms", &ptr_temp_id);
281     if (1 == ret)
282     {
283         OICStrcpy(temp_id, sizeof(temp_id), ptr_temp_id);
284         OICFree(ptr_temp_id);
285     }
286     else
287     {
288         printf("Error while input\n");
289         return -1;
290     }
291     j = 0;
292     for (int k = 0; temp_id[k] != '\0'; k++)
293     {
294         if (DASH != temp_id[k])
295         {
296             acl->rownerID.id[j++] = temp_id[k];
297         }
298     }
299     return 0;
300 }
301
302
303 //FILE *client_fopen(const char *path, const char *mode)
304 FILE *client_fopen(const char* UNUSED_PARAM , const char *mode)
305 {
306     (void)UNUSED_PARAM;
307     return fopen(PROV_TOOL_DB_FILE, mode);
308 }
309
310 void PrintfResult(const char* procName, void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
311 {
312     printf("-----------------------------------------------------------\n");
313     if(!hasError)
314     {
315         printf("%s was successfully done.\n", procName);
316     }
317     else
318     {
319         for(int i = 0; i < nOfRes; i++)
320         {
321             printf("UUID : ");
322             for(int j = 0; j < UUID_LENGTH; j++)
323             {
324                 printf("%c", arr[i].deviceId.id[j]);
325             }
326             printf("\t");
327             printf("Result=%d\n", arr[i].res);
328         }
329     }
330
331     if(ctx)
332     {
333         printf("Context is %s\n", (char*)ctx);
334     }
335     printf("-----------------------------------------------------------\n");
336 }
337
338 void ProvisionCertCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
339 {
340     if(!hasError)
341     {
342         gOwnershipState = 1;
343         PrintfResult("Provision Credential", ctx, nOfRes, arr, hasError);
344     }
345     else printf("Cert provisioning error\n-----------------------------------------");
346 }
347
348 void ProvisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
349 {
350     if(!hasError)
351     {
352         gOwnershipState = 1;
353         PrintfResult("Provision ACL", ctx, nOfRes, arr, hasError);
354     }
355 }
356
357 void ProvisionCrlCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
358 {
359     if(!hasError)
360     {
361         gOwnershipState = 1;
362         PrintfResult("Provision CRL", ctx, nOfRes, arr, hasError);
363     }
364 }
365
366
367
368 void OwnershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
369 {
370     if(!hasError)
371     {
372         gOwnershipState = 1;
373         PrintfResult("Ownership transfer", ctx, nOfRes, arr, hasError);
374     }
375 }
376
377 static short IsCKMInfoFileExists()
378 {
379     FILE *ckmInf = fopen(CA_STORAGE_FILE, "r");
380     if (NULL != ckmInf)
381     {
382         fclose(ckmInf);
383         return 1;
384     }
385     return 0;
386 }
387
388 static PKIError InitCA()
389 {
390     FUNCTION_INIT();
391
392     if (IsCKMInfoFileExists())
393     {
394         CHECK_CALL(InitCKMInfo);
395     }
396     else
397     {
398         ByteArray rootName  = BYTE_ARRAY_INITIALIZER;
399         ByteArray CAPubKey  = BYTE_ARRAY_INITIALIZER;
400         ByteArray CAPrivKey = BYTE_ARRAY_INITIALIZER;
401         ByteArray rootCert  = BYTE_ARRAY_INITIALIZER;
402
403
404         uint8_t rootCertData[ISSUER_MAX_CERT_SIZE];
405         uint8_t CAPubKeyData[PUBLIC_KEY_SIZE];
406         uint8_t CAPrivKeyData[PRIVATE_KEY_SIZE];
407         const char rootNameStr[] = "Sample_Root";
408
409         CAPubKey.data  = CAPubKeyData;
410         CAPubKey.len   = PUBLIC_KEY_SIZE;
411         CAPrivKey.data = CAPrivKeyData;
412         CAPrivKey.len  = PRIVATE_KEY_SIZE;
413         rootCert.data  = rootCertData;
414         rootCert.len   = ISSUER_MAX_CERT_SIZE;
415         rootName.data  = (uint8_t *)rootNameStr;
416         rootName.len   = strlen(rootNameStr);
417
418         CHECK_CALL(SetRootName, rootName);
419         CHECK_CALL(GenerateCAKeyPair, &CAPrivKey, &CAPubKey);
420         CHECK_CALL(SetSerialNumber, 1);
421         CHECK_CALL(CKMIssueRootCertificate, NULL, NULL, &rootCert);
422         CHECK_CALL(SetCACertificate, &rootCert);
423     }
424
425     FUNCTION_CLEAR();
426 }
427
428 static int InputCRL(OicSecCrl_t *crlRes)
429 {
430     FUNCTION_INIT(
431             ByteArray crl = BYTE_ARRAY_INITIALIZER;
432             );
433
434     const int MAX_Revoked_NUMBER = 9;
435     uint8_t uint8ThisUpdateTime[DATE_LENGTH] = "130101000005Z";
436     uint32_t revokedNumbers[MAX_Revoked_NUMBER];
437     const uint8_t* revocationDates[MAX_Revoked_NUMBER];
438    // const uint8_t revocationDatesContent[MAX_Revoked_NUMBER][DATE_LENGTH];
439     uint32_t nuberOfRevoked = 0;
440     printf("Enter number of Revoked certificates(1..%d)\n", MAX_Revoked_NUMBER);
441     int ret = 0;
442     ret = scanf("%u", &nuberOfRevoked);
443     if(-1 == ret)
444     {
445         printf("Error while input\n");
446         return PKI_UNKNOWN_ERROR;
447     }
448
449     if((uint32_t)MAX_Revoked_NUMBER < nuberOfRevoked)
450     {
451         OIC_LOG(ERROR, TAG, "Wrong revoked certificate number");
452         return PKI_UNKNOWN_ERROR;
453     }
454
455     for (size_t i = 0; i < nuberOfRevoked; ++i)
456     {
457         printf("Revoked certificate %d:", i);
458         printf("Serial number (E. g.: 100):");
459         ret = scanf("%u", &revokedNumbers[i]);
460         if(-1 == ret)
461         {
462             printf("Error while input\n");
463             return PKI_UNKNOWN_ERROR;
464         }
465
466         revocationDates[i] = (const uint8_t*)"130101000005Z";
467     }
468
469     crl.len = CRL_MIN_SIZE + nuberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4)/* + 1000*/;
470     crl.data = (uint8_t *)OICCalloc(1, crl.len);
471
472     if (NULL == crl.data)
473     {
474         OIC_LOG(ERROR, TAG, "Error while memory allocation");
475         return PKI_MEMORY_ALLOC_FAILED;
476     }
477
478     CHECK_CALL(CKMIssueCRL, uint8ThisUpdateTime, nuberOfRevoked, revokedNumbers,
479             revocationDates, &crl);
480     PRINT_BYTE_ARRAY("CRL:\n",crl);
481     CHECK_CALL(SetCertificateRevocationList, &crl);
482     crlRes->CrlData = crl;
483     crlRes->ThisUpdate.data = uint8ThisUpdateTime;
484     crlRes->ThisUpdate.len = DATE_LENGTH;
485     crlRes->CrlId = 1;
486
487
488     FUNCTION_CLEAR(
489     //OICFree(crl.data);
490             );
491 }
492
493
494 /**
495  * Provisioning client sample using ProvisioningAPI
496  */
497 int main()
498 {
499     OCStackResult res = OC_STACK_OK;
500     OCProvisionDev_t* pDeviceList = NULL;
501     OCProvisionDev_t *pOwnedList = NULL;
502
503     // Initialize Persistent Storage for SVR database
504     OCPersistentStorage ps = { .open = client_fopen,
505                                .read = fread,
506                                .write = fwrite,
507                                .close = fclose,
508                                .unlink = unlink};
509
510     OCRegisterPersistentStorageHandler(&ps);
511
512     if (OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
513     {
514         OIC_LOG(ERROR, TAG, "OCStack init error");
515         goto error;
516     }
517     if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
518     {
519         OIC_LOG(ERROR, TAG, "OC_PM init error");
520         goto error;
521     }
522
523     res = OCDiscoverUnownedDevices(PREDEFINED_TIMEOUT, &pDeviceList);
524     if(OC_STACK_OK != res)
525     {
526         OIC_LOG_V(ERROR, TAG, "Failed to PMDeviceDiscovery : %d", res);
527         goto error;
528     }
529
530     OCProvisionDev_t* pCurDev = pDeviceList;
531     int i;
532     while(pCurDev !=NULL)
533     {
534         for(i = 0; i < UUID_LENGTH; i++)
535         {
536             printf("%c", pCurDev->doxm->deviceID.id[i]);
537         }
538         printf("\n");
539         pCurDev = pCurDev->next;
540     }
541
542     //Register callback function to each OxM
543     OTMCallbackData_t justWorksCBData = {.loadSecretCB=NULL,
544                                          .createSecureSessionCB=NULL,
545                                          .createSelectOxmPayloadCB=NULL,
546                                          .createOwnerTransferPayloadCB=NULL};
547     justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
548     justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
549     justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
550     justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
551     OTMSetOwnershipTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData);
552
553     char* myContext = "OTM Context";
554     //Perform ownership transfer
555     res = OCDoOwnershipTransfer((void*)myContext, pDeviceList, OwnershipTransferCB);
556     if(OC_STACK_OK == res)
557     {
558         OIC_LOG(INFO, TAG, "Request for ownership transfer is sent successfully.");
559     }
560     else
561     {
562         OIC_LOG_V(ERROR, TAG, "Failed to OCDoOwnershipTransfer : %d", res);
563     }
564
565     gOwnershipState = 0;
566     while (gOwnershipState == 0)
567     {
568         if (OCProcess() != OC_STACK_OK)
569         {
570             OIC_LOG(ERROR, TAG, "OCStack process error");
571             goto error;
572         }
573         sleep(1);
574     }
575
576 // Credential & ACL provisioning between two devices.
577
578     OCProvisionDev_t *pOwnedDevices [MAX_OWNED_DEVICE] = {0,};
579     int nOwnedDevice = 0;
580
581     res = OCDiscoverOwnedDevices(PREDEFINED_TIMEOUT, &pOwnedList);
582     if (OC_STACK_OK == res)
583     {
584         printf("################## Owned Device List #######################\n");
585         while (pOwnedList != NULL)
586         {
587             nOwnedDevice ++;
588             printf(" %d : ", nOwnedDevice);
589             for (int i = 0; i < UUID_LENGTH; i++)
590             {
591                 printf("%c", pOwnedList->doxm->deviceID.id[i]);
592             }
593             printf("\n");
594             pOwnedDevices[nOwnedDevice] = pOwnedList;
595             pOwnedList = pOwnedList->next;
596         }
597     }
598     else
599     {
600         OIC_LOG(ERROR, TAG, "Error while Owned Device Discovery");
601     }
602
603     int Device1 = 0;
604     int Device2 = 0;
605     int ret = 0;
606
607     printf("Select 2 devices for Credential & ACL provisioning\n");
608     printf("Device 1: ");
609     ret = scanf("%d", &Device1);
610     if(-1 == ret)
611     {
612         printf("Error while input\n");
613         goto error;
614     }
615
616     printf("Device 2: ");
617     ret = scanf("%d", &Device2);
618     if(-1 == ret)
619     {
620         printf("Error while input\n");
621         goto error;
622     }
623
624     if( 0 > Device1 || 0 > Device2 || Device1 > nOwnedDevice || Device2 > nOwnedDevice)
625     {
626         OIC_LOG(ERROR, TAG, "Wrong devices number");
627         goto error;
628     }
629
630     gAcl = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
631     if (NULL == gAcl)
632     {
633         OIC_LOG(ERROR, TAG, "Error while memory allocation");
634         goto error;
635     }
636
637     if (PKI_SUCCESS != InitCA())
638     {
639         OIC_LOG(ERROR, TAG, "CA init error");
640         goto error;
641     }
642
643
644     char *ctx = "DUMMY";
645
646     res = OCProvisionCredentials(ctx, SIGNED_ASYMMETRIC_KEY, 0, pOwnedDevices[Device1],
647                                                                 NULL, ProvisionCertCB);
648     if (OC_STACK_OK != res) OIC_LOG_V(ERROR, TAG, "Failed to provision Device 1 : %d", res);
649     gOwnershipState = 0;
650     while ( gOwnershipState == 0 )
651     {
652         if (OCProcess() != OC_STACK_OK)
653         {
654             OIC_LOG(ERROR, TAG, "OCStack process error");
655             goto error;
656         }
657         sleep(1);
658     }
659
660     res = OCProvisionCredentials(ctx, SIGNED_ASYMMETRIC_KEY, 0, pOwnedDevices[Device2],
661                                                                 NULL, ProvisionCertCB);
662     if (OC_STACK_OK != res)
663     {
664         OIC_LOG_V(ERROR, TAG, "Failed to provision Device 2 : %d", res);
665     }
666
667     gOwnershipState = 0;
668     while (gOwnershipState == 0)
669     {
670         if (OCProcess() != OC_STACK_OK)
671         {
672             OIC_LOG(ERROR, TAG, "OCStack process error");
673             goto error;
674         }
675         sleep(1);
676     }
677
678     printf("Input ACL for Device2\n");
679     if (0 == InputACL(gAcl))
680     {
681         printf("Success Input ACL\n");
682     }
683     else
684     {
685         OIC_LOG(ERROR, TAG, "InputACL error");
686         goto error;
687     }
688     res = OCProvisionACL(ctx, pOwnedDevices[Device2], gAcl, &ProvisionAclCB);
689     if (OC_STACK_OK != res)
690     {
691         OIC_LOG_V(ERROR, TAG, "Failed to ACL provision Device 2 : %d", res);
692     }
693
694     gOwnershipState = 0;
695     while (gOwnershipState == 0)
696     {
697         if (OCProcess() != OC_STACK_OK)
698         {
699             OIC_LOG(ERROR, TAG, "OCStack process error");
700             goto error;
701         }
702         sleep(1);
703     }
704     gCrl = (OicSecCrl_t *)OICMalloc(sizeof(OicSecCrl_t));
705
706     if (NULL == gCrl)
707     {
708         OIC_LOG(ERROR, TAG, "Error while memory allocation");
709         goto error;
710     }
711
712     if (PKI_SUCCESS != InputCRL(gCrl))
713     {
714         OIC_LOG(ERROR, TAG, "CA init error");
715         goto error;
716     }
717
718     PRINT_BYTE_ARRAY("gCrl = \n", gCrl->CrlData);
719
720     res = OCProvisionCRL(ctx, pOwnedDevices[Device2], gCrl, &ProvisionCrlCB);
721     if (OC_STACK_OK != res) OIC_LOG_V(ERROR, TAG, "Failed to CRL provision Device 2 : %d", res);
722
723     gOwnershipState = 0;
724     while (gOwnershipState == 0)
725     {
726         if (OCProcess() != OC_STACK_OK)
727         {
728             OIC_LOG(ERROR, TAG, "OCStack process error");
729             goto error;
730         }
731         sleep(1);
732     }
733
734     if (OCStop() != OC_STACK_OK)
735     {
736         OIC_LOG(ERROR, TAG, "OCStack process error");
737         goto error;
738     }
739
740 error:
741     deleteACL(gAcl);
742     OCDeleteDiscoveredDevices(pDeviceList);
743     OCDeleteDiscoveredDevices(pOwnedList);
744
745     return 0;
746 }