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)
46 #define PREDEFINED_TIMEOUT (10)
47 #define MAX_OWNED_DEVICE (10)
48 #define DATE_LENGTH (14)
49 #define TAG "provisioningclient"
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;
59 ownershipDone = 1 << 1,
60 finalizeDone = 1 << 2,
61 provisionAclDone = 1 << 3,
62 provisionCert1Done = 1 << 4,
63 provisionCert2Done = 1 << 5,
64 provisionCrlDone = 1 << 6
69 * Perform cleanup for ACL
72 static void deleteACL(OicSecAcl_t *acl)
77 for (size_t i = 0; i < (acl)->resourcesLen; i++)
79 OICFree((acl)->resources[i]);
81 OICFree((acl)->resources);
83 /* Clean ACL node itself */
90 void deleteCrl(OicSecCrl_t *crl)
95 OICFree(crl->ThisUpdate.data);
98 OICFree(crl->CrlData.data);
106 * Calculate ACL permission from string to bit
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.
112 static int CalculateAclPermission(const char *temp_pms, uint16_t *pms)
116 if (NULL == temp_pms || NULL == pms)
121 while (temp_pms[i] != '\0')
170 * Get the ACL property from user
172 * @param[in] ACL Datastructure to save user inputs
173 * @return 0 on success otherwise -1.
175 static int InputACL(OicSecAcl_t *acl)
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");
185 printf("-URN identifying the subject\n");
186 printf("ex) doorDeviceUUID00 (16 Numbers except to '-')\n");
187 printf("Subject : ");
189 ret = scanf("%19ms", &ptr);
192 OICStrcpy(temp_id, sizeof(temp_id), ptr);
197 printf("Error while input\n");
201 for (int i = 0; temp_id[i] != '\0'; i++)
203 if (DASH != temp_id[i])
207 printf("Invalid input\n");
210 acl->subject.id[j++] = temp_id[i];
215 printf("Num. of Resource : \n");
216 ret = scanf("%zu", &acl->resourcesLen);
219 printf("Error while input\n");
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)
227 OIC_LOG(ERROR, TAG, "Error while memory allocation");
230 for (size_t i = 0; i < acl->resourcesLen; i++)
232 printf("[%zu]Resource : ", i + 1);
233 char *ptr_tempRsc = NULL;
234 ret = scanf("%64ms", &ptr_tempRsc);
237 OICStrcpy(temp_rsc, sizeof(temp_rsc), ptr_tempRsc);
238 OICFree(ptr_tempRsc);
242 printf("Error while input\n");
245 acl->resources[i] = OICStrdup(temp_rsc);
247 if (NULL == acl->resources[i])
249 OIC_LOG(ERROR, TAG, "Error while memory allocation");
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);
263 OICStrcpy(temp_pms, sizeof(temp_pms), ptr_temp_pms);
264 OICFree(ptr_temp_pms);
269 printf("Error while input\n");
273 while (0 != CalculateAclPermission(temp_pms, &(acl->permission)) );
275 printf("-URN identifying the rowner\n");
276 printf("ex) lightDeviceUUID0 (16 Numbers except to '-')\n");
279 char *ptr_temp_id = NULL;
280 ret = scanf("%19ms", &ptr_temp_id);
283 OICStrcpy(temp_id, sizeof(temp_id), ptr_temp_id);
284 OICFree(ptr_temp_id);
288 printf("Error while input\n");
292 for (int k = 0; temp_id[k] != '\0'; k++)
294 if (DASH != temp_id[k])
296 acl->rownerID.id[j++] = temp_id[k];
303 //FILE *client_fopen(const char *path, const char *mode)
304 FILE *client_fopen(const char* UNUSED_PARAM , const char *mode)
307 return fopen(PROV_TOOL_DB_FILE, mode);
310 void PrintfResult(const char* procName, void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
312 printf("-----------------------------------------------------------\n");
315 printf("%s was successfully done.\n", procName);
319 for(int i = 0; i < nOfRes; i++)
322 for(int j = 0; j < UUID_LENGTH; j++)
324 printf("%c", arr[i].deviceId.id[j]);
327 printf("Result=%d\n", arr[i].res);
333 printf("Context is %s\n", (char*)ctx);
335 printf("-----------------------------------------------------------\n");
338 void ProvisionCertCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
343 PrintfResult("Provision Credential", ctx, nOfRes, arr, hasError);
345 else printf("Cert provisioning error\n-----------------------------------------");
348 void ProvisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
353 PrintfResult("Provision ACL", ctx, nOfRes, arr, hasError);
357 void ProvisionCrlCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
362 PrintfResult("Provision CRL", ctx, nOfRes, arr, hasError);
368 void OwnershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
373 PrintfResult("Ownership transfer", ctx, nOfRes, arr, hasError);
377 static short IsCKMInfoFileExists()
379 FILE *ckmInf = fopen(CA_STORAGE_FILE, "r");
388 static PKIError InitCA()
392 if (IsCKMInfoFileExists())
394 CHECK_CALL(InitCKMInfo);
398 ByteArray rootName = BYTE_ARRAY_INITIALIZER;
399 ByteArray CAPubKey = BYTE_ARRAY_INITIALIZER;
400 ByteArray CAPrivKey = BYTE_ARRAY_INITIALIZER;
401 ByteArray rootCert = BYTE_ARRAY_INITIALIZER;
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";
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);
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);
428 static int InputCRL(OicSecCrl_t *crlRes)
431 ByteArray crl = BYTE_ARRAY_INITIALIZER;
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);
442 ret = scanf("%u", &nuberOfRevoked);
445 printf("Error while input\n");
446 return PKI_UNKNOWN_ERROR;
449 if((uint32_t)MAX_Revoked_NUMBER < nuberOfRevoked)
451 OIC_LOG(ERROR, TAG, "Wrong revoked certificate number");
452 return PKI_UNKNOWN_ERROR;
455 for (size_t i = 0; i < nuberOfRevoked; ++i)
457 printf("Revoked certificate %d:", i);
458 printf("Serial number (E. g.: 100):");
459 ret = scanf("%u", &revokedNumbers[i]);
462 printf("Error while input\n");
463 return PKI_UNKNOWN_ERROR;
466 revocationDates[i] = (const uint8_t*)"130101000005Z";
469 crl.len = CRL_MIN_SIZE + nuberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4)/* + 1000*/;
470 crl.data = (uint8_t *)OICCalloc(1, crl.len);
472 if (NULL == crl.data)
474 OIC_LOG(ERROR, TAG, "Error while memory allocation");
475 return PKI_MEMORY_ALLOC_FAILED;
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;
495 * Provisioning client sample using ProvisioningAPI
499 OCStackResult res = OC_STACK_OK;
500 OCProvisionDev_t* pDeviceList = NULL;
501 OCProvisionDev_t *pOwnedList = NULL;
503 // Initialize Persistent Storage for SVR database
504 OCPersistentStorage ps = { .open = client_fopen,
510 OCRegisterPersistentStorageHandler(&ps);
512 if (OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
514 OIC_LOG(ERROR, TAG, "OCStack init error");
517 if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
519 OIC_LOG(ERROR, TAG, "OC_PM init error");
523 res = OCDiscoverUnownedDevices(PREDEFINED_TIMEOUT, &pDeviceList);
524 if(OC_STACK_OK != res)
526 OIC_LOG_V(ERROR, TAG, "Failed to PMDeviceDiscovery : %d", res);
530 OCProvisionDev_t* pCurDev = pDeviceList;
532 while(pCurDev !=NULL)
534 for(i = 0; i < UUID_LENGTH; i++)
536 printf("%c", pCurDev->doxm->deviceID.id[i]);
539 pCurDev = pCurDev->next;
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);
553 char* myContext = "OTM Context";
554 //Perform ownership transfer
555 res = OCDoOwnershipTransfer((void*)myContext, pDeviceList, OwnershipTransferCB);
556 if(OC_STACK_OK == res)
558 OIC_LOG(INFO, TAG, "Request for ownership transfer is sent successfully.");
562 OIC_LOG_V(ERROR, TAG, "Failed to OCDoOwnershipTransfer : %d", res);
566 while (gOwnershipState == 0)
568 if (OCProcess() != OC_STACK_OK)
570 OIC_LOG(ERROR, TAG, "OCStack process error");
576 // Credential & ACL provisioning between two devices.
578 OCProvisionDev_t *pOwnedDevices [MAX_OWNED_DEVICE] = {0,};
579 int nOwnedDevice = 0;
581 res = OCDiscoverOwnedDevices(PREDEFINED_TIMEOUT, &pOwnedList);
582 if (OC_STACK_OK == res)
584 printf("################## Owned Device List #######################\n");
585 while (pOwnedList != NULL)
588 printf(" %d : ", nOwnedDevice);
589 for (int i = 0; i < UUID_LENGTH; i++)
591 printf("%c", pOwnedList->doxm->deviceID.id[i]);
594 pOwnedDevices[nOwnedDevice] = pOwnedList;
595 pOwnedList = pOwnedList->next;
600 OIC_LOG(ERROR, TAG, "Error while Owned Device Discovery");
607 printf("Select 2 devices for Credential & ACL provisioning\n");
608 printf("Device 1: ");
609 ret = scanf("%d", &Device1);
612 printf("Error while input\n");
616 printf("Device 2: ");
617 ret = scanf("%d", &Device2);
620 printf("Error while input\n");
624 if( 0 > Device1 || 0 > Device2 || Device1 > nOwnedDevice || Device2 > nOwnedDevice)
626 OIC_LOG(ERROR, TAG, "Wrong devices number");
630 gAcl = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
633 OIC_LOG(ERROR, TAG, "Error while memory allocation");
637 if (PKI_SUCCESS != InitCA())
639 OIC_LOG(ERROR, TAG, "CA init error");
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);
650 while ( gOwnershipState == 0 )
652 if (OCProcess() != OC_STACK_OK)
654 OIC_LOG(ERROR, TAG, "OCStack process error");
660 res = OCProvisionCredentials(ctx, SIGNED_ASYMMETRIC_KEY, 0, pOwnedDevices[Device2],
661 NULL, ProvisionCertCB);
662 if (OC_STACK_OK != res)
664 OIC_LOG_V(ERROR, TAG, "Failed to provision Device 2 : %d", res);
668 while (gOwnershipState == 0)
670 if (OCProcess() != OC_STACK_OK)
672 OIC_LOG(ERROR, TAG, "OCStack process error");
678 printf("Input ACL for Device2\n");
679 if (0 == InputACL(gAcl))
681 printf("Success Input ACL\n");
685 OIC_LOG(ERROR, TAG, "InputACL error");
688 res = OCProvisionACL(ctx, pOwnedDevices[Device2], gAcl, &ProvisionAclCB);
689 if (OC_STACK_OK != res)
691 OIC_LOG_V(ERROR, TAG, "Failed to ACL provision Device 2 : %d", res);
695 while (gOwnershipState == 0)
697 if (OCProcess() != OC_STACK_OK)
699 OIC_LOG(ERROR, TAG, "OCStack process error");
704 gCrl = (OicSecCrl_t *)OICMalloc(sizeof(OicSecCrl_t));
708 OIC_LOG(ERROR, TAG, "Error while memory allocation");
712 if (PKI_SUCCESS != InputCRL(gCrl))
714 OIC_LOG(ERROR, TAG, "CA init error");
718 PRINT_BYTE_ARRAY("gCrl = \n", gCrl->CrlData);
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);
724 while (gOwnershipState == 0)
726 if (OCProcess() != OC_STACK_OK)
728 OIC_LOG(ERROR, TAG, "OCStack process error");
734 if (OCStop() != OC_STACK_OK)
736 OIC_LOG(ERROR, TAG, "OCStack process error");
742 OCDeleteDiscoveredDevices(pDeviceList);
743 OCDeleteDiscoveredDevices(pOwnedList);