Commit e904ff29 authored by Chul Lee's avatar Chul Lee Committed by Randeep

Manufacturer certificate based ownership transfer support.

1. Add manufacturer certificate OxM callbacks
   : resource/csdk/security/provisioning/src/oxmmanufacturercert.c
   : resource/csdk/security/provisioning/include/oxm/oxmmanufacturercert.h

2. Apply the manufacturer cert based OxM on the client & server.
   : resource/csdk/security/provisioning/src/ownershiptransfermanager.c
   : resource/csdk/security/src/doxmresource.c

3. Add manufacturer certificate supported sample server
   : resource/csdk/security/provisioning/sample/sampleserver_mfg.cpp

4. Add API to set the allowed/not-allowed OxM which is OCSetOxmAllowStatus()
   : resource/csdk/security/provisioning/src/ocprovisioningmanager.c
   : resource/csdk/security/provisioning/include/ocprovisioningmanager.h

5. Add OCStackResult code to handle not allowed OxM exception.
   : resource/csdk/stack/include/octypes.h
   : resource/src/OCException.cpp
   : resource/include/StringConstants.h
   : resource/unittests/OCExceptionTest.cpp

6. Update the SConscript according to above modifications.
   : resource/csdk/security/provisioning/SConscript
   : resource/csdk/security/provisioning/sample/SConscript

Change-Id: Ibb4b4eec33a1e39234f808e32cc3b96aff4879ad
Signed-off-by: default avatarChul Lee <chuls.lee@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/14275Tested-by: default avatarjenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Randeep's avatarRandeep Singh <randeep.s@samsung.com>
(cherry picked from commit 7b7e5a97)
Reviewed-on: https://gerrit.iotivity.org/gerrit/14503
parent 54e90219
......@@ -32,6 +32,7 @@ OCRemoveDeviceWithUuid
OCResetDevice
OCSetOwnerTransferCallbackData
OCUnlinkDevices
OCSetOxmAllowStatus
SetGeneratePinCB
SetInputPinCB
......
......@@ -104,6 +104,7 @@ provisioning_src = [
'src/ocprovisioningmanager.c',
'src/oxmjustworks.c',
'src/oxmrandompin.c',
'src/oxmmanufacturercert.c',
'src/provisioningdatabasemanager.c' ]
if provisioning_env.get('MULTIPLE_OWNER') == '1':
......
......@@ -47,6 +47,17 @@ typedef struct OTMContext OTMContext_t;
OCStackResult OTMDoOwnershipTransfer(void* ctx,
OCProvisionDev_t* selectedDeviceList, OCProvisionResultCB resultCB);
/**
* API to set a allow status of OxM
*
* @param[in] oxm Owership transfer method (ref. OicSecOxm_t)
* @param[in] allowStatus allow status (true = allow, false = not allow)
*
* @return OC_STACK_OK in case of success and other value otherwise.
*/
OCStackResult OTMSetOxmAllowStatus(const OicSecOxm_t oxm, const bool allowStatus);
/*
*Callback for load secret for temporal secure session
*
......
......@@ -81,6 +81,16 @@ OCStackResult OCDoOwnershipTransfer(void* ctx,
OCProvisionDev_t *targetDevices,
OCProvisionResultCB resultCallback);
/**
* API to set a allow status of OxM
*
* @param[in] oxm Owership transfer method (ref. OicSecOxm_t)
* @param[in] allowStatus allow status (true = allow, false = not allow)
*
* @return OC_STACK_OK in case of success and other value otherwise.
*/
OCStackResult OCSetOxmAllowStatus(const OicSecOxm_t oxm, const bool allowStatus);
#ifdef _ENABLE_MULTIPLE_OWNER_
/**
* API to perfrom multiple ownership transfer for MOT enabled device.
......
//******************************************************************
//
// Copyright 2016 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.
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#ifndef _OXM_MANUFACTURER_CERTIFICATE_H_
#define _OXM_MANUFACTURER_CERTIFICATE_H_
#include "ocstack.h"
#include "securevirtualresourcetypes.h"
#include "ownershiptransfermanager.h"
#include "pmtypes.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/**
* Callback implementation to prepare manufacturer certificate based OT.
*
* @param otmCtx Context of OTM, It includes current device information.
*
* @return ::OC_STACK_SUCCESS in case of success and other value otherwise.
*/
OCStackResult PrepareMCertificateCallback(OTMContext_t *otmCtx);
/**
* Callback implementation to establish a secure channel with RSA cipher suite.
*
* @param otmCtx Context of OTM, It includes current device information.
*
* @return ::OC_STACK_SUCCESS in case of success and other value otherwise.
*/
OCStackResult CreateSecureSessionMCertificateCallback(OTMContext_t *otmCtx);
/**
* Generate payload for select OxM request.
*
* @param otmCtx Context of OTM, It includes current device information.
* @param cborPayload is the DOXM CBOR payload including the selected OxM.
* @note Returned memory should be deallocated by caller.
* @param cborSize is the size of the cborPayload.
*
* @return ::OC_STACK_SUCCESS in case of success and other value otherwise.
*/
OCStackResult CreateMCertificateBasedSelectOxmPayload(OTMContext_t *otmCtx, uint8_t **cborPayload,
size_t *cborSize);
/**
* Generate payload for owner transfer request.
*
* @param otmCtx Context of OTM, It includes current device information.
* @param cborPaylaod is the DOXM CBOR payload including the owner information.
* @note Returned memory should be deallocated by caller.
* @param cborSize is the size of the cborPayload.
*
* @return ::OC_STACK_SUCCESS in case of success and other value otherwise.
*/
OCStackResult CreateMCertificateBasedOwnerTransferPayload(OTMContext_t *otmCtx, uint8_t **cborPayload,
size_t *cborSize);
#ifdef __cplusplus
}
#endif
#endif //_OXM_MANUFACTURER_CERTIFICATE_H_
......@@ -103,6 +103,7 @@ if target_os in ['linux', 'tizen']:
provisioningclient = provisioning_env.Program('provisioningclient', 'provisioningclient.c')
sampleserver_justworks = provisioning_env.Program('sampleserver_justworks', 'sampleserver_justworks.cpp')
sampleserver_randompin = provisioning_env.Program('sampleserver_randompin', 'sampleserver_randompin.cpp')
sampleserver_mfg = provisioning_env.Program('sampleserver_mfg', 'sampleserver_mfg.cpp')
if provisioning_env.get('MULTIPLE_OWNER') == '1':
subownerclient = provisioning_env.Program('subownerclient', 'subownerclient.c')
......@@ -127,6 +128,8 @@ justworksdat = provisioning_env.Install(sec_provisioning_build_dir,
sec_provisioning_src_dir + 'oic_svr_db_server_justworks.dat')
randompindat = provisioning_env.Install(sec_provisioning_build_dir,
sec_provisioning_src_dir+ 'oic_svr_db_server_randompin.dat')
mfgdat = provisioning_env.Install(sec_provisioning_build_dir,
sec_provisioning_src_dir+ 'oic_svr_db_server_mfg.dat')
randompin_with_emptyuuid_dat = provisioning_env.Install(sec_provisioning_build_dir,
sec_provisioning_src_dir+ 'oic_svr_db_randompin_with_empty_deviceid.dat')
......@@ -145,16 +148,16 @@ if provisioning_env.get('WITH_TCP') == True:
if provisioning_env.get('MULTIPLE_OWNER') == '1':
Alias("samples", [
provisioningclient, subownerclient,
sampleserver_justworks, sampleserver_randompin,
sampleserver_justworks, sampleserver_randompin, sampleserver_mfg,
clientdat, subownerclientdat,
justworksdat, randompindat, randompin_with_emptyuuid_dat
justworksdat, randompindat, mfgdat, randompin_with_emptyuuid_dat
])
else:
Alias("samples", [
provisioningclient,
sampleserver_justworks, sampleserver_randompin,
sampleserver_justworks, sampleserver_randompin, sampleserver_mfg,
clientdat,
justworksdat, randompindat, randompin_with_emptyuuid_dat
justworksdat, randompindat, mfgdat, randompin_with_emptyuuid_dat
])
provisioning_env.AppendTarget('samples')
......
......@@ -2099,6 +2099,12 @@ int main()
goto PMCLT_ERROR;
}
// Client can choose a allowed/not-allowed OxM method.
if(OC_STACK_OK != OCSetOxmAllowStatus(OIC_DECENTRALIZED_PUBLIC_KEY, false))
{
OIC_LOG(WARNING, TAG, "Failed to disable OIC_DECENTRALIZED_PUBLIC_KEY OxM");
}
#ifdef _ENABLE_MULTIPLE_OWNER_
SetPreconfigPin("12341234", 8);
#endif //_ENABLE_MULTIPLE_OWNER_
......
/******************************************************************
*
* Copyright 2016 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.
*
******************************************************************/
///////////////////////////////////////////////////////////////////////
//NOTE : This sample server is generated based on ocserverbasicops.cpp
///////////////////////////////////////////////////////////////////////
#include "iotivity_config.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#endif
#include <signal.h>
#include "ocstack.h"
#include "ocpayload.h"
#ifdef HAVE_WINDOWS_H
#include <windows.h>
/** @todo stop-gap for naming issue. Windows.h does not like us to use ERROR */
#ifdef ERROR
#undef ERROR
#endif //ERROR
#endif //HAVE_WINDOWS_H
#include "platform_features.h"
#include "logger.h"
#define TAG "SAMPLE_MANUFACTURER_CERT"
int gQuitFlag = 0;
/* Structure to represent a LED resource */
typedef struct LEDRESOURCE{
OCResourceHandle handle;
bool state;
int power;
} LEDResource;
static LEDResource LED;
// This variable determines instance number of the LED resource.
// Used by POST method to create a new instance of LED resource.
static int gCurrLedInstance = 0;
#define SAMPLE_MAX_NUM_POST_INSTANCE 2
static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
char *gResourceUri= (char *)"/a/led";
//Secure Virtual Resource database for Iotivity Server
//It contains Server's Identity and the manufacturer certificate
static char CRED_FILE[] = "oic_svr_db_server_mfg.dat";
/* Function that creates a new LED resource by calling the
* OCCreateResource() method.
*/
int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower);
/* This method converts the payload to JSON format */
OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest);
/* Following methods process the PUT, GET, POST
* requests
*/
OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
OCRepPayload **payload);
OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
OCRepPayload **payload);
OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
OCEntityHandlerResponse *response,
OCRepPayload **payload);
/* Entity Handler callback functions */
OCEntityHandlerResult
OCEntityHandlerCb (OCEntityHandlerFlag flag,
OCEntityHandlerRequest *entityHandlerRequest,
void* callbackParam);
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";
#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";
}
}
OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
{
OCRepPayload* payload = OCRepPayloadCreate();
if(!payload)
{
OIC_LOG(ERROR, TAG, "Failed to allocate Payload");
return NULL;
}
OCRepPayloadSetUri(payload, uri);
OCRepPayloadSetPropBool(payload, "state", state);
OCRepPayloadSetPropInt(payload, "power", power);
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)
{
OIC_LOG(ERROR, TAG, "Incoming payload not a representation");
return NULL;
}
OCRepPayload* input = (OCRepPayload*)(ehRequest->payload);
LEDResource *currLEDResource = &LED;
if (ehRequest->resource == gLedInstance[0].handle)
{
currLEDResource = &gLedInstance[0];
gResourceUri = (char *) "/a/led/0";
}
else if (ehRequest->resource == gLedInstance[1].handle)
{
currLEDResource = &gLedInstance[1];
gResourceUri = (char *) "/a/led/1";
}
if(OC_REST_PUT == ehRequest->method)
{
// Get pointer to query
int64_t pow;
if(OCRepPayloadGetPropInt(input, "power", &pow))
{
currLEDResource->power =pow;
}
bool state;
if(OCRepPayloadGetPropBool(input, "state", &state))
{
currLEDResource->state = state;
}
}
return getPayload(gResourceUri, currLEDResource->power, currLEDResource->state);
}
OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
OCRepPayload **payload)
{
OCEntityHandlerResult ehResult;
OCRepPayload *getResp = constructResponse(ehRequest);
if(getResp)
{
*payload = getResp;
ehResult = OC_EH_OK;
}
else
{
ehResult = OC_EH_ERROR;
}
return ehResult;
}
OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
OCRepPayload **payload)
{
OCEntityHandlerResult ehResult;
OCRepPayload *putResp = constructResponse(ehRequest);
if(putResp)
{
*payload = putResp;
ehResult = OC_EH_OK;
}
else
{
ehResult = OC_EH_ERROR;
}
return ehResult;
}
OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
OCEntityHandlerResponse *response, OCRepPayload **payload)
{
OCRepPayload *respPLPost_led = NULL;
OCEntityHandlerResult ehResult = OC_EH_OK;
/*
* The entity handler determines how to process a POST request.
* Per the REST paradigm, POST can also be used to update representation of existing
* resource or create a new resource.
* In the sample below, if the POST is for /a/led then a new instance of the LED
* resource is created with default representation (if representation is included in
* POST payload it can be used as initial values) as long as the instance is
* lesser than max new instance count. Once max instance count is reached, POST on
* /a/led updated the representation of /a/led (just like PUT)
*/
if (ehRequest->resource == LED.handle)
{
if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
{
// Create new LED instance
char newLedUri[15] = "/a/led/";
int newLedUriLength = strlen(newLedUri);
snprintf (newLedUri + newLedUriLength, sizeof(newLedUri)-newLedUriLength, "%d", gCurrLedInstance);
respPLPost_led = OCRepPayloadCreate();
OCRepPayloadSetUri(respPLPost_led, gResourceUri);
OCRepPayloadSetPropString(respPLPost_led, "createduri", newLedUri);
if (0 == createLEDResource (newLedUri, &gLedInstance[gCurrLedInstance], false, 0))
{
OIC_LOG (INFO, TAG, "Created new LED instance");
gLedInstance[gCurrLedInstance].state = 0;
gLedInstance[gCurrLedInstance].power = 0;
gCurrLedInstance++;
strncpy ((char *)response->resourceUri, newLedUri, MAX_URI_LENGTH);
ehResult = OC_EH_RESOURCE_CREATED;
}
}
else
{
respPLPost_led = constructResponse(ehRequest);
}
}
else
{
for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
{
if (ehRequest->resource == gLedInstance[i].handle)
{
if (i == 0)
{
respPLPost_led = constructResponse(ehRequest);
break;
}
else if (i == 1)
{
respPLPost_led = constructResponse(ehRequest);
}
}
}
}
if (respPLPost_led != NULL)
{
*payload = respPLPost_led;
ehResult = OC_EH_OK;
}
else
{
OIC_LOG_V (INFO, TAG, "Payload was NULL");
ehResult = OC_EH_ERROR;
}
return ehResult;
}
OCEntityHandlerResult
OCEntityHandlerCb (OCEntityHandlerFlag flag,
OCEntityHandlerRequest *entityHandlerRequest,
void* callbackParam)
{
OIC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
(void)callbackParam;
OCEntityHandlerResult ehResult = OC_EH_ERROR;
OCEntityHandlerResponse response;
memset(&response, 0, sizeof(response));
// Validate pointer
if (!entityHandlerRequest)
{
OIC_LOG (ERROR, TAG, "Invalid request pointer");
return OC_EH_ERROR;
}
OCRepPayload* payload = NULL;
if (flag & OC_REQUEST_FLAG)
{
OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
if (entityHandlerRequest)
{
if (OC_REST_GET == entityHandlerRequest->method)
{
OIC_LOG (INFO, TAG, "Received OC_REST_GET from client");
ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
}
else if (OC_REST_PUT == entityHandlerRequest->method)
{
OIC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
}
else if (OC_REST_POST == entityHandlerRequest->method)
{
OIC_LOG (INFO, TAG, "Received OC_REST_POST from client");
ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
}
else
{
OIC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
entityHandlerRequest->method);
ehResult = OC_EH_ERROR;
}
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 = (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)
{
OIC_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)
{
(void)path;
return fopen(CRED_FILE, mode);
}
int main()
{
struct timespec timeout;
OIC_LOG(DEBUG, TAG, "OCServer is starting...");
// Initialize Persistent Storage for SVR database
OCPersistentStorage ps = {server_fopen, fread, fwrite, fclose, unlink};
OCRegisterPersistentStorageHandler(&ps);
if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
{
OIC_LOG(ERROR, TAG, "OCStack init error");