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