--- /dev/null
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include <iostream>
+#include <sstream>
+#include "ocstack.h"
+#include "logger.h"
+#include "cJSON.h"
+#include "global.h"
+#include "cainterface.h"
+#include "cacommon.h"
+#include "ocstackinternal.h"
+#include "payload_logging.h"
+#include "ocpayload.h"
+
+
+#define TAG "DEMO"
+#define DEFAULT_CONTEXT_VALUE 0x99
+#define STATE "state"
+#define OPEN_DURATION "openDuration"
+#define OPEN_ALARM "openAlarm"
+
+static const char MULTICAST_DISCOVERY_QUERY[] = "/oic/res";
+
+volatile sig_atomic_t gQuitFlag = 0;
+OCPersistentStorage ps = {0, 0, 0, 0, 0};
+static const char *gResourceUri = "/a/door";
+uint8_t lightIpAddr[4] = {};
+uint16_t lightPortNu;
+static bool isUpdated = false;
+static std::string coapServerIP;
+static std::string coapServerPort;
+static std::string coapServerResource;
+static OCConnectivityType ocConnType;
+
+static std::string address;
+
+static int coapSecureResource;
+
+static const char CRED_FILE[] = "oic_svr_db_door.json";
+
+CAEndpoint_t endpoint = {CA_DEFAULT_ADAPTER, CA_DEFAULT_FLAGS, 0, {0}, 0};
+
+// myDoorState_t variable to store resource's state .
+typedef enum
+{
+ STATE_OPEN, /**< State is opened */
+ STATE_CLOSED /**< State is closed*/
+} myDoorState_t;
+
+//Structure to represent a door resource and its attributes
+typedef struct DOORRESOURCE
+{
+ OCResourceHandle handle;
+ myDoorState_t state; //ReadOnly, The state of the door (open or closed)"
+ char *openDuration; //ReadOnly, The time duration the door has been open
+ bool openAlarm ; //The state of the door open alarm
+
+} DoorResource;
+
+static DoorResource Door;
+
+int parseClientResponse(OCClientResponse * clientResponse)
+{
+ if(!clientResponse)
+ {
+ return 0;
+ }
+
+ OCResourcePayload* res = ((OCDiscoveryPayload*)clientResponse->payload)->resources;
+
+ // Initialize all global variables
+ coapServerResource.clear();
+ coapSecureResource = 0;
+
+ while (res)
+ {
+ coapServerResource.assign(res->uri);
+ OC_LOG_V(INFO, TAG, "Uri -- %s", coapServerResource.c_str());
+
+ if (res->secure)
+ {
+ endpoint.port = res->port;
+ coapSecureResource = 1;
+ }
+
+ OC_LOG_V(INFO, TAG, "Secure -- %s", coapSecureResource == 1 ? "YES" : "NO");
+
+ // If we discovered a secure resource, exit from here
+ if (coapSecureResource)
+ {
+ break;
+ }
+
+ res = res->next;
+ }
+
+ return 0;
+}
+
+OCRepPayload* getPayload(const char* uri, int64_t state, char* openDuration, bool openAlarm)
+{
+ OCRepPayload* payload = OCRepPayloadCreate();
+ if (!payload)
+ {
+ OC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
+ return nullptr;
+ }
+
+ OCRepPayloadSetUri(payload, uri);
+ OCRepPayloadSetPropInt(payload, STATE, state);
+ OCRepPayloadSetPropString(payload, OPEN_DURATION, openDuration);
+ OCRepPayloadSetPropBool(payload, OPEN_ALARM, openAlarm);
+
+ return payload;
+}
+
+//This function takes the request as an input and returns the response
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
+{
+ if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
+ {
+ OC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
+ return nullptr;
+ }
+
+ DoorResource *currdoorResource = &Door;
+
+ return getPayload(gResourceUri, currdoorResource->state, currdoorResource->openDuration, currdoorResource->openAlarm);
+}
+
+OCEntityHandlerResult ProcessGetRequest(OCEntityHandlerRequest *ehRequest,
+ OCRepPayload **payload)
+{
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
+ OCRepPayload *getResp = constructResponse(ehRequest);
+
+ if(getResp)
+ {
+ *payload = getResp;
+ ehResult = OC_EH_OK;
+ }
+
+ return ehResult;
+}
+
+OCEntityHandlerResult OCEntityHandlerCb(OCEntityHandlerFlag flag,
+ OCEntityHandlerRequest *entityHandlerRequest,
+ void* /*callbackParam*/)
+{
+ OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+
+ OCEntityHandlerResult ehResult = OC_EH_ERROR;
+ OCEntityHandlerResponse response;
+
+ // Validate pointer
+ if (!entityHandlerRequest)
+ {
+ OC_LOG (ERROR, TAG, "Invalid request pointer");
+ return OC_EH_ERROR;
+ }
+
+ OCRepPayload* payload = nullptr;
+
+ if (flag & OC_REQUEST_FLAG)
+ {
+ OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
+
+ if (entityHandlerRequest)
+ {
+ switch(entityHandlerRequest->method)
+ {
+ case OC_REST_GET:
+ {
+ OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+ ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
+ }
+ break;
+ default:
+ {
+ OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+ entityHandlerRequest->method);
+ ehResult = OC_EH_ERROR;
+ }
+ break;
+ }
+
+ if (ehResult == OC_EH_OK && ehResult != OC_EH_FORBIDDEN)
+ {
+ // Format the response. Note this requires some info about the request
+ response.requestHandle = entityHandlerRequest->requestHandle;
+ response.resourceHandle = entityHandlerRequest->resource;
+ response.ehResult = ehResult;
+ response.payload = reinterpret_cast<OCPayload*>(payload);
+ response.numSendVendorSpecificHeaderOptions = 0;
+ memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
+ memset(response.resourceUri, 0, sizeof(response.resourceUri));
+ // Indicate that response is NOT in a persistent buffer
+ response.persistentBufferFlag = 0;
+
+ // Send the response
+ if (OCDoResponse(&response) != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "Error sending response");
+ ehResult = OC_EH_ERROR;
+ }
+ }
+ }
+ }
+
+ OCPayloadDestroy(response.payload);
+ return ehResult;
+}
+
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+ if (signum == SIGINT)
+ {
+ gQuitFlag = 1;
+ }
+}
+
+FILE *server_fopen(const char * /*path*/, const char *mode)
+{
+ return fopen(CRED_FILE, mode);
+}
+
+void SetPersistentHandler(OCPersistentStorage *ps)
+{
+ if (ps)
+ {
+ ps->open = server_fopen;
+ ps->read = fread;
+ ps->write = fwrite;
+ ps->close = fclose;
+ ps->unlink = unlink;
+
+ OCRegisterPersistentStorageHandler(ps);
+ }
+}
+
+/**
+ * GetResult is returned result to string.
+ * @param result [IN] stack result
+ * @return converted OCStackResult as string for debugging
+ */
+static const char *getResult(OCStackResult result)
+{
+ switch (result)
+ {
+ case OC_STACK_OK:
+ return "OC_STACK_OK";
+ case OC_STACK_RESOURCE_CREATED:
+ return "OC_STACK_RESOURCE_CREATED";
+ case OC_STACK_RESOURCE_DELETED:
+ return "OC_STACK_RESOURCE_DELETED";
+ case OC_STACK_INVALID_URI:
+ return "OC_STACK_INVALID_URI";
+ case OC_STACK_INVALID_QUERY:
+ return "OC_STACK_INVALID_QUERY";
+ case OC_STACK_INVALID_IP:
+ return "OC_STACK_INVALID_IP";
+ case OC_STACK_INVALID_PORT:
+ return "OC_STACK_INVALID_PORT";
+ case OC_STACK_INVALID_CALLBACK:
+ return "OC_STACK_INVALID_CALLBACK";
+ case OC_STACK_INVALID_METHOD:
+ return "OC_STACK_INVALID_METHOD";
+ case OC_STACK_NO_MEMORY:
+ return "OC_STACK_NO_MEMORY";
+ case OC_STACK_COMM_ERROR:
+ return "OC_STACK_COMM_ERROR";
+ case OC_STACK_INVALID_PARAM:
+ return "OC_STACK_INVALID_PARAM";
+ case OC_STACK_NOTIMPL:
+ return "OC_STACK_NOTIMPL";
+ case OC_STACK_NO_RESOURCE:
+ return "OC_STACK_NO_RESOURCE";
+ case OC_STACK_RESOURCE_ERROR:
+ return "OC_STACK_RESOURCE_ERROR";
+ case OC_STACK_SLOW_RESOURCE:
+ return "OC_STACK_SLOW_RESOURCE";
+ case OC_STACK_NO_OBSERVERS:
+ return "OC_STACK_NO_OBSERVERS";
+ case OC_STACK_UNAUTHORIZED_REQ:
+ return "OC_STACK_UNAUTHORIZED_REQ";
+ #ifdef WITH_PRESENCE
+ case OC_STACK_PRESENCE_STOPPED:
+ return "OC_STACK_PRESENCE_STOPPED";
+ #endif
+ case OC_STACK_ERROR:
+ return "OC_STACK_ERROR";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+
+/**
+ * CreateDoorResource creates a new door resource by calling the OCCreateResource() method.
+ * @param uri [IN] uri
+ * @param doorResource [IN] info of resource
+ * @return ::OC_STACK_OK on success, some other value upon failure.
+ */
+int createDoorResource (const char *uri, DoorResource *doorResource)
+{
+ if (!uri)
+ {
+ OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
+
+ }
+
+ doorResource->state = STATE_CLOSED; //1:closed , 0: open
+ char str[] = "10min";
+ doorResource->openDuration = str;
+ doorResource->openAlarm = false;
+ OCStackResult res = OCCreateResource(&(doorResource->handle),
+ "core.door",
+ OC_RSRVD_INTERFACE_DEFAULT,
+ uri,
+ OCEntityHandlerCb,
+ NULL,
+ OC_DISCOVERABLE | OC_OBSERVABLE | OC_SECURE);
+
+ OC_LOG_V(INFO, TAG, "Created Door resource with result: %s", getResult(res));
+ return 0;
+}
+
+OCStackApplicationResult putReqCB(void * ctx, OCDoHandle /*handle*/, OCClientResponse *clientResponse)
+{
+ if (ctx == (void *)DEFAULT_CONTEXT_VALUE)
+ {
+ OC_LOG(INFO, TAG, "Callback Context for PUT recvd successfully");
+ }
+
+ if (clientResponse)
+ {
+ OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+ OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+ OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ if ((OCSecurityPayload*)clientResponse->payload)
+ {
+ OC_LOG_V(INFO, TAG, "=============> Put Response",
+ ((OCSecurityPayload*)clientResponse->payload)->securityData);
+ }
+ }
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackApplicationResult getReqCB(void * /*ctx*/, OCDoHandle /*handle*/, OCClientResponse *clientResponse)
+{
+ OC_LOG(INFO, TAG, "Callback Context for GET query recvd successfully");
+
+ if (clientResponse)
+ {
+ OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+ OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
+ OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ if ((OCSecurityPayload*)clientResponse->payload)
+ {
+ OC_LOG(INFO, TAG, PCF("=============> Get Response"));
+ }
+ }
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+// This is a function called back when a device is discovered
+OCStackApplicationResult discoveryReqCB(void* /*ctx*/, OCDoHandle /*handle*/,
+ OCClientResponse * clientResponse)
+{
+ OC_LOG(INFO, TAG, "Callback Context for DISCOVER query recvd successfully");
+
+ if (clientResponse)
+ {
+ OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+ OC_LOG_V(INFO, TAG,
+ "Device =============> Discovered @ %s:%d",
+ clientResponse->devAddr.addr,
+ clientResponse->devAddr.port);
+
+ if (clientResponse->result == OC_STACK_OK)
+ {
+ OC_LOG_PAYLOAD(INFO, TAG, clientResponse->payload);
+ ocConnType = clientResponse->connType;
+ parseClientResponse(clientResponse);
+ }
+ }
+
+ return OC_STACK_KEEP_TRANSACTION;
+
+}
+
+
+
+void initAddress()
+{
+ static bool initFlag = false;
+ if (!initFlag)
+ {
+ OC_LOG(INFO, TAG, "Enter IP address (with optional port) of the Server hosting resource\n");
+ OC_LOG(INFO, TAG, "IPv4: 192.168.0.15:45454\n");
+ OC_LOG(INFO, TAG, "IPv6: [fe80::20c:29ff:fe1b:9c5]:45454\n");
+
+ std::cin >> address;
+ }
+ initFlag = true;
+}
+
+// Local function to send get request of light resource
+void SendGetRequest()
+{
+ OCStackResult ret;
+ OC_LOG(INFO, TAG, "Send Get REQ to Light server");
+
+ initAddress();
+
+ char szQueryUri[64] = { '\0'};
+ OCDoHandle handle;
+ OCCallbackData cbData;
+ cbData.cb = getReqCB;
+ cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
+ cbData.cd = NULL;
+ OC_LOG_V(INFO, TAG, "Get payload from Door sample = /a/light ");
+ snprintf(szQueryUri, sizeof(szQueryUri), "coaps://%s/a/light", const_cast<char*> (address.c_str())); // lightPortNu);
+ ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, NULL, ocConnType, OC_LOW_QOS,
+ &cbData, NULL, 0);
+ if (ret != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack resource error");
+ }
+}
+
+
+void *input_function(void * /*data*/)
+{
+ char input;
+ char szQueryUri[64] = { 0 };
+ OCDoHandle handle;
+ OCCallbackData cbData;
+ cbData.cb = discoveryReqCB;
+ cbData.context = (void *)DEFAULT_CONTEXT_VALUE;
+ cbData.cd = NULL;
+
+ strcpy(szQueryUri, MULTICAST_DISCOVERY_QUERY);
+
+ while (1)
+ {
+ std::cin >> input;
+ switch (input)
+ {
+ case 'D':
+ case 'd':
+ if (isUpdated == false)
+ {
+ OC_LOG(INFO, TAG, "isUpdated is false...");
+ OCDoResource(&handle, OC_REST_DISCOVER, szQueryUri, 0, 0, CT_DEFAULT, OC_LOW_QOS, &cbData, NULL, 0);
+
+ }
+ break;
+ case 'G':
+ case 'g':
+ isUpdated = true;
+ if (isUpdated == true)
+ {
+ OC_LOG(INFO, TAG, "isUpdated is true...");
+ SendGetRequest();
+ }
+ break;
+ case 'Q':
+ case 'q':
+ gQuitFlag = 1;
+ return 0;
+ default: break;
+ }
+ }
+ return 0;
+}
+
+static void PrintUsage()
+{
+ OC_LOG(INFO, TAG, "*******************************************");
+ OC_LOG(INFO, TAG, "Input D or d to discover Resources");
+ OC_LOG(INFO, TAG, "Input G or g to initiate Get Request");
+ OC_LOG(INFO, TAG, "Input Q or q to exit");
+ OC_LOG(INFO, TAG, "*******************************************");
+}
+
+int main()
+{
+
+ OC_LOG(INFO, TAG, "OCServer is starting...");
+ SetPersistentHandler(&ps);
+ //PrintUsage();
+ if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack init error");
+ return 0;
+ }
+
+ /*
+ * Declare and create the example resource: Door
+ */
+ createDoorResource(gResourceUri, &Door);
+ PrintUsage();
+
+ //select ciphersuite for certificates
+ CASelectCipherSuite(TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
+
+ struct timespec timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 100000000L;
+
+ // Break from loop with Ctrl-C
+ OC_LOG(INFO, TAG, "Entering ocserver main loop...");
+ signal(SIGINT, handleSigInt);
+ int thr_id;
+ pthread_t p_thread;
+ thr_id = pthread_create(&p_thread, NULL, input_function, (void *)NULL);
+ if (thr_id < 0)
+ {
+ OC_LOG(ERROR, TAG, "create thread error");
+ return 0;
+ }
+
+ while (!gQuitFlag)
+ {
+
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ return 0;
+ }
+
+
+ nanosleep(&timeout, NULL);
+ }
+
+ pthread_join(p_thread, NULL);
+
+ OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
+
+ if (OCStop() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ }
+
+ return 0;
+}
--- /dev/null
+/******************************************************************
+*
+* Copyright 2015 Samsung Electronics All Rights Reserved.
+*
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+******************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "logger.h"
+#include "oic_malloc.h"
+#include "utlist.h"
+#include "ocprovisioningmanager.h"
+#include "secureresourceprovider.h"
+#include "oxmjustworks.h"
+#include "oic_string.h"
+#include "securevirtualresourcetypes.h"
+#include "cacommon.h"
+#include "ck_manager.h"
+#include "ckm_info.h"
+#include "crlresource.h"
+
+#define MAX_URI_LENGTH (64)
+#define MAX_PERMISSION_LENGTH (5)
+#define CREATE (1)
+#define READ (2)
+#define UPDATE (4)
+#define DELETE (8)
+#define NOTIFY (16)
+#define DASH '-'
+#define PREDEFINED_TIMEOUT (10)
+#define MAX_OWNED_DEVICE (10)
+#define DATE_LENGTH (14)
+#define TAG "provisioningclient"
+
+static OicSecAcl_t *gAcl = NULL;
+static OicSecCrl_t *gCrl = NULL;
+static char PROV_TOOL_DB_FILE[] = "oic_svr_db_pt.json";
+static int gOwnershipState = 0;
+
+typedef enum
+{
+ ownershipDone = 1 << 1,
+ finalizeDone = 1 << 2,
+ provisionAclDone = 1 << 3,
+ provisionCert1Done = 1 << 4,
+ provisionCert2Done = 1 << 5,
+ provisionCrlDone = 1 << 6
+} StateManager;
+
+
+/**
+ * Perform cleanup for ACL
+ * @param[in] ACL
+ */
+static void deleteACL(OicSecAcl_t *acl)
+{
+ if (acl)
+ {
+ /* Clean Resources */
+ for (size_t i = 0; i < (acl)->resourcesLen; i++)
+ {
+ OICFree((acl)->resources[i]);
+ }
+ OICFree((acl)->resources);
+
+ /* Clean Owners */
+ OICFree((acl)->owners);
+
+ /* Clean ACL node itself */
+ OICFree((acl));
+
+ acl = NULL;
+ }
+}
+
+void deleteCrl(OicSecCrl_t *crl)
+{
+ if (crl)
+ {
+ //Clean ThisUpdate
+ OICFree(crl->ThisUpdate.data);
+
+ //clean CrlData
+ OICFree(crl->CrlData.data);
+
+ //Clean crl itself
+ OICFree(crl);
+ }
+}
+
+/**
+ * Calculate ACL permission from string to bit
+ *
+ * @param[in] temp_psm Input data of ACL permission string
+ * @param[in,out] pms The pointer of ACL permission value
+ * @return 0 on success otherwise -1.
+ */
+static int CalculateAclPermission(const char *temp_pms, uint16_t *pms)
+{
+ int i = 0;
+
+ if (NULL == temp_pms || NULL == pms)
+ {
+ return -1;
+ }
+ *pms = 0;
+ while (temp_pms[i] != '\0')
+ {
+ switch (temp_pms[i])
+ {
+ case 'C':
+ {
+ *pms += CREATE;
+ i++;
+ break;
+ }
+ case 'R':
+ {
+ *pms += READ;
+ i++;
+ break;
+ }
+ case 'U':
+ {
+ *pms += UPDATE;
+ i++;
+ break;
+ }
+ case 'D':
+ {
+ *pms += DELETE;
+ i++;
+ break;
+ }
+ case 'N':
+ {
+ *pms += NOTIFY;
+ i++;
+ break;
+ }
+ case '_':
+ {
+ i++;
+ break;
+ }
+ default:
+ {
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Get the ACL property from user
+ *
+ * @param[in] ACL Datastructure to save user inputs
+ * @return 0 on success otherwise -1.
+ */
+static int InputACL(OicSecAcl_t *acl)
+{
+ int ret;
+ char temp_id [UUID_LENGTH + 4] = {0,};
+ char temp_rsc[MAX_URI_LENGTH + 1] = {0,};
+ char temp_pms[MAX_PERMISSION_LENGTH + 1] = {0,};
+ printf("******************************************************************************\n");
+ printf("-Set ACL policy for target device\n");
+ printf("******************************************************************************\n");
+ //Set Subject.
+ printf("-URN identifying the subject\n");
+ printf("ex) doorDeviceUUID00 (16 Numbers except to '-')\n");
+ printf("Subject : ");
+ char *ptr = NULL;
+ ret = scanf("%19ms", &ptr);
+ if(1==ret)
+ {
+ OICStrcpy(temp_id, sizeof(temp_id), ptr);
+ OICFree(ptr);
+ }
+ else
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+ int j = 0;
+ for (int i = 0; temp_id[i] != '\0'; i++)
+ {
+ if (DASH != temp_id[i])
+ {
+ if(j>UUID_LENGTH)
+ {
+ printf("Invalid input\n");
+ return -1;
+ }
+ acl->subject.id[j++] = temp_id[i];
+ }
+ }
+
+ //Set Resource.
+ printf("Num. of Resource : \n");
+ ret = scanf("%zu", &acl->resourcesLen);
+ printf("-URI of resource\n");
+ printf("ex) /a/light (Max_URI_Length: 64 Byte )\n");
+ acl->resources = (char **)OICCalloc(acl->resourcesLen, sizeof(char *));
+ if (NULL == acl->resources)
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ return -1;
+ }
+ for (size_t i = 0; i < acl->resourcesLen; i++)
+ {
+ printf("[%zu]Resource : ", i + 1);
+ char *ptr_tempRsc = NULL;
+ ret = scanf("%64ms", &ptr_tempRsc);
+ if (1==ret)
+ {
+ OICStrcpy(temp_rsc, sizeof(temp_rsc), ptr_tempRsc);
+ OICFree(ptr_tempRsc);
+ }
+ else
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+ acl->resources[i] = OICStrdup(temp_rsc);
+
+ if (NULL == acl->resources[i])
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ return -1;
+ }
+ }
+ // Set Permission
+ do
+ {
+ printf("-Set the permission(C,R,U,D,N)\n");
+ printf("ex) CRUDN, CRU_N,..(5 Charaters)\n");
+ printf("Permission : ");
+ char *ptr_temp_pms = NULL;
+ ret = scanf("%5ms", &ptr_temp_pms);
+ if(1 == ret)
+ {
+ OICStrcpy(temp_pms, sizeof(temp_pms), ptr_temp_pms);
+ OICFree(ptr_temp_pms);
+
+ }
+ else
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+ }
+ while (0 != CalculateAclPermission(temp_pms, &(acl->permission)) );
+ // Set Rowner
+ printf("Num. of Rowner : ");
+ ret = scanf("%zu", &acl->ownersLen);
+ printf("-URN identifying the rowner\n");
+ printf("ex) lightDeviceUUID0 (16 Numbers except to '-')\n");
+ acl->owners = (OicUuid_t *)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
+ if (NULL == acl->owners)
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ return -1;
+ }
+ for (size_t i = 0; i < acl->ownersLen; i++)
+ {
+ printf("[%zu]Rowner : ", i + 1);
+ char *ptr_temp_id = NULL;
+ ret = scanf("%19ms", &ptr_temp_id);
+ if (1 == ret)
+ {
+ OICStrcpy(temp_id, sizeof(temp_id), ptr_temp_id);
+ OICFree(ptr_temp_id);
+ }
+ else
+ {
+ printf("Error while input\n");
+ return -1;
+ }
+ j = 0;
+ for (int k = 0; temp_id[k] != '\0'; k++)
+ {
+ if (DASH != temp_id[k])
+ {
+ acl->owners[i].id[j++] = temp_id[k];
+ }
+ }
+ }
+ return 0;
+}
+
+
+//FILE *client_fopen(const char *path, const char *mode)
+FILE *client_fopen(const char* UNUSED_PARAM , const char *mode)
+{
+ (void)UNUSED_PARAM;
+ return fopen(PROV_TOOL_DB_FILE, mode);
+}
+
+void PrintfResult(const char* procName, void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+ printf("-----------------------------------------------------------\n");
+ if(!hasError)
+ {
+ printf("%s was successfully done.\n", procName);
+ }
+ else
+ {
+ for(int i = 0; i < nOfRes; i++)
+ {
+ printf("UUID : ");
+ for(int j = 0; j < UUID_LENGTH; j++)
+ {
+ printf("%c", arr[i].deviceId.id[j]);
+ }
+ printf("\t");
+ printf("Result=%d\n", arr[i].res);
+ }
+ }
+
+ if(ctx)
+ {
+ printf("Context is %s\n", (char*)ctx);
+ }
+ printf("-----------------------------------------------------------\n");
+}
+
+void ProvisionCertCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+ if(!hasError)
+ {
+ gOwnershipState = 1;
+ PrintfResult("Provision Credential", ctx, nOfRes, arr, hasError);
+ }
+ else printf("Cert provisioning error\n-----------------------------------------");
+}
+
+void ProvisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+ if(!hasError)
+ {
+ gOwnershipState = 1;
+ PrintfResult("Provision ACL", ctx, nOfRes, arr, hasError);
+ }
+}
+
+void ProvisionCrlCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+ if(!hasError)
+ {
+ gOwnershipState = 1;
+ PrintfResult("Provision CRL", ctx, nOfRes, arr, hasError);
+ }
+}
+
+
+
+void OwnershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+ if(!hasError)
+ {
+ gOwnershipState = 1;
+ PrintfResult("Ownership transfer", ctx, nOfRes, arr, hasError);
+ }
+}
+
+static short IsCKMInfoFileExists()
+{
+ FILE *ckmInf = fopen(CA_STORAGE_FILE, "r");
+ if (NULL != ckmInf)
+ {
+ fclose(ckmInf);
+ return 1;
+ }
+ return 0;
+}
+
+static PKIError InitCA()
+{
+ FUNCTION_INIT();
+
+ if (IsCKMInfoFileExists())
+ {
+ CHECK_CALL(InitCKMInfo);
+ }
+ else
+ {
+ ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+ ByteArray CAPubKey = BYTE_ARRAY_INITIALIZER;
+ ByteArray CAPrivKey = BYTE_ARRAY_INITIALIZER;
+ ByteArray rootCert = BYTE_ARRAY_INITIALIZER;
+
+
+ uint8_t rootCertData[ISSUER_MAX_CERT_SIZE];
+ uint8_t CAPubKeyData[PUBLIC_KEY_SIZE];
+ uint8_t CAPrivKeyData[PRIVATE_KEY_SIZE];
+ const char rootNameStr[] = "Sample_Root";
+
+ CAPubKey.data = CAPubKeyData;
+ CAPubKey.len = PUBLIC_KEY_SIZE;
+ CAPrivKey.data = CAPrivKeyData;
+ CAPrivKey.len = PRIVATE_KEY_SIZE;
+ rootCert.data = rootCertData;
+ rootCert.len = ISSUER_MAX_CERT_SIZE;
+ rootName.data = (uint8_t *)rootNameStr;
+ rootName.len = strlen(rootNameStr);
+
+ CHECK_CALL(SetRootName, rootName);
+ CHECK_CALL(GenerateCAKeyPair, &CAPrivKey, &CAPubKey);
+ CHECK_CALL(SetSerialNumber, 1);
+ CHECK_CALL(CKMIssueRootCertificate, NULL, NULL, &rootCert);
+ CHECK_CALL(SetCACertificate, &rootCert);
+ }
+
+ FUNCTION_CLEAR();
+}
+
+static int InputCRL(OicSecCrl_t *crlRes)
+{
+ FUNCTION_INIT(
+ ByteArray crl = BYTE_ARRAY_INITIALIZER;
+ );
+
+ const int MAX_Revoked_NUMBER = 9;
+ uint8_t uint8ThisUpdateTime[DATE_LENGTH] = "130101000005Z";
+ uint32_t revokedNumbers[MAX_Revoked_NUMBER];
+ const uint8_t* revocationDates[MAX_Revoked_NUMBER];
+ // const uint8_t revocationDatesContent[MAX_Revoked_NUMBER][DATE_LENGTH];
+ uint32_t nuberOfRevoked = 0;
+ printf("Enter number of Revoked certificates(1..%d)\n", MAX_Revoked_NUMBER);
+ scanf("%u", &nuberOfRevoked);
+
+ for (size_t i = 0; i < nuberOfRevoked; ++i)
+ {
+ printf("Revoked certificate %d:", i);
+ printf("Serial number (E. g.: 100):");
+ scanf("%u", &revokedNumbers[i]);
+ revocationDates[i] = (const uint8_t*)"130101000005Z";
+ }
+
+ crl.len = CRL_MIN_SIZE + nuberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4)/* + 1000*/;
+ crl.data = (uint8_t *)OICCalloc(1, crl.len);
+
+ CHECK_CALL(CKMIssueCRL, uint8ThisUpdateTime, nuberOfRevoked, revokedNumbers,
+ revocationDates, &crl);
+ PRINT_BYTE_ARRAY("CRL:\n",crl);
+ CHECK_CALL(SetCertificateRevocationList, &crl);
+ crlRes->CrlData = crl;
+ crlRes->ThisUpdate.data = uint8ThisUpdateTime;
+ crlRes->ThisUpdate.len = DATE_LENGTH;
+ crlRes->CrlId = 1;
+
+
+ FUNCTION_CLEAR(
+ //OICFree(crl.data);
+ );
+}
+
+
+/**
+ * Provisioning client sample using ProvisioningAPI
+ */
+int main()
+{
+ OCStackResult res = OC_STACK_OK;
+
+ // Initialize Persistent Storage for SVR database
+ OCPersistentStorage ps = { .open = client_fopen,
+ .read = fread,
+ .write = fwrite,
+ .close = fclose,
+ .unlink = unlink};
+
+ OCRegisterPersistentStorageHandler(&ps);
+
+ if (OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
+ {
+ OC_LOG(ERROR, TAG, "OCStack init error");
+ goto error;
+ }
+
+ OCProvisionDev_t* pDeviceList = NULL;
+ res = OCDiscoverUnownedDevices(PREDEFINED_TIMEOUT, &pDeviceList);
+ if(OC_STACK_OK != res)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed to PMDeviceDiscovery : %d", res);
+ goto error;
+ }
+
+ OCProvisionDev_t* pCurDev = pDeviceList;
+ int i;
+ while(pCurDev !=NULL)
+ {
+ for(i = 0; i < UUID_LENGTH; i++)
+ {
+ printf("%c", pCurDev->doxm->deviceID.id[i]);
+ }
+ printf("\n");
+ pCurDev = pCurDev->next;
+ }
+
+ //Register callback function to each OxM
+ OTMCallbackData_t justWorksCBData = {.loadSecretCB=NULL,
+ .createSecureSessionCB=NULL,
+ .createSelectOxmPayloadCB=NULL,
+ .createOwnerTransferPayloadCB=NULL};
+ justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
+ justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
+ justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
+ justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
+ OTMSetOwnershipTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData);
+
+ char* myContext = "OTM Context";
+ //Perform ownership transfer
+ res = OCDoOwnershipTransfer((void*)myContext, pDeviceList, OwnershipTransferCB);
+ if(OC_STACK_OK == res)
+ {
+ OC_LOG(INFO, TAG, "Request for ownership transfer is sent successfully.");
+ }
+ else
+ {
+ OC_LOG_V(ERROR, TAG, "Failed to OCDoOwnershipTransfer : %d", res);
+ }
+
+ gOwnershipState = 0;
+ while (gOwnershipState == 0)
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ goto error;
+ }
+ sleep(1);
+ }
+
+// Credential & ACL provisioning between two devices.
+
+ OCProvisionDev_t *pOwnedList = NULL;
+ OCProvisionDev_t *pOwnedDevices [MAX_OWNED_DEVICE] = {0,};
+ int nOwnedDevice = 0;
+
+ res = OCDiscoverOwnedDevices(PREDEFINED_TIMEOUT, &pOwnedList);
+ if (OC_STACK_OK == res)
+ {
+ printf("################## Owned Device List #######################\n");
+ while (pOwnedList != NULL)
+ {
+ nOwnedDevice ++;
+ printf(" %d : ", nOwnedDevice);
+ for (int i = 0; i < UUID_LENGTH; i++)
+ {
+ printf("%c", pOwnedList->doxm->deviceID.id[i]);
+ }
+ printf("\n");
+ pOwnedDevices[nOwnedDevice] = pOwnedList;
+ pOwnedList = pOwnedList->next;
+ }
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "Error while Owned Device Discovery");
+ }
+
+ int Device1 = 0;
+ int Device2 = 0;
+
+ printf("Select 2 devices for Credential & ACL provisioning\n");
+ printf("Device 1: ");
+ scanf("%d", &Device1);
+ printf("Device 2: ");
+ scanf("%d", &Device2);
+
+
+ gAcl = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
+ if (NULL == gAcl)
+ {
+ OC_LOG(ERROR, TAG, "Error while memory allocation");
+ goto error;
+ }
+
+ if (PKI_SUCCESS != InitCA())
+ {
+ OC_LOG(ERROR, TAG, "CA init error");
+ goto error;
+ }
+
+
+ char *ctx = "DUMMY";
+
+ res = OCProvisionCredentials(ctx, SIGNED_ASYMMETRIC_KEY, 0, pOwnedDevices[Device1],
+ NULL, ProvisionCertCB);
+ if (OC_STACK_OK != res) OC_LOG_V(ERROR, TAG, "Failed to provision Device 1 : %d", res);
+ gOwnershipState = 0;
+ while ( gOwnershipState == 0 )
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ goto error;
+ }
+ sleep(1);
+ }
+
+ res = OCProvisionCredentials(ctx, SIGNED_ASYMMETRIC_KEY, 0, pOwnedDevices[Device2],
+ NULL, ProvisionCertCB);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed to provision Device 2 : %d", res);
+ }
+
+ gOwnershipState = 0;
+ while (gOwnershipState == 0)
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ goto error;
+ }
+ sleep(1);
+ }
+
+ printf("Input ACL for Device2\n");
+ if (0 == InputACL(gAcl))
+ {
+ printf("Success Input ACL\n");
+ }
+ else
+ {
+ OC_LOG(ERROR, TAG, "InputACL error");
+ goto error;
+ }
+ res = OCProvisionACL(ctx, pOwnedDevices[Device2], gAcl, &ProvisionAclCB);
+ if (OC_STACK_OK != res)
+ {
+ OC_LOG_V(ERROR, TAG, "Failed to ACL provision Device 2 : %d", res);
+ }
+
+ gOwnershipState = 0;
+ while (gOwnershipState == 0)
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ goto error;
+ }
+ sleep(1);
+ }
+ gCrl = (OicSecCrl_t *)OICMalloc(sizeof(OicSecCrl_t));
+ if (PKI_SUCCESS != InputCRL(gCrl))
+ {
+ OC_LOG(ERROR, TAG, "CA init error");
+ goto error;
+ }
+
+ PRINT_BYTE_ARRAY("gCrl = \n", gCrl->CrlData);
+
+
+ res = OCProvisionCRL(ctx, pOwnedDevices[Device2], gCrl, &ProvisionCrlCB);
+ if (OC_STACK_OK != res) OC_LOG_V(ERROR, TAG, "Failed to CRL provision Device 2 : %d", res);
+
+ gOwnershipState = 0;
+ while (gOwnershipState == 0)
+ {
+ if (OCProcess() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ goto error;
+ }
+ sleep(1);
+ }
+
+ if (OCStop() != OC_STACK_OK)
+ {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ goto error;
+ }
+
+error:
+ deleteACL(gAcl);
+ OCDeleteDiscoveredDevices(&pDeviceList);
+ OCDeleteDiscoveredDevices(&pOwnedList);
+
+ return 0;
+}
--- /dev/null
+/******************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * LICENSE-2.0" target="_blank">http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+
+ ******************************************************************/
+
+
+#include <iostream>
+#include <string.h>
+#include <oic_malloc.h>
+#include <gtest/gtest.h>
+#include "ocstack.h"
+
+#include "cert_generator.h"
+#include "ck_manager.h"
+#include "pki.h"
+#include "sn_store.h"
+#include "der_dec.h"
+#include "crl.h"
+#include "crl_generator.h"
+#include "crlresource.h"
+#include "ckm_info.h"
+
+
+#define RUNS 1
+#define MAX_LEN 1000
+#define TEST_SN 50
+#define READ_WRITE_BLOCK_N 1ul
+#define N_LENGTH_BYTES 3
+
+const char *CKMI_JSON_FILE_NAME = "CKMInfo.json";
+
+#define CRL_DEFAULT_CRL_ID 1
+#define CRL_DEFAULT_THIS_UPDATE "150101000000Z"
+#define CRL_DEFAULT_CRL_DATA "-"
+
+#define NUMBER_OF_REVOKED 2
+
+OCPersistentStorage ps = { NULL, NULL, NULL, NULL, NULL};
+
+//#define NUM_ACE_FOR_WILDCARD_IN_CKM1_JSON (2)
+
+FILE* ckm_fopen(const char * /*path*/, const char *mode)
+{
+ return fopen(CKMI_JSON_FILE_NAME, mode);
+}
+
+void SetPersistentHandler(OCPersistentStorage *ps)
+{
+ if(ps)
+ {
+ ps->open = ckm_fopen;
+ ps->read = fread;
+ ps->write = fwrite;
+ ps->close = fclose;
+ ps->unlink = unlink;
+ }
+}
+
+// Length of test certificate
+#define SIMPLE_CRT_LEN 469
+
+class PKITest : public ::testing::Test
+{
+public:
+ static void SetUpTestCase()
+ {
+ SetPersistentHandler(&ps);
+ OCStackResult res = OCRegisterPersistentStorageHandler(&ps);
+ ASSERT_TRUE(res == OC_STACK_OK);
+ }
+
+ static void TearDownTestCase()
+ {
+ }
+
+ static CertificateX509 g_certificate;
+
+ static const ByteArray g_caPublicKey;
+
+ static const ByteArray g_derCode ;
+
+ static ByteArray g_serNum;
+};
+
+CertificateX509 PKITest::g_certificate;
+
+const ByteArray PKITest::g_derCode = {(uint8_t[])
+ {
+ 0x30, 0x82, 0x01, 0xd1, 0x30, 0x82, 0x01, 0x77, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00,
+ 0xd7, 0x56, 0x8c, 0xfc, 0x53, 0x18, 0xb0, 0xab, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
+ 0x3d, 0x04, 0x03, 0x02, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f,
+ 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+ 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31,
+ 0x35, 0x30, 0x33, 0x31, 0x32, 0x31, 0x32, 0x32, 0x35, 0x31, 0x31, 0x5a, 0x17, 0x0d, 0x31, 0x37,
+ 0x30, 0x33, 0x31, 0x31, 0x31, 0x32, 0x32, 0x35, 0x31, 0x31, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30,
+ 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31,
+ 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+ 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
+ 0x74, 0x64, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
+ 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x8c, 0xc8, 0x92,
+ 0x1d, 0xaa, 0x7f, 0xf0, 0xe4, 0xb2, 0x75, 0xd6, 0x4a, 0xf1, 0xd5, 0x14, 0x3f, 0x1a, 0x09, 0xc5,
+ 0x3e, 0x52, 0xd6, 0xda, 0xa0, 0xbf, 0x90, 0x43, 0xd1, 0x6b, 0xfe, 0xd1, 0xb3, 0x75, 0x5c, 0xdd,
+ 0x69, 0xac, 0x42, 0xa1, 0xcb, 0x03, 0x16, 0xee, 0xa4, 0x30, 0xa5, 0x8d, 0x36, 0x8f, 0xc5, 0x7b,
+ 0xb4, 0xb5, 0x6a, 0x7d, 0x9b, 0x16, 0x04, 0x46, 0xab, 0xae, 0xbb, 0x56, 0xa1, 0xa3, 0x50, 0x30,
+ 0x4e, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x5c, 0x0e, 0x30, 0xa8,
+ 0x8e, 0x7f, 0xc9, 0x02, 0xcd, 0xa8, 0xed, 0x0d, 0x1a, 0x1b, 0xd9, 0x7d, 0xe6, 0xce, 0x2a, 0x59,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x5c, 0x0e, 0x30,
+ 0xa8, 0x8e, 0x7f, 0xc9, 0x02, 0xcd, 0xa8, 0xed, 0x0d, 0x1a, 0x1b, 0xd9, 0x7d, 0xe6, 0xce, 0x2a,
+ 0x59, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+ 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
+ 0x02, 0x21, 0x00, 0xf6, 0x79, 0xed, 0x69, 0xd5, 0xe5, 0xba, 0x42, 0x14, 0xfc, 0xce, 0x47, 0xf1,
+ 0x61, 0x1c, 0x51, 0x11, 0x2b, 0xba, 0x04, 0x70, 0x56, 0x78, 0xaf, 0xa9, 0xa6, 0x98, 0x8f, 0x4b,
+ 0xa8, 0x11, 0x67, 0x02, 0x20, 0x3a, 0xdf, 0xf1, 0x74, 0xc9, 0x2f, 0xfb, 0x84, 0x46, 0xde, 0xbc,
+ 0x2d, 0xda, 0xe3, 0x05, 0xb4, 0x81, 0x31, 0x45, 0xf7, 0x3d, 0x71, 0x46, 0x07, 0xa7, 0xd8, 0xcb,
+ 0xae, 0x1e, 0x1b, 0x1c, 0x5a
+ }, SIMPLE_CRT_LEN };
+
+
+const ByteArray PKITest::g_caPublicKey = {(uint8_t[])
+{
+ 0x8c, 0xc8, 0x92, 0x1d, 0xaa, 0x7f, 0xf0, 0xe4, 0xb2, 0x75, 0xd6, 0x4a, 0xf1, 0xd5, 0x14, 0x3f,
+ 0x1a, 0x09, 0xc5, 0x3e, 0x52, 0xd6, 0xda, 0xa0, 0xbf, 0x90, 0x43, 0xd1, 0x6b, 0xfe, 0xd1, 0xb3,
+ 0x75, 0x5c, 0xdd, 0x69, 0xac, 0x42, 0xa1, 0xcb, 0x03, 0x16, 0xee, 0xa4, 0x30, 0xa5, 0x8d, 0x36,
+ 0x8f, 0xc5, 0x7b, 0xb4, 0xb5, 0x6a, 0x7d, 0x9b, 0x16, 0x04, 0x46, 0xab, 0xae, 0xbb, 0x56, 0xa1
+}, PUBLIC_KEY_SIZE };
+
+
+ByteArray PKITest::g_serNum = {(uint8_t[SERIAL_NUMBER_MAX_LEN]) {0}, SERIAL_NUMBER_MAX_LEN};
+
+//registering persistent storage test
+TEST(CKManager, RegisterPersistentStorage)
+{
+ SetPersistentHandler(&ps);
+ ASSERT_EQ(OC_STACK_OK, OCRegisterPersistentStorageHandler(&ps));
+}
+
+//check decoding predefined certificate
+TEST(X509Certificate, DecodeTest)
+{
+ ByteArray code = PKITest::g_derCode;
+
+ ASSERT_EQ(DecodeCertificate(code, &PKITest::g_certificate), PKI_SUCCESS);
+ code.data = NULL;
+ ASSERT_NE(DecodeCertificate(code, &PKITest::g_certificate), PKI_SUCCESS);
+}
+
+//check decoding of random symbols sequence
+TEST(X509Certificate, RandomDecode)
+{
+ srand((unsigned int)time(NULL));
+
+ ByteArray code;
+ INIT_BYTE_ARRAY(code);
+
+ for (unsigned int i = 0; i < RUNS; i++)
+ {
+ code.len = rand() % MAX_LEN;
+ code.data = (uint8_t *)malloc(code.len * sizeof(uint8_t));
+
+ EXPECT_NE(code.data, (uint8_t *)NULL);
+
+ for (unsigned int j = 0; j < code.len; j++)
+ {
+ code.data[j] = (uint8_t)(rand() % 128 + 1);
+ }
+
+ EXPECT_NE(PKI_SUCCESS, DecodeCertificate(code, &PKITest::g_certificate));
+
+ free(code.data);
+ }
+}
+//testing validity check of predefined certificate
+TEST(X509Certificate, testCheckValidity)
+{
+ CertificateX509 tempCrt;
+ ASSERT_EQ(PKI_SUCCESS, DecodeCertificate(PKITest::g_derCode, &tempCrt));
+ ASSERT_EQ(PKI_SUCCESS, CheckValidity(tempCrt.validFrom, tempCrt.validTo));
+ ByteArray temp = tempCrt.validTo;
+
+ tempCrt.validTo = tempCrt.validFrom;
+ tempCrt.validFrom = temp;
+ ASSERT_EQ(PKI_CERT_DATE_INVALID, CheckValidity(tempCrt.validFrom, tempCrt.validTo));
+}
+
+//testing signature check of predefined certificate
+TEST(X509Certificate, CheckSignature)
+{
+ ByteArray code = PKITest::g_derCode;
+
+ ASSERT_EQ(PKI_SUCCESS, CheckCertificate(code, PKITest::g_caPublicKey));
+ code.data = NULL;
+ ASSERT_NE(PKI_SUCCESS, CheckCertificate(code, PKITest::g_caPublicKey));
+}
+
+//test saving certificate into file
+TEST_F(PKITest, DERCertificateFile)
+{
+ uint8_t derData[ISSUER_MAX_CERT_SIZE] = {0};
+ uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+ uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+
+ ByteArray certDer = BYTE_ARRAY_INITIALIZER;
+ ByteArray pubKeyIss = BYTE_ARRAY_INITIALIZER;
+ ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER;
+ ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+
+ certDer.data = derData;
+ certDer.len = ISSUER_MAX_CERT_SIZE;
+
+ pubKeyIss.data = caPubKey;
+ pubKeyIss.len = sizeof(caPubKey);
+ privKeyIss.data = caPrivKey;
+ privKeyIss.len = sizeof(caPrivKey);
+ rootName.data = (uint8_t *)"ROOT1";
+ rootName.len = strlen((char *)rootName.data);
+ ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+
+ for (int i = 1; i <= RUNS; i++)
+ {
+ ASSERT_EQ(PKI_SUCCESS, GenerateCAKeyPair(&privKeyIss, &pubKeyIss));
+ ASSERT_EQ(PKI_SUCCESS, SetSerialNumber(i));
+ ASSERT_EQ(PKI_SUCCESS, SetRootName(rootName));
+ ASSERT_EQ(PKI_SUCCESS, CKMIssueRootCertificate(0, 0, &certDer));
+ ASSERT_EQ(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+ ASSERT_EQ(PKI_SUCCESS, GenerateDERCertificateFile (&certDer, "der_cert"));
+ }
+ ASSERT_EQ(CloseCKMInfo(), PKI_SUCCESS);
+}
+
+//test checking time validity of generated certificate
+TEST_F(PKITest, TimeValidity)
+{
+ uint8_t derData[ISSUER_MAX_CERT_SIZE] = {0};
+ uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+ uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+
+ ByteArray certDer = BYTE_ARRAY_INITIALIZER;
+ ByteArray pubKey = BYTE_ARRAY_INITIALIZER;
+ ByteArray privKey = BYTE_ARRAY_INITIALIZER;
+ ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+
+ privKey.data = caPrivKey;
+ privKey.len = sizeof(caPrivKey);
+
+ certDer.data = derData;
+ certDer.len = sizeof(derData);
+
+ pubKey.data = caPubKey;
+ pubKey.len = sizeof(caPubKey);
+
+ rootName.data = (uint8_t *)"ROOT3";
+ rootName.len = strlen((char *)rootName.data);
+ ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+
+ for (int i = 1; i <= RUNS; i++)
+ {
+ ASSERT_EQ(PKI_SUCCESS, GenerateCAKeyPair(&privKey, &pubKey));
+ ASSERT_EQ(PKI_SUCCESS, SetSerialNumber(i));
+ ASSERT_EQ(PKI_SUCCESS, SetRootName(rootName));
+
+ ASSERT_EQ(PKI_SUCCESS, CKMIssueRootCertificate(0, 0, &certDer));
+ ASSERT_EQ(PKI_SUCCESS, CheckCertificate(certDer, pubKey));
+
+ certDer.len = sizeof(derData);
+ ASSERT_EQ(PKI_SUCCESS, CKMIssueRootCertificate(0, (uint8_t *)"130101000000Z", &certDer));
+ ASSERT_EQ(PKI_CERT_DATE_INVALID, CheckCertificate(certDer, pubKey));
+
+ certDer.len = sizeof(derData);
+ ASSERT_EQ(PKI_SUCCESS, CKMIssueRootCertificate((uint8_t *)"160101000000Z", 0, &certDer));
+ ASSERT_EQ(PKI_CERT_DATE_INVALID, CheckCertificate(certDer, pubKey));
+ }
+ ASSERT_EQ(PKI_SUCCESS, CloseCKMInfo());
+}
+
+//testing certificate generation by certificate signing request
+TEST_F(PKITest, CertificateSigningRequest)
+{
+ uint8_t certData[ISSUER_MAX_CERT_SIZE] = {0};
+ uint8_t csrData[CSR_MAX_SIZE] = {0};
+ uint8_t subjPubKey[PUBLIC_KEY_SIZE] = {0};
+ uint8_t subjPrivKey[PRIVATE_KEY_SIZE] = {0};
+ uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+ uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+ uint8_t *subjName = (uint8_t *)"Subject05";
+
+ ByteArray certDer = BYTE_ARRAY_INITIALIZER;
+ ByteArray csrDer = BYTE_ARRAY_INITIALIZER;
+ ByteArray pubKeyIss = BYTE_ARRAY_INITIALIZER;
+ ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER;
+ ByteArray pubKeySubj = BYTE_ARRAY_INITIALIZER;
+ ByteArray privKeySubj = BYTE_ARRAY_INITIALIZER;
+ ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+
+ certDer.data = certData;
+ certDer.len = sizeof(certData);
+ csrDer.data = csrData;
+ csrDer.len = CSR_MAX_SIZE;
+
+ pubKeyIss.data = caPubKey;
+ pubKeyIss.len = sizeof(caPubKey);
+ privKeyIss.data = caPrivKey;
+ privKeyIss.len = sizeof(caPrivKey);
+ pubKeySubj.data = subjPubKey;
+ pubKeySubj.len = sizeof(subjPubKey);
+ privKeySubj.data = subjPrivKey;
+ privKeySubj.len = sizeof(subjPrivKey);
+ rootName.data = (uint8_t *)"ROOT2";
+ rootName.len = strlen((char *)rootName.data);
+ ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+
+ ASSERT_EQ(GenerateCAKeyPair(&privKeyIss, &pubKeyIss), PKI_SUCCESS);
+ ASSERT_EQ(SetSerialNumber(1), PKI_SUCCESS);
+ ASSERT_EQ(SetRootName(rootName), PKI_SUCCESS);
+
+ for (int i = 1; i <= RUNS; i++)
+ {
+ ASSERT_EQ(PKI_SUCCESS, GenerateKeyPair(&privKeySubj, &pubKeySubj));
+ ASSERT_EQ(PKI_SUCCESS, GenerateCSR(subjName, subjPubKey, subjPrivKey, &csrDer));
+ ASSERT_EQ(PKI_SUCCESS, GenerateCertificateByCSR(&csrDer, &certDer));
+ ASSERT_EQ(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+ certDer.data[0]++;
+ ASSERT_NE(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+ certDer.data[0]--;
+ ASSERT_EQ(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+ }
+ ASSERT_EQ(PKI_SUCCESS, CloseCKMInfo());
+}
+
+//test public key structure parsing
+TEST(X509Certificate, testParsePublicKey)
+{
+ ASSERT_EQ(PKI_SUCCESS, ParsePublicKey((ByteArray*)&PKITest::g_caPublicKey));
+
+ size_t length = 3;
+ uint8_t shortAr[length];
+ ByteArray shortArray = {shortAr, length};
+ ASSERT_EQ(PKI_WRONG_ARRAY_LEN, ParsePublicKey(&shortArray));
+
+ uint8_t uncompressed[PUBLIC_KEY_SIZE + 2];
+ uncompressed[0] = 0;
+ uncompressed[1] = ASN1_UNCOMPRESSED_KEY;
+ memcpy(&uncompressed[2], PKITest::g_caPublicKey.data, PUBLIC_KEY_SIZE);
+ ByteArray uncomprArr = {uncompressed, PUBLIC_KEY_SIZE+2};
+ ParsePublicKey(&uncomprArr);
+ ASSERT_EQ((size_t)PUBLIC_KEY_SIZE, uncomprArr.len);
+ ASSERT_EQ(0, memcmp(uncomprArr.data, PKITest::g_caPublicKey.data, PUBLIC_KEY_SIZE));
+}
+
+//test checking of certificate generated by OpenSSL
+TEST(OpenSSLCompatibility, verifyOpenSslCertSign)
+{
+ ByteArray crtDer = BYTE_ARRAY_INITIALIZER;
+ CertificateX509 certificate;
+
+ FILE *fileCert = fopen("01.der", "rb");
+ ASSERT_TRUE(fileCert != NULL);
+
+ //get the length
+ fseek(fileCert, 0, SEEK_END);
+ crtDer.len = ftell(fileCert);
+ fseek(fileCert, 0, SEEK_SET);
+ //allocate memory
+ crtDer.data = (uint8_t*)malloc(crtDer.len+1);
+ //read the content
+ EXPECT_EQ(READ_WRITE_BLOCK_N, fread(crtDer.data, crtDer.len, READ_WRITE_BLOCK_N, fileCert));
+ fclose(fileCert);
+
+ ByteArray pubKey = BYTE_ARRAY_INITIALIZER;
+ FILE * fileKey = fopen("capub.der", "rb");
+ ASSERT_TRUE(fileKey != NULL);
+ fseek(fileKey, 0, SEEK_END);
+ pubKey.len = ftell(fileKey);
+ fseek(fileKey, 0, SEEK_SET);
+ //openssl generates a public key that is longer than 64 bytes
+ //with additional 27 bytes prepending the actual key
+ if(pubKey.len > PUBLIC_KEY_SIZE){
+ fseek(fileKey, (pubKey.len - PUBLIC_KEY_SIZE), SEEK_SET);
+ pubKey.len = PUBLIC_KEY_SIZE;
+ }
+ pubKey.data = (uint8_t*)malloc(pubKey.len+1);
+ //read the content
+ EXPECT_EQ(READ_WRITE_BLOCK_N, fread(pubKey.data, pubKey.len, READ_WRITE_BLOCK_N, fileKey));
+ fclose(fileKey);
+
+ EXPECT_EQ(PKI_SUCCESS, DecodeCertificate(crtDer, &certificate));
+ EXPECT_EQ(PKI_SUCCESS, CheckCertificate(crtDer, pubKey));
+
+ free(crtDer.data);
+ free(pubKey.data);
+}
+
+//test parsing of certificate chain generated by OpenSSL
+TEST(CertificateChain, LoadCertificateChain)
+{
+ ByteArray crtChainDer[MAX_CHAIN_LEN] = {{0,0},};
+ CertificateX509 crtChain[MAX_CHAIN_LEN] = {{{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}},};
+ ByteArray msg = BYTE_ARRAY_INITIALIZER;
+ uint8_t chainLength;
+
+ FILE *file = fopen("cert_chain.dat", "rb");
+
+ ASSERT_TRUE(file != NULL);
+
+ while (!feof (file))
+ {
+ msg.data = (uint8_t *) realloc (msg.data, msg.len + 1);
+ msg.data[msg.len] = fgetc (file);
+ msg.len++;
+ }
+ msg.len--;
+ fclose (file);
+ INC_BYTE_ARRAY(msg, 3);
+ EXPECT_EQ(PKI_SUCCESS, LoadCertificateChain (msg, crtChainDer, &chainLength));
+#ifdef X509_DEBUG
+ printf("chain len: %d\n", chainLength);
+#endif
+ EXPECT_EQ(PKI_UNKNOWN_OID, ParseCertificateChain (crtChainDer, crtChain, chainLength));
+
+ free(msg.data - 3);
+}
+
+//test checking CA certificate generated by OpenSSL
+TEST(OpenSSLCompatibility, testOpenSSLCertificate)
+{
+ ByteArray crtDer = BYTE_ARRAY_INITIALIZER;
+ FILE *fileCert = fopen("cacert.der", "rb");
+ ASSERT_TRUE(fileCert != NULL);
+
+ //get the length
+ fseek(fileCert, 0, SEEK_END);
+ crtDer.len = ftell(fileCert);
+ fseek(fileCert, 0, SEEK_SET);
+ //allocate memory
+ crtDer.data = (uint8_t*)malloc(crtDer.len+1);
+ //read the content
+ EXPECT_EQ(READ_WRITE_BLOCK_N, fread(crtDer.data, crtDer.len, READ_WRITE_BLOCK_N, fileCert));
+
+ fclose(fileCert);
+ #ifdef X509_DEBUG
+ printf("Length of cert: %lu\n", crtDer.len);
+ #endif
+ EXPECT_EQ(PKI_SUCCESS, DecodeCertificate(crtDer, &PKITest::g_certificate));
+ free(crtDer.data);
+}
+
+//test signatures checking of certificate chain generated by OpenSSL
+TEST(OpenSSLCompatibility, ParseAndCheckCertificateChain)
+{
+ ByteArray crtChainDer[MAX_CHAIN_LEN] = {{0,0},};
+ CertificateX509 crtChain[MAX_CHAIN_LEN] = {{{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}},};
+ ByteArray msg = BYTE_ARRAY_INITIALIZER;
+ uint8_t chainLength;
+
+ const char* chainPath = {"chain.der"};
+ FILE *fileChain = fopen(chainPath, "rb");
+ ASSERT_TRUE(fileChain != NULL);
+
+ //get the length
+ fseek(fileChain, 0, SEEK_END);
+ msg.len = ftell(fileChain);
+ fseek(fileChain, 0, SEEK_SET);
+ //allocate memory
+ msg.data = (uint8_t*)malloc(msg.len+1);
+ //read the content
+ EXPECT_EQ(READ_WRITE_BLOCK_N, fread(msg.data, msg.len, READ_WRITE_BLOCK_N, fileChain));
+
+ fclose (fileChain);
+
+ INC_BYTE_ARRAY(msg, 3);
+ EXPECT_EQ(PKI_SUCCESS, LoadCertificateChain(msg, crtChainDer, &chainLength));
+ EXPECT_EQ(3, chainLength);
+ #ifdef X509_DEBUG
+ printf("Length of the chain: %d\n", chainLength);
+ #endif
+
+ EXPECT_EQ(PKI_SUCCESS, ParseCertificateChain(crtChainDer, crtChain, chainLength));
+
+ ByteArray caPubKey = BYTE_ARRAY_INITIALIZER;
+
+ const char* caPubKeyPath = {"capub.der"};
+ FILE *fileCaPubKey = fopen(caPubKeyPath, "rb");
+ ASSERT_TRUE(fileCaPubKey != NULL);
+
+ fseek(fileCaPubKey, 0, SEEK_END);
+ caPubKey.len = ftell(fileCaPubKey);
+ fseek(fileCaPubKey, 0, SEEK_SET);
+ if(caPubKey.len > PUBLIC_KEY_SIZE){
+ fseek(fileCaPubKey, (caPubKey.len - PUBLIC_KEY_SIZE), SEEK_SET);
+ caPubKey.len = PUBLIC_KEY_SIZE;
+ }
+ caPubKey.data = (uint8_t*)malloc(caPubKey.len+1);
+ //read the content
+ EXPECT_EQ(READ_WRITE_BLOCK_N, fread(caPubKey.data, caPubKey.len, READ_WRITE_BLOCK_N, fileCaPubKey));
+ fclose(fileCaPubKey);
+
+ EXPECT_EQ(PKI_SUCCESS, CheckCertificateChain(crtChain, chainLength, caPubKey));
+
+ free(msg.data - 3);
+ free(caPubKey.data);
+}
+
+//testing correctness of decoding certificate length from ASN.1 structure
+TEST(CRL, testDecodeLength)
+{
+ ByteArray cert = BYTE_ARRAY_INITIALIZER;
+ size_t length(0);
+ EXPECT_EQ(PKI_NULL_PASSED, DecodeLength(&cert, &length));
+
+ //a simple DER
+ size_t derLength = (size_t)rand() % LEN_LONG;
+ cert.len = derLength + 2;
+ uint8_t *certData = (uint8_t*)malloc(cert.len);
+ cert.data = certData;
+ cert.data[0] = (uint8_t)0x30; //mixed types
+ cert.data[1] = (uint8_t)(derLength & 0xff);
+ EXPECT_EQ(PKI_SUCCESS, DecodeLength(&cert, &length));
+ EXPECT_EQ(derLength, length);
+ free(certData);
+}
+
+//testing serial number storage
+TEST(CRL, StoreSerialNumber)
+{
+ uint8_t data[10] = {0x01, 0x82, 0x01, 0xd1, 0x30, 0x82, 0x01, 0x77, 0xa0, 0x03};
+ const ByteArray sn = { data, sizeof(data) / sizeof(uint8_t)};
+ int i;
+ for (i = 0; i < 400; i++)
+ {
+ sn.data[0] = i % 20;
+ ASSERT_EQ(PKI_SUCCESS, StoreSerialNumber(sn));
+ }
+ ASSERT_EQ(PKI_CERT_REVOKED, CheckSerialNumber(sn));
+
+ sn.data[1] = 0x01;
+ ASSERT_EQ(PKI_SUCCESS, CheckSerialNumber(sn));
+
+ FreeSNStore();
+}
+#ifdef ARDUINO_MEMORY_DEBUG
+//testing memory allocation fault handling at Arduino
+TEST(SNStore, MemoryOverflow)
+{
+ uint8_t data[10] = {0x01, 0x82, 0x01, 0xd1, 0x30, 0x82, 0x01, 0x77, 0xa0, 0x03};
+ const ByteArray sn = { data, sizeof(data) / sizeof(uint8_t)};
+ int i;
+ PKIError res;
+ do
+ {
+ res = StoreSerialNumber(sn);
+ }
+ while (res == PKI_SUCCESS);
+ ASSERT_EQ(PKI_MEMORY_ALLOC_FAILED, res);
+
+ FreeSNStore();
+}
+#endif /* ARDUINO_MEMORY_DEBUG */
+
+//testing next certificate serial number handling by "CKM info" unit
+TEST_F(PKITest, CAInitAndSerialNum)
+{
+ ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+ long serialNum = rand() % (MAX_LEN - 1) + 1;
+ ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+ //all the serials should start from
+ ASSERT_EQ(PKI_SUCCESS, SetSerialNumber(serialNum));
+ long nextSerial;
+ ASSERT_EQ(PKI_SUCCESS, GetNextSerialNumber(&nextSerial));
+ ASSERT_EQ(nextSerial, serialNum);
+ ASSERT_EQ(PKI_SUCCESS, CloseCKMInfo());
+}
+
+//testing CA name handling by "CKM info" unit
+TEST_F(PKITest, testCAName)
+{
+ ByteArray caName = BYTE_ARRAY_INITIALIZER;
+ caName.len = ((size_t)rand() % (ISSUER_MAX_NAME_SIZE - 1) + 1);
+ caName.data = (uint8_t*)malloc(caName.len);
+ size_t i;
+ for(i = 0; i < caName.len; i++){
+ caName.data[i] = (uint8_t)(rand() % 128);
+ }
+ EXPECT_EQ(PKI_SUCCESS, InitCKMInfo());
+ EXPECT_EQ(PKI_SUCCESS, SetRootName(caName));
+ ByteArray getName = BYTE_ARRAY_INITIALIZER;
+ uint8_t uint8CAName[ISSUER_MAX_NAME_SIZE] = {0};
+ getName.data = uint8CAName;
+ getName.len = ISSUER_MAX_NAME_SIZE;
+ EXPECT_EQ(PKI_SUCCESS, GetCAName(&getName));
+ EXPECT_EQ(0, memcmp(caName.data, getName.data, caName.len));
+ free(caName.data);
+ ASSERT_EQ(PKI_SUCCESS, CloseCKMInfo());
+}
+
+//testing key pair generation and storing by "CKM info" unit
+TEST_F(PKITest, testKeyPair)
+{
+ ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+ rootName.data = (uint8_t *)"ROOT";
+ rootName.len = strlen((char *)rootName.data);
+ SetRootName(rootName);
+
+ //first test the GenerateCAKeyPair - this writes to the CA storage
+ ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER;
+ privKeyIss.len = PRIVATE_KEY_SIZE;
+ uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+ privKeyIss.data = caPrivKey;
+
+ ByteArray pubKeyIss = BYTE_ARRAY_INITIALIZER;
+ pubKeyIss.len = PUBLIC_KEY_SIZE;
+ uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+ pubKeyIss.data = caPubKey;
+
+ ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+ ASSERT_EQ(PKI_SUCCESS, GenerateCAKeyPair(&privKeyIss, &pubKeyIss));
+
+ ByteArray keyCheck = BYTE_ARRAY_INITIALIZER;
+ keyCheck.len = PUBLIC_KEY_SIZE;
+ uint8_t keyCheckData[PUBLIC_KEY_SIZE] = {0};
+ keyCheck.data = keyCheckData;
+ ASSERT_EQ(PKI_SUCCESS, GetCAPrivateKey(&keyCheck));
+ ASSERT_EQ(0, memcmp(keyCheck.data, privKeyIss.data, PRIVATE_KEY_SIZE));
+
+ ASSERT_EQ(PKI_SUCCESS, GetCAPublicKey(&keyCheck));
+ ASSERT_EQ(0, memcmp(keyCheck.data, pubKeyIss.data, PUBLIC_KEY_SIZE));
+
+ //now test the GenerateKeyPair - does not write to the CA storage
+ ASSERT_EQ(PKI_SUCCESS, GenerateKeyPair(&privKeyIss, &pubKeyIss));
+
+ ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+ ASSERT_EQ(PKI_SUCCESS, GetCAPrivateKey(&keyCheck));
+ ASSERT_NE(0, memcmp(keyCheck.data, privKeyIss.data, PRIVATE_KEY_SIZE));
+
+ ASSERT_EQ(PKI_SUCCESS, GetCAPublicKey(&keyCheck));
+ ASSERT_NE(0, memcmp(keyCheck.data, pubKeyIss.data, PUBLIC_KEY_SIZE));
+ ASSERT_EQ(PKI_SUCCESS, CloseCKMInfo());
+}
+
+//testing CRL encoding
+TEST_F(PKITest, testEncodeCRL)
+{
+ CertificateList crl;
+
+ uint8_t *uint8ThisUpdateTime = (uint8_t *)"130101000000Z";
+ uint32_t numberOfRevoked = 0;
+ uint32_t revokedNumbers[2];
+ const uint8_t *revocationDates[2];
+
+ ByteArray code = BYTE_ARRAY_INITIALIZER;
+ ByteArray pubKeyIss = BYTE_ARRAY_INITIALIZER;
+ ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER;
+ ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+
+ uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+ uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+
+ pubKeyIss.data = caPubKey;
+ pubKeyIss.len = PUBLIC_KEY_SIZE;
+ privKeyIss.data = caPrivKey;
+ privKeyIss.len = PRIVATE_KEY_SIZE;
+
+ numberOfRevoked = 2;
+
+ revokedNumbers[0] = 100; // serial number of first revoked certificate
+ revokedNumbers[1] = 200; // serial number of second revoked certificate
+ revocationDates[0] = (const uint8_t *)"130101000001Z";
+ revocationDates[1] = (const uint8_t *)"130101000002Z";
+
+ rootName.data = (uint8_t *)"ROOT2";
+ rootName.len = strlen((char *)rootName.data);
+ ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+ ASSERT_EQ(PKI_SUCCESS, SetRootName(rootName));
+ ASSERT_EQ(PKI_SUCCESS, GenerateCAKeyPair(&privKeyIss, &pubKeyIss));
+
+ code.data = (uint8_t *)calloc(1,
+ (CRL_MIN_SIZE + numberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4)));
+ code.len = (CRL_MIN_SIZE + numberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4));
+
+ EXPECT_EQ(PKI_SUCCESS,CKMIssueCRL(uint8ThisUpdateTime, numberOfRevoked, revokedNumbers,
+ revocationDates,&code));
+ EXPECT_EQ(PKI_SUCCESS, DecodeCertificateList (code, &crl, pubKeyIss));
+#ifdef X509_DEBUG
+ PrintSNStore();
+ PrintCRL(&crl);
+#endif
+
+ FreeSNStore();
+ free(code.data);
+ ASSERT_EQ(PKI_SUCCESS, CloseCKMInfo());
+}
+
+//check correctness of certificate revocation by CKMIssueCRL() and CKMRevocateCertificate()
+TEST_F(PKITest, testRevocateCertificate)
+{
+ CertificateList crl;
+
+ uint8_t *uint8ThisUpdateTime = (uint8_t *)"130101000000Z";
+ uint32_t numberOfRevoked = 0;
+ uint32_t revokedNumbers[2];
+ const uint8_t *revocationDates[2];
+
+ ByteArray code = BYTE_ARRAY_INITIALIZER;
+ ByteArray pubKeyIss = BYTE_ARRAY_INITIALIZER;
+ ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER;
+ ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+
+ uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+ uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+
+ pubKeyIss.data = caPubKey;
+ pubKeyIss.len = sizeof(caPubKey);
+ privKeyIss.data = caPrivKey;
+ privKeyIss.len = sizeof(caPrivKey);
+
+ numberOfRevoked = 2;
+
+ revokedNumbers[0] = 100; // serial number of first revoked certificate
+ revokedNumbers[1] = 200; // serial number of second revoked certificate
+ revocationDates[0] = (const uint8_t *)"130101000001Z";
+ revocationDates[1] = (const uint8_t *)"130101000002Z";
+
+ rootName.data = (uint8_t *)"ROOT2";
+ rootName.len = strlen((char *)rootName.data);
+ ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+ ASSERT_EQ(PKI_SUCCESS, SetRootName(rootName));
+ ASSERT_EQ(PKI_SUCCESS, GenerateCAKeyPair(&privKeyIss, &pubKeyIss));
+
+ code.len = CRL_MIN_SIZE + numberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4);
+ code.data = (uint8_t *)calloc(1, code.len);
+
+ EXPECT_EQ(PKI_SUCCESS, CKMIssueCRL (uint8ThisUpdateTime, numberOfRevoked, revokedNumbers,
+ revocationDates, &code));
+ EXPECT_EQ(PKI_SUCCESS, DecodeCertificateList (code, &crl, pubKeyIss));
+ free(code.data);
+ numberOfRevoked++;
+ code.len = CRL_MIN_SIZE + numberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4);
+ code.data = (uint8_t *)calloc(1, code.len);
+ EXPECT_EQ(PKI_SUCCESS, CKMRevocateCertificate (uint8ThisUpdateTime, 50, &code));
+ EXPECT_EQ(PKI_SUCCESS, DecodeCertificateList (code, &crl, pubKeyIss));
+#ifdef X509_DEBUG
+ PrintSNStore();
+ PrintCRL(&crl);
+#endif
+
+ FreeSNStore();
+ free(code.data);
+ ASSERT_EQ(PKI_SUCCESS, CloseCKMInfo());
+}
+
+//checck correctness of saving root certificate to binary file
+TEST_F(PKITest, StoreCKMInfo)
+{
+ ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+ uint8_t derData[ISSUER_MAX_CERT_SIZE] = {0};
+ uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+ uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+ const long serNum = 48598490;
+ CertificateList crl;
+ uint8_t *uint8ThisUpdateTime = (uint8_t *)"130101000000Z";
+ uint32_t numberOfRevoked = 0;
+ uint32_t revokedNumbers[2];
+ const uint8_t *revocationDates[2];
+
+ ByteArray certDer = BYTE_ARRAY_INITIALIZER;
+ ByteArray pubKeyIss = BYTE_ARRAY_INITIALIZER;
+ ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER;
+ ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+ ByteArray code = BYTE_ARRAY_INITIALIZER;
+
+ certDer.data = derData;
+ certDer.len = ISSUER_MAX_CERT_SIZE;
+ pubKeyIss.data = caPubKey;
+ pubKeyIss.len = PUBLIC_KEY_SIZE;
+ privKeyIss.data = caPrivKey;
+ privKeyIss.len = PRIVATE_KEY_SIZE;
+ rootName.data = (uint8_t *)"ROOT";
+ rootName.len = strlen((char *)rootName.data);
+
+ //generate CA Certificate
+ ASSERT_EQ(PKI_SUCCESS, GenerateCAKeyPair(&privKeyIss, &pubKeyIss));
+ ASSERT_EQ(PKI_SUCCESS, SetSerialNumber(serNum));
+ ASSERT_EQ(PKI_SUCCESS, SetRootName(rootName));
+ ASSERT_EQ(PKI_SUCCESS, CKMIssueRootCertificate(0, 0, &certDer));
+
+ //generate CRL
+ numberOfRevoked = NUMBER_OF_REVOKED;
+
+ revokedNumbers[0] = 100; // serial number of first revoked certificate
+ revokedNumbers[1] = 200; // serial number of second revoked certificate
+ revocationDates[0] = (const uint8_t *)"130101000001Z";
+ revocationDates[1] = (const uint8_t *)"130101000002Z";
+
+ code.data = (uint8_t *)calloc(1,
+ (CRL_MIN_SIZE + numberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4)));
+ code.len = (CRL_MIN_SIZE + numberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4));
+
+ ASSERT_EQ(PKI_SUCCESS, CKMIssueCRL (uint8ThisUpdateTime, numberOfRevoked, revokedNumbers,
+ revocationDates, &code));
+
+ // Check Certificate file
+ CertificateX509 certificate;
+ ByteArray crtDer = BYTE_ARRAY_INITIALIZER;
+ FILE *filePtr = fopen(CA_STORAGE_CRT_FILE , "rb");
+ ASSERT_TRUE(filePtr != NULL);
+
+ //get the length
+ fseek(filePtr, 0, SEEK_END);
+ crtDer.len = ftell(filePtr);
+ fseek(filePtr, 0, SEEK_SET);
+ //allocate memory
+ crtDer.data = (uint8_t*)malloc(crtDer.len+1);
+ //read the content
+ EXPECT_EQ(READ_WRITE_BLOCK_N, fread(crtDer.data, crtDer.len, READ_WRITE_BLOCK_N, filePtr));
+ fclose(filePtr);
+ ByteArray crtCheck;
+ crtCheck.data = crtDer.data + 3; //now file contains length of certificate
+ crtCheck.len = crtDer.len - 3;
+ EXPECT_EQ(PKI_SUCCESS, DecodeCertificate(crtCheck, &certificate));
+#ifdef X509_DEBUG
+ PrintCertificate(&certificate);
+#endif
+
+ //check CRL
+ ByteArray crlDer = BYTE_ARRAY_INITIALIZER;
+ crlDer.len = (CRL_MIN_SIZE + numberOfRevoked * (sizeof(CertificateRevocationInfo_t) + 4));
+ crlDer.data = (uint8_t *)malloc(crlDer.len);
+
+ EXPECT_EQ(PKI_SUCCESS, GetCertificateRevocationList(&crlDer));
+
+ EXPECT_EQ(PKI_SUCCESS, DecodeCertificateList (crlDer, &crl, pubKeyIss));
+#ifdef X509_DEBUG
+ PrintCRL(&crl);
+#endif
+ EXPECT_EQ(PKI_SUCCESS, CloseCKMInfo());
+ free(crlDer.data);
+ free(code.data);
+ free(crtDer.data);
+}
+
+//check correctness of root certificate generation
+TEST_F(PKITest, GenerateRootCertificate)
+{
+ uint8_t derData[ISSUER_MAX_CERT_SIZE] = {0};
+ uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+ uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+
+ ByteArray certDer = BYTE_ARRAY_INITIALIZER;
+ ByteArray pubKeyIss = BYTE_ARRAY_INITIALIZER;
+ ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER;
+ ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+
+ certDer.data = derData;
+ certDer.len = sizeof(derData);
+
+ pubKeyIss.data = caPubKey;
+ pubKeyIss.len = sizeof(caPubKey);
+ privKeyIss.data = caPrivKey;
+ privKeyIss.len = sizeof(caPrivKey);
+ rootName.data = (uint8_t *)"ROOT";
+ rootName.len = strlen((char *)rootName.data);
+ ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+
+ for (int i = 1; i <= RUNS; i++)
+ {
+ ASSERT_EQ(PKI_SUCCESS, GenerateCAKeyPair(&privKeyIss, &pubKeyIss));
+ ASSERT_EQ(PKI_SUCCESS, SetSerialNumber(i));
+ ASSERT_EQ(PKI_SUCCESS, SetRootName(rootName));
+ ASSERT_EQ(PKI_SUCCESS, CKMIssueRootCertificate(0, 0, &certDer));
+
+ ASSERT_EQ(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+ certDer.data[0]++;
+ ASSERT_NE(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+ certDer.data[0]--;
+ ASSERT_EQ(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+ }
+ ASSERT_EQ(PKI_SUCCESS, CloseCKMInfo());
+}
+
+//check correctness of ordinal device certificate generation
+TEST_F(PKITest, GenerateDeviceCertificate)
+{
+ uint8_t derData[ISSUER_MAX_CERT_SIZE] = {0};
+ uint8_t subjPubKey[PUBLIC_KEY_SIZE] = {0};
+ uint8_t subjPrivKey[PRIVATE_KEY_SIZE] = {0};
+ uint8_t caPubKey[PUBLIC_KEY_SIZE] = {0};
+ uint8_t caPrivKey[PRIVATE_KEY_SIZE] = {0};
+ uint8_t *subjName = (uint8_t *)"Subject Name";
+
+ ByteArray certDer = BYTE_ARRAY_INITIALIZER;
+ ByteArray pubKeyIss = BYTE_ARRAY_INITIALIZER;
+ ByteArray privKeyIss = BYTE_ARRAY_INITIALIZER;
+ ByteArray pubKeySubj = BYTE_ARRAY_INITIALIZER;
+ ByteArray privKeySubj = BYTE_ARRAY_INITIALIZER;
+ ByteArray rootName = BYTE_ARRAY_INITIALIZER;
+
+ certDer.data = derData;
+ certDer.len = ISSUER_MAX_CERT_SIZE;
+
+ pubKeyIss.data = caPubKey;
+ pubKeyIss.len = sizeof(caPubKey);
+ privKeyIss.data = caPrivKey;
+ privKeyIss.len = sizeof(caPrivKey);
+ pubKeySubj.data = subjPubKey;
+ pubKeySubj.len = sizeof(subjPubKey);
+ privKeySubj.data = subjPrivKey;
+ privKeySubj.len = sizeof(subjPrivKey);
+ rootName.data = (uint8_t *)"ROOT2";
+ rootName.len = strlen((char *)rootName.data);
+ ASSERT_EQ(PKI_SUCCESS, InitCKMInfo());
+
+ ASSERT_EQ(GenerateCAKeyPair(&privKeyIss, &pubKeyIss), PKI_SUCCESS);
+ for (int i = 1; i <= RUNS; i++)
+ {
+ ASSERT_EQ(PKI_SUCCESS, GenerateKeyPair(&privKeySubj, &pubKeySubj));
+ ASSERT_EQ(PKI_SUCCESS, SetSerialNumber(i));
+ ASSERT_EQ(PKI_SUCCESS, SetRootName(rootName));
+ ASSERT_EQ(PKI_SUCCESS, CKMIssueDeviceCertificate(subjName, 0, 0, subjPubKey, &certDer));
+
+ ASSERT_EQ(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+ certDer.data[0]++;
+ ASSERT_NE(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+ certDer.data[0]--;
+ ASSERT_EQ(PKI_SUCCESS, CheckCertificate(certDer, pubKeyIss));
+ }
+ ASSERT_EQ(CloseCKMInfo(), PKI_SUCCESS);
+}
+
+//check correctness of saving CRL to storage and loading CRL from storage
+TEST_F(PKITest, CRLSetGet)
+{
+ OicSecCrl_t *defaultCrl = NULL;
+ defaultCrl = (OicSecCrl_t *)OICCalloc(1, sizeof(OicSecCrl_t));
+ defaultCrl->CrlId = CRL_DEFAULT_CRL_ID;
+ defaultCrl->CrlData.data = (uint8_t *)CRL_DEFAULT_CRL_DATA;
+ defaultCrl->CrlData.len = strlen(CRL_DEFAULT_CRL_DATA);
+ defaultCrl->ThisUpdate.data = (uint8_t *)CRL_DEFAULT_THIS_UPDATE;
+ defaultCrl->ThisUpdate.len = strlen(CRL_DEFAULT_THIS_UPDATE);
+ EXPECT_EQ(OC_STACK_OK, UpdateCRLResource(defaultCrl));
+
+ EXPECT_NE((void *)NULL, GetBase64CRL());
+ OICFree(defaultCrl);
+
+
+}
+
+int main(int argc, char **argv)
+{
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}