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