1 /******************************************************************
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************/
26 #include "oic_malloc.h"
28 #include "ocprovisioningmanager.h"
29 #include "secureresourceprovider.h"
30 #include "oxmjustworks.h"
31 #include "oic_string.h"
32 #include "securevirtualresourcetypes.h"
34 #include "ck_manager.h"
36 #include "crlresource.h"
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)
51 #define PREDEFINED_TIMEOUT (10)
52 #define MAX_OWNED_DEVICE (10)
53 #define DATE_LENGTH (14)
54 #define TAG "provisioningclient"
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;
64 ownershipDone = 1 << 1,
65 finalizeDone = 1 << 2,
66 provisionAclDone = 1 << 3,
67 provisionCert1Done = 1 << 4,
68 provisionCert2Done = 1 << 5,
69 provisionCrlDone = 1 << 6
72 void deleteCrl(OicSecCrl_t *crl)
77 OICFree(crl->ThisUpdate.data);
80 OICFree(crl->CrlData.data);
88 * Calculate ACL permission from string to bit
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.
94 static int CalculateAclPermission(const char *temp_pms, uint16_t *pms)
98 if (NULL == temp_pms || NULL == pms)
103 while (temp_pms[i] != '\0')
152 * Get the ACL property from user
154 * @param[in] ACL Datastructure to save user inputs
155 * @return 0 on success otherwise -1.
157 static int InputACL(OicSecAcl_t *acl)
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));
167 printf("Failed to memory allocation\n");
170 LL_APPEND(acl->aces, ace);
172 printf("******************************************************************************\n");
173 printf("-Set ACL policy for target device\n");
174 printf("******************************************************************************\n");
177 printf("-URN identifying the subject\n");
178 printf("ex) doorDeviceUUID00 (16 Numbers except to '-')\n");
179 printf("Subject : ");
181 ret = scanf("%19ms", &ptr);
184 OICStrcpy(temp_id, sizeof(temp_id), ptr);
189 printf("Error while input\n");
193 for (int i = 0; temp_id[i] != '\0'; i++)
195 if (DASH != temp_id[i])
199 printf("Invalid input\n");
202 ace->subjectuuid.id[j++] = temp_id[i];
207 printf("Num. of Resource : \n");
209 ret = scanf("%zu", &inputLen);
210 if(-1 == ret || MAX_ACE_LENGTH < inputLen)
212 printf("Error while input\n");
215 printf("-URI of resource\n");
216 printf("ex) /a/light (Max_URI_Length: 64 Byte )\n");
218 for(size_t i = 0; i < inputLen; i++)
220 OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
223 printf("Failed to memory allocation\n");
226 LL_APPEND(ace->resources, rsrc);
228 //Input the resource URI for each resource
229 printf("[%zu]Resource : ", i + 1);
230 ret = scanf("%s", input_buffer);
233 rsrc->href = OICStrdup(input_buffer);
236 printf("Failed to OICStrdup\n");
242 printf("Error while input\n");
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)
251 printf("Error while input\n");
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)
260 printf("Failed to memory allocation\n");
263 for(size_t j = 0; j < rsrc->interfaceLen; j++)
265 printf("Interface[%zu] : ", j + 1);
266 ret = scanf("%s", input_buffer);
269 rsrc->interfaces[i] = OICStrdup(input_buffer);
270 if(!rsrc->interfaces[i])
272 printf("Failed to OICStrdup\n");
278 printf("Error while input\n");
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)
288 printf("Error while input\n");
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*));
297 printf("Failed to memory allocation\n");
300 for(size_t j = 0; j < rsrc->typeLen; j++)
302 printf("Resource type[%zu] : ", j + 1);
303 ret = scanf("%s", input_buffer);
306 rsrc->types[i] = OICStrdup(input_buffer);
309 printf("Failed to OICStrdup\n");
315 printf("Error while input\n");
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);
330 OICStrcpy(temp_pms, sizeof(temp_pms), input_buffer);
334 printf("Error while input\n");
338 while (0 != CalculateAclPermission(temp_pms, &(ace->permission)) );
345 //FILE *client_fopen(const char *path, const char *mode)
346 FILE *client_fopen(const char* UNUSED_PARAM , const char *mode)
349 return fopen(PROV_TOOL_DB_FILE, mode);
352 void PrintfResult(const char* procName, void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
354 printf("-----------------------------------------------------------\n");
357 printf("%s was successfully done.\n", procName);
361 for(int i = 0; i < nOfRes; i++)
364 for(int j = 0; j < UUID_LENGTH; j++)
366 printf("%c", arr[i].deviceId.id[j]);
369 printf("Result=%d\n", arr[i].res);
375 printf("Context is %s\n", (char*)ctx);
377 printf("-----------------------------------------------------------\n");
380 void ProvisionCertCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
385 PrintfResult("Provision Credential", ctx, nOfRes, arr, hasError);
387 else printf("Cert provisioning error\n-----------------------------------------");
390 void ProvisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
395 PrintfResult("Provision ACL", ctx, nOfRes, arr, hasError);
399 void ProvisionCrlCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
404 PrintfResult("Provision CRL", ctx, nOfRes, arr, hasError);
410 void OwnershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
415 PrintfResult("Ownership transfer", ctx, nOfRes, arr, hasError);
419 static short IsCKMInfoFileExists()
421 FILE *ckmInf = fopen(CA_STORAGE_FILE, "r");
430 static PKIError InitCA()
434 if (IsCKMInfoFileExists())
436 CHECK_CALL(InitCKMInfo);
440 ByteArray rootName = BYTE_ARRAY_INITIALIZER;
441 ByteArray CAPubKey = BYTE_ARRAY_INITIALIZER;
442 ByteArray CAPrivKey = BYTE_ARRAY_INITIALIZER;
443 ByteArray rootCert = BYTE_ARRAY_INITIALIZER;
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";
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);
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);
470 static int InputCRL(OicSecCrl_t *crlRes)
473 ByteArray crl = BYTE_ARRAY_INITIALIZER;
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);
484 ret = scanf("%u", &nuberOfRevoked);
487 printf("Error while input\n");
488 return PKI_UNKNOWN_ERROR;
491 if((uint32_t)MAX_Revoked_NUMBER < nuberOfRevoked)
493 OIC_LOG(ERROR, TAG, "Wrong revoked certificate number");
494 return PKI_UNKNOWN_ERROR;
497 for (size_t i = 0; i < nuberOfRevoked; ++i)
499 printf("Revoked certificate %d:", i);
500 printf("Serial number (E. g.: 100):");
501 ret = scanf("%u", &revokedNumbers[i]);
504 printf("Error while input\n");
505 return PKI_UNKNOWN_ERROR;
508 revocationDates[i] = (const uint8_t*)"130101000005Z";
511 crl.len = CRL_MIN_SIZE + nuberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4)/* + 1000*/;
512 crl.data = (uint8_t *)OICCalloc(1, crl.len);
514 if (NULL == crl.data)
516 OIC_LOG(ERROR, TAG, "Error while memory allocation");
517 return PKI_MEMORY_ALLOC_FAILED;
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;
529 if(NULL == crlRes->ThisUpdate.data)
531 printf("OICStrdup failed\n");
532 return PKI_MEMORY_ALLOC_FAILED;
542 * Provisioning client sample using ProvisioningAPI
546 OCStackResult res = OC_STACK_OK;
547 OCProvisionDev_t* pDeviceList = NULL;
548 OCProvisionDev_t *pOwnedList = NULL;
550 // Initialize Persistent Storage for SVR database
551 OCPersistentStorage ps = { .open = client_fopen,
557 OCRegisterPersistentStorageHandler(&ps);
559 if (OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
561 OIC_LOG(ERROR, TAG, "OCStack init error");
564 if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
566 OIC_LOG(ERROR, TAG, "OC_PM init error");
570 res = OCDiscoverUnownedDevices(PREDEFINED_TIMEOUT, &pDeviceList);
571 if(OC_STACK_OK != res)
573 OIC_LOG_V(ERROR, TAG, "Failed to PMDeviceDiscovery : %d", res);
577 OCProvisionDev_t* pCurDev = pDeviceList;
579 while(pCurDev !=NULL)
581 for(i = 0; i < UUID_LENGTH; i++)
583 printf("%c", pCurDev->doxm->deviceID.id[i]);
586 pCurDev = pCurDev->next;
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);
600 char* myContext = "OTM Context";
601 //Perform ownership transfer
602 res = OCDoOwnershipTransfer((void*)myContext, pDeviceList, OwnershipTransferCB);
603 if(OC_STACK_OK == res)
605 OIC_LOG(INFO, TAG, "Request for ownership transfer is sent successfully.");
609 OIC_LOG_V(ERROR, TAG, "Failed to OCDoOwnershipTransfer : %d", res);
613 while (gOwnershipState == 0)
615 if (OCProcess() != OC_STACK_OK)
617 OIC_LOG(ERROR, TAG, "OCStack process error");
623 // Credential & ACL provisioning between two devices.
625 OCProvisionDev_t *pOwnedDevices [MAX_OWNED_DEVICE] = {0,};
626 int nOwnedDevice = 0;
628 res = OCDiscoverOwnedDevices(PREDEFINED_TIMEOUT, &pOwnedList);
629 if (OC_STACK_OK == res)
631 printf("################## Owned Device List #######################\n");
632 while (pOwnedList != NULL)
635 printf(" %d : ", nOwnedDevice);
636 for (int i = 0; i < UUID_LENGTH; i++)
638 printf("%c", pOwnedList->doxm->deviceID.id[i]);
641 pOwnedDevices[nOwnedDevice] = pOwnedList;
642 pOwnedList = pOwnedList->next;
647 OIC_LOG(ERROR, TAG, "Error while Owned Device Discovery");
654 printf("Select 2 devices for Credential & ACL provisioning\n");
655 printf("Device 1: ");
656 ret = scanf("%d", &Device1);
659 printf("Error while input\n");
663 printf("Device 2: ");
664 ret = scanf("%d", &Device2);
667 printf("Error while input\n");
671 if( 0 > Device1 || 0 > Device2 || Device1 > nOwnedDevice || Device2 > nOwnedDevice)
673 OIC_LOG(ERROR, TAG, "Wrong devices number");
677 gAcl = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
680 OIC_LOG(ERROR, TAG, "Error while memory allocation");
684 if (PKI_SUCCESS != InitCA())
686 OIC_LOG(ERROR, TAG, "CA init error");
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);
697 while ( gOwnershipState == 0 )
699 if (OCProcess() != OC_STACK_OK)
701 OIC_LOG(ERROR, TAG, "OCStack process error");
707 res = OCProvisionCredentials(ctx, SIGNED_ASYMMETRIC_KEY, 0, pOwnedDevices[Device2],
708 NULL, ProvisionCertCB);
709 if (OC_STACK_OK != res)
711 OIC_LOG_V(ERROR, TAG, "Failed to provision Device 2 : %d", res);
715 while (gOwnershipState == 0)
717 if (OCProcess() != OC_STACK_OK)
719 OIC_LOG(ERROR, TAG, "OCStack process error");
725 printf("Input ACL for Device2\n");
726 if (0 == InputACL(gAcl))
728 printf("Success Input ACL\n");
732 OIC_LOG(ERROR, TAG, "InputACL error");
735 res = OCProvisionACL(ctx, pOwnedDevices[Device2], gAcl, &ProvisionAclCB);
736 if (OC_STACK_OK != res)
738 OIC_LOG_V(ERROR, TAG, "Failed to ACL provision Device 2 : %d", res);
742 while (gOwnershipState == 0)
744 if (OCProcess() != OC_STACK_OK)
746 OIC_LOG(ERROR, TAG, "OCStack process error");
751 gCrl = (OicSecCrl_t *)OICMalloc(sizeof(OicSecCrl_t));
755 OIC_LOG(ERROR, TAG, "Error while memory allocation");
759 if (PKI_SUCCESS != InputCRL(gCrl))
761 OIC_LOG(ERROR, TAG, "CA init error");
765 PRINT_BYTE_ARRAY("gCrl = \n", gCrl->CrlData);
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);
771 while (gOwnershipState == 0)
773 if (OCProcess() != OC_STACK_OK)
775 OIC_LOG(ERROR, TAG, "OCStack process error");
781 if (OCStop() != OC_STACK_OK)
783 OIC_LOG(ERROR, TAG, "OCStack process error");
790 OCDeleteDiscoveredDevices(pDeviceList);
791 OCDeleteDiscoveredDevices(pOwnedList);