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_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)
50 #define PREDEFINED_TIMEOUT (10)
51 #define MAX_OWNED_DEVICE (10)
52 #define DATE_LENGTH (14)
53 #define TAG "provisioningclient"
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;
63 ownershipDone = 1 << 1,
64 finalizeDone = 1 << 2,
65 provisionAclDone = 1 << 3,
66 provisionCert1Done = 1 << 4,
67 provisionCert2Done = 1 << 5,
68 provisionCrlDone = 1 << 6
71 void deleteCrl(OicSecCrl_t *crl)
76 OICFree(crl->ThisUpdate.data);
79 OICFree(crl->CrlData.data);
87 * Calculate ACL permission from string to bit
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.
93 static int CalculateAclPermission(const char *temp_pms, uint16_t *pms)
97 if (NULL == temp_pms || NULL == pms)
102 while (temp_pms[i] != '\0')
151 * Get the ACL property from user
153 * @param[in] ACL Datastructure to save user inputs
154 * @return 0 on success otherwise -1.
156 static int InputACL(OicSecAcl_t *acl)
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));
166 printf("Failed to memory allocation\n");
169 LL_APPEND(acl->aces, ace);
171 printf("******************************************************************************\n");
172 printf("-Set ACL policy for target device\n");
173 printf("******************************************************************************\n");
176 printf("-URN identifying the subject\n");
177 printf("ex) doorDeviceUUID00 (16 Numbers except to '-')\n");
178 printf("Subject : ");
180 ret = scanf("%19ms", &ptr);
183 OICStrcpy(temp_id, sizeof(temp_id), ptr);
188 printf("Error while input\n");
192 for (int i = 0; temp_id[i] != '\0'; i++)
194 if (DASH != temp_id[i])
198 printf("Invalid input\n");
201 ace->subjectuuid.id[j++] = temp_id[i];
206 printf("Num. of Resource : \n");
208 ret = scanf("%zu", &inputLen);
209 if(-1 == ret || MAX_ACE_LENGTH < inputLen)
211 printf("Error while input\n");
214 printf("-URI of resource\n");
215 printf("ex) /a/light (Max_URI_Length: %d Byte )\n", MAX_URI_LENGTH);
217 for(size_t i = 0; i < inputLen; i++)
219 OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
222 printf("Failed to memory allocation\n");
225 LL_APPEND(ace->resources, rsrc);
227 //Input the resource URI for each resource
228 printf("[%zu]Resource : ", i + 1);
229 ret = scanf("%s", input_buffer);
232 rsrc->href = OICStrdup(input_buffer);
235 printf("Failed to OICStrdup\n");
241 printf("Error while input\n");
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)
250 printf("Error while input\n");
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)
259 printf("Failed to memory allocation\n");
262 for(size_t j = 0; j < rsrc->interfaceLen; j++)
264 printf("Interface[%zu] : ", j + 1);
265 ret = scanf("%s", input_buffer);
268 rsrc->interfaces[i] = OICStrdup(input_buffer);
269 if(!rsrc->interfaces[i])
271 printf("Failed to OICStrdup\n");
277 printf("Error while input\n");
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)
287 printf("Error while input\n");
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*));
296 printf("Failed to memory allocation\n");
299 for(size_t j = 0; j < rsrc->typeLen; j++)
301 printf("Resource type[%zu] : ", j + 1);
302 ret = scanf("%s", input_buffer);
305 rsrc->types[i] = OICStrdup(input_buffer);
308 printf("Failed to OICStrdup\n");
314 printf("Error while input\n");
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);
329 OICStrcpy(temp_pms, sizeof(temp_pms), input_buffer);
333 printf("Error while input\n");
337 while (0 != CalculateAclPermission(temp_pms, &(ace->permission)) );
344 //FILE *client_fopen(const char *path, const char *mode)
345 FILE *client_fopen(const char* UNUSED_PARAM , const char *mode)
348 return fopen(PROV_TOOL_DB_FILE, mode);
351 void PrintfResult(const char* procName, void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
353 printf("-----------------------------------------------------------\n");
356 printf("%s was successfully done.\n", procName);
360 for(int i = 0; i < nOfRes; i++)
363 for(int j = 0; j < UUID_LENGTH; j++)
365 printf("%c", arr[i].deviceId.id[j]);
368 printf("Result=%d\n", arr[i].res);
374 printf("Context is %s\n", (char*)ctx);
376 printf("-----------------------------------------------------------\n");
379 void ProvisionCertCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
384 PrintfResult("Provision Credential", ctx, nOfRes, arr, hasError);
386 else printf("Cert provisioning error\n-----------------------------------------");
389 void ProvisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
394 PrintfResult("Provision ACL", ctx, nOfRes, arr, hasError);
398 void ProvisionCrlCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
403 PrintfResult("Provision CRL", ctx, nOfRes, arr, hasError);
409 void OwnershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
414 PrintfResult("Ownership transfer", ctx, nOfRes, arr, hasError);
418 static short IsCKMInfoFileExists()
420 FILE *ckmInf = fopen(CA_STORAGE_FILE, "r");
429 static PKIError InitCA()
433 if (IsCKMInfoFileExists())
435 CHECK_CALL(InitCKMInfo);
439 ByteArray rootName = BYTE_ARRAY_INITIALIZER;
440 ByteArray CAPubKey = BYTE_ARRAY_INITIALIZER;
441 ByteArray CAPrivKey = BYTE_ARRAY_INITIALIZER;
442 ByteArray rootCert = BYTE_ARRAY_INITIALIZER;
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";
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);
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);
469 static int InputCRL(OicSecCrl_t *crlRes)
472 ByteArray crl = BYTE_ARRAY_INITIALIZER;
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);
483 ret = scanf("%u", &nuberOfRevoked);
486 printf("Error while input\n");
487 return PKI_UNKNOWN_ERROR;
490 if((uint32_t)MAX_Revoked_NUMBER < nuberOfRevoked)
492 OIC_LOG(ERROR, TAG, "Wrong revoked certificate number");
493 return PKI_UNKNOWN_ERROR;
496 for (size_t i = 0; i < nuberOfRevoked; ++i)
498 printf("Revoked certificate %d:", i);
499 printf("Serial number (E. g.: 100):");
500 ret = scanf("%u", &revokedNumbers[i]);
503 printf("Error while input\n");
504 return PKI_UNKNOWN_ERROR;
507 revocationDates[i] = (const uint8_t*)"130101000005Z";
510 crl.len = CRL_MIN_SIZE + nuberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4)/* + 1000*/;
511 crl.data = (uint8_t *)OICCalloc(1, crl.len);
513 if (NULL == crl.data)
515 OIC_LOG(ERROR, TAG, "Error while memory allocation");
516 return PKI_MEMORY_ALLOC_FAILED;
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;
528 if(NULL == crlRes->ThisUpdate.data)
530 printf("OICStrdup failed\n");
531 return PKI_MEMORY_ALLOC_FAILED;
541 * Provisioning client sample using ProvisioningAPI
545 OCStackResult res = OC_STACK_OK;
546 OCProvisionDev_t* pDeviceList = NULL;
547 OCProvisionDev_t *pOwnedList = NULL;
549 // Initialize Persistent Storage for SVR database
550 OCPersistentStorage ps = { .open = client_fopen,
556 OCRegisterPersistentStorageHandler(&ps);
558 if (OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
560 OIC_LOG(ERROR, TAG, "OCStack init error");
563 if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
565 OIC_LOG(ERROR, TAG, "OC_PM init error");
569 res = OCDiscoverUnownedDevices(PREDEFINED_TIMEOUT, &pDeviceList);
570 if(OC_STACK_OK != res)
572 OIC_LOG_V(ERROR, TAG, "Failed to PMDeviceDiscovery : %d", res);
576 OCProvisionDev_t* pCurDev = pDeviceList;
578 while(pCurDev !=NULL)
580 for(i = 0; i < UUID_LENGTH; i++)
582 printf("%c", pCurDev->doxm->deviceID.id[i]);
585 pCurDev = pCurDev->next;
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);
599 char* myContext = "OTM Context";
600 //Perform ownership transfer
601 res = OCDoOwnershipTransfer((void*)myContext, pDeviceList, OwnershipTransferCB);
602 if(OC_STACK_OK == res)
604 OIC_LOG(INFO, TAG, "Request for ownership transfer is sent successfully.");
608 OIC_LOG_V(ERROR, TAG, "Failed to OCDoOwnershipTransfer : %d", res);
612 while (gOwnershipState == 0)
614 if (OCProcess() != OC_STACK_OK)
616 OIC_LOG(ERROR, TAG, "OCStack process error");
622 // Credential & ACL provisioning between two devices.
624 OCProvisionDev_t *pOwnedDevices [MAX_OWNED_DEVICE] = {0,};
625 int nOwnedDevice = 0;
627 res = OCDiscoverOwnedDevices(PREDEFINED_TIMEOUT, &pOwnedList);
628 if (OC_STACK_OK == res)
630 printf("################## Owned Device List #######################\n");
631 while (pOwnedList != NULL)
634 printf(" %d : ", nOwnedDevice);
635 for (int i = 0; i < UUID_LENGTH; i++)
637 printf("%c", pOwnedList->doxm->deviceID.id[i]);
640 pOwnedDevices[nOwnedDevice] = pOwnedList;
641 pOwnedList = pOwnedList->next;
646 OIC_LOG(ERROR, TAG, "Error while Owned Device Discovery");
653 printf("Select 2 devices for Credential & ACL provisioning\n");
654 printf("Device 1: ");
655 ret = scanf("%d", &Device1);
658 printf("Error while input\n");
662 printf("Device 2: ");
663 ret = scanf("%d", &Device2);
666 printf("Error while input\n");
670 if( 0 > Device1 || 0 > Device2 || Device1 > nOwnedDevice || Device2 > nOwnedDevice)
672 OIC_LOG(ERROR, TAG, "Wrong devices number");
676 gAcl = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
679 OIC_LOG(ERROR, TAG, "Error while memory allocation");
683 if (PKI_SUCCESS != InitCA())
685 OIC_LOG(ERROR, TAG, "CA init error");
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);
696 while ( gOwnershipState == 0 )
698 if (OCProcess() != OC_STACK_OK)
700 OIC_LOG(ERROR, TAG, "OCStack process error");
706 res = OCProvisionCredentials(ctx, SIGNED_ASYMMETRIC_KEY, 0, pOwnedDevices[Device2],
707 NULL, ProvisionCertCB);
708 if (OC_STACK_OK != res)
710 OIC_LOG_V(ERROR, TAG, "Failed to provision Device 2 : %d", res);
714 while (gOwnershipState == 0)
716 if (OCProcess() != OC_STACK_OK)
718 OIC_LOG(ERROR, TAG, "OCStack process error");
724 printf("Input ACL for Device2\n");
725 if (0 == InputACL(gAcl))
727 printf("Success Input ACL\n");
731 OIC_LOG(ERROR, TAG, "InputACL error");
734 res = OCProvisionACL(ctx, pOwnedDevices[Device2], gAcl, &ProvisionAclCB);
735 if (OC_STACK_OK != res)
737 OIC_LOG_V(ERROR, TAG, "Failed to ACL provision Device 2 : %d", res);
741 while (gOwnershipState == 0)
743 if (OCProcess() != OC_STACK_OK)
745 OIC_LOG(ERROR, TAG, "OCStack process error");
750 gCrl = (OicSecCrl_t *)OICMalloc(sizeof(OicSecCrl_t));
754 OIC_LOG(ERROR, TAG, "Error while memory allocation");
758 if (PKI_SUCCESS != InputCRL(gCrl))
760 OIC_LOG(ERROR, TAG, "CA init error");
764 PRINT_BYTE_ARRAY("gCrl = \n", gCrl->CrlData);
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);
770 while (gOwnershipState == 0)
772 if (OCProcess() != OC_STACK_OK)
774 OIC_LOG(ERROR, TAG, "OCStack process error");
780 if (OCStop() != OC_STACK_OK)
782 OIC_LOG(ERROR, TAG, "OCStack process error");
789 OCDeleteDiscoveredDevices(pDeviceList);
790 OCDeleteDiscoveredDevices(pOwnedList);