help_vars.Add(EnumVariable('TARGET_ARCH', 'Target architecture', default_arch, os_arch_map[target_os]))
help_vars.Add(EnumVariable('SECURED', 'Build with DTLS', '0', allowed_values=('0', '1')))
+help_vars.Add(EnumVariable('MULTIPLE_OWNER', 'Enable multiple owner', '0', allowed_values=('0', '1')))
help_vars.Add(EnumVariable('TEST', 'Run unit tests', '0', allowed_values=('0', '1')))
help_vars.Add(BoolVariable('LOGGING', 'Enable stack logging', logging_default))
help_vars.Add(BoolVariable('UPLOAD', 'Upload binary ? (For Arduino)', require_upload))
typedef int (*CAgetPskCredentialsHandler)(CADtlsPskCredType_t type,
const uint8_t *desc, size_t desc_len,
uint8_t *result, size_t result_length);
+
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * API to get a secure connected peer information
+ *
+ * @param[in] peer peer information includs IP address and port.
+ *
+ * @return secure connected peer information on success, otherwise NULL
+ */
+const CASecureEndpoint_t *CAGetSecureEndpointData(const CAEndpoint_t *peer);
+#endif //_ENABLE_MULTIPLE_OWNER_
+#endif
+
/**
* This internal callback is used by CA layer to
* retrieve all credential types from SRM
const uint8_t* rsrcServerDeviceId, const size_t rsrcServerDeviceIdLen,
const uint8_t* provServerDeviceId, const size_t provServerDeviceIdLen,
uint8_t* ownerPsk, const size_t ownerPskSize);
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * Gets CA secure endpoint info corresponding for endpoint.
+ *
+ * @param[in] peer remote address
+ *
+ * @return CASecureEndpoint or NULL
+ */
+const CASecureEndpoint_t *GetCASecureEndpointData(const CAEndpoint_t* peer);
+#endif
+
#ifdef __cplusplus
}
#endif //__cplusplus
void CADTLSSetHandshakeCallback(CAErrorCallback dtlsHandshakeCallback);
/**
- * Register callback to get DTLS PSK credentials.
- * @param[in] credCallback callback to get DTLS PSK credentials.
- */
-void CADTLSSetCredentialsCallback(CAGetDTLSPskCredentialsHandler credCallback);
-
-/**
* Select the cipher suite for dtls handshake
*
* @param[in] cipher cipher suite
uint8_t *data,
uint32_t dataLen);
+
+/**
+ * API to get a secure connected peer information
+ * NOTE : This API use the mutex lock to access 'g_caDtlsContext',
+ * Please do not invoke this API for internal function of dtls adapter
+ *
+ * @param[in] peer peer information includs IP address and port.
+ *
+ * @ return secure connected peer information on success, otherwise NULL
+ */
+CASecureEndpoint_t *CAGetSecurePeerInfo(const CAEndpoint_t *peer);
+
#endif /* CA_ADAPTER_NET_DTLS_H_ */
ca_os = env.get('TARGET_OS')
ca_transport = env.get('TARGET_TRANSPORT')
secured = env.get('SECURED')
+multiple_owner = env.get('MULTIPLE_OWNER')
with_ra = env.get ('WITH_RA')
with_ra_ibb = env.get('WITH_RA_IBB')
with_tcp = env.get('WITH_TCP')
if ((secured == '1') and (with_tcp == True)):
env.AppendUnique(CPPDEFINES = ['__WITH_TLS__'])
+if (multiple_owner == '1'):
+ env.AppendUnique(CPPDEFINES=['_ENABLE_MULTIPLE_OWNER_'])
+
ca_common_src = None
if with_ra:
transports.append('ra_adapter')
- if ca_os in ['linux']:
+ if ca_os in ['linux']:
transports.append('ip_adapter')
transports.append('bt_le_adapter')
- elif ca_os in ['tizen']:
+ elif ca_os in ['tizen']:
transports.append('ip_adapter')
transports.append('bt_edr_adapter')
transports.append('bt_le_adapter')
- elif ca_os in ['android']:
+ elif ca_os in ['android']:
transports.append('ip_adapter')
transports.append('bt_edr_adapter')
transports.append('bt_le_adapter')
OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
return NULL;
}
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * Gets CA secure endpoint info corresponding for endpoint.
+ *
+ * @param[in] peer remote address
+ *
+ * @return CASecureEndpoint or NULL
+ */
+const CASecureEndpoint_t *GetCASecureEndpointData(const CAEndpoint_t* peer)
+{
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "In %s", __func__);
+
+ // TODO: Added as workaround, need to debug
+ ca_mutex_unlock(g_sslContextMutex);
+
+ ca_mutex_lock(g_sslContextMutex);
+ if (NULL == g_caSslContext)
+ {
+ OIC_LOG(ERROR, NET_SSL_TAG, "Context is NULL");
+ ca_mutex_unlock(g_sslContextMutex);
+ return NULL;
+ }
+
+ SslEndPoint_t* sslPeer = GetSslPeer(peer);
+ if(sslPeer)
+ {
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+ ca_mutex_unlock(g_sslContextMutex);
+ return &sslPeer->sep;
+ }
+
+ OIC_LOG(DEBUG, NET_SSL_TAG, "Return NULL");
+ OIC_LOG_V(DEBUG, NET_SSL_TAG, "Out %s", __func__);
+ ca_mutex_unlock(g_sslContextMutex);
+ return NULL;
+}
+#endif
+
/**
* Deletes cached message.
*
VERIFY_NON_NULL_RET(provServerDeviceId, NET_SSL_TAG, "provId is NULL", CA_STATUS_INVALID_PARAM);
VERIFY_NON_NULL_RET(ownerPsk, NET_SSL_TAG, "ownerPSK is NULL", CA_STATUS_INVALID_PARAM);
+ // TODO: Added as workaround, need to debug
+ ca_mutex_unlock(g_sslContextMutex);
+
ca_mutex_lock(g_sslContextMutex);
if (NULL == g_caSslContext)
{
CASetInterfaceCallbacks(ReqHandler, RespHandler, ErrorHandler);
}
+
#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
+#ifdef _ENABLE_MULTIPLE_OWNER_
+const CASecureEndpoint_t *CAGetSecureEndpointData(const CAEndpoint_t *peer)
+{
+ OIC_LOG(DEBUG, TAG, "IN CAGetSecurePeerInfo");
+
+ if (!g_isInitialized)
+ {
+ OIC_LOG(DEBUG, TAG, "CA is not initialized");
+ return NULL;
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT CAGetSecurePeerInfo");
+ return GetCASecureEndpointData(peer);
+}
+#endif //_ENABLE_MULTIPLE_OWNER_
+
CAResult_t CAregisterSslHandshakeCallback(CAErrorCallback tlsHandshakeCallback)
{
OIC_LOG(DEBUG, TAG, "CAregisterSslHandshakeCallback");
-
if(!g_isInitialized)
{
return CA_STATUS_NOT_INITIALIZED;
if env.get('LOGGING'):
libocsrm_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+if env.get('MULTIPLE_OWNER') == '1':
+ libocsrm_env.AppendUnique(CPPDEFINES=['_ENABLE_MULTIPLE_OWNER_'])
+
######################################################################
# Source files and Targets
######################################################################
*/
OCStackResult AclToCBORPayload(const OicSecAcl_t * acl, uint8_t **outPayload, size_t *size);
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * Function to check the ACL access of SubOwner
+ *
+ * @param[in] uuid SubOwner's UUID
+ * @param[in] cborPayload CBOR payload of ACL
+ * @param[in] size Byte length of cborPayload
+ *
+ * @return ::true for valid access, otherwise invalid access
+ */
+bool IsValidAclAccessForSubOwner(const OicUuid_t* uuid, const uint8_t *cborPayload, const size_t size);
+#endif //_ENABLE_MULTIPLE_OWNER_
+
+
/**
* This method removes ACE for the subject and resource from the ACL
*
OCStackResult CredToCBORPayload(const OicSecCred_t* cred, uint8_t **cborPayload,
size_t *cborSize, int secureFlag);
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * Function to check the credential access of SubOwner
+ *
+ * @param[in] uuid SubOwner's UUID
+ * @param[in] cborPayload CBOR payload of credential
+ * @param[in] size Byte length of cborPayload
+ *
+ * @return ::true for valid access, otherwise invalid access
+ */
+bool IsValidCredentialAccessForSubOwner(const OicUuid_t* uuid, const uint8_t *cborPayload, size_t size);
+#endif //_ENABLE_MULTIPLE_OWNER_
+
/**
* This function generates the bin credential data.
*
* @param publicData public data such as public key.
* @param privateData private data such as private key.
* @param rownerID Resource owner's UUID.
+ * @param eownerID Entry owner's UUID.
*
* @return pointer to instance of @ref OicSecCred_t if successful. else NULL in case of error.
*/
OicSecCred_t * GenerateCredential(const OicUuid_t* subject, OicSecCredType_t credType,
const OicSecCert_t * publicData, const OicSecKey_t * privateData,
- const OicUuid_t * rownerID);
+ const OicUuid_t * rownerID, const OicUuid_t * eownerID);
/**
* This function adds the new cred to the credential list.
#define IOTVT_SRM_DOXM_H
#include "octypes.h"
+#ifdef _ENABLE_MULTIPLE_OWNER_
+#include "cacommon.h"
+#endif //_ENABLE_MULTIPLE_OWNER_
#ifdef __cplusplus
extern "C" {
* Gets the bool state of "isOwned" property on the doxm resource.
*
* @param isOwned a pointer to be assigned to isOwned property
- * @return ::OC_STACK_OK if isOwned is assigned correctly, else ::OC_STACK_ERROR.
+ * @return ::OC_STACK_OK if isOwned is assigned correctly, else ::OC_STACK_ERROR.
*/
OCStackResult GetDoxmIsOwned(bool *isOwned);
*/
OCStackResult GetDoxmRownerId(OicUuid_t *rowneruuid);
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * Compare the UUID to SubOwner.
+ *
+ * @param[in] uuid device UUID
+ *
+ * @return true if uuid exists in the SubOwner list of doxm, else false.
+ */
+bool IsSubOwner(const OicUuid_t* uuid);
+#endif //_ENABLE_MULTIPLE_OWNER_
+
/** This function deallocates the memory for OicSecDoxm_t .
*
* @param doxm is the pointer to @ref OicSecDoxm_t.
*/
void RestoreDoxmToInitState();
+#if defined(__WITH_DTLS__) && defined(_ENABLE_MULTIPLE_OWNER_)
+/**
+ * Callback function to handle MOT DTLS handshake result.
+ * @param[out] object remote device information.
+ * @param[out] errorInfo CA Error information.
+ */
+void MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *object,
+ const CAErrorInfo_t *errorInfo);
+#endif //__WITH_DTLS__ && _ENABLE_MULTIPLE_OWNER_
+
#ifdef __cplusplus
}
#endif
bool amsProcessing;
SRMAccessResponse_t retVal;
AmsMgrContext_t *amsMgrContext;
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ uint8_t* payload;
+ size_t payloadSize;
+#endif //_ENABLE_MULTIPLE_OWNER_
} PEContext_t;
/**
extern const char * OIC_JSON_OWNERS_NAME;
extern const char * OIC_JSON_OWNER_NAME;
extern const char * OIC_JSON_DEVOWNERID_NAME;
+#ifdef _ENABLE_MULTIPLE_OWNER_
+extern const char * OIC_JSON_SUBOWNERID_NAME;
+#endif //_ENABLE_MULTIPLE_OWNER_
extern const char * OIC_JSON_OWNED_NAME;
extern const char * OIC_JSON_OXM_NAME;
extern const char * OIC_JSON_OXMS_NAME;
+#ifdef _ENABLE_MULTIPLE_OWNER_
+extern const char * OIC_JSON_MOM_NAME;
+#endif //_ENABLE_MULTIPLE_OWNER_
extern const char * OIC_JSON_OXM_TYPE_NAME;
extern const char * OIC_JSON_OXM_SEL_NAME;
extern const char * OIC_JSON_DEVICE_ID_FORMAT_NAME;
extern const char * OIC_JSON_RT_NAME;
extern const char * OIC_JSON_IF_NAME;
extern const char * OIC_JSON_ROWNERID_NAME;
+#ifdef _ENABLE_MULTIPLE_OWNER_
+extern const char * OIC_JSON_EOWNERID_NAME;
+#endif //_ENABLE_MULTIPLE_OWNER_
extern const char * OIC_JSON_ENCODING_NAME;
extern const char * OIC_JSON_DATA_NAME;
extern const char * OIC_JSON_SEC_V_NAME;
extern const char * OXM_JUST_WORKS;
extern const char * OXM_RANDOM_DEVICE_PIN;
extern const char * OXM_MANUFACTURER_CERTIFICATE;
+#ifdef _ENABLE_MULTIPLE_OWNER_
+extern const char * OXM_PRECONF_PIN;
+#endif //_ENABLE_MULTIPLE_OWNER_
extern const char * OIC_SEC_ENCODING_BASE64;
extern const char * OIC_SEC_ENCODING_RAW;
extern "C" {
#endif // __cplusplus
-#define OXM_RANDOM_PIN_SIZE 8
+#define OXM_RANDOM_PIN_SIZE (8)
+#define OXM_PRECONFIG_PIN_SIZE (OXM_RANDOM_PIN_SIZE)
+
/**
* Function pointer to print pin code.
*/
void SetInputPinCB(InputPinCallback pinCB);
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * Function to save the preconfig PIN getter from user.
+ *
+ * @param pinCB implementation of preconfig PIN function.
+ */
+void SetGetPreconfigPinCB(InputPinCallback pinCB);
+#endif //_ENABLE_MULTIPLE_OWNER_
+
/**
* Function to generate random PIN.
* This function will send generated PIN to user via callback.
*/
OCStackResult InputPin(char* pinBuffer, size_t bufferSize);
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * Function to save the Pre-configured PIN.
+ *
+ * @param[in] pinBuffer PIN data
+ * @param[in] pinLength byte length of PIN
+ *
+ * @return ::OC_STACK_SUCCESS in case of success or other value in ccase of error.
+ */
+OCStackResult SetPreconfigPin(const char* pinBuffer, size_t pinLength);
+
+/**
+ * Function to read preconfig PIN.
+ *
+ * @param[in,out] pinBuffer is the reference to the buffer to store the preconfigured PIN.
+ * @param[in] bufferSize is the size of buffer.
+ *
+ * @return ::OC_STACK_SUCCESS in case of success or other value in ccase of error.
+ */
+OCStackResult GetPreconfigPin(char* pinBuffer, size_t bufferSize);
+#endif
+
#ifdef __WITH_DTLS__
/**
* This function is used by OTM and SRM to
* register device UUID is required to derive the temporal PSK.
*/
-void SetUuidForRandomPinOxm(const OicUuid_t* uuid);
+void SetUuidForPinBasedOxm(const OicUuid_t* uuid);
/**
- * This internal callback is used while PIN based ownership transfer.
+ * This internal callback is used while Random PIN based OTM.
* This callback will be used to establish a temporary secure session according to
* TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256.
*
* @param[in] type type of PSK data required by tinyDTLS layer during DTLS handshake.
- * @param[in] desc UNUSED.
- * @param[in] desc_len UNUSED.
+ * @param[in] UNUSED1 UNUSED.
+ * @param[in] UNUSED2 UNUSED.
* @param[out] result Must be filled with the requested information.
* @param[in] result_length Maximum size of @p result.
*
int32_t GetDtlsPskForRandomPinOxm( CADtlsPskCredType_t type,
const unsigned char *UNUSED1, size_t UNUSED2,
unsigned char *result, size_t result_length);
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * This internal callback is used while Random PIN based MOT.
+ * This callback will be used to establish a temporary secure session according to
+ * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256.
+ *
+ * @param[in] type type of PSK data required by tinyDTLS layer during DTLS handshake.
+ * @param[in] UNUSED1 UNUSED.
+ * @param[in] UNUSED2 UNUSED.
+ * @param[out] result Must be filled with the requested information.
+ * @param[in] result_length Maximum size of @p result.
+ *
+ * @return The number of bytes written to @p result or a value
+ * less than zero on error.
+ */
+int32_t GetDtlsPskForMotRandomPinOxm( CADtlsPskCredType_t type,
+ const unsigned char *UNUSED1, size_t UNUSED2,
+ unsigned char *result, size_t result_length);
+
+
+/**
+ * This internal callback is used while Preconfigured-PIN OTM.
+ * This callback will be used to establish a temporary secure session according to
+ * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256.
+ *
+ * @param[in] type type of PSK data required by tinyDTLS layer during DTLS handshake.
+ * @param[in] UNUSED1 UNUSED.
+ * @param[in] UNUSED2 UNUSED.
+ * @param[out] result Must be filled with the requested information.
+ * @param[in] result_length Maximum size of @p result.
+ *
+ * @return The number of bytes written to @p result or a value
+ * less than zero on error.
+ */
+int32_t GetDtlsPskForPreconfPinOxm( CADtlsPskCredType_t type,
+ const unsigned char *UNUSED1, size_t UNUSED2,
+ unsigned char *result, size_t result_length);
+
+
+/**
+ * This internal callback is used while Preconfigured-PIN MOT.
+ * This callback will be used to establish a temporary secure session according to
+ * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256.
+ *
+ * @param[in] type type of PSK data required by tinyDTLS layer during DTLS handshake.
+ * @param[in] UNUSED1 UNUSED.
+ * @param[in] UNUSED2 UNUSED.
+ * @param[out] result Must be filled with the requested information.
+ * @param[in] result_length Maximum size of @p result.
+ *
+ * @return The number of bytes written to @p result or a value
+ * less than zero on error.
+ */
+int32_t GetDtlsPskForMotPreconfPinOxm( CADtlsPskCredType_t type,
+ const unsigned char *UNUSED1, size_t UNUSED2,
+ unsigned char *result, size_t result_length);
+
+#endif //_ENABLE_MULTIPLE_OWNER_
+
+
+/**
+ * API to derive the PSK based on PIN and new device's UUID.
+ * New device's UUID should be set through SetUuidForPinBasedOxm() API before this API is invoked.
+ *
+ * @param[out] result generated PSK
+ *
+ * @return 0 for success, otherwise error.
+ */
+int DerivePSKUsingPIN(uint8_t* result);
+
#endif //__WITH_DTLS__
#ifdef __cplusplus
SECURITY_MANAGEMENT_SERVICES = (0x1 << 3),
PROVISION_CREDENTIALS = (0x1 << 4),
PROVISION_ACLS = (0x1 << 5),
- // << 6 THROUGH 15 RESERVED
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ TAKE_SUB_OWNER = (0x1 << 6),
+#endif
+ // << 7 THROUGH 15 RESERVED
} OicSecDpm_t;
// These types are taken from the Security Spec v1.1.12 /pstat resource definition
OIC_JUST_WORKS = 0x0,
OIC_RANDOM_DEVICE_PIN = 0x1,
OIC_MANUFACTURER_CERTIFICATE = 0x2,
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ OIC_PRECONFIG_PIN = 0x3,
+#endif //_ENABLE_MULTIPLE_OWNER_
OIC_OXM_COUNT
}OicSecOxm_t;
OIC_ENCODING_DER = 4
}OicEncodingType_t;
+#ifdef _ENABLE_MULTIPLE_OWNER_
+typedef enum
+{
+ MOT_STATUS_READY = 0,
+ MOT_STATUS_IN_PROGRESS = 1,
+ MOT_STATUS_DONE = 2,
+}MotStatus_t;
+#endif //_ENABLE_MULTIPLE_OWNER_
+
+/*
+ * oic.sec.mom type definition
+ * TODO: This type will be included to OIC Security Spec.
+ * 0 : Disable multiple owner
+ * 1 : Enable multiple owner (Always on)
+ * 2 : Timely multiple owner enable
+ */
+typedef enum
+{
+ OIC_MULTIPLE_OWNER_DISABLE = 0,
+ OIC_MULTIPLE_OWNER_ENABLE = 1,
+ OIC_MULTIPLE_OWNER_TIMELY_ENABLE = 2,
+ OIC_NUMBER_OF_MOM_TYPE = 3
+}OicSecMomType_t;
+
typedef struct OicSecKey OicSecKey_t;
typedef struct OicSecPstat OicSecPstat_t;
typedef struct OicUuid OicUuid_t; //TODO is UUID type defined elsewhere?
+#ifdef _ENABLE_MULTIPLE_OWNER_
+typedef struct OicSecSubOwner OicSecSubOwner_t;
+typedef struct OicSecMom OicSecMom_t;
+#endif //_ENABLE_MULTIPLE_OWNER_
+
#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
typedef struct OicSecCrl OicSecCrl_t;
struct OicSecAce
{
// <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
- OicUuid_t subjectuuid; // 0:R:S:Y:uuid
- OicSecRsrc_t *resources; // 1:R:M:Y:Resource
- uint16_t permission; // 2:R:S:Y:UINT16
- OicSecValidity_t *validities; // 3:R:M:N:Time-interval
+ OicUuid_t subjectuuid; // 0:R:S:Y:uuid
+ OicSecRsrc_t *resources; // 1:R:M:Y:Resource
+ uint16_t permission; // 2:R:S:Y:UINT16
+ OicSecValidity_t *validities; // 3:R:M:N:Time-interval
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ OicUuid_t* eownerID; //4:R:S:N:oic.uuid
+#endif
OicSecAce_t *next;
};
#endif /* __WITH_DTLS__ or __WITH_TLS__*/
OicSecKey_t privateData; // 6:R:S:N:oic.sec.key
char *period; // 7:R:S:N:String
- OicUuid_t rownerID; // 8:R:S:Y:oic.uuid
+ OicUuid_t rownerID; // 8:R:S:Y:oic.uuid
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ OicUuid_t *eownerID; //9:R:S:N:oic.uuid
+#endif //_ENABLE_MULTIPLE_OWNER_
OicSecCred_t *next;
};
+#ifdef _ENABLE_MULTIPLE_OWNER_
+struct OicSecSubOwner {
+ OicUuid_t uuid;
+ MotStatus_t status;
+ OicSecSubOwner_t* next;
+};
+
+struct OicSecMom{
+ OicSecMomType_t mode;
+};
+#endif //_ENABLE_MULTIPLE_OWNER_
+
/**
* /oic/sec/doxm (Device Owner Transfer Methods) data type
* Derived from OIC Security Spec; see Spec for details.
OicUuid_t deviceID; // 6:R:S:Y:oic.uuid
bool dpc; // 7:R:S:Y:Boolean
OicUuid_t owner; // 8:R:S:Y:oic.uuid
- OicUuid_t rownerID; // 9:R:S:Y:oic.uuid
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ OicSecSubOwner_t* subOwners; //9:R/W:M:N:oic.uuid
+ OicSecMom_t *mom; //10:R/W:S:N:oic.sec.mom
+#endif //_ENABLE_MULTIPLE_OWNER_
+ OicUuid_t rownerID; // 11:R:S:Y:oic.uuid
};
/**
if provisioning_env.get('LOGGING'):
provisioning_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+if provisioning_env.get('MULTIPLE_OWNER') == '1':
+ provisioning_env.AppendUnique(CPPDEFINES=['_ENABLE_MULTIPLE_OWNER_'])
+
######################################################################
# Source files and Targets
######################################################################
'src/oxmrandompin.c',
'src/provisioningdatabasemanager.c' ]
+if provisioning_env.get('MULTIPLE_OWNER') == '1':
+ provisioning_src = provisioning_src + [
+ 'src/multipleownershiptransfermanager.c',
+ 'src/oxmpreconfpin.c']
+
if provisioning_env.get('WITH_TCP') == True:
provisioning_env.AppendUnique(CPPDEFINES= ['__WITH_TLS__'])
provisioning_src = provisioning_src + [
--- /dev/null
+/* *****************************************************************
+ *
+ * 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 OTM_MULTIPLE_OWNERSHIPTRANSFERMANAGER_H_
+#define OTM_MULTIPLE_OWNERSHIPTRANSFERMANAGER_H_
+
+#include "pmtypes.h"
+#include "ocstack.h"
+#include "octypes.h"
+#include "securevirtualresourcetypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**********************************************************************
+ * API for Super Owner
+ **********************************************************************/
+
+/**
+ * API to add 'doxm.oxms' to resource server.
+ *
+ * @param[in] targetDeviceInfo Selected target device.
+ * @param[in] newOxm OxMs to be added (ref. oic.sec.oxm)
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * POST 'oxms' request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult MOTAddMOTMethod(void *ctx, OCProvisionDev_t *targetDeviceInfo,
+ const OicSecOxm_t newOxm, OCProvisionResultCB resultCallback);
+
+/**
+ * API to update 'doxm.oxmsel' to resource server.
+ *
+ * @param[in] targetDeviceInfo Selected target device.
+ * @param[in] oxmSelValue Method of multiple ownership transfer (ref. oic.sec.oxm)
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * POST 'oxmsel' request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult MOTSelectMOTMethod(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
+ const OicSecOxm_t oxmSelValue, OCProvisionResultCB resultCallback);
+
+/**
+ * API to update 'doxm.mom' to resource server.
+ *
+ * @param[in] targetDeviceInfo Selected target device.
+ * @param[in] momType Mode of multiple ownership transfer (ref. oic.sec.mom)
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * POST 'mom' request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult MOTChangeMode(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
+ const OicSecMomType_t momType, OCProvisionResultCB resultCallback);
+
+/**
+ * API to provision preconfigured PIN to resource server.
+ *
+ * @param[in] targetDeviceInfo Selected target device.
+ * @param[in] preconfPIN Preconfig PIN which is used while multiple owner authentication
+ * @param[in] preconfPINLen Byte length of preconfig PIN
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * POST credential request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult MOTProvisionPreconfigPIN(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
+ const char* preconfPIN, size_t preconfPINLen, OCProvisionResultCB resultCallback);
+
+/**********************************************************************
+ * API for Sub Owner
+ **********************************************************************/
+
+/**
+ * API to perform the multiple ownership transfer.
+ *
+ * @param[in] ctx Application context would be returned in result callback
+ * @param[in] selectedDeviceList linked list of multiple ownership transfer candidate devices.
+ * @param[in] resultCB Result callback function to be invoked when multiple ownership transfer finished.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult MOTDoOwnershipTransfer(void* ctx,
+ OCProvisionDev_t *selectedDevicelist,
+ OCProvisionResultCB resultCallback);
+
+
+/**
+ * API to add preconfigured PIN to local SVR DB.
+ *
+ * @param[in] targetDeviceInfo Selected target device.
+ * @param[in] preconfPIN Preconfig PIN which is used while multiple owner authentication
+ * @param[in] preconfPINLen Byte length of preconfig PIN
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult MOTAddPreconfigPIN(const OCProvisionDev_t *targetDeviceInfo,
+ const char* preconfPIN, size_t preconfPINLen);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //OTM_MULTIPLE_OWNERSHIPTRANSFERMANAGER_H_
\ No newline at end of file
#include "octypes.h"\r
#include "pmtypes.h"\r
#include "ownershiptransfermanager.h"\r
+#ifdef _ENABLE_MULTIPLE_OWNER_\r
+#include "securevirtualresourcetypes.h"\r
+#endif //_ENABLE_MULTIPLE_OWNER_\r
\r
#ifdef __cplusplus\r
extern "C" {\r
OCProvisionDev_t *targetDevices,\r
OCProvisionResultCB resultCallback);\r
\r
+#ifdef _ENABLE_MULTIPLE_OWNER_\r
+/**\r
+ * API to perfrom multiple ownership transfer for MOT enabled device.\r
+ *\r
+ * @param[in] ctx Application context would be returned in result callback\r
+ * @param[in] targetDevices List of devices to perform ownership transfer.\r
+ * @param[in] resultCallback Result callback function to be invoked when ownership transfer finished.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCDoMultipleOwnershipTransfer(void* ctx,\r
+ OCProvisionDev_t *targetDevices,\r
+ OCProvisionResultCB resultCallback);\r
+#endif //_ENABLE_MULTIPLE_OWNER_\r
+\r
/**\r
* API to register for particular OxM.\r
*\r
*/\r
OCStackResult OCDiscoverOwnedDevices(unsigned short timeout, OCProvisionDev_t **ppList);\r
\r
+#ifdef _ENABLE_MULTIPLE_OWNER_\r
+/**\r
+ * The function is responsible for discovery of MOT enabled device is current subnet.\r
+ *\r
+ * @param[in] timeout Timeout in seconds, value till which function will listen to responses from\r
+ * server before returning the list of devices.\r
+ * @param[out] ppList List of MOT enabled devices.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCDiscoverMultipleOwnerEnabledDevices(unsigned short timeout, OCProvisionDev_t **ppList);\r
+\r
+/**\r
+ * The function is responsible for discovery of Multiple Owned device is current subnet.\r
+ *\r
+ * @param[in] timeout Timeout in seconds, value till which function will listen to responses from\r
+ * server before returning the list of devices.\r
+ * @param[out] ppList List of Multiple Owned devices.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCDiscoverMultipleOwnedDevices(unsigned short timeout, OCProvisionDev_t **ppList);\r
+#endif //_ENABLE_MULTIPLE_OWNER_\r
+\r
/**\r
* API to provision credentials between two devices and ACLs for the devices who act as a server.\r
*\r
const OCProvisionDev_t *pDev2,\r
OCProvisionResultCB resultCallback);\r
\r
+#ifdef _ENABLE_MULTIPLE_OWNER_\r
+/**\r
+ * API to provision preconfigured PIN to device(NOT LIST).\r
+ * If device does not support the Preconfigured PIN OxM,\r
+ * OCProvisionPreconfPin API will be update the device's Doxm\r
+ * and then try prevonfigured PIN provisioning once again.\r
+ *\r
+ * @param[in] ctx Application context would be returned in result callback.\r
+ * @param[in] targetDeviceInfo Selected target device.\r
+ * @param[in] preconfPin string of preconfigured PIN.\r
+ * @param[in] preconfPinLen string length of 'preconfPin'.\r
+ * @param[in] resultCallback callback provided by API user, callback will be called when\r
+ * provisioning request recieves a response from first resource server.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCProvisionPreconfPin(void* ctx,\r
+ OCProvisionDev_t *targetDeviceInfo,\r
+ const char * preconfPin, size_t preconfPinLen,\r
+ OCProvisionResultCB resultCallback);\r
+\r
+/**\r
+ * API to add preconfigured PIN to local SVR DB.\r
+ *\r
+ * @param[in] targetDeviceInfo Selected target device.\r
+ * @param[in] preconfPIN Preconfig PIN which is used while multiple owner authentication\r
+ * @param[in] preconfPINLen Byte length of preconfig PIN\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCAddPreconfigPIN(const OCProvisionDev_t *targetDeviceInfo,\r
+ const char* preconfPIN, size_t preconfPINLen);\r
+\r
+/**\r
+ * API to update 'doxm.mom' to resource server.\r
+ *\r
+ * @param[in] targetDeviceInfo Selected target device.\r
+ * @param[in] momType Mode of multiple ownership transfer (ref. oic.sec.mom)\r
+ * @param[in] resultCallback callback provided by API user, callback will be called when\r
+ * POST 'mom' request recieves a response from resource server.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCChangeMOTMode(void *ctx, const OCProvisionDev_t *targetDeviceInfo,\r
+ const OicSecMomType_t momType, OCProvisionResultCB resultCallback);\r
+\r
+/**\r
+ * API to update 'doxm.oxmsel' to resource server.\r
+ *\r
+ * @param[in] targetDeviceInfo Selected target device.\r
+ * @param[in] oxmSelValue Method of multiple ownership transfer (ref. oic.sec.oxm)\r
+ * @param[in] resultCallback callback provided by API user, callback will be called when\r
+ * POST 'oxmsel' request recieves a response from resource server.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCSelectMOTMethod(void *ctx, const OCProvisionDev_t *targetDeviceInfo,\r
+ const OicSecOxm_t oxmSelValue, OCProvisionResultCB resultCallback);\r
+#endif //_ENABLE_MULTIPLE_OWNER_\r
+\r
/**\r
* Function to unlink devices.\r
* This function will remove the credential & relasionship between the two devices.\r
--- /dev/null
+//******************************************************************
+//
+// 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_PRECONF_PIN_H_
+#define OXM_PRECONF_PIN_H_
+
+#include "ocstack.h"
+#include "securevirtualresourcetypes.h"
+#include "ownershiptransfermanager.h"
+#include "pmtypes.h"
+#include "pinoxmcommon.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+/**
+ * Callback implementation to load preconfig PIN.
+ *
+ * @param otmCtx Context of OTM, It includes current device information.
+ *
+ * @return ::OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult LoadPreconfPinCodeCallback(OTMContext_t *otmCtx);
+
+/**
+ * Callback implementation to establish a secure channel with PSK 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 CreateSecureSessionPreconfPinCallback(OTMContext_t *otmCtx);
+
+/**
+ * Generate payload for select OxM request.
+ *
+ * @param otmCtx Context of OTM, It includes current device information.
+ * @param cborPaylaod 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 CreatePreconfPinBasedSelectOxmPayload(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 CreatePreconfPinBasedOwnerTransferPayload(OTMContext_t *otmCtx, uint8_t **cborPayload,
+ size_t *cborSize);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //OXM_PRECONF_PIN_H_
+
*/
OCStackResult PMDeviceDiscovery(unsigned short waittime, bool isOwned, OCProvisionDev_t **ppList);
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * Discover multiple OTM enabled devices in the same IP subnet.
+ *
+ * @param[in] waittime Timeout in seconds.
+ * @param[in] isMultipleOwned bool flag for MOT enabled / multiple owned discovery
+ * @param[in] ppDevicesList List of OCProvisionDev_t.
+ *
+ * @return OC_STACK_OK on success otherwise error.
+ */
+OCStackResult PMMultipleOwnerDeviceDiscovery(unsigned short waittime, bool isMultipleOwned, OCProvisionDev_t **ppDevicesList);
+#endif //_ENABLE_MULTIPLE_OWNER_
+
/**
* This function deletes list of provision target devices
*
provisioning_env.AppendUnique(LIBS = ['mbedtls','mbedx509','mbedcrypto'])
+if env.get('MULTIPLE_OWNER') == '1':
+ provisioning_env.AppendUnique(CPPDEFINES = ['_ENABLE_MULTIPLE_OWNER_'])
+
provisioning_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
if target_os == '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')
+
+if provisioning_env.get('MULTIPLE_OWNER') == '1':
+ subownerclient = provisioning_env.Program('subownerclient', 'subownerclient.c')
+ sampleclient_ownedbysubowner = provisioning_env.Program('sampleclient_ownedbysubowner', 'sampleclient_owned_by_subowner.cpp')
+
if provisioning_env.get('WITH_TCP') == True:
cloud_src = [
'cloud/cloudAuth.c',
sec_provisioning_src_dir+ 'oic_svr_db_server_randompin.dat')
randompin_with_emptyuuid_dat = provisioning_env.Install(sec_provisioning_build_dir,
sec_provisioning_src_dir+ 'oic_svr_db_randompin_with_empty_deviceid.dat')
+
+if provisioning_env.get('MULTIPLE_OWNER') == '1':
+ subownerclientdat = provisioning_env.Install(sec_provisioning_build_dir,
+ sec_provisioning_src_dir + 'oic_svr_db_subowner_client.dat')
+ clientownedbysubownerdat = provisioning_env.Install(sec_provisioning_build_dir,
+ sec_provisioning_src_dir + 'oic_svr_db_client_owned_by_subowner.dat')
+
if provisioning_env.get('WITH_TCP') == True:
clouddat = provisioning_env.Install(sec_provisioning_build_dir,
sec_provisioning_src_dir + 'cloud.dat')
Alias("cloud", [clouddat, rootcert, cloudClient, cloudServer])
provisioning_env.AppendTarget("cloud")
-Alias("samples", [provisioningclient, sampleserver_justworks, sampleserver_randompin, clientdat, justworksdat, randompindat, randompin_with_emptyuuid_dat])
+if provisioning_env.get('MULTIPLE_OWNER') == '1':
+ Alias("samples", [
+ provisioningclient, subownerclient, sampleclient_ownedbysubowner,
+ sampleserver_justworks, sampleserver_randompin,
+ clientdat, subownerclientdat, clientownedbysubownerdat,
+ justworksdat, randompindat, randompin_with_emptyuuid_dat
+ ])
+else:
+ Alias("samples", [
+ provisioningclient,
+ sampleserver_justworks, sampleserver_randompin,
+ clientdat,
+ justworksdat, randompindat, randompin_with_emptyuuid_dat
+ ])
+
provisioning_env.AppendTarget('samples')
if (!readFile(filename, (OCByteString *)&trustCertChainArray))
{
OIC_LOG_V(ERROR, TAG, "Can't read %s file", filename);
+ OICFree(((OCByteString *)&trustCertChainArray)->bytes);
return OC_STACK_ERROR;
}
OIC_LOG_BUFFER(DEBUG, TAG, trustCertChainArray.data, trustCertChainArray.len);
--- /dev/null
+{\r
+ "acl": {\r
+ "aclist": {\r
+ "aces": [\r
+ {\r
+ "subjectuuid": "*",\r
+ "resources": [\r
+ {\r
+ "href": "/oic/res",\r
+ "rel": "",\r
+ "rt": ["oic.wk.res"],\r
+ "if": ["oic.if.ll"]\r
+ },{\r
+ "href": "/oic/d",\r
+ "rel": "",\r
+ "rt": ["oic.wk.d"],\r
+ "if": ["oic.if.baseline", "oic.if.r"]\r
+ },{\r
+ "href": "/oic/p",\r
+ "rel": "",\r
+ "rt": ["oic.wk.p"],\r
+ "if": ["oic.if.baseline", "oic.if.r"]\r
+ }\r
+ ],\r
+ "permission": 2\r
+ },\r
+ {\r
+ "subjectuuid": "*",\r
+ "resources": [\r
+ {\r
+ "href": "/oic/sec/doxm",\r
+ "rel": "",\r
+ "rt": ["oic.r.doxm"],\r
+ "if": ["oic.if.baseline"]\r
+ },\r
+ {\r
+ "href": "/oic/sec/pstat",\r
+ "rel": "",\r
+ "rt": ["oic.r.pstat"],\r
+ "if": ["oic.if.baseline"]\r
+ },\r
+ {\r
+ "href": "/oic/sec/acl",\r
+ "rel": "",\r
+ "rt": ["oic.r.acl"],\r
+ "if": ["oic.if.baseline"]\r
+ },\r
+ {\r
+ "href": "/oic/sec/cred",\r
+ "rel": "",\r
+ "rt": ["oic.r.cred"],\r
+ "if": ["oic.if.baseline"]\r
+ }\r
+ ],\r
+ "permission": 6\r
+ },\r
+ {\r
+ "subjectuuid": "*",\r
+ "resources": [\r
+ {\r
+ "href": "/oic/sec/pconf",\r
+ "rel": "",\r
+ "rt": ["oic.r.pconf"],\r
+ "if": ["oic.if.baseline"]\r
+ },\r
+ {\r
+ "href": "/oic/sec/dpairing",\r
+ "rel": "",\r
+ "rt": ["oic.r.dpairing"],\r
+ "if": ["oic.if.baseline"]\r
+ }\r
+ ],\r
+ "permission": 6\r
+ },\r
+ {\r
+ "subjectuuid": "*",\r
+ "resources": [\r
+ {\r
+ "href": "/oic/sec/ver",\r
+ "rel": "",\r
+ "rt": ["oic.r.ver"],\r
+ "if": ["oic.if.baseline"]\r
+ }\r
+ ],\r
+ "permission": 2\r
+ }\r
+ ]\r
+ },\r
+ "rowneruuid" : "4F776E65-6442-7953-7562-4F776E657230"\r
+ },\r
+ "pstat": {\r
+ "isop": false,\r
+ "deviceuuid": "4F776E65-6442-7953-7562-4F776E657230",\r
+ "rowneruuid": "4F776E65-6442-7953-7562-4F776E657230",\r
+ "cm": 2,\r
+ "tm": 0,\r
+ "om": 3,\r
+ "sm": 3\r
+ },\r
+ "doxm": {\r
+ "oxms": [0],\r
+ "oxmsel": 0,\r
+ "sct": 1,\r
+ "owned": false,\r
+ "deviceuuid": "4F776E65-6442-7953-7562-4F776E657230",\r
+ "devowneruuid": "",\r
+ "rowneruuid": "4F776E65-6442-7953-7562-4F776E657230",\r
+ "x.org.iotivity.dpc": true\r
+ }\r
+}\r
--- /dev/null
+{\r
+ "acl": {\r
+ "aclist": {\r
+ "aces": [\r
+ {\r
+ "subjectuuid": "*",\r
+ "resources": [\r
+ {\r
+ "href": "/oic/res",\r
+ "rel": "",\r
+ "rt": ["oic.wk.res"],\r
+ "if": ["oic.if.ll"]\r
+ },{\r
+ "href": "/oic/d",\r
+ "rel": "",\r
+ "rt": ["oic.wk.d"],\r
+ "if": ["oic.if.baseline", "oic.if.r"]\r
+ },{\r
+ "href": "/oic/p",\r
+ "rel": "",\r
+ "rt": ["oic.wk.p"],\r
+ "if": ["oic.if.baseline", "oic.if.r"]\r
+ }\r
+ ],\r
+ "permission": 2\r
+ },\r
+ {\r
+ "subjectuuid": "*",\r
+ "resources": [\r
+ {\r
+ "href": "/oic/sec/doxm",\r
+ "rel": "",\r
+ "rt": ["oic.r.doxm"],\r
+ "if": ["oic.if.baseline"]\r
+ },\r
+ {\r
+ "href": "/oic/sec/pstat",\r
+ "rel": "",\r
+ "rt": ["oic.r.pstat"],\r
+ "if": ["oic.if.baseline"]\r
+ }\r
+ ],\r
+ "permission": 2\r
+ },\r
+ {\r
+ "subjectuuid": "*",\r
+ "resources": [\r
+ {\r
+ "href": "/oic/sec/pconf",\r
+ "rel": "",\r
+ "rt": ["oic.r.pconf"],\r
+ "if": ["oic.if.baseline"]\r
+ },\r
+ {\r
+ "href": "/oic/sec/dpairing",\r
+ "rel": "",\r
+ "rt": ["oic.r.dpairing"],\r
+ "if": ["oic.if.baseline"]\r
+ }\r
+ ],\r
+ "permission": 2\r
+ }\r
+ ]\r
+ },\r
+ "rowneruuid" : "5375624F-776E-6572-436C-69656E743030"\r
+ },\r
+ "pstat": {\r
+ "isop": true,\r
+ "cm": 0,\r
+ "tm": 0,\r
+ "om": 3,\r
+ "sm": 3,\r
+ "deviceuuid": "5375624F-776E-6572-436C-69656E743030",\r
+ "rowneruuid": "5375624F-776E-6572-436C-69656E743030"\r
+ },\r
+ "doxm": {\r
+ "oxms": [0],\r
+ "oxmsel": 0,\r
+ "sct": 1,\r
+ "owned": true,\r
+ "deviceuuid": "5375624F-776E-6572-436C-69656E743030",\r
+ "x.org.iotivity.dpc": false,\r
+ "devowneruuid": "5375624F-776E-6572-436C-69656E743030",\r
+ "rowneruuid": "5375624F-776E-6572-436C-69656E743030"\r
+ }\r
+}\r
#define _10_DISCOV_ALL_DEVS_ 10
#define _11_DISCOV_UNOWN_DEVS_ 11
#define _12_DISCOV_OWN_DEVS_ 12
+#ifdef _ENABLE_MULTIPLE_OWNER_
+#define _13_MOT_DISCOV_DEV_ 13
+#endif //_ENABLE_MULTIPLE_OWNER_
#define _20_REGIST_DEVS_ 20
#define _30_PROVIS_PAIR_DEVS_ 30
#define _31_PROVIS_CRED_ 31
#define _52_RESET_SELEC_DEV_ 52
#define _60_GET_CRED_ 60
#define _61_GET_ACL_ 61
-#define _70_SELECT_PROTOCOL_ 70
+#ifdef _ENABLE_MULTIPLE_OWNER_
+#define _70_MOT_CHANGE_MOM_ 70
+#define _71_MOT_PROV_PRECONF_PIN_ 71
+#define _72_MOT_OXM_SEL_ 72
+#endif //_ENABLE_MULTIPLE_OWNER_
+#define _80_SELECT_PROTOCOL_ 80
#define _99_EXIT_PRVN_CLT_ 99
#define ACL_RESRC_MAX_NUM 16
static OCProvisionDev_t* g_unown_list;
static int g_own_cnt;
static int g_unown_cnt;
+#ifdef _ENABLE_MULTIPLE_OWNER_
+static OCProvisionDev_t* g_mot_enable_list;
+static int g_mot_enable_cnt;
+#endif //_ENABLE_MULTIPLE_OWNER_
+
static bool g_doneCB;
#ifdef __WITH_TLS__
static int secure_protocol = 1;
g_doneCB = true;
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+static void updateDoxmForMOTCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+ if(!hasError)
+ {
+ OIC_LOG_V(INFO, TAG, "POST 'doxm' SUCCEEDED - ctx: %s", (char*) ctx);
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "POST 'doxm' FAILED - ctx: %s", (char*) ctx);
+ printResultList((const OCProvisionResult_t*) arr, nOfRes);
+ }
+ g_doneCB = true;
+}
+#endif //_ENABLE_MULTIPLE_OWNER_
+
static void inputPinCB(char* pin, size_t len)
{
if(!pin || OXM_RANDOM_PIN_SIZE>=len)
return -1;
}
- // register callback function(s) to each OxM
- OTMCallbackData_t otmcb =
- {
- .loadSecretCB = LoadSecretJustWorksCallback,
- .createSecureSessionCB = CreateSecureSessionJustWorksCallback,
- .createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload,
- .createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload
- };
- if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_JUST_WORKS, &otmcb))
- {
- OIC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_JUST_WORKS");
- return -1;
- }
- otmcb.loadSecretCB = InputPinCodeCallback;
- otmcb.createSecureSessionCB = CreateSecureSessionRandomPinCallback;
- otmcb.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
- otmcb.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
- if(OC_STACK_OK != OCSetOwnerTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &otmcb))
- {
- OIC_LOG(ERROR, TAG, "OCSetOwnerTransferCallbackData error: OIC_RANDOM_DEVICE_PIN");
- return -1;
- }
SetInputPinCB(inputPinCB);
return 0;
return 0;
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+static int discoverMOTEnabledDevices(void)
+{
+ // delete owned device list before updating it
+ if(g_mot_enable_list)
+ {
+ OCDeleteDiscoveredDevices(g_mot_enable_list);
+ g_mot_enable_list = NULL;
+ }
+
+ // call |OCDiscoverOwnedDevices| API actually
+ printf(" Discovering Multiple Ownership Transfer Enabled Devices on Network..\n");
+ if(OC_STACK_OK != OCDiscoverMultipleOwnerEnabledDevices(DISCOVERY_TIMEOUT, &g_mot_enable_list))
+ {
+ OIC_LOG(ERROR, TAG, "OCDiscoverMultipleOwnerEnalbedDevices API error");
+ return -1;
+ }
+
+ // display the discovered owned list
+ printf(" > Discovered Multiple Ownership Transfer Enabled Devices\n");
+ g_mot_enable_cnt = printDevList(g_mot_enable_list);
+
+ return 0;
+}
+#endif //_ENABLE_MULTIPLE_OWNER_
+
static int registerDevices(void)
{
// check |unown_list| for registering devices
return 0;
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+static int changeMultipleOwnershipTrnasferMode(void)
+{
+ // check |own_list| for removing device
+ if(!g_own_list || 1>g_own_cnt)
+ {
+ printf(" > Owned Device List is Empty\n");
+ printf(" > Please Discover the Owned Devices, with [12] Menu\n");
+ return 0; // normal case
+ }
+
+ // select device for removing it
+ int dev_num = 0;
+ for( ; ; )
+ {
+ printf(" > Enter Device Number, for MOT Device: ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &dev_num);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(0<dev_num && g_own_cnt>=dev_num)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+
+ int mom = 0;
+ for( ; ; )
+ {
+ printf(" 0. Disable Multuple Ownership Transfer\n");
+ printf(" 1. Enable Multuple Ownership Transfer\n");
+ printf(" 2. (Not Supported yet) Timely Enable Multuple Ownership Transfer\n");
+ printf(" > Enter Mode of Multuple Ownership Transfer : ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &mom);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(0 <= dev_num && OIC_NUMBER_OF_MOM_TYPE > dev_num)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+
+ OCProvisionDev_t* motDev = getDevInst(g_own_list, dev_num);
+ if(OC_STACK_OK == MOTChangeMode(NULL, motDev, (OicSecMomType_t)dev_num, updateDoxmForMOTCB))
+ {
+ g_doneCB = false;
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "MOTChangeMode API error");
+ return -1;
+ }
+
+ if(waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OIC_LOG(ERROR, TAG, "waitCallbackRet callback error");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int selectMultipleOwnershipTrnasferMethod(void)
+{
+ // check |own_list| for removing device
+ if(!g_mot_enable_list || 1>g_mot_enable_cnt)
+ {
+ printf(" > Multiple Ownership Transfer Enabled Device List is Empty\n");
+ printf(" > Please Discover the Multiple Ownership Transfer Enabled Devices, with [13] Menu\n");
+ return 0; // normal case
+ }
+
+ // select device for removing it
+ int dev_num = 0;
+ for( ; ; )
+ {
+ printf(" > Enter Device Number, for MOT Device: ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &dev_num);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(0<dev_num && g_mot_enable_cnt>=dev_num)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+
+ int oxm = 0;
+ for( ; ; )
+ {
+ printf(" 0. (Not Supported)\n");
+ printf(" 1. Random PIN OxM\n");
+ printf(" 2. (Not Supported)\n");
+ printf(" 3. Pre-Configured PIN OxM\n");
+ printf(" > Enter Number of OxM for Multiple Ownership Transfer : ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &oxm);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(OIC_PRECONFIG_PIN == oxm || OIC_RANDOM_DEVICE_PIN == oxm)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+
+ OCProvisionDev_t* motDev = getDevInst(g_mot_enable_list, dev_num);
+ if(OC_STACK_OK == MOTSelectMOTMethod(NULL, motDev, (OicSecOxm_t)oxm, updateDoxmForMOTCB))
+ {
+ g_doneCB = false;
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "MOTSelectMOTMethod API error");
+ return -1;
+ }
+
+ if(waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OIC_LOG(ERROR, TAG, "waitCallbackRet callback error");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int provisionPreconfigPIN()
+{
+ // check |own_list| for removing device
+ if(!g_mot_enable_list || 1>g_mot_enable_cnt)
+ {
+ printf(" > Multiple Ownership Transfer Enabled Device List is Empty\n");
+ printf(" > Please Discover the Multiple Ownership Transfer Enabled Devices, with [13] Menu\n");
+ return 0; // normal case
+ }
+
+ // select device for removing it
+ int dev_num = 0;
+ for( ; ; )
+ {
+ printf(" > Enter Device Number, for MOT Device: ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &dev_num);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(0<dev_num && g_mot_enable_cnt>=dev_num)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+
+ char preconfPIN[9] = {0};
+ printf(" > Input the PreconfigPIN (e.g. 12341234) : ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%8s", preconfPIN);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+
+ OCProvisionDev_t* motDev = getDevInst(g_mot_enable_list, dev_num);
+ if(OC_STACK_OK == OCProvisionPreconfPin(NULL, motDev, preconfPIN, strlen(preconfPIN), provisionCredCB))
+ {
+ g_doneCB = false;
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "OCProvisionPreconfPin API error");
+ return -1;
+ }
+
+ if(waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OIC_LOG(ERROR, TAG, "waitCallbackRet callback error");
+ return -1;
+ }
+
+ return 0;
+}
+#endif //_ENABLE_MULTIPLE_OWNER_
+
static int resetDevice(void)
{
// check |own_list| for removing device
printf("** [A] DISCOVER DEVICES ON NETWORK\n");
printf("** 10. Discover All Un/Owned Devices on Network\n");
printf("** 11. Discover Only Unowned Devices on Network\n");
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ printf("** 12. Discover Only Owned Devices on Network\n");
+ printf("** 13. Discover Multiple Ownership Transfer Enabled Devices on Network\n\n");
+#else
printf("** 12. Discover Only Owned Devices on Network\n\n");
+#endif //_ENABLE_MULTIPLE_OWNER_
printf("** [B] REGISTER/OWN ALL DISCOVERED UNOWNED DEVICES\n");
printf("** 20. Register/Own All Discovered Unowned Devices\n\n");
printf("** [F] GET SECURITY RESOURCE FOR DEBUGGING ONLY\n");
printf("** 60. Get the Credential resources of the Selected Device\n");
printf("** 61. Get the ACL resources of the Selected Device\n\n");
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ printf("** [G] UPDATE THE MULTIPLE OWNERSHIP TRANSFER RELATED VALUE\n");
+ printf("** 70. Change the Multiple Ownership transfer MODE(update mom)\n");
+ printf("** 71. Provision Preconfigured PIN\n");
+ printf("** 72. Change the Multiple Ownership transfer METHOD(update oxmsel)\n\n");
+#endif //_ENABLE_MULTIPLE_OWNER_
+
#ifdef __WITH_TLS__
- printf("** [F] SELECT SECURE PROTOCOL DTLS/TLS\n");
- printf("** 70. Select secure protocol(default DTLS)\n\n");
+ printf("** [H] SELECT SECURE PROTOCOL DTLS/TLS\n");
+ printf("** 80. Select secure protocol(default DTLS)\n\n");
+
+ printf("** [I] EXIT PROVISIONING CLIENT\n");
+#else
+ printf("** [H] EXIT PROVISIONING CLIENT\n");
#endif
- printf("** [F] EXIT PROVISIONING CLIENT\n");
+
printf("** 99. Exit Provisionong Client\n\n");
printf("************************************************************\n\n");
goto PMCLT_ERROR;
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ SetPreconfigPin("12341234", 8);
+#endif //_ENABLE_MULTIPLE_OWNER_
+
// main loop for provisioning manager
int mn_num = 0;
for( ; ; )
OIC_LOG(ERROR, TAG, "_12_DISCOV_OWN_DEVS_: error");
}
break;
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ case _13_MOT_DISCOV_DEV_:
+ if(discoverMOTEnabledDevices())
+ {
+ OIC_LOG(ERROR, TAG, "_13_MOT_DISCOV_DEV_: error");
+ }
+ break;
+#endif //_ENABLE_MULTIPLE_OWNER_
case _20_REGIST_DEVS_:
if(registerDevices())
{
OIC_LOG(ERROR, TAG, "_61_GET_ACL_: error");
}
break;
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ case _70_MOT_CHANGE_MOM_:
+ if(changeMultipleOwnershipTrnasferMode())
+ {
+ OIC_LOG(ERROR, TAG, "_70_MOT_CHANGE_MOM_: error");
+ }
+ break;
+ case _71_MOT_PROV_PRECONF_PIN_:
+ if(provisionPreconfigPIN())
+ {
+ OIC_LOG(ERROR, TAG, "_71_MOT_PROV_PRECONF_PIN_: error");
+ }
+ break;
+ case _72_MOT_OXM_SEL_:
+ if(selectMultipleOwnershipTrnasferMethod())
+ {
+ OIC_LOG(ERROR, TAG, "_72_MOT_OXM_SEL_: error");
+ }
+ break;
+#endif //_ENABLE_MULTIPLE_OWNER_
#ifdef __WITH_TLS__
- case _70_SELECT_PROTOCOL_:
+ case _80_SELECT_PROTOCOL_:
selectSecureProtocol();
break;
#endif
}
OCDeleteDiscoveredDevices(g_own_list); // after here |g_own_list| points nothing
OCDeleteDiscoveredDevices(g_unown_list); // after here |g_unown_list| points nothing
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ OCDeleteDiscoveredDevices(g_mot_enable_list); // after here |g_motdev_list| points nothing
+#endif //_ENABLE_MULTIPLE_OWNER_
if(g_svr_fname)
{
--- /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 "oic_string.h"
+#include "ocprovisioningmanager.h"
+#include "oxmjustworks.h"
+#include "oxmrandompin.h"
+#include "securevirtualresourcetypes.h"
+#include "srmutility.h"
+#include "pmtypes.h"
+
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif //__cplusplus
+
+#define TAG "ClientOwnedBySubOwner"
+static bool g_doneCB;
+
+static pthread_t oc_process_thread;
+static bool g_LoopFlag = true;
+
+static void* oc_process_loop(void* ptr)
+{
+ struct timespec timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 100000000L;
+
+ while(g_LoopFlag)
+ {
+ OCProcess();
+ nanosleep(&timeout, NULL);
+ }
+ pthread_join(&oc_process_thread, NULL);
+ return NULL;
+}
+
+static void StartOCProcessThread()
+{
+ pthread_create(&oc_process_thread, NULL, oc_process_loop, NULL);
+}
+
+static void StopOCProcessThread()
+{
+ g_LoopFlag = false;
+}
+
+// declaration(s) for provisioning client using C-level provisioning API
+// user input definition for main loop on provisioning client
+#define _10_DISCOV_OWN_DEVS_ 10
+#define _20_GET_LED_RESOURCE_ 20
+#define _21_PUT_LED_RESOURCE_ 21
+#define _99_EXIT_PRVN_CLT_ 99
+
+#define DISCOVERY_TIMEOUT 5 // 10 sec
+#define CALLBACK_TIMEOUT 60 // 1 min
+
+static const char* SVR_DB_FILE_NAME = "oic_svr_db_client_owned_by_subowner.dat";
+ // '_' for separaing from the same constant variable in |srmresourcestrings.c|
+static const char* PRVN_DB_FILE_NAME = "oic_prvn_cobs.db";
+// |g_ctx| means provision manager application context and
+// the following, includes |un/own_list|, could be variables, which |g_ctx| has,
+// for accessing all function(s) for these, they are declared on global domain
+static const char* g_ctx = "Provision Manager Client Application Context";
+static char* g_svr_fname;
+static char* g_prvn_fname;
+static OCProvisionDev_t* g_own_list;
+static int g_own_cnt;
+
+// function declaration(s) for calling them before implementing
+static OCProvisionDev_t* getDevInst(const OCProvisionDev_t*, const int);
+static int printDevList(const OCProvisionDev_t*);
+static size_t printUuidList(const OCUuidList_t*);
+static int printResultList(const OCProvisionResult_t*, const int);
+static void printUuid(const OicUuid_t*);
+static FILE* fopen_prvnMng(const char*, const char*);
+static int waitCallbackRet(void);
+static int selectTwoDiffNum(int*, int*, const int, const char*);
+
+// callback function(s) for provisioning client using C-level provisioning API
+static void ownershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+ if(!hasError)
+ {
+ OIC_LOG_V(INFO, TAG, "Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "Ownership Transfer FAILED - ctx: %s", (char*) ctx);
+ printResultList((const OCProvisionResult_t*) arr, nOfRes);
+ }
+ g_doneCB = true;
+}
+
+// response handler for LED requests.
+static void LedCB(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ if(clientResponse)
+ {
+ if(clientResponse->result == OC_STACK_OK)
+ {
+ printf("Get OC_STACK_OK from server\n");
+ if(clientResponse->payload)
+ {
+ printf("Response ===================> %s\n", clientResponse->payload);
+ }
+ }
+ else
+ {
+ printf("Error in response : %d\n", clientResponse->result);
+ }
+ }
+ else
+ {
+ printf("Hit the response callback but can not find response data\n");
+ }
+
+ g_doneCB = true;
+}
+
+
+// function(s) for provisioning client using C-level provisioning API
+static int initProvisionClient(void)
+{
+ // initialize persistent storage for SVR DB
+ static OCPersistentStorage ps = {fopen_prvnMng, fread, fwrite, fclose, unlink};
+ if(OC_STACK_OK != OCRegisterPersistentStorageHandler(&ps))
+ {
+ OIC_LOG(ERROR, TAG, "OCRegisterPersistentStorageHandler error");
+ return -1;
+ }
+
+ // initialize OC stack and provisioning manager
+ if(OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
+ {
+ OIC_LOG(ERROR, TAG, "OCStack init error");
+ return -1;
+ }
+
+ if (access(PRVN_DB_FILE_NAME, F_OK) != -1)
+ {
+ printf("************************************************************\n");
+ printf("************Provisioning DB file already exists.************\n");
+ printf("************************************************************\n");
+ }
+ else
+ {
+ printf("*************************************************************\n");
+ printf("************No provisioning DB file, creating new************\n");
+ printf("*************************************************************\n");
+ }
+
+ if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
+ {
+ OIC_LOG(ERROR, TAG, "OC_PM init error");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int discoverOwnedDevices(void)
+{
+ // delete owned device list before updating it
+ if(g_own_list)
+ {
+ OCDeleteDiscoveredDevices(g_own_list);
+ g_own_list = NULL;
+ }
+
+ // call |OCDiscoverOwnedDevices| API actually
+ printf(" Discovering Only Owned Devices on Network..\n");
+ if(OC_STACK_OK != OCDiscoverOwnedDevices(DISCOVERY_TIMEOUT, &g_own_list))
+ {
+ OIC_LOG(ERROR, TAG, "OCDiscoverOwnedDevices API error");
+ return -1;
+ }
+
+ // display the discovered owned list
+ printf(" > Discovered Owned Devices\n");
+ g_own_cnt = printDevList(g_own_list);
+
+ return 0;
+}
+
+static OCProvisionDev_t* getDevInst(const OCProvisionDev_t* dev_lst, const int dev_num)
+{
+ if(!dev_lst || 0>=dev_num)
+ {
+ printf(" Device List is Empty..\n");
+ return NULL;
+ }
+
+ OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
+ for(int i=0; lst; )
+ {
+ if(dev_num == ++i)
+ {
+ return lst;
+ }
+ lst = lst->next;
+ }
+
+ return NULL; // in here |lst| is always |NULL|
+}
+
+static int printDevList(const OCProvisionDev_t* dev_lst)
+{
+ if(!dev_lst)
+ {
+ printf(" Device List is Empty..\n\n");
+ return 0;
+ }
+
+ OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
+ int lst_cnt = 0;
+ for( ; lst; )
+ {
+ printf(" [%d] ", ++lst_cnt);
+ printUuid((const OicUuid_t*) &lst->doxm->deviceID);
+ printf("\n");
+ lst = lst->next;
+ }
+ printf("\n");
+
+ return lst_cnt;
+}
+
+static size_t printUuidList(const OCUuidList_t* uid_lst)
+{
+ if(!uid_lst)
+ {
+ printf(" Device List is Empty..\n\n");
+ return 0;
+ }
+
+ OCUuidList_t* lst = (OCUuidList_t*) uid_lst;
+ size_t lst_cnt = 0;
+ for( ; lst; )
+ {
+ printf(" [%zu] ", ++lst_cnt);
+ printUuid((const OicUuid_t*) &lst->dev);
+ printf("\n");
+ lst = lst->next;
+ }
+ printf("\n");
+
+ return lst_cnt;
+}
+
+static int printResultList(const OCProvisionResult_t* rslt_lst, const int rslt_cnt)
+{
+ if(!rslt_lst || 0>=rslt_cnt)
+ {
+ printf(" Device List is Empty..\n\n");
+ return 0;
+ }
+
+ int lst_cnt = 0;
+ for( ; rslt_cnt>lst_cnt; ++lst_cnt)
+ {
+ printf(" [%d] ", lst_cnt+1);
+ printUuid((const OicUuid_t*) &rslt_lst[lst_cnt].deviceId);
+ printf(" - result: %d\n", rslt_lst[lst_cnt].res);
+ }
+ printf("\n");
+
+ return lst_cnt;
+}
+
+static void printUuid(const OicUuid_t* uid)
+{
+ int i;
+ for(i=0; i<UUID_LENGTH; )
+ {
+ printf("%02X", (*uid).id[i++]);
+ if(i==4 || i==6 || i==8 || i==10) // canonical format for UUID has '8-4-4-4-12'
+ {
+ printf("-");
+ }
+ }
+
+ printf("\t(");
+ for(i = 0; i < UUID_LENGTH; i++)
+ {
+ printf("%c", (*uid).id[i]);
+ }
+ printf(")");
+}
+
+static FILE* fopen_prvnMng(const char* path, const char* mode)
+{
+ (void)path; // unused |path| parameter
+
+ // input |g_svr_db_fname| internally by force, not using |path| parameter
+ // because |OCPersistentStorage::open| is called |OCPersistentStorage| internally
+ // with its own |SVR_DB_FILE_NAME|
+ return fopen(SVR_DB_FILE_NAME, mode);
+}
+
+static int waitCallbackRet(void)
+{
+ for(int i=0; !g_doneCB && CALLBACK_TIMEOUT>i; ++i)
+ {
+ sleep(1);
+ }
+
+ return 0;
+}
+
+static void printMenu(void)
+{
+ printf("************************************************************\n");
+ printf("****** OIC MOT Client with using C-level API ******\n");
+ printf("************************************************************\n\n");
+
+ printf("** [A] DISCOVER DEVICES ON NETWORK\n");
+ printf("** 10. Discover Owned Devices on Network\n\n");
+
+ printf("** [B] SEND GET/PUT Request\n");
+ printf("** 20. Send GET request\n");
+ printf("** 21. Send PUT request\n\n");
+
+ printf("** [G] EXIT PROVISIONING CLIENT\n");
+ printf("** 99. Exit Provisionong Client\n\n");
+
+ printf("************************************************************\n\n");
+}
+
+#if 0 // Code for enabling path configuration for PDB and SVR DBf
+static void printUsage(void)
+{
+ printf("\n");
+ printf("OIC Provisioning Client with using C-level API\n");
+ printf("Usage: provisioningclient [option]...\n");
+ printf("\n");
+ printf(" -h print help for this provisioning client\n");
+ printf(" -p=[prvn_db_file_path/name] input PRVN DB file path and name\n");
+ printf(" if not exists, will load default DB file\n");
+ printf(" (default: |oic_prvn_mng.db| on working dir)\n");
+ printf(" (ex. -p=oic_prvn_mng.db)\n");
+ printf(" -s=[svr_db_file_path/name] input SVR DB file path and name\n");
+ printf(" if not exists, will load default DB file\n");
+ printf(" (default: |oic_svr_db_client.json| on working dir)\n");
+ printf(" (ex. -s=oic_svr_db_client.json)\n");
+ printf("\n");
+}
+#endif
+
+// main function for provisioning client using C-level provisioning API
+int main()
+{
+ OCProvisionDev_t* selDev = NULL;
+ int selDevNum = 0;
+ int mn_num = 0;
+
+ // initialize provisioning client
+ if(initProvisionClient())
+ {
+ OIC_LOG(ERROR, TAG, "ProvisionClient init error");
+ goto PMCLT_ERROR;
+ }
+
+ StartOCProcessThread();
+ printf("Client started...\n");
+ // main loop for provisioning manager
+ for( ; ; )
+ {
+ printf("\n");
+ printMenu();
+ printf(">> Enter Menu Number: ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &mn_num);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ printf("\n");
+ switch(mn_num)
+ {
+ case _10_DISCOV_OWN_DEVS_:
+ if(discoverOwnedDevices())
+ {
+ OIC_LOG(ERROR, TAG, "_12_DISCOV_OWN_DEVS_: error");
+ }
+ break;
+ case _20_GET_LED_RESOURCE_:
+ {
+ char query[256] = {0};
+ OCCallbackData cbData;
+ cbData.cb = &LedCB;
+ cbData.context = NULL;
+ cbData.cd = NULL;
+
+ printDevList(g_own_list);
+
+ for( ; ; )
+ {
+ printf("Select the device : ");
+ for(int ret=0; 1!=ret; )
+ {
+ scanf(" %d", &selDevNum);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(0<selDevNum && g_own_cnt>=selDevNum)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+
+ selDev = getDevInst(g_own_list, selDevNum);
+ if(!selDev)
+ {
+ OIC_LOG(ERROR, TAG, "getDevInst: device instance empty");
+ goto PMCLT_ERROR;
+ }
+
+ g_doneCB = false;
+ snprintf(query, MAX_URI_LENGTH, "coaps://%s:%d/a/led", selDev->endpoint.addr, selDev->securePort);
+ if(OC_STACK_OK != OCDoResource(NULL, OC_REST_GET, query, NULL, NULL, selDev->connType, OC_LOW_QOS, &cbData, NULL, 0))
+ {
+ printf("********************************\n");
+ printf("Failed to send GET request to %s\n", query);
+ printf("********************************\n");
+ g_doneCB = true;
+ break;
+ }
+
+ waitCallbackRet();
+
+ break;
+ }
+ case _21_PUT_LED_RESOURCE_:
+ {
+ char query[256] = {0};
+ OCCallbackData cbData;
+ cbData.cb = &LedCB;
+ cbData.context = NULL;
+ cbData.cd = NULL;
+
+ printDevList(g_own_list);
+
+ for( ; ; )
+ {
+ printf("Select the device : ");
+ for(int ret=0; 1!=ret; )
+ {
+ scanf(" %d", &selDevNum);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(0<selDevNum && g_own_cnt>=selDevNum)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+
+ selDev = getDevInst(g_own_list, selDevNum);
+ if(!selDev)
+ {
+ OIC_LOG(ERROR, TAG, "getDevInst: device instance empty");
+ goto PMCLT_ERROR;
+ }
+
+ g_doneCB = false;
+ snprintf(query, MAX_URI_LENGTH, "coaps://%s:%d/a/led", selDev->endpoint.addr, selDev->securePort);
+ if(OC_STACK_OK != OCDoResource(NULL, OC_REST_PUT, query, NULL, NULL, selDev->connType, OC_LOW_QOS, &cbData, NULL, 0))
+ {
+ printf("********************************\n");
+ printf("Failed to send PUT request to %s\n", query);
+ printf("********************************\n");
+ g_doneCB = true;
+ break;
+ }
+
+ waitCallbackRet();
+
+ break;
+ }
+ case _99_EXIT_PRVN_CLT_:
+ goto PMCLT_ERROR;
+ default:
+ printf(">> Entered Wrong Number. Please Enter Again\n\n");
+ break;
+ }
+ }
+
+PMCLT_ERROR:
+ if(OC_STACK_OK != OCStop())
+ {
+ OIC_LOG(ERROR, TAG, "OCStack stop error");
+ }
+ OCDeleteDiscoveredDevices(g_own_list); // after here |g_own_list| points nothing
+
+ if(g_svr_fname)
+ {
+ OICFree(g_svr_fname); // after here |g_svr_fname| points nothing
+ }
+ if(g_prvn_fname)
+ {
+ OICFree(g_prvn_fname); // after here |g_prvn_fname| points nothing
+ }
+
+ StopOCProcessThread();
+
+ return 0; // always return normal case
+}
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
#define TAG "SAMPLE_RANDOMPIN"
int gQuitFlag = 0;
+#ifdef _ENABLE_MULTIPLE_OWNER_
+static bool g_LoopFlag = true;
+#endif //_ENABLE_MULTIPLE_OWNER_
/* Structure to represent a LED resource */
typedef struct LEDRESOURCE{
}
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+static pthread_t oc_process_thread;
+
+static void* oc_process_loop(void* ptr)
+{
+ struct timespec timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 100000000L;
+
+ while(g_LoopFlag)
+ {
+ OCProcess();
+ nanosleep(&timeout, NULL);
+ }
+ pthread_join(&oc_process_thread, NULL);
+ return NULL;
+}
+
+static void StartOCProcessThread()
+{
+ pthread_create(&oc_process_thread, NULL, oc_process_loop, NULL);
+}
+
+static void StopOCProcessThread()
+{
+ g_LoopFlag = false;
+}
+#endif //_ENABLE_MULTIPLE_OWNER_
+
OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
{
OCRepPayload* payload = OCRepPayloadCreate();
int main()
{
- struct timespec timeout;
-
OIC_LOG(DEBUG, TAG, "OCServer is starting...");
// Initialize Persistent Storage for SVR database
* If server supported random pin based ownership transfer,
* callback of print PIN should be registered before runing server.
*/
- SetGeneratePinCB(&GeneratePinCB);
+ SetGeneratePinCB(GeneratePinCB);
/*
* Declare and create the example resource: LED
*/
createLEDResource(gResourceUri, &LED, false, 0);
- timeout.tv_sec = 0;
- timeout.tv_nsec = 100000000L;
-
// Break from loop with Ctrl-C
OIC_LOG(INFO, TAG, "Entering ocserver main loop...");
signal(SIGINT, handleSigInt);
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ StartOCProcessThread();
+
+ while(!gQuitFlag)
+ {
+ printf("Press 'G' to generate random PIN...\n");
+ printf("Press 'E' to exit...\n");
+ char in = getchar();
+ if('G' == in || 'g' == in)
+ {
+ char ranPin[OXM_RANDOM_PIN_SIZE + 1] = {0};
+ GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1);
+ }
+ if('E' == in || 'e' == in)
+ {
+ break;
+ }
+ }
+
+ StopOCProcessThread();
+#else
+ struct timespec timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_nsec = 100000000L;
+
while (!gQuitFlag)
{
if (OCProcess() != OC_STACK_OK)
}
nanosleep(&timeout, NULL);
}
+#endif //_ENABLE_MULTIPLE_OWNER_
OIC_LOG(INFO, TAG, "Exiting ocserver main loop...");
--- /dev/null
+/******************************************************************
+ *
+ * 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.
+ *
+ *****************************************************************/
+#include "iotivity_config.h"
+
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "platform_features.h"
+#include "utlist.h"
+#include "logger.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "ocprovisioningmanager.h"
+#include "oxmjustworks.h"
+#include "oxmrandompin.h"
+#include "securevirtualresourcetypes.h"
+#include "srmutility.h"
+#include "pmtypes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif //__cplusplus
+
+// declaration(s) for provisioning client using C-level provisioning API
+// user input definition for main loop on provisioning client
+#define _10_DISCOV_MOT_ENABLED_DEV_ 10
+#define _11_DISCOV_MULTIPLE_OWNED_DEV_ 11
+#define _20_PERFORM_MOT_ 20
+#define _30_GET_LED_RESOURCE_ 30
+#define _31_PUT_LED_RESOURCE_ 31
+#define _40_PROVISION_ACL_ 40
+#define _41_PROVISION_CRED_ 41
+#define _99_EXIT_PRVN_CLT_ 99
+
+#define ACL_RESRC_MAX_NUM 16
+#define ACL_RESRC_ARRAY_SIZE 3 //This value is used only for sample (not OCF spec)
+#define ACL_RESRC_MAX_LEN 128
+#define ACL_PEMISN_CNT 5
+#define DISCOVERY_TIMEOUT 5 // 5 sec
+#define CALLBACK_TIMEOUT 60 // 1 min
+#define TAG "subownerclient"
+
+static const char* SVR_DB_FILE_NAME = "oic_svr_db_subowner_client.dat";
+ // '_' for separaing from the same constant variable in |srmresourcestrings.c|
+static const char* PRVN_DB_FILE_NAME = "oic_pdm_subowner.db";
+static const OicSecPrm_t SUPPORTED_PRMS[1] =
+{
+ PRM_PRE_CONFIGURED,
+};
+
+// |g_ctx| means provision manager application context and
+// the following, includes |un/own_list|, could be variables, which |g_ctx| has,
+// for accessing all function(s) for these, they are declared on global domain
+static const char* g_ctx = "SubOwner Client Application Context";
+static char* g_svr_fname;
+static char* g_prvn_fname;
+static OCProvisionDev_t* g_own_list;
+static OCProvisionDev_t* g_unown_list;
+static OCProvisionDev_t* g_motdev_list;
+static OCProvisionDev_t* g_mowned_list;
+static int g_own_cnt;
+static int g_unown_cnt;
+static int g_motdev_cnt;
+static int g_mowned_cnt;
+static bool g_doneCB;
+
+// function declaration(s) for calling them before implementing
+static OCProvisionDev_t* getDevInst(const OCProvisionDev_t*, const int);
+static int printDevList(const OCProvisionDev_t*);
+static size_t printUuidList(const OCUuidList_t*);
+static int printResultList(const OCProvisionResult_t*, const int);
+static void printUuid(const OicUuid_t*);
+static FILE* fopen_prvnMng(const char*, const char*);
+static int waitCallbackRet(void);
+static int selectTwoDiffNum(int*, int*, const int, const char*);
+
+// callback function(s) for provisioning client using C-level provisioning API
+static void multipleOwnershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+ if(!hasError)
+ {
+ OIC_LOG_V(INFO, TAG, "Multiple Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "Multiple Ownership Transfer FAILED - ctx: %s", (char*) ctx);
+ printResultList((const OCProvisionResult_t*) arr, nOfRes);
+ }
+ g_doneCB = true;
+}
+
+// callback function(s) for provisioning client using C-level provisioning API
+static void ownershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+ if(!hasError)
+ {
+ OIC_LOG_V(INFO, TAG, "Ownership Transfer SUCCEEDED - ctx: %s", (char*) ctx);
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "Ownership Transfer FAILED - ctx: %s", (char*) ctx);
+ printResultList((const OCProvisionResult_t*) arr, nOfRes);
+ }
+ g_doneCB = true;
+}
+
+static void updateDoxmForMOTCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+ if(!hasError)
+ {
+ OIC_LOG_V(INFO, TAG, "POST 'doxm' SUCCEEDED - ctx: %s", (char*) ctx);
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "POST 'doxm' FAILED - ctx: %s", (char*) ctx);
+ printResultList((const OCProvisionResult_t*) arr, nOfRes);
+ }
+ g_doneCB = true;
+}
+
+static void provisionCredCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+ if(!hasError)
+ {
+ OIC_LOG_V(INFO, TAG, "Provision Credential SUCCEEDED - ctx: %s", (char*) ctx);
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "Provision Credential FAILED - ctx: %s", (char*) ctx);
+ printResultList((const OCProvisionResult_t*) arr, nOfRes);
+ }
+ g_doneCB = true;
+}
+
+static void provisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+ if(!hasError)
+ {
+ OIC_LOG_V(INFO, TAG, "Provision ACL SUCCEEDED - ctx: %s", (char*) ctx);
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "Provision ACL FAILED - ctx: %s", (char*) ctx);
+ printResultList((const OCProvisionResult_t*) arr, nOfRes);
+ }
+ g_doneCB = true;
+}
+
+// response handler for LED requests.
+static void LedCB(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ if(clientResponse)
+ {
+ if(clientResponse->result == OC_STACK_OK)
+ {
+ printf("Get OC_STACK_OK from server\n");
+ if(clientResponse->payload)
+ {
+ printf("Response ===================> %s\n", clientResponse->payload);
+ }
+ }
+ else
+ {
+ printf("Error in response : %d\n", clientResponse->result);
+ }
+ }
+ else
+ {
+ printf("Hit the response callback but can not find response data\n");
+ }
+
+ g_doneCB = true;
+}
+
+static void inputPinCB(char* pin, size_t len)
+{
+ if(!pin || OXM_RANDOM_PIN_SIZE>=len)
+ {
+ OIC_LOG(ERROR, TAG, "inputPinCB invalid parameters");
+ return;
+ }
+
+ printf(" > INPUT PIN: ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%8s", pin);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+}
+
+// function(s) for provisioning client using C-level provisioning API
+static int initProvisionClient(void)
+{
+ // initialize persistent storage for SVR DB
+ static OCPersistentStorage ps = {fopen_prvnMng, fread, fwrite, fclose, unlink};
+ if(OC_STACK_OK != OCRegisterPersistentStorageHandler(&ps))
+ {
+ OIC_LOG(ERROR, TAG, "OCRegisterPersistentStorageHandler error");
+ return -1;
+ }
+
+ // initialize OC stack and provisioning manager
+ if(OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
+ {
+ OIC_LOG(ERROR, TAG, "OCStack init error");
+ return -1;
+ }
+
+ if (access(PRVN_DB_FILE_NAME, F_OK) != -1)
+ {
+ printf("************************************************************\n");
+ printf("************Provisioning DB file already exists.************\n");
+ printf("************************************************************\n");
+ }
+ else
+ {
+ printf("*************************************************************\n");
+ printf("************No provisioning DB file, creating new************\n");
+ printf("*************************************************************\n");
+ }
+
+ if(OC_STACK_OK != OCInitPM(PRVN_DB_FILE_NAME))
+ {
+ OIC_LOG(ERROR, TAG, "OC_PM init error");
+ return -1;
+ }
+
+ SetInputPinCB(inputPinCB);
+
+ return 0;
+}
+
+static int discoverMotSupportedDevices(void)
+{
+ // delete un/owned device lists before updating them
+ if(g_motdev_list)
+ {
+ OCDeleteDiscoveredDevices(g_motdev_list);
+ g_motdev_list = NULL;
+ }
+
+ // call |OCDiscoverMultipleOwnerEnabledDevices| API actually
+ printf(" Discovering Multiple Ownership Transfer enabled Devices on Network..\n");
+ if(OC_STACK_OK != OCDiscoverMultipleOwnerEnabledDevices(DISCOVERY_TIMEOUT, &g_motdev_list))
+ {
+ OIC_LOG(ERROR, TAG, "OCDiscoverMultipleOwnerEnalbedDevices API error");
+ return -1;
+ }
+
+ // display the discovered device lists
+ printf(" > Discovered Multiple Ownership Transfer Enabled Devices\n");
+ g_motdev_cnt = printDevList(g_motdev_list);
+
+ return 0;
+}
+
+static int discoverSubOwnerDevices()
+{
+ // delete un/owned device lists before updating them
+ if(g_mowned_list)
+ {
+ OCDeleteDiscoveredDevices(g_mowned_list);
+ g_mowned_list = NULL;
+ }
+
+ // call |OCDiscoverMultipleOwnedDevices| API actually
+ printf(" Discovering Multiple Owned Devices on Network..\n");
+ if(OC_STACK_OK != OCDiscoverMultipleOwnedDevices(DISCOVERY_TIMEOUT, &g_mowned_list))
+ {
+ OIC_LOG(ERROR, TAG, "OCDiscoverMultipleOwnerEnabledDevices API error");
+ return -1;
+ }
+
+ // display the discovered device lists
+ printf(" > Discovered Multiple Owned Devices\n");
+ g_mowned_cnt = printDevList(g_mowned_list);
+
+ return 0;
+}
+
+static int multipleOwnershipTransfer(void)
+{
+ // check |unown_list| for registering devices
+ if(!g_motdev_list || 0 >=g_motdev_cnt)
+ {
+ printf(" > MultipleOwnershipTransfer Enabled Device List is Empty\n");
+ printf(" > Please Discover Devices first, with [10] Menu\n");
+ return 0; // normal case
+ }
+
+ // call |getDevInst| API actually
+ // calling this API with callback actually acts like blocking
+ // for error checking, the return value saved and printed
+ g_doneCB = false;
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ OCProvisionDev_t* dev = NULL;
+ LL_FOREACH(g_motdev_list, dev)
+ {
+ if(OIC_PRECONFIG_PIN == dev->doxm->oxmSel)
+ {
+ //Pre-Configured PIN initialization
+ if(OC_STACK_OK != OCAddPreconfigPIN(dev, "12341234", OXM_PRECONFIG_PIN_SIZE))
+ {
+ printf("\n\n\n*** %60s ***\n", "WARNNING : Failed to save the pre-configured PIN");
+ printf("*** %60s ***\n\n\n", "WARNNING : You can't use the pre-configured PIN OxM for MOT");
+ return -1;
+ }
+ }
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
+
+ if(OC_STACK_OK != OCDoMultipleOwnershipTransfer(g_ctx, g_motdev_list, multipleOwnershipTransferCB))
+ {
+ OIC_LOG(ERROR, TAG, "_20_PERFORM_MOT_: error");
+ return -1;
+ }
+
+ if(waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
+ return -1;
+ }
+
+ // display the registered result
+ printf(" > Registered Discovered Devices\n");
+
+ return 0;
+}
+
+static int sendGetLed()
+{
+ int selDevNum;
+ char query[256] = {0};
+ OCCallbackData cbData;
+ cbData.cb = &LedCB;
+ cbData.context = NULL;
+ cbData.cd = NULL;
+
+ printDevList(g_mowned_list);
+
+ // select device for provisioning access control list
+ for( ; ; )
+ {
+ printf(" > Enter Device Number, for sending GET LED request: ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &selDevNum);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(0<selDevNum && g_mowned_cnt>=selDevNum)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+
+ OCProvisionDev_t* selDev = getDevInst(g_mowned_list, selDevNum);
+ if(NULL == selDev)
+ {
+ printf("Failed to getDevInst()\n");
+ return -1;
+ }
+
+ g_doneCB = false;
+ snprintf(query, MAX_URI_LENGTH, "coaps://%s:%d/a/led", selDev->endpoint.addr, selDev->securePort);
+ printf("query=%s\n", query);
+ if(OC_STACK_OK != OCDoResource(NULL, OC_REST_GET, query, NULL, NULL, selDev->connType, OC_HIGH_QOS, &cbData, NULL, 0))
+ {
+ printf("********************************\n");
+ printf("Failed to send GET request to %s\n", query);
+ printf("********************************\n");
+ g_doneCB = true;
+ return -1;
+ }
+
+ waitCallbackRet();
+
+ return 0;
+}
+
+static int sendPutLed()
+{
+ int selDevNum;
+ char query[256] = {0};
+ OCCallbackData cbData;
+ cbData.cb = &LedCB;
+ cbData.context = NULL;
+ cbData.cd = NULL;
+
+ printDevList(g_mowned_list);
+ // select device for provisioning access control list
+ for( ; ; )
+ {
+ printf(" > Enter Device Number, for sending PUT LED request: ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &selDevNum);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(0<selDevNum && g_mowned_cnt>=selDevNum)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+
+ OCProvisionDev_t* selDev = getDevInst(g_mowned_list, selDevNum);
+ if(NULL == selDev)
+ {
+ printf("Failed to getDevInst()\n");
+ return -1;
+ }
+
+ g_doneCB = false;
+ snprintf(query, MAX_URI_LENGTH, "coaps://%s:%d/a/led", selDev->endpoint.addr, selDev->securePort);
+ if(OC_STACK_OK != OCDoResource(NULL, OC_REST_PUT, query, NULL, NULL, selDev->connType, OC_LOW_QOS, &cbData, NULL, 0))
+ {
+ printf("********************************\n");
+ printf("Failed to send PUT request to %s\n", query);
+ printf("********************************\n");
+ g_doneCB = true;
+ return -1;
+ }
+
+ waitCallbackRet();
+
+ return 0;
+}
+
+
+static OicSecAcl_t* createAclForLEDAccess(const OicUuid_t* subject)
+{
+ if(NULL == subject)
+ {
+ OIC_LOG(ERROR, TAG, "createAcl: Invalid paramters");
+ return NULL;
+ }
+ // allocate memory for |acl| struct
+ OicSecAcl_t* acl = (OicSecAcl_t*) OICCalloc(1, sizeof(OicSecAcl_t));
+ if(!acl)
+ {
+ OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
+ return NULL; // not need to 'goto' |ERROR| before allocating |acl|
+ }
+ OicSecAce_t* ace = (OicSecAce_t*) OICCalloc(1, sizeof(OicSecAce_t));
+ if(!ace)
+ {
+ OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
+ return NULL; // not need to 'goto' |ERROR| before allocating |acl|
+ }
+ LL_APPEND(acl->aces, ace);
+ memcpy(ace->subjectuuid.id, subject->id, sizeof(subject->id));
+
+ // fill the href
+ char* rsrc_in = "/a/led"; // '1' for null termination
+ OicSecRsrc_t* rsrc = (OicSecRsrc_t*)OICCalloc(1, sizeof(OicSecRsrc_t));
+ if(!rsrc)
+ {
+ OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
+ goto CRACL_ERROR;
+ }
+
+ size_t len = strlen(rsrc_in)+1; // '1' for null termination
+ rsrc->href = (char*) OICCalloc(len, sizeof(char));
+ if(!rsrc->href)
+ {
+ OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
+ goto CRACL_ERROR;
+ }
+ OICStrcpy(rsrc->href, len, rsrc_in);
+
+ //fill the resource type (rt)
+ rsrc->typeLen = 1;
+ rsrc->types = (char**)OICCalloc(1, sizeof(char*));
+ if(!rsrc->types)
+ {
+ OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
+ goto CRACL_ERROR;
+ }
+ rsrc->types[0] = OICStrdup("oic.r.core");
+ if(!rsrc->types[0])
+ {
+ OIC_LOG(ERROR, TAG, "createAcl: OICStrdup error return");
+ goto CRACL_ERROR;
+ }
+
+ //fill the interface (if)
+ rsrc->interfaceLen = 1;
+ rsrc->interfaces = (char**)OICCalloc(1, sizeof(char*));
+ if(!rsrc->interfaces)
+ {
+ OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
+ goto CRACL_ERROR;
+ }
+ rsrc->interfaces[0] = OICStrdup("oic.if.baseline");
+ if(!rsrc->interfaces[0])
+ {
+ OIC_LOG(ERROR, TAG, "createAcl: OICStrdup error return");
+ goto CRACL_ERROR;
+ }
+
+ LL_APPEND(ace->resources, rsrc);
+
+ // full permission for /a/led
+ ace->permission = PERMISSION_FULL_CONTROL;
+
+ ace->eownerID = (OicUuid_t*)OICCalloc(1, sizeof(OicUuid_t));
+ if(NULL == ace->eownerID)
+ {
+ OIC_LOG(ERROR, TAG, "createAcl: OICCalloc error return");
+ goto CRACL_ERROR;
+ }
+
+ //fill the eowner id as my deviceID.
+ OicUuid_t myUuid = {.id={0}};
+ if(OC_STACK_OK != GetDoxmDeviceID(&myUuid))
+ {
+ OIC_LOG(ERROR, TAG, "createAcl: GetDoxmDeviceID error return");
+ goto CRACL_ERROR;
+ }
+ memcpy(ace->eownerID->id, myUuid.id, sizeof(myUuid.id));
+
+ return acl;
+
+CRACL_ERROR:
+ OCDeleteACLList(acl); // after here |acl| points nothing
+ return NULL;
+}
+
+static int provisionAclForLed()
+{
+ OicSecAcl_t* acl = NULL;
+
+ // check |own_list| for provisioning access control list
+ if(!g_mowned_list || 1> g_mowned_cnt)
+ {
+ printf(" > MOT Device List is Empty\n");
+ printf(" > Please Perform MOT first, with [12|21] Menu\n");
+ return 0; // normal case
+ }
+
+ // display the MOT dev list
+ printf(" > MOT Devices\n");
+ g_mowned_cnt = printDevList(g_mowned_list);
+
+ // select device for provisioning access control list
+ int dev_num = 0;
+ for( ; ; )
+ {
+ printf(" > Enter Device Number, for Provisioning LED's ACL: ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &dev_num);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(0<dev_num && g_mowned_list>=dev_num)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+
+ g_doneCB = false;
+ printf(" Provisioning Selected ACL..\n");
+ OCProvisionDev_t* dev = getDevInst((const OCProvisionDev_t*) g_mowned_list, dev_num);
+ if(!dev)
+ {
+ OIC_LOG(ERROR, TAG, "provisionAcl: device instance empty");
+ goto PVACL_ERROR;
+ }
+
+ OicUuid_t subjectUuid;
+ OCStackResult rst = GetDoxmDeviceID(&subjectUuid);
+ if(OC_STACK_OK != rst)
+ {
+ OIC_LOG_V(ERROR, TAG, "GetDoxmDeviceID API error: %d", rst);
+ goto PVACL_ERROR;
+ }
+
+ acl = createAclForLEDAccess(&subjectUuid);
+ if(NULL == acl)
+ {
+ OIC_LOG(ERROR, TAG, "provisionAcl: Failed to create ACL for LED");
+ return -1;
+ }
+
+ rst = OCProvisionACL((void*) g_ctx, dev, acl, provisionAclCB);
+ if(OC_STACK_OK != rst)
+ {
+ OIC_LOG_V(ERROR, TAG, "OCProvisionACL API error: %d", rst);
+ goto PVACL_ERROR;
+ }
+ if(waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
+ goto PVACL_ERROR;
+ }
+ // display the ACL-provisioned result
+ printf(" > Provisioned Selected ACL\n");
+
+ OCDeleteACLList(acl); // after here |acl| points nothing
+ return 0;
+
+PVACL_ERROR:
+ OCDeleteACLList(acl);
+ return -1;
+}
+
+static int provisionCred()
+{
+ // check |unown_list| for registering devices
+ if(!g_mowned_list|| 0 >=g_mowned_cnt)
+ {
+ printf(" > Multiple Owned Device List is Empty\n");
+ printf(" > Please Discover Devices first, with [13] Menu\n");
+ return 0; // normal case
+ }
+
+ // display the MOT dev list
+ printf(" > Multiple Owned Devices\n");
+ g_mowned_cnt = printDevList(g_mowned_list);
+
+ int dev_num = 0;
+ for( ; ; )
+ {
+ printf(" > Enter Multiple Owned Device Number to link : ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &dev_num);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(0<dev_num && g_mowned_cnt>=dev_num)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+
+ OCProvisionDev_t* motDev = getDevInst(g_mowned_list, dev_num);
+ if(NULL == motDev)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to getDevInst()");
+ return -1;
+ }
+
+ // display the MOT dev list
+ printf(" > Owned Devices\n");
+ g_own_cnt = printDevList(g_own_list);
+
+ for( ; ; )
+ {
+ printf(" > Enter Owned Device Number to link : ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &dev_num);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(0<dev_num && g_own_cnt>=dev_num)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+
+ OCProvisionDev_t* ownDev = getDevInst(g_own_list, dev_num);
+ if(NULL == ownDev)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to getDevInst()");
+ return -1;
+ }
+
+ // call |OCProvisionCredentials| API actually
+ // calling this API with callback actually acts like blocking
+ // for error checking, the return value saved and printed
+ g_doneCB = false;
+ printf(" Provisioning Selected Pairwise Devices..\n");
+ OCStackResult rst = OCProvisionCredentials((void*) g_ctx,
+ SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128,
+ ownDev, motDev, provisionCredCB);
+ if(OC_STACK_OK != rst)
+ {
+ OIC_LOG_V(ERROR, TAG, "OCProvisionPairwiseDevices API error: %d", rst);
+ goto PVPWS_ERROR;
+ }
+ if(waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OIC_LOG(ERROR, TAG, "OCProvisionCredentials callback error");
+ goto PVPWS_ERROR;
+ }
+
+ // display the pairwise-provisioned result
+ printf(" > Provisioned Selected Pairwise Devices\n");
+
+ return 0;
+
+PVPWS_ERROR:
+ return -1;
+}
+
+static OCProvisionDev_t* getDevInst(const OCProvisionDev_t* dev_lst, const int dev_num)
+{
+ if(!dev_lst || 0>=dev_num)
+ {
+ printf(" Device List is Empty..\n");
+ return NULL;
+ }
+
+ OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
+ for(int i=0; lst; )
+ {
+ if(dev_num == ++i)
+ {
+ return lst;
+ }
+ lst = lst->next;
+ }
+
+ return NULL; // in here |lst| is always |NULL|
+}
+
+static int printDevList(const OCProvisionDev_t* dev_lst)
+{
+ if(!dev_lst)
+ {
+ printf(" Device List is Empty..\n\n");
+ return 0;
+ }
+
+ OCProvisionDev_t* lst = (OCProvisionDev_t*) dev_lst;
+ int lst_cnt = 0;
+ for( ; lst; )
+ {
+ printf(" [%d] ", ++lst_cnt);
+ printUuid((const OicUuid_t*) &lst->doxm->deviceID);
+ printf("\n");
+ lst = lst->next;
+ }
+ printf("\n");
+
+ return lst_cnt;
+}
+
+static size_t printUuidList(const OCUuidList_t* uid_lst)
+{
+ if(!uid_lst)
+ {
+ printf(" Device List is Empty..\n\n");
+ return 0;
+ }
+
+ OCUuidList_t* lst = (OCUuidList_t*) uid_lst;
+ size_t lst_cnt = 0;
+ for( ; lst; )
+ {
+ printf(" [%zu] ", ++lst_cnt);
+ printUuid((const OicUuid_t*) &lst->dev);
+ printf("\n");
+ lst = lst->next;
+ }
+ printf("\n");
+
+ return lst_cnt;
+}
+
+static int printResultList(const OCProvisionResult_t* rslt_lst, const int rslt_cnt)
+{
+ if(!rslt_lst || 0>=rslt_cnt)
+ {
+ printf(" Device List is Empty..\n\n");
+ return 0;
+ }
+
+ int lst_cnt = 0;
+ for( ; rslt_cnt>lst_cnt; ++lst_cnt)
+ {
+ printf(" [%d] ", lst_cnt+1);
+ printUuid((const OicUuid_t*) &rslt_lst[lst_cnt].deviceId);
+ printf(" - result: %d\n", rslt_lst[lst_cnt].res);
+ }
+ printf("\n");
+
+ return lst_cnt;
+}
+
+static void printUuid(const OicUuid_t* uid)
+{
+ for(int i=0; i<UUID_LENGTH; )
+ {
+ printf("%02X", (*uid).id[i++]);
+ if(i==4 || i==6 || i==8 || i==10) // canonical format for UUID has '8-4-4-4-12'
+ {
+ printf("-");
+ }
+ }
+}
+
+static FILE* fopen_prvnMng(const char* path, const char* mode)
+{
+ (void)path; // unused |path| parameter
+
+ // input |g_svr_db_fname| internally by force, not using |path| parameter
+ // because |OCPersistentStorage::open| is called |OCPersistentStorage| internally
+ // with its own |SVR_DB_FILE_NAME|
+ return fopen(SVR_DB_FILE_NAME, mode);
+}
+
+static int waitCallbackRet(void)
+{
+ for(int i=0; !g_doneCB && CALLBACK_TIMEOUT>i; ++i)
+ {
+ sleep(1);
+ if(OC_STACK_OK != OCProcess())
+ {
+ OIC_LOG(ERROR, TAG, "OCStack process error");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int selectTwoDiffNum(int* a, int* b, const int max, const char* str)
+{
+ if(!a || !b || 2>max || !str)
+ {
+ return -1;
+ }
+
+ for( ; ; )
+ {
+ for(int i=0; 2>i; ++i)
+ {
+ int* num = 0==i?a:b;
+ for( ; ; )
+ {
+ printf(" > Enter Device[%d] Number, %s: ", i+1, str);
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", num);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ if(0<*num && max>=*num)
+ {
+ break;
+ }
+ printf(" Entered Wrong Number. Please Enter Again\n");
+ }
+ }
+ if(*a != *b)
+ {
+ printf("\n");
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static void printMenu(void)
+{
+ printf("************************************************************\n");
+ printf("****** OIC Provisioning Client with using C-level API ******\n");
+ printf("************************************************************\n\n");
+
+ printf("** [A] DISCOVER DEVICES ON NETWORK\n");
+ printf("** 10. Discover Multiple Ownership Transfer Enabled Devices on Network\n");
+ printf("** 11. Discover Multiple Owned Devices on Network\n\n");
+
+ printf("** [B] PERFORM MULTIPLE OWNERSHIP TRANSFER\n");
+ printf("** 20. Perform the Multiple Ownership Transfer for ALL discovered dievices\n\n");
+
+ printf("** [C] Get/Put Request for APPLICATION RESOURCE\n");
+ printf("** 30. Get LED resource\n");
+ printf("** 31. Put LED resource\n\n");
+
+ printf("** [D] LINK DEVICES\n");
+ printf("** 40. Provision ACL for LED Resource\n");
+ printf("** 41. Provison Credential\n\n");
+
+ printf("** [F] EXIT PROVISIONING CLIENT\n");
+ printf("** 99. Exit Provisionong Client\n\n");
+
+ printf("************************************************************\n\n");
+}
+
+// main function for provisioning client using C-level provisioning API
+int main()
+{
+ // initialize provisioning client
+ if(initProvisionClient())
+ {
+ OIC_LOG(ERROR, TAG, "ProvisionClient init error");
+ goto PMCLT_ERROR;
+ }
+
+ // main loop for provisioning manager
+ int mnNum = 0;
+ int selDevNum = 0;
+ for( ; ; )
+ {
+ printf("\n");
+ printMenu();
+ printf(">> Enter Menu Number: ");
+ for(int ret=0; 1!=ret; )
+ {
+ ret = scanf("%d", &mnNum);
+ for( ; 0x20<=getchar(); ); // for removing overflow garbages
+ // '0x20<=code' is character region
+ }
+ printf("\n");
+ switch(mnNum)
+ {
+ case _10_DISCOV_MOT_ENABLED_DEV_:
+ if(discoverMotSupportedDevices())
+ {
+ OIC_LOG(ERROR, TAG, "_12_MOT_DISCOV_DEV_: error");
+ }
+ break;
+ case _11_DISCOV_MULTIPLE_OWNED_DEV_:
+ if(discoverSubOwnerDevices())
+ {
+ OIC_LOG(ERROR, TAG, "_13_DISCOV_MULTIPLE_OWNED_DEV_: error");
+ }
+ break;
+ case _20_PERFORM_MOT_:
+ if(multipleOwnershipTransfer())
+ {
+ OIC_LOG(ERROR, TAG, "_21_PERFORM_MOT_: error");
+ }
+ break;
+ case _30_GET_LED_RESOURCE_:
+ if(sendGetLed())
+ {
+ OIC_LOG(ERROR, TAG, "_30_GET_LED_RESOURCE_: error");
+ }
+ break;
+ case _31_PUT_LED_RESOURCE_:
+ if(sendPutLed())
+ {
+ OIC_LOG(ERROR, TAG, "_31_PUT_LED_RESOURCE_: error");
+ }
+ break;
+ case _40_PROVISION_ACL_:
+ if(provisionAclForLed())
+ {
+ OIC_LOG(ERROR, TAG, "_40_PROVISION_ACL_: error");
+ }
+ break;
+ case _41_PROVISION_CRED_:
+ OIC_LOG(ERROR, TAG, "NOT SUPPORTED YET.");
+ break;
+ /*
+ if(provisionCred())
+ {
+ OIC_LOG(ERROR, TAG, "_41_PROVISION_CRED_: error");
+ }
+ break;
+ */
+ case _99_EXIT_PRVN_CLT_:
+ goto PMCLT_ERROR;
+ default:
+ printf(">> Entered Wrong Number. Please Enter Again\n\n");
+ break;
+ }
+ }
+
+PMCLT_ERROR:
+ if(OC_STACK_OK != OCStop())
+ {
+ OIC_LOG(ERROR, TAG, "OCStack stop error");
+ }
+ OCDeleteDiscoveredDevices(g_own_list); // after here |g_own_list| points nothing
+ OCDeleteDiscoveredDevices(g_unown_list); // after here |g_unown_list| points nothing
+ OCDeleteDiscoveredDevices(g_motdev_list); // after here |g_motdev_list| points nothing
+
+ if(g_svr_fname)
+ {
+ OICFree(g_svr_fname); // after here |g_svr_fname| points nothing
+ }
+ if(g_prvn_fname)
+ {
+ OICFree(g_prvn_fname); // after here |g_prvn_fname| points nothing
+ }
+ return 0; // always return normal case
+}
+
+#ifdef __cplusplus
+}
+#endif //__cplusplus
OCFillRandomMem(privData, privDataKeySize);
// TODO: currently owner array is 1. only provisioning tool's id.
- tempFirstCred = GenerateCredential(secondDeviceId, type, NULL, &privKey, ptDeviceId);
+ tempFirstCred = GenerateCredential(secondDeviceId, type, NULL, &privKey, ptDeviceId, NULL);
VERIFY_NON_NULL(TAG, tempFirstCred, ERROR);
// TODO: currently owner array is 1. only provisioning tool's id.
- tempSecondCred = GenerateCredential(firstDeviceId, type, NULL, &privKey, ptDeviceId);
+ tempSecondCred = GenerateCredential(firstDeviceId, type, NULL, &privKey, ptDeviceId, NULL);
VERIFY_NON_NULL(TAG, tempSecondCred, ERROR);
*firstCred = tempFirstCred;
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ * *****************************************************************/
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <stdbool.h>
+#include <string.h>
+
+#include "utlist.h"
+#include "logger.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "cacommon.h"
+#include "cainterface.h"
+#include "base64.h"
+#include "cJSON.h"
+#include "global.h"
+
+#include "srmresourcestrings.h"
+#include "doxmresource.h"
+#include "pstatresource.h"
+#include "credresource.h"
+#include "aclresource.h"
+#include "ownershiptransfermanager.h"
+#include "securevirtualresourcetypes.h"
+#include "oxmjustworks.h"
+#include "pmtypes.h"
+#include "pmutility.h"
+#include "srmutility.h"
+#include "provisioningdatabasemanager.h"
+#include "oxmrandompin.h"
+#include "ocpayload.h"
+#include "payload_logging.h"
+#include "oxmjustworks.h"
+#include "oxmpreconfpin.h"
+#include "oxmrandompin.h"
+
+#define TAG "MULTIPLE_OTM"
+
+/**********************************************************************
+ * API for Super Owner
+ **********************************************************************/
+
+/**
+ * Structure to carry SuperOwner's multiple ownership transfer API data to callback.
+ */
+typedef struct MOTContext MOTContext_t;
+struct MOTContext
+{
+ void *ctx; /**< Pointer to user context.**/
+ const OCProvisionDev_t *deviceInfo; /**< Pointer to OCProvisionDev_t.**/
+ OCProvisionResultCB resultCallback; /**< Pointer to result callback.**/
+ OCProvisionResult_t *resArr; /**< Result array.**/
+ int numOfResults; /**< Number of results in result array.**/
+ bool hasError; /**< Does MOT API have any error.. **/
+};
+
+/**
+ * Callback handler of security resource's POST request.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] UNUSED handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult MOTUpdateSecurityResourceCB(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ OIC_LOG_V(INFO, TAG, "Inside MOTUpdateMomCB.");
+ (void)UNUSED;
+ MOTContext_t *motCtx = (MOTContext_t*)ctx;
+ VERIFY_NON_NULL(TAG, motCtx, ERROR);
+ VERIFY_NON_NULL(TAG, motCtx->resultCallback, ERROR);
+ VERIFY_NON_NULL(TAG, motCtx->resArr, ERROR);
+
+ if(clientResponse)
+ {
+ memcpy(motCtx->resArr[0].deviceId.id, motCtx->deviceInfo->doxm->deviceID.id, sizeof(OicUuid_t));
+ motCtx->resArr[0].res = clientResponse->result;
+
+ if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
+ {
+ motCtx->hasError = false;
+ }
+ else
+ {
+ motCtx->hasError = true;
+ }
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "SRPGetACLResourceCB received Null clientResponse");
+ motCtx->resArr[0].res = OC_STACK_ERROR;
+ motCtx->hasError = true;
+ }
+
+ motCtx->resultCallback(motCtx->ctx, motCtx->numOfResults, motCtx->resArr, motCtx->hasError);
+
+exit:
+ if(motCtx)
+ {
+ OICFree(motCtx->resArr);
+ OICFree(motCtx);
+ }
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Internal API to send POST doxm request
+ */
+static OCStackResult MOTSendPostDoxm(void *ctx,
+ const OCProvisionDev_t *targetDeviceInfo,
+ OCProvisionResultCB resultCallback,
+ const OicSecDoxm_t* doxm)
+{
+ OCStackResult postMomRes = OC_STACK_ERROR;
+ OCSecurityPayload* secPayload = NULL;
+ MOTContext_t *motCtx = NULL;
+ bool freeFlag = true;
+
+ OIC_LOG(DEBUG, TAG, "IN MOTSendPostDoxm");
+
+ //Generate the security payload using updated doxm
+ secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+ VERIFY_NON_NULL(TAG, secPayload, ERROR);
+ secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+
+ postMomRes = DoxmToCBORPayload(doxm, &secPayload->securityData, &secPayload->payloadSize, true);
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
+
+ OIC_LOG(DEBUG, TAG, "Created doxm payload to update doxm:");
+ OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
+
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ bool queryGenRes = PMGenerateQuery(true,
+ targetDeviceInfo->endpoint.addr,
+ targetDeviceInfo->securePort,
+ targetDeviceInfo->connType,
+ query, sizeof(query), OIC_RSRC_DOXM_URI);
+ VERIFY_SUCCESS(TAG, (true == queryGenRes), ERROR);
+ OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+ //Create the MOT Context to handle the response message
+ motCtx = (MOTContext_t*)OICCalloc(1, sizeof(MOTContext_t));
+ VERIFY_NON_NULL(TAG, motCtx, ERROR);
+ motCtx->deviceInfo = targetDeviceInfo;
+ motCtx->resultCallback = resultCallback;
+ motCtx->numOfResults=1;
+ motCtx->hasError = false;
+ motCtx->ctx = ctx;
+ motCtx->resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
+ VERIFY_NON_NULL(TAG, motCtx->resArr, ERROR);
+
+ //Send POST request
+ OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
+ cbData.cb = &MOTUpdateSecurityResourceCB;
+ cbData.context = (void *)motCtx;
+ OIC_LOG(DEBUG, TAG, "Sending POST 'doxm' request to resource server");
+ postMomRes = OCDoResource(NULL, OC_REST_POST, query,
+ &targetDeviceInfo->endpoint, (OCPayload*)secPayload,
+ targetDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
+
+ freeFlag = false;
+
+ OIC_LOG(DEBUG, TAG, "OUT MOTSendPostDoxm");
+
+exit:
+ //If POST request successfully sent, motCtx will be cleaned from response handler.
+ if(freeFlag && motCtx)
+ {
+ OICFree(motCtx->resArr);
+ OICFree(motCtx);
+ }
+
+ return postMomRes;
+}
+
+/**
+ * API to update 'doxm.mom' to resource server.
+ *
+ * @param[in] targetDeviceInfo Selected target device.
+ * @param[in] momType Mode of multiple ownership transfer (ref. oic.sec.mom)
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * POST 'mom' request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult MOTChangeMode(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
+ const OicSecMomType_t momType, OCProvisionResultCB resultCallback)
+{
+ OCStackResult postMomRes = OC_STACK_INVALID_PARAM;
+ OicSecDoxm_t* doxm = NULL;
+ uint8_t* doxmPayload = NULL;
+ size_t doxmPayloadLen = 0;
+
+ OIC_LOG(DEBUG, TAG, "IN MOTChangeMode");
+
+ VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
+ VERIFY_NON_NULL(TAG, resultCallback, ERROR);
+
+ //Dulpicate doxm resource to update the 'mom' property
+ postMomRes = DoxmToCBORPayload(targetDeviceInfo->doxm, &doxmPayload, &doxmPayloadLen, false);
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
+
+ postMomRes = CBORPayloadToDoxm(doxmPayload, doxmPayloadLen, &doxm);
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
+ VERIFY_NON_NULL(TAG, doxm, ERROR);
+
+ if(NULL == doxm->mom)
+ {
+ doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
+ VERIFY_NON_NULL(TAG, (doxm->mom), ERROR);
+ }
+ doxm->mom->mode = momType;
+
+ //Send POST reuqest for update doxm
+ postMomRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, doxm);
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
+
+ OIC_LOG(DEBUG, TAG, "OUT MOTChangeMode");
+
+exit:
+ OICFree(doxmPayload);
+ DeleteDoxmBinData(doxm);
+ return postMomRes;
+}
+
+/**
+ * API to add 'doxm.oxms' to resource server.
+ *
+ * @param[in] targetDeviceInfo Selected target device.
+ * @param[in] newOxm OxMs to be added (ref. oic.sec.oxm)
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * POST 'oxms' request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult MOTAddMOTMethod(void *ctx, OCProvisionDev_t *targetDeviceInfo,
+ const OicSecOxm_t newOxm, OCProvisionResultCB resultCallback)
+{
+ OCStackResult postOxmRes = OC_STACK_INVALID_PARAM;
+ OicSecOxm_t* newOxms = NULL;
+ uint8_t* doxmPayload = NULL;
+ size_t doxmPayloadLen = 0;
+
+ OIC_LOG(DEBUG, TAG, "IN MOTAddMOTMethod");
+
+ VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
+ VERIFY_NON_NULL(TAG, resultCallback, ERROR);
+
+ for(size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
+ {
+ if(targetDeviceInfo->doxm->oxm[i] == newOxm)
+ {
+ OIC_LOG_V(INFO, TAG, "[%d] OxM already supported", (int)newOxm);
+
+ OCProvisionResult_t* resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
+ resArr->res = OC_STACK_OK;
+ memcpy(resArr->deviceId.id, targetDeviceInfo->doxm->deviceID.id, sizeof(resArr->deviceId.id));
+ resultCallback(ctx, 1, resArr, false);
+
+ return OC_STACK_OK;
+ }
+ }
+
+ newOxms = (OicSecOxm_t*)OICMalloc(sizeof(OicSecOxm_t) * (targetDeviceInfo->doxm->oxmLen + 1));
+ VERIFY_NON_NULL(TAG, newOxms , ERROR);
+
+ for(size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
+ {
+ newOxms[i] = targetDeviceInfo->doxm->oxm[i];
+ }
+ newOxms[targetDeviceInfo->doxm->oxmLen] = newOxm;
+ targetDeviceInfo->doxm->oxmLen++;
+ OICFree(targetDeviceInfo->doxm->oxm);
+ targetDeviceInfo->doxm->oxm = newOxms;
+
+ //Send POST reuqest for update doxm
+ postOxmRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, targetDeviceInfo->doxm);
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == postOxmRes), ERROR);
+
+ OIC_LOG(DEBUG, TAG, "OUT MOTAddMOTMethod");
+
+exit:
+ OICFree(doxmPayload);
+ return postOxmRes;
+}
+
+/**
+ * API to update 'doxm.oxmsel' to resource server.
+ *
+ * @param[in] targetDeviceInfo Selected target device.
+ * @param[in] oxmSelValue Method of multiple ownership transfer (ref. oic.sec.oxm)
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * POST 'oxmsel' request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult MOTSelectMOTMethod(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
+ const OicSecOxm_t oxmSelValue, OCProvisionResultCB resultCallback)
+{
+ OCStackResult postMomRes = OC_STACK_INVALID_PARAM;
+ OicSecDoxm_t* doxm = NULL;
+ uint8_t* doxmPayload = NULL;
+ size_t doxmPayloadLen = 0;
+
+ OIC_LOG(DEBUG, TAG, "IN MOTSelectOTMethod");
+
+ VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
+ VERIFY_NON_NULL(TAG, resultCallback, ERROR);
+
+ bool isValidOxmsel = false;
+ for(size_t i = 0; i < targetDeviceInfo->doxm->oxmLen; i++)
+ {
+ if(targetDeviceInfo->doxm->oxm[i] == oxmSelValue)
+ {
+ isValidOxmsel = true;
+ break;
+ }
+ }
+ VERIFY_SUCCESS(TAG, isValidOxmsel, ERROR);
+
+ //Dulpicate doxm resource to update the 'oxmsel' property
+ postMomRes = DoxmToCBORPayload(targetDeviceInfo->doxm, &doxmPayload, &doxmPayloadLen, false);
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
+
+ postMomRes = CBORPayloadToDoxm(doxmPayload, doxmPayloadLen, &doxm);
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
+ VERIFY_NON_NULL(TAG, doxm, ERROR);
+
+ doxm->oxmSel = oxmSelValue;
+
+ //Send POST reuqest for update doxm
+ postMomRes = MOTSendPostDoxm(ctx, targetDeviceInfo, resultCallback, doxm);
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == postMomRes), ERROR);
+
+ OIC_LOG(DEBUG, TAG, "OUT MOTSelectOTMethod");
+
+exit:
+ OICFree(doxmPayload);
+ DeleteDoxmBinData(doxm);
+ return postMomRes;
+}
+
+/**
+ * API to provision preconfigured PIN to resource server.
+ *
+ * @param[in] targetDeviceInfo Selected target device.
+ * @param[in] preconfPIN Preconfig PIN which is used while multiple owner authentication
+ * @param[in] preconfPINLen Byte length of preconfig PIN
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * POST credential request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult MOTProvisionPreconfigPIN(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
+ const char* preconfPIN, size_t preconfPINLen, OCProvisionResultCB resultCallback)
+{
+ OCStackResult postCredRes = OC_STACK_INVALID_PARAM;
+ bool freeFlag = true;
+ OCSecurityPayload* secPayload = NULL;
+ MOTContext_t *motCtx = NULL;
+ OicSecCred_t* pinCred = NULL;
+
+ OIC_LOG(DEBUG, TAG, "IN MOTProvisionPreconfigPIN");
+
+ VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
+ VERIFY_NON_NULL(TAG, resultCallback, ERROR);
+ VERIFY_NON_NULL(TAG, preconfPIN, ERROR);
+ VERIFY_SUCCESS(TAG, (0 != preconfPINLen), ERROR);
+ VERIFY_SUCCESS(TAG, (0 != preconfPINLen && OXM_PRECONFIG_PIN_SIZE >= preconfPINLen), ERROR);
+
+ postCredRes = OC_STACK_NO_MEMORY;
+ //Generate PIN based credential
+ pinCred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
+ VERIFY_NON_NULL(TAG, pinCred, ERROR);
+
+ pinCred->privateData.data = (uint8_t*)OICMalloc(preconfPINLen + 1);
+ VERIFY_NON_NULL(TAG, pinCred->privateData.data, ERROR);
+
+ memcpy(pinCred->privateData.data, preconfPIN, preconfPINLen);
+ pinCred->privateData.data[preconfPINLen] = '\0';
+ pinCred->privateData.len = preconfPINLen;
+ pinCred->privateData.encoding = OIC_ENCODING_RAW;
+ pinCred->credType = PIN_PASSWORD;
+ OICStrcpy(pinCred->subject.id, sizeof(pinCred->subject.id), WILDCARD_SUBJECT_ID.id);
+
+ //Generate the security payload using updated doxm
+ secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+ VERIFY_NON_NULL(TAG, secPayload, ERROR);
+ secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+
+ postCredRes = CredToCBORPayload(pinCred, &secPayload->securityData, &secPayload->payloadSize, false);
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == postCredRes), ERROR);
+
+ OIC_LOG(DEBUG, TAG, "Created Credential payload to register PIN credential:");
+ OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
+
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ bool queryGenRes = PMGenerateQuery(true,
+ targetDeviceInfo->endpoint.addr,
+ targetDeviceInfo->securePort,
+ targetDeviceInfo->connType,
+ query, sizeof(query), OIC_RSRC_CRED_URI);
+ VERIFY_SUCCESS(TAG, (true == queryGenRes), ERROR);
+ OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
+
+ //Create the MOT Context to handle the response message
+ motCtx = (MOTContext_t*)OICCalloc(1, sizeof(MOTContext_t));
+ VERIFY_NON_NULL(TAG, motCtx, ERROR);
+ motCtx->deviceInfo = targetDeviceInfo;
+ motCtx->resultCallback = resultCallback;
+ motCtx->numOfResults=1;
+ motCtx->hasError = false;
+ motCtx->ctx = ctx;
+ motCtx->resArr = (OCProvisionResult_t*)OICCalloc(1, sizeof(OCProvisionResult_t));
+ VERIFY_NON_NULL(TAG, motCtx->resArr, ERROR);
+
+ //Send POST request
+ OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
+ cbData.cb = &MOTUpdateSecurityResourceCB;
+ cbData.context = (void *)motCtx;
+ OIC_LOG(DEBUG, TAG, "Sending POST Preconfiged PIN credenatial request to resource server");
+ postCredRes = OCDoResource(NULL, OC_REST_POST, query,
+ &targetDeviceInfo->endpoint, (OCPayload*)secPayload,
+ targetDeviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == postCredRes), ERROR);
+
+ freeFlag = false;
+
+ OIC_LOG(DEBUG, TAG, "OUT MOTProvisionPreconfigPIN");
+
+ return postCredRes;
+
+exit:
+ //If POST request successfully sent, motCtx will be cleaned from response handler.
+ if(freeFlag && motCtx)
+ {
+ OICFree(motCtx->resArr);
+ OICFree(motCtx);
+ }
+ if(pinCred)
+ {
+ OICFree(pinCred->privateData.data);
+ OICFree(pinCred);
+ }
+ return postCredRes;
+}
+
+
+/**********************************************************************
+ * API for Sub Owner
+ **********************************************************************/
+
+static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t* motCtx,
+ OCProvisionDev_t* selectedDevice);
+
+/**
+ * Array to store the callbacks for each owner transfer method.
+ */
+static OTMCallbackData_t g_MOTCbDatas[OIC_OXM_COUNT] = {
+ //Just works
+ {.loadSecretCB = LoadSecretJustWorksCallback,
+ .createSecureSessionCB = CreateSecureSessionJustWorksCallback,
+ .createSelectOxmPayloadCB = NULL,
+ .createOwnerTransferPayloadCB = NULL},
+
+ //Random PIN
+ {.loadSecretCB = InputPinCodeCallback,
+ .createSecureSessionCB = CreateSecureSessionRandomPinCallback,
+ .createSelectOxmPayloadCB = NULL,
+ .createOwnerTransferPayloadCB = NULL},
+
+ //Manufacturer Cert
+ {.loadSecretCB = NULL,
+ .createSecureSessionCB = NULL,
+ .createSelectOxmPayloadCB = NULL,
+ .createOwnerTransferPayloadCB = NULL},
+
+ //Preconfig PIN
+ {.loadSecretCB = LoadPreconfPinCodeCallback,
+ .createSecureSessionCB = CreateSecureSessionPreconfPinCallback,
+ .createSelectOxmPayloadCB = NULL,
+ .createOwnerTransferPayloadCB = NULL},
+};
+
+static OTMContext_t* g_MotCtx = NULL;
+
+static bool IsComplete(OTMContext_t* otmCtx)
+{
+ for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
+ {
+ if(OC_STACK_CONTINUE == otmCtx->ctxResultArray[i].res)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Function to save the result of multiple ownership transfer.
+ *
+ * @param[in,out] motCtx Context instance of multiple ownership transfer.
+ * @param[in] res result of multiple ownership transfer.
+ */
+static void SetMOTResult(OTMContext_t* motCtx, const OCStackResult res)
+{
+ OIC_LOG_V(DEBUG, TAG, "IN SetMOTResult : %d ", res);
+
+ VERIFY_NON_NULL(TAG, motCtx, ERROR);
+
+ if(motCtx->selectedDeviceInfo)
+ {
+ //Revert psk_info callback in case of random PIN OxM
+ if(OIC_RANDOM_DEVICE_PIN == motCtx->selectedDeviceInfo->doxm->oxmSel ||
+ OIC_PRECONFIG_PIN == motCtx->selectedDeviceInfo->doxm->oxmSel)
+ {
+ if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
+ {
+ OIC_LOG(WARNING, TAG, "Failed to revert the DTLS credential handler.");
+ }
+ OicUuid_t emptyUuid = { .id={0}};
+ SetUuidForPinBasedOxm(&emptyUuid);
+ }
+
+ for(size_t i = 0; i < motCtx->ctxResultArraySize; i++)
+ {
+ if(memcmp(motCtx->selectedDeviceInfo->doxm->deviceID.id,
+ motCtx->ctxResultArray[i].deviceId.id, UUID_LENGTH) == 0)
+ {
+ motCtx->ctxResultArray[i].res = res;
+ if(OC_STACK_OK != res)
+ {
+ motCtx->ctxHasError = true;
+ }
+ }
+ }
+
+ g_MotCtx = NULL;
+
+ //If all request is completed, invoke the user callback.
+ if(IsComplete(motCtx))
+ {
+ motCtx->ctxResultCallback(motCtx->userCtx, motCtx->ctxResultArraySize,
+ motCtx->ctxResultArray, motCtx->ctxHasError);
+
+ OICFree(motCtx->ctxResultArray);
+ OICFree(motCtx);
+ }
+ else
+ {
+ if(OC_STACK_OK != StartMultipleOwnershipTransfer(motCtx,
+ motCtx->selectedDeviceInfo->next))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to StartMultipleOwnershipTransfer");
+ }
+ }
+ }
+
+exit:
+ OIC_LOG(DEBUG, TAG, "OUT SetMOTResult");
+}
+
+/**
+ * API to add preconfigured PIN to local SVR DB.
+ *
+ * @param[in] targetDeviceInfo Selected target device.
+ * @param[in] preconfPIN Preconfig PIN which is used while multiple owner authentication
+ * @param[in] preconfPINLen Byte length of preconfig PIN
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * POST credential request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult MOTAddPreconfigPIN(const OCProvisionDev_t *targetDeviceInfo,
+ const char* preconfPIN, size_t preconfPINLen)
+{
+ OCStackResult addCredRes = OC_STACK_INVALID_PARAM;
+ OicSecCred_t* pinCred = NULL;
+ bool freeFlag = true;
+
+ OIC_LOG(DEBUG, TAG, "IN MOTAddPreconfigPIN");
+
+ VERIFY_NON_NULL(TAG, targetDeviceInfo, ERROR);
+ VERIFY_NON_NULL(TAG, preconfPIN, ERROR);
+ VERIFY_SUCCESS(TAG, (0 != preconfPINLen), ERROR);
+ VERIFY_SUCCESS(TAG, (0 != preconfPINLen && OXM_PRECONFIG_PIN_SIZE >= preconfPINLen), ERROR);
+
+ OicSecCred_t* prevCred = GetCredResourceData(&targetDeviceInfo->doxm->deviceID);
+ if(NULL != prevCred)
+ {
+ OIC_LOG(INFO, TAG, "PIN/PW Credential already exist!");
+ return OC_STACK_OK;
+ }
+
+ addCredRes = OC_STACK_NO_MEMORY;
+ //Generate PIN based credential
+ pinCred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
+ VERIFY_NON_NULL(TAG, pinCred, ERROR);
+
+ pinCred->privateData.data = (uint8_t*)OICMalloc(preconfPINLen + 1);
+ VERIFY_NON_NULL(TAG, pinCred->privateData.data, ERROR);
+
+ memcpy(pinCred->privateData.data, preconfPIN, preconfPINLen);
+ pinCred->privateData.data[preconfPINLen] = '\0';
+ pinCred->privateData.len = preconfPINLen;
+ pinCred->privateData.encoding = OIC_ENCODING_RAW;
+ pinCred->credType = PIN_PASSWORD;
+ memcpy(pinCred->subject.id, targetDeviceInfo->doxm->deviceID.id, sizeof(pinCred->subject.id));
+
+ addCredRes = AddCredential(pinCred);
+ VERIFY_SUCCESS(TAG, (OC_STACK_OK == addCredRes), ERROR);
+
+ OIC_LOG(DEBUG, TAG, "OUT MOTAddPreconfigPIN");
+
+ return addCredRes;
+
+exit:
+ if(pinCred)
+ {
+ OICFree(pinCred->privateData.data);
+ OICFree(pinCred);
+ }
+ return addCredRes;
+}
+
+/**
+ * Function to save the SubOwner PSK.
+ *
+ * @param[in] selectedDeviceInfo selected device information to performing provisioning.
+ * @return OC_STACK_OK on success
+ */
+static OCStackResult SaveSubOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
+{
+ OIC_LOG(DEBUG, TAG, "IN SaveSubOwnerPSK");
+
+ OCStackResult res = OC_STACK_ERROR;
+
+ CAEndpoint_t endpoint;
+ memset(&endpoint, 0x00, sizeof(CAEndpoint_t));
+ OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
+ endpoint.addr[MAX_ADDR_STR_SIZE_CA - 1] = '\0';
+ endpoint.port = selectedDeviceInfo->securePort;
+ endpoint.adapter = selectedDeviceInfo->endpoint.adapter;
+
+ OicUuid_t ownerDeviceID = {.id={0}};
+ if (OC_STACK_OK != GetDoxmDeviceID(&ownerDeviceID))
+ {
+ OIC_LOG(ERROR, TAG, "Error while retrieving SubOwner's device ID");
+ return res;
+ }
+
+ uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
+ OicSecKey_t ownerKey = {ownerPSK, OWNER_PSK_LENGTH_128};
+
+ //Generating SubOwnerPSK
+ CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
+ (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
+ strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)),
+ ownerDeviceID.id, sizeof(ownerDeviceID.id),
+ selectedDeviceInfo->doxm->deviceID.id, sizeof(selectedDeviceInfo->doxm->deviceID.id),
+ ownerPSK, OWNER_PSK_LENGTH_128);
+
+ if (CA_STATUS_OK == pskRet)
+ {
+ OIC_LOG(INFO, TAG, "SubOwner PSK dump:");
+ OIC_LOG_BUFFER(INFO, TAG, ownerPSK, OWNER_PSK_LENGTH_128);
+ //Generating new credential for provisioning tool
+ OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
+ SYMMETRIC_PAIR_WISE_KEY, NULL,
+ &ownerKey, &ownerDeviceID, &ownerDeviceID);
+ VERIFY_NON_NULL(TAG, cred, ERROR);
+
+ uint32_t outSize = 0;
+ size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
+ char* b64Buf = (uint8_t *)OICCalloc(1, b64BufSize);
+ VERIFY_NON_NULL(TAG, b64Buf, ERROR);
+ b64Encode(cred->privateData.data, cred->privateData.len, b64Buf, b64BufSize, &outSize);
+
+ OICFree( cred->privateData.data );
+ cred->privateData.data = (uint8_t *)OICCalloc(1, outSize + 1);
+ VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
+
+ strncpy(cred->privateData.data, b64Buf, outSize);
+ cred->privateData.data[outSize] = '\0';
+ cred->privateData.encoding = OIC_ENCODING_BASE64;
+ cred->privateData.len = outSize;
+ OICFree(b64Buf);
+
+ //Add SubOwnerPSK
+ res = AddCredential(cred);
+ if(res != OC_STACK_OK)
+ {
+ DeleteCredList(cred);
+ return res;
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT SaveSubOwnerPSK");
+exit:
+ return res;
+}
+
+
+/**
+ * Response handler for update subowner crendetial request.
+ *
+ * @param[in] ctx ctx value passed to callback from calling function.
+ * @param[in] UNUSED handle to an invocation
+ * @param[in] clientResponse Response from queries to remote servers.
+ * @return OC_STACK_DELETE_TRANSACTION to delete the transaction
+ * and OC_STACK_KEEP_TRANSACTION to keep it.
+ */
+static OCStackApplicationResult SubOwnerCredentialHandler(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+ VERIFY_NON_NULL(TAG, ctx, WARNING);
+
+ OIC_LOG(DEBUG, TAG, "IN SubOwnerCredentialHandler");
+ (void)UNUSED;
+ OCStackResult res = OC_STACK_ERROR;
+ OTMContext_t* motCtx = (OTMContext_t*)ctx;
+
+ if(OC_STACK_RESOURCE_CHANGED == clientResponse->result)
+ {
+ if(motCtx && motCtx->selectedDeviceInfo)
+ {
+ //Close the temporal secure session to verify the owner credential
+ CAEndpoint_t* endpoint = (CAEndpoint_t *)&motCtx->selectedDeviceInfo->endpoint;
+ endpoint->port = motCtx->selectedDeviceInfo->securePort;
+ CAResult_t caResult = CAcloseSslSession(endpoint);
+ if(CA_STATUS_OK != caResult)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to close DTLS session");
+ SetMOTResult(motCtx, OC_STACK_ERROR);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 = 0xC037, /**< see RFC 5489 */
+ caResult = CASelectCipherSuite(0xC037, endpoint->adapter);
+ if(CA_STATUS_OK != caResult)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to select TLS_NULL_WITH_NULL_NULL");
+ SetMOTResult(motCtx, OC_STACK_ERROR);
+ return OC_STACK_DELETE_TRANSACTION;
+ }
+
+ res = PDMAddDevice(&motCtx->selectedDeviceInfo->doxm->deviceID);
+ if (OC_STACK_OK == res)
+ {
+ OIC_LOG_V(INFO, TAG, "Add device's UUID in PDM_DB");
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "MOT is complete but adding information to DB is failed.");
+ }
+
+ SetMOTResult(motCtx, res);
+ }
+ }
+ else
+ {
+ res = clientResponse->result;
+ OIC_LOG_V(ERROR, TAG, "SubOwnerCredentialHandler : Unexpected result %d", res);
+ SetMOTResult(motCtx, res);
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT SubOwnerCredentialHandler");
+
+exit:
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+static OCStackResult PostSubOwnerCredential(OTMContext_t* motCtx)
+{
+ OIC_LOG(DEBUG, TAG, "IN PostSubOwnerCredential");
+
+ if(!motCtx || !motCtx->selectedDeviceInfo)
+ {
+ OIC_LOG(ERROR, TAG, "Invalid parameters");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OCProvisionDev_t* deviceInfo = motCtx->selectedDeviceInfo;
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+
+ if(!PMGenerateQuery(true,
+ deviceInfo->endpoint.addr, deviceInfo->securePort,
+ deviceInfo->connType,
+ query, sizeof(query), OIC_RSRC_CRED_URI))
+ {
+ OIC_LOG(ERROR, TAG, "PostSubOwnerCredential : Failed to generate query");
+ return OC_STACK_ERROR;
+ }
+ OIC_LOG_V(DEBUG, TAG, "Query=%s", query);
+ OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+ if(!secPayload)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to memory allocation");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ //Generate sub-owner credential for new device
+ secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+ const OicSecCred_t* ownerCredential = GetCredResourceData(&(deviceInfo->doxm->deviceID));
+ if(!ownerCredential)
+ {
+ OIC_LOG(ERROR, TAG, "Can not find SubOwnerPSK.");
+ return OC_STACK_NO_RESOURCE;
+ }
+
+ OicUuid_t ownerId = {.id={0}};
+ if(OC_STACK_OK == GetDoxmDeviceID(&ownerId))
+ {
+ OicSecCred_t newCredential;
+ memcpy(&newCredential, ownerCredential, sizeof(OicSecCred_t));
+ newCredential.next = NULL;
+
+ //Set subject ID as SubOwner's ID
+ memcpy(&(newCredential.subject), &ownerId, sizeof(OicUuid_t));
+
+ //Set eowner ID as SubOwner's ID
+ if(NULL == newCredential.eownerID)
+ {
+ newCredential.eownerID = OICCalloc(1, sizeof(OicUuid_t));
+ if(NULL == newCredential.eownerID)
+ {
+ return OC_STACK_NO_MEMORY;
+ }
+ }
+ memcpy(newCredential.eownerID->id, ownerId.id, sizeof(ownerId.id));
+
+ //Fill private data as empty string
+ newCredential.privateData.data = "";
+ newCredential.privateData.len = 0;
+ newCredential.privateData.encoding = ownerCredential->privateData.encoding;
+#ifdef __WITH_X509__
+ newCredential.publicData.data = NULL;
+ newCredential.publicData.len = 0;
+#endif
+ //Send owner credential to new device : POST /oic/sec/cred [ owner credential ]
+ if (OC_STACK_OK != CredToCBORPayload(&newCredential, &secPayload->securityData,
+ &secPayload->payloadSize, 0))
+ {
+ OICFree(secPayload);
+ OIC_LOG(ERROR, TAG, "Error while converting bin to cbor.");
+ return OC_STACK_ERROR;
+ }
+ OIC_LOG(DEBUG, TAG, "Cred Payload:");
+ OIC_LOG_BUFFER(DEBUG, TAG, secPayload->securityData, secPayload->payloadSize);
+
+ OCCallbackData cbData;
+ cbData.cb = &SubOwnerCredentialHandler;
+ cbData.context = (void *)motCtx;
+ cbData.cd = NULL;
+ OCStackResult res = OCDoResource(NULL, OC_REST_POST, query,
+ &deviceInfo->endpoint, (OCPayload*)secPayload,
+ deviceInfo->connType, OC_HIGH_QOS, &cbData, NULL, 0);
+ if (res != OC_STACK_OK)
+ {
+ OIC_LOG(ERROR, TAG, "OCStack resource error");
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Failed to read DOXM device ID.");
+ return OC_STACK_NO_RESOURCE;
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT PostSubOwnerCredential");
+
+ return OC_STACK_OK;
+}
+
+
+/**
+ * Function to handle the handshake result in MOT.
+ * This function will be invoked after DTLS handshake
+ * @param endPoint [IN] The remote endpoint.
+ * @param errorInfo [IN] Error information from the endpoint.
+ * @return NONE
+ */
+static void MOTDtlsHandshakeCB(const CAEndpoint_t *endpoint, const CAErrorInfo_t *info)
+{
+ if(NULL != g_MotCtx && NULL != g_MotCtx->selectedDeviceInfo &&
+ NULL != endpoint && NULL != info)
+ {
+ OIC_LOG_V(INFO, TAG, "Received status from remote device(%s:%d) : %d",
+ endpoint->addr, endpoint->port, info->result);
+
+ OicSecDoxm_t* newDevDoxm = g_MotCtx->selectedDeviceInfo->doxm;
+
+ if(NULL != newDevDoxm)
+ {
+ OicUuid_t emptyUuid = {.id={0}};
+
+ //Make sure the address matches.
+ if(strncmp(g_MotCtx->selectedDeviceInfo->endpoint.addr,
+ endpoint->addr,
+ sizeof(endpoint->addr)) == 0 &&
+ g_MotCtx->selectedDeviceInfo->securePort == endpoint->port)
+ {
+ OCStackResult res = OC_STACK_ERROR;
+
+ //If temporal secure sesstion established successfully
+ if(CA_STATUS_OK == info->result)
+ {
+ //Delete previous credential such as preconfigured-pin
+ RemoveCredential(&(g_MotCtx->selectedDeviceInfo->doxm->deviceID));
+
+ res = SaveSubOwnerPSK(g_MotCtx->selectedDeviceInfo);
+ if(OC_STACK_OK == res)
+ {
+ //POST sub owner credential to new device.
+ res = PostSubOwnerCredential(g_MotCtx);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG,
+ "Failed to send POST request for SubOwner Credential");
+ SetMOTResult(g_MotCtx, res);
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Failed to save the SubOwner PSK.");
+ SetMOTResult(g_MotCtx, res);
+ }
+ }
+ //In case of authentication failure
+ else if(CA_DTLS_AUTHENTICATION_FAILURE == info->result)
+ {
+ //in case of error from wrong PIN, re-start the ownership transfer
+ if(OIC_RANDOM_DEVICE_PIN == newDevDoxm->oxmSel)
+ {
+ OIC_LOG(ERROR, TAG, "The PIN number may incorrect.");
+
+ g_MotCtx->attemptCnt++;
+
+ if(WRONG_PIN_MAX_ATTEMP > g_MotCtx->attemptCnt)
+ {
+ res = StartMultipleOwnershipTransfer(g_MotCtx, g_MotCtx->selectedDeviceInfo);
+ if(OC_STACK_OK != res)
+ {
+ SetMOTResult(g_MotCtx, res);
+ OIC_LOG(ERROR, TAG, "Failed to Re-StartOwnershipTransfer");
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "User has exceeded the number of authentication attempts.");
+ SetMOTResult(g_MotCtx, OC_STACK_AUTHENTICATION_FAILURE);
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Failed to establish DTLS session.");
+ SetMOTResult(g_MotCtx, OC_STACK_AUTHENTICATION_FAILURE);
+ }
+ }
+ }
+ }
+ }
+}
+
+static OCStackResult StartMultipleOwnershipTransfer(OTMContext_t* motCtx,
+ OCProvisionDev_t* selectedDevice)
+{
+ OIC_LOG(INFO, TAG, "IN StartMultipleOwnershipTransfer");
+ OCStackResult res = OC_STACK_INVALID_PARAM;
+
+ VERIFY_NON_NULL(TAG, selectedDevice, ERROR);
+ VERIFY_NON_NULL(TAG, selectedDevice->doxm, ERROR);
+
+ motCtx->selectedDeviceInfo = selectedDevice;
+
+ //Register DTLS event handler to catch the dtls event while handshake
+ if(CA_STATUS_OK != CAregisterSslHandshakeCallback(MOTDtlsHandshakeCB))
+ {
+ OIC_LOG(WARNING, TAG, "StartOwnershipTransfer : Failed to register DTLS handshake callback.");
+ }
+
+ size_t oxmSel = (size_t)(selectedDevice->doxm->oxmSel);
+ OIC_LOG_V(DEBUG, TAG, "Multiple Ownership Transfer method = %d", selectedDevice->doxm->oxmSel);
+
+ if(OIC_PRECONFIG_PIN != oxmSel && OIC_RANDOM_DEVICE_PIN != oxmSel)
+ {
+ OIC_LOG(ERROR, TAG, "Unsupported OxM");
+ return OC_STACK_ERROR;
+ }
+
+ if(OIC_RANDOM_DEVICE_PIN == selectedDevice->doxm->oxmSel)
+ {
+ if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM.");
+ }
+ }
+
+ res = g_MOTCbDatas[oxmSel].loadSecretCB(motCtx);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
+
+ //Save the current context instance to use on the dtls handshake callback
+ g_MotCtx = motCtx;
+
+ res = g_MOTCbDatas[oxmSel].createSecureSessionCB(motCtx);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
+
+ OIC_LOG(INFO, TAG, "OUT StartMultipleOwnershipTransfer");
+
+exit:
+ return res;
+}
+
+OCStackResult MOTDoOwnershipTransfer(void* ctx,
+ OCProvisionDev_t *selectedDevicelist,
+ OCProvisionResultCB resultCallback)
+{
+ OIC_LOG(DEBUG, TAG, "IN MOTDoOwnershipTransfer");
+ OCStackResult res = OC_STACK_INVALID_PARAM;
+ OTMContext_t* motCtx = NULL;
+ OCProvisionDev_t* pCurDev = NULL;
+
+ VERIFY_NON_NULL(TAG, selectedDevicelist, ERROR);
+ VERIFY_NON_NULL(TAG, resultCallback, ERROR);
+
+ res = OC_STACK_NO_MEMORY;
+ motCtx = (OTMContext_t*)OICCalloc(1,sizeof(OTMContext_t));
+ VERIFY_NON_NULL(TAG, motCtx, ERROR);
+
+ motCtx->ctxResultCallback = resultCallback;
+ motCtx->ctxHasError = false;
+ motCtx->userCtx = ctx;
+ motCtx->ctxResultArraySize = 0;
+ LL_FOREACH(selectedDevicelist, pCurDev)
+ {
+ motCtx->ctxResultArraySize++;
+ }
+
+ motCtx->ctxResultArray =
+ (OCProvisionResult_t*)OICCalloc(motCtx->ctxResultArraySize, sizeof(OCProvisionResult_t));
+ VERIFY_NON_NULL(TAG, motCtx->ctxResultArray, ERROR);
+
+ //Fill the device UUID for result array.
+ size_t devIdx = 0;
+ res = OC_STACK_OK;
+ pCurDev = NULL;
+ LL_FOREACH(selectedDevicelist, pCurDev)
+ {
+ //Checking duplication of Device ID.
+ bool isDuplicate = true;
+ res = PDMIsDuplicateDevice(&pCurDev->doxm->deviceID, &isDuplicate);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
+
+ if (isDuplicate)
+ {
+ bool isStale = false;
+ res = PDMIsDeviceStale(&pCurDev->doxm->deviceID, &isStale);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
+ VERIFY_SUCCESS(TAG, isStale, ERROR);
+
+ if(isStale)
+ {
+ OIC_LOG(INFO, TAG, "Detected duplicated UUID in stale status, "\
+ "this UUID will be removed from PDM");
+
+ res = PDMDeleteDevice(&pCurDev->doxm->deviceID);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
+ }
+ }
+
+ memcpy(motCtx->ctxResultArray[devIdx].deviceId.id,
+ pCurDev->doxm->deviceID.id,
+ UUID_LENGTH);
+ motCtx->ctxResultArray[devIdx].res = OC_STACK_CONTINUE;
+ devIdx++;
+ }
+
+ res = StartMultipleOwnershipTransfer(motCtx, selectedDevicelist);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == res, ERROR);
+
+ OIC_LOG(DEBUG, TAG, "OUT MOTDoOwnershipTransfer");
+
+exit:
+ if(OC_STACK_OK != res)
+ {
+ if(motCtx)
+ {
+ OICFree(motCtx->ctxResultArray);
+ OICFree(motCtx);
+ }
+ }
+ return res;
+}
#include "pmutility.h"
#include "srmutility.h"
#include "ownershiptransfermanager.h"
+#ifdef _ENABLE_MULTIPLE_OWNER_
+#include "multipleownershiptransfermanager.h"
+#endif //_ENABLE_MULTIPLE_OWNER_
#include "oic_malloc.h"
#include "logger.h"
#include "secureresourceprovider.h"
};
+#ifdef _ENABLE_MULTIPLE_OWNER_
+typedef struct ProvPreconfPINCtx ProvPreconfPINCtx_t;
+struct ProvPreconfPINCtx
+{
+ void *ctx;
+ const OCProvisionDev_t *devInfo;
+ const char* pin;
+ size_t pinLen;
+ OCProvisionResultCB resultCallback;
+};
+#endif //_ENABLE_MULTIPLE_OWNER_
+
/**
* The function is responsible for initializaton of the provisioning manager. It will load
* provisioning database which have owned device's list and their linked status.
return PMDeviceDiscovery(timeout, true, ppList);
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * The function is responsible for discovery of MOT enabled device is current subnet.
+ *
+ * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
+ * server before returning the list of devices.
+ * @param[out] ppList List of MOT enabled devices.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCDiscoverMultipleOwnerEnabledDevices(unsigned short timeout, OCProvisionDev_t **ppList)
+{
+ if( ppList == NULL || *ppList != NULL || 0 == timeout)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ return PMMultipleOwnerDeviceDiscovery(timeout, false, ppList);
+}
+
+/**
+ * The function is responsible for discovery of Multiple Owned device is current subnet.
+ *
+ * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
+ * server before returning the list of devices.
+ * @param[out] ppList List of Multiple Owned devices.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCDiscoverMultipleOwnedDevices(unsigned short timeout, OCProvisionDev_t **ppList)
+{
+ if( ppList == NULL || *ppList != NULL || 0 == timeout)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ return PMMultipleOwnerDeviceDiscovery(timeout, true, ppList);
+}
+
+
+/**
+ * API to add preconfigured PIN to local SVR DB.
+ *
+ * @param[in] targetDeviceInfo Selected target device.
+ * @param[in] preconfPIN Preconfig PIN which is used while multiple owner authentication
+ * @param[in] preconfPINLen Byte length of preconfig PIN
+ *
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCAddPreconfigPIN(const OCProvisionDev_t *targetDeviceInfo,
+ const char* preconfPIN, size_t preconfPINLen)
+{
+ return MOTAddPreconfigPIN( targetDeviceInfo, preconfPIN, preconfPINLen);
+}
+
+
+OCStackResult OCDoMultipleOwnershipTransfer(void* ctx,
+ OCProvisionDev_t *targetDevices,
+ OCProvisionResultCB resultCallback)
+{
+ if( NULL == targetDevices )
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+ if (NULL == resultCallback)
+ {
+ OIC_LOG(INFO, TAG, "OCDoOwnershipTransfer : NULL Callback");
+ return OC_STACK_INVALID_CALLBACK;
+ }
+ return MOTDoOwnershipTransfer(ctx, targetDevices, resultCallback);
+}
+
+#endif //_ENABLE_MULTIPLE_OWNER_
+
/**
* API to register for particular OxM.
*
return SRPProvisionDirectPairing(ctx, selectedDeviceInfo, pconf, resultCallback);
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+static void AddPreconfPinOxMCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+ ProvPreconfPINCtx_t* provCtx = (ProvPreconfPINCtx_t*)ctx;
+ if(provCtx)
+ {
+ OCStackResult res = MOTProvisionPreconfigPIN(provCtx->ctx, provCtx->devInfo, provCtx->pin, provCtx->pinLen, provCtx->resultCallback);
+ if(OC_STACK_OK != res)
+ {
+ arr->res = res;
+ provCtx->resultCallback(provCtx->ctx, nOfRes, arr, true);
+ }
+ }
+}
+
+OCStackResult OCProvisionPreconfPin(void* ctx,
+ OCProvisionDev_t *targetDeviceInfo,
+ const char * preconfPin, size_t preconfPinLen,
+ OCProvisionResultCB resultCallback)
+{
+ if( NULL == targetDeviceInfo )
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+ if (NULL == resultCallback)
+ {
+ OIC_LOG(INFO, TAG, "OCProvisionPreconfPINCredential : NULL Callback");
+ return OC_STACK_INVALID_CALLBACK;
+ }
+
+ ProvPreconfPINCtx_t* provCtx = (ProvPreconfPINCtx_t*)OICCalloc(1, sizeof(ProvPreconfPINCtx_t));
+ if(NULL == provCtx)
+ {
+ return OC_STACK_NO_MEMORY;
+ }
+ provCtx->ctx = ctx;
+ provCtx->devInfo = targetDeviceInfo;
+ provCtx->pin = preconfPin;
+ provCtx->pinLen = preconfPinLen;
+ provCtx->resultCallback = resultCallback;
+ /*
+ * First of all, update OxMs to support preconfigured PIN OxM.
+ * In case of Preconfigured PIN OxM already supported on the server side,
+ * MOTAddMOTMethod API will be send POST Cred request.
+ * In case of Preconfigure PIN OxM not exist on the server side,
+ * the MOTAddMOTMethod API will be send POST doxm request to update OxMs and then send POST Cred request.
+ */
+ return MOTAddMOTMethod((void*)provCtx, targetDeviceInfo, OIC_PRECONFIG_PIN, AddPreconfPinOxMCB);
+}
+#endif //_ENABLE_MULTIPLE_OWNER_
+
/*
* Function to unlink devices.
* This function will remove the credential & relationship between the two devices.
{
FreePdAclList(pPdAcl);
}
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * API to update 'doxm.mom' to resource server.
+ *
+ * @param[in] targetDeviceInfo Selected target device.
+ * @param[in] momType Mode of multiple ownership transfer (ref. oic.sec.mom)
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * POST 'mom' request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCChangeMOTMode(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
+ const OicSecMomType_t momType, OCProvisionResultCB resultCallback)
+{
+ return MOTChangeMode(ctx, targetDeviceInfo, momType, resultCallback);
+}
+
+/**
+ * API to update 'doxm.oxmsel' to resource server.
+ *
+ * @param[in] targetDeviceInfo Selected target device.
+ * @param[in] oxmSelValue Method of multiple ownership transfer (ref. oic.sec.oxm)
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ * POST 'oxmsel' request recieves a response from resource server.
+ * @return OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCSelectMOTMethod(void *ctx, const OCProvisionDev_t *targetDeviceInfo,
+ const OicSecOxm_t oxmSelValue, OCProvisionResultCB resultCallback)
+{
+ return MOTSelectMOTMethod(ctx, targetDeviceInfo, oxmSelValue, resultCallback);
+}
+#endif //_ENABLE_MULTIPLE_OWNER_
+
#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
/**
* function to provision Trust certificate chain to devices.
return SRPProvisionTrustCertChain(ctx, type, credId,
selectedDeviceInfo, resultCallback);
}
+
/**
* function to save Trust certificate chain into Cred of SVR.
*
#include "ownershiptransfermanager.h"
#include "securevirtualresourcetypes.h"
#include "oxmjustworks.h"
+#ifdef _ENABLE_MULTIPLE_OWNER_
+#include "oxmrandompin.h"
+#include "oxmpreconfpin.h"
+#endif //_ENABLE_MULTIPLE_OWNER_
#include "pmtypes.h"
#include "pmutility.h"
#include "srmutility.h"
/**
* Array to store the callbacks for each owner transfer method.
*/
-static OTMCallbackData_t g_OTMDatas[OIC_OXM_COUNT];
+static OTMCallbackData_t g_OTMCbDatas[OIC_OXM_COUNT] = {
+ //Just works
+ {.loadSecretCB = LoadSecretJustWorksCallback,
+ .createSecureSessionCB = CreateSecureSessionJustWorksCallback,
+ .createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload,
+ .createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload},
+
+ //Random PIN
+ {.loadSecretCB = InputPinCodeCallback,
+ .createSecureSessionCB = CreateSecureSessionRandomPinCallback,
+ .createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload,
+ .createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload},
+
+ //Manufacturer Cert
+ {.loadSecretCB = NULL,
+ .createSecureSessionCB = NULL,
+ .createSelectOxmPayloadCB = NULL,
+ .createOwnerTransferPayloadCB = NULL},
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ //Preconfig PIN
+ {.loadSecretCB = LoadPreconfPinCodeCallback,
+ .createSecureSessionCB = CreateSecureSessionPreconfPinCallback,
+ .createSelectOxmPayloadCB = CreatePreconfPinBasedSelectOxmPayload,
+ .createOwnerTransferPayloadCB = CreatePreconfPinBasedOwnerTransferPayload},
+#endif //_ENABLE_MULTIPLE_OWNER_
+};
/**
* Variables for pointing the OTMContext to be used in the DTLS handshake result callback.
}
}
+ if(NULL == g_OTMCbDatas[(*selectedMethod)].loadSecretCB ||
+ NULL == g_OTMCbDatas[(*selectedMethod)].createSecureSessionCB ||
+ NULL == g_OTMCbDatas[(*selectedMethod)].createSelectOxmPayloadCB ||
+ NULL == g_OTMCbDatas[(*selectedMethod)].createOwnerTransferPayloadCB)
+ {
+ OIC_LOG_V(ERROR, TAG, "Please make sure the OxM(%d)'s callback registration", (int)(*selectedMethod));
+ return OC_STACK_INVALID_CALLBACK;
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT SelectProvisioningMethod");
+
return OC_STACK_OK;
}
OIC_LOG(WARNING, TAG, "Failed to revert is DTLS credential handler.");
}
OicUuid_t emptyUuid = { .id={0}};
- SetUuidForRandomPinOxm(&emptyUuid);
+ SetUuidForPinBasedOxm(&emptyUuid);
}
for(size_t i = 0; i < otmCtx->ctxResultArraySize; i++)
}
/**
- * Function to save ownerPSK at provisioning tool end.
+ * Function to save the Owner/SubOwner PSK.
*
* @param[in] selectedDeviceInfo selected device information to performing provisioning.
* @return OC_STACK_OK on success
endpoint.port = selectedDeviceInfo->securePort;
endpoint.adapter = selectedDeviceInfo->endpoint.adapter;
- OicUuid_t ptDeviceID = {.id={0}};
- if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
+ OicUuid_t ownerDeviceID = {.id={0}};
+ if (OC_STACK_OK != GetDoxmDeviceID(&ownerDeviceID))
{
- OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+ OIC_LOG(ERROR, TAG, "Error while retrieving Owner's device ID");
return res;
}
CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
(uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)),
- ptDeviceID.id, sizeof(ptDeviceID.id),
+ ownerDeviceID.id, sizeof(ownerDeviceID.id),
selectedDeviceInfo->doxm->deviceID.id, sizeof(selectedDeviceInfo->doxm->deviceID.id),
ownerPSK, OWNER_PSK_LENGTH_128);
if (CA_STATUS_OK == pskRet)
{
- OIC_LOG(INFO, TAG,"ownerPSK dump:\n");
+ OIC_LOG(INFO, TAG,"Owner PSK dump:\n");
OIC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
//Generating new credential for provisioning tool
OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
- SYMMETRIC_PAIR_WISE_KEY, NULL,
- &ownerKey, &ptDeviceID);
+ SYMMETRIC_PAIR_WISE_KEY, NULL,
+ &ownerKey, &ownerDeviceID, NULL);
VERIFY_NON_NULL(TAG, cred, ERROR);
// TODO: Added as workaround. Will be replaced soon.
{
OCStackResult res = OC_STACK_ERROR;
OicSecOxm_t selOxm = otmCtx->selectedDeviceInfo->doxm->oxmSel;
+
//DTLS Handshake
//Load secret for temporal secure session.
- if(g_OTMDatas[selOxm].loadSecretCB)
+ if(g_OTMCbDatas[selOxm].loadSecretCB)
{
- res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
+ res = g_OTMCbDatas[selOxm].loadSecretCB(otmCtx);
if(OC_STACK_OK != res)
{
OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
g_otmCtx = otmCtx;
//Try DTLS handshake to generate secure session
- if(g_OTMDatas[selOxm].createSecureSessionCB)
+ if(g_OTMCbDatas[selOxm].createSecureSessionCB)
{
- res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
+ res = g_OTMCbDatas[selOxm].createSecureSessionCB(otmCtx);
if(OC_STACK_OK != res)
{
OIC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
{
OicUuid_t emptyUuid = { .id={0}};
- SetUuidForRandomPinOxm(&emptyUuid);
+ SetUuidForPinBasedOxm(&emptyUuid);
caResult = CAregisterPskCredentialsHandler(GetDtlsPskCredentials);
static OCStackResult PostOwnerAcl(OTMContext_t* otmCtx)
{
OCStackResult res = OC_STACK_ERROR;
- OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
- char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
- OicSecAcl_t* ownerAcl = NULL;
OIC_LOG(DEBUG, TAG, "IN PostOwnerAcl");
return OC_STACK_INVALID_PARAM;
}
+ OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
+ char query[MAX_URI_LENGTH + MAX_QUERY_LENGTH] = {0};
+ OicSecAcl_t* ownerAcl = NULL;
+
if(!PMGenerateQuery(true,
deviceInfo->endpoint.addr, deviceInfo->securePort,
deviceInfo->connType,
return OC_STACK_NO_MEMORY;
}
secPayload->base.type = PAYLOAD_TYPE_SECURITY;
- OCStackResult res = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx,
+ OCStackResult res = g_OTMCbDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx,
&secPayload->securityData, &secPayload->payloadSize);
if (OC_STACK_OK != res && NULL == secPayload->securityData)
{
return OC_STACK_NO_MEMORY;
}
secPayload->base.type = PAYLOAD_TYPE_SECURITY;
- OCStackResult res = g_OTMDatas[deviceInfo->doxm->oxmSel].createOwnerTransferPayloadCB(
+ OCStackResult res = g_OTMCbDatas[deviceInfo->doxm->oxmSel].createOwnerTransferPayloadCB(
otmCtx, &secPayload->securityData, &secPayload->payloadSize);
if (OC_STACK_OK != res && NULL == secPayload->securityData)
{
static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
{
OIC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
+ OCStackResult res = OC_STACK_INVALID_PARAM;
+
+ VERIFY_NON_NULL(TAG, selectedDevice, ERROR);
+ VERIFY_NON_NULL(TAG, selectedDevice->doxm, ERROR);
+
OTMContext_t* otmCtx = (OTMContext_t*)ctx;
otmCtx->selectedDeviceInfo = selectedDevice;
//Set to the lowest level OxM, and then find more higher level OxM.
- OCStackResult res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
- selectedDevice->doxm->oxmLen,
- &selectedDevice->doxm->oxmSel);
+ res = SelectProvisioningMethod(selectedDevice->doxm->oxm,
+ selectedDevice->doxm->oxmLen,
+ &selectedDevice->doxm->oxmSel);
if(OC_STACK_OK != res)
{
OIC_LOG(ERROR, TAG, "Failed to select the provisioning method");
}
OIC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
- //Send Req: POST /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
+ //Send Req: POST /oic/sec/doxm [{..."OxmSel" :g_OTMCbDatas[Index of Selected OxM].OXMString,...}]
res = PostOwnerTransferModeToResource(otmCtx);
if(OC_STACK_OK != res)
{
#endif // __WITH_DTLS__ or __WITH_TLS__
OIC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
+exit:
return res;
-
}
OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
return OC_STACK_INVALID_PARAM;
}
- g_OTMDatas[oxmType].loadSecretCB= data->loadSecretCB;
- g_OTMDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
- g_OTMDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
- g_OTMDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
+ g_OTMCbDatas[oxmType].loadSecretCB= data->loadSecretCB;
+ g_OTMCbDatas[oxmType].createSecureSessionCB = data->createSecureSessionCB;
+ g_OTMCbDatas[oxmType].createSelectOxmPayloadCB = data->createSelectOxmPayloadCB;
+ g_OTMCbDatas[oxmType].createOwnerTransferPayloadCB = data->createOwnerTransferPayloadCB;
OIC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
--- /dev/null
+/* *****************************************************************
+ *
+ * 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.
+ *
+ * *****************************************************************/
+
+#include <memory.h>
+
+#include "ocstack.h"
+#include "securevirtualresourcetypes.h"
+#include "doxmresource.h"
+#include "credresource.h"
+#include "cacommon.h"
+#include "cainterface.h"
+#include "ocrandom.h"
+#include "oic_malloc.h"
+#include "logger.h"
+#include "pbkdf2.h"
+#include "global.h"
+#include "base64.h"
+#include "oxmpreconfpin.h"
+#include "ownershiptransfermanager.h"
+#include "pinoxmcommon.h"
+#include "srmresourcestrings.h"
+
+#define TAG "OXM_PreconfigPIN"
+
+OCStackResult CreatePreconfPinBasedSelectOxmPayload(OTMContext_t* otmCtx, uint8_t **payload, size_t *size)
+{
+ if(!otmCtx || !otmCtx->selectedDeviceInfo || !payload || *payload || !size)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ otmCtx->selectedDeviceInfo->doxm->oxmSel = OIC_PRECONFIG_PIN;
+
+ return DoxmToCBORPayload(otmCtx->selectedDeviceInfo->doxm, payload, size, true);
+}
+
+OCStackResult CreatePreconfPinBasedOwnerTransferPayload(OTMContext_t* otmCtx, uint8_t **payload, size_t *size)
+{
+ if(!otmCtx || !otmCtx->selectedDeviceInfo || !payload || *payload || !size)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ OicUuid_t uuidPT = {.id={0}};
+ *payload = NULL;
+ *size = 0;
+
+ if (OC_STACK_OK != GetDoxmDeviceID(&uuidPT))
+ {
+ OIC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+ return OC_STACK_ERROR;
+ }
+ memcpy(otmCtx->selectedDeviceInfo->doxm->owner.id, uuidPT.id , UUID_LENGTH);
+
+ return DoxmToCBORPayload(otmCtx->selectedDeviceInfo->doxm, payload, size, true);
+}
+
+OCStackResult LoadPreconfPinCodeCallback(OTMContext_t *otmCtx)
+{
+ OIC_LOG(INFO, TAG, "IN LoadPreconfPinCodeCallback");
+ OCStackResult res = OC_STACK_ERROR;
+ OicSecCred_t* cred = GetCredResourceData(&otmCtx->selectedDeviceInfo->doxm->deviceID);
+ if(NULL == cred)
+ {
+ OicUuid_t uuid = {.id={0}};
+ OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
+ cred = GetCredResourceData(&uuid);
+ if(NULL == cred)
+ {
+ OIC_LOG(ERROR, TAG, "Can not find the Credential for MOT");
+ OIC_LOG(ERROR, TAG, "Please make sure the preconfigured PIN");
+ return OC_STACK_ERROR;
+ }
+ }
+
+ uint8_t* pinBuffer = NULL;
+ size_t pinBufLen = 0;
+ if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
+ {
+ //In case of 'preconfig PIN', secret data(PIN) already exist.
+ pinBufLen = B64DECODE_OUT_SAFESIZE(cred->privateData.len + 1);
+ pinBuffer = (uint8_t*)OICCalloc(1, pinBufLen);
+ if(NULL == pinBuffer)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to memory allocation.");
+ return OC_STACK_NO_MEMORY;
+ }
+ uint32_t pinLen = 0;
+ if(B64_OK != b64Decode(cred->privateData.data, cred->privateData.len, pinBuffer, pinBufLen, &pinLen))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to base64 deconding for preconfig PIN");
+ OICFree(pinBuffer);
+ return OC_STACK_ERROR;
+ }
+ pinBufLen = pinLen;
+ }
+ else if(OIC_ENCODING_RAW == cred->privateData.encoding)
+ {
+ pinBuffer = (uint8_t*)OICMalloc(cred->privateData.len + 1);
+ if(NULL == pinBuffer)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to memory allocation.");
+ return OC_STACK_NO_MEMORY;
+ }
+ memcpy(pinBuffer, cred->privateData.data, cred->privateData.len);
+ pinBuffer[cred->privateData.len] = '\0';
+ pinBufLen = cred->privateData.len;
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Unknown encoding type for PreConfigured PIN credential");
+ return OC_STACK_ERROR;
+ }
+
+ res = SetPreconfigPin((char*)pinBuffer, pinBufLen);
+ OICFree(pinBuffer);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed to save the preconfig PIN : %d", res);
+ return res;
+ }
+
+ //in case of OTM
+ if(false == otmCtx->selectedDeviceInfo->doxm->owned)
+ {
+ if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForPreconfPinOxm))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to register DTLS credentials handler for random PIN OxM.");
+ res = OC_STACK_ERROR;
+ }
+ }
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ //in case of MOT
+ else if(true == otmCtx->selectedDeviceInfo->doxm->owned &&
+ otmCtx->selectedDeviceInfo->doxm->mom &&
+ OIC_MULTIPLE_OWNER_DISABLE != otmCtx->selectedDeviceInfo->doxm->mom->mode)
+ {
+ if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForMotPreconfPinOxm))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to register DTLS credentials handler for random PIN OxM.");
+ res = OC_STACK_ERROR;
+ }
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
+
+ //Set the device id to derive temporal PSK
+ SetUuidForPinBasedOxm(&(otmCtx->selectedDeviceInfo->doxm->deviceID));
+
+ OIC_LOG(INFO, TAG, "OUT LoadPreconfPinCodeCallback");
+
+ return res;
+}
+
+OCStackResult CreateSecureSessionPreconfPinCallback(OTMContext_t* otmCtx)
+{
+ OIC_LOG(INFO, TAG, "IN CreateSecureSessionPreconfPinCallback");
+
+ if (!otmCtx || !otmCtx->selectedDeviceInfo)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ CAResult_t caresult = CAEnableAnonECDHCipherSuite(false);
+ if (CA_STATUS_OK != caresult)
+ {
+ OIC_LOG_V(ERROR, TAG, "Unable to disable anon cipher suite");
+ return OC_STACK_ERROR;
+ }
+ OIC_LOG(INFO, TAG, "Anonymous cipher suite disabled.");
+
+ caresult = CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, otmCtx->selectedDeviceInfo->endpoint.adapter);
+ if (CA_STATUS_OK != caresult)
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed to select TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256");
+ return OC_STACK_ERROR;
+ }
+ OIC_LOG(INFO, TAG, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 cipher suite selected.");
+
+ OCProvisionDev_t* selDevInfo = otmCtx->selectedDeviceInfo;
+ CAEndpoint_t *endpoint = (CAEndpoint_t *)OICCalloc(1, sizeof (CAEndpoint_t));
+ if (NULL == endpoint)
+ {
+ return OC_STACK_NO_MEMORY;
+ }
+ memcpy(endpoint,&selDevInfo->endpoint,sizeof(CAEndpoint_t));
+ endpoint->port = selDevInfo->securePort;
+ caresult = CAInitiateHandshake(endpoint);
+ OICFree(endpoint);
+ if (CA_STATUS_OK != caresult)
+ {
+ OIC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
+ return OC_STACK_ERROR;
+ }
+
+ OIC_LOG(INFO, TAG, "OUT CreateSecureSessionPreconfPinCallback");
+
+ return OC_STACK_OK;
+}
* Credential should not be saved into SVR.
* For this reason, We will use a temporary get_psk_info callback to random PIN OxM.
*/
-
- if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
+ //in case of OTM
+ if(!(otmCtx->selectedDeviceInfo->doxm->owned))
+ {
+ if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to register DTLS credentials handler for random PIN OxM.");
+ res = OC_STACK_ERROR;
+ }
+ }
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ //in case of MOT
+ else if(otmCtx->selectedDeviceInfo->doxm->owned &&
+ otmCtx->selectedDeviceInfo->doxm->mom &&
+ OIC_MULTIPLE_OWNER_DISABLE != otmCtx->selectedDeviceInfo->doxm->mom->mode)
{
- OIC_LOG(ERROR, TAG, "Failed to register TLS credentials handler for random PIN OxM.");
- res = OC_STACK_ERROR;
+ if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForMotRandomPinOxm))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to register TLS credentials handler for random PIN OxM.");
+ res = OC_STACK_ERROR;
+ }
}
+#endif //_ENABLE_MULTIPLE_OWNER_
//Set the device id to derive temporal PSK
- SetUuidForRandomPinOxm(&(otmCtx->selectedDeviceInfo->doxm->deviceID));
+ SetUuidForPinBasedOxm(&(otmCtx->selectedDeviceInfo->doxm->deviceID));
return res;
}
return res;
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+static OCStackApplicationResult MOTDeviceDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
+ OCClientResponse *clientResponse)
+{
+ if (ctx == NULL)
+ {
+ OIC_LOG(ERROR, TAG, "Lost List of device information");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ (void)UNUSED;
+ if (clientResponse)
+ {
+ if (NULL == clientResponse->payload)
+ {
+ OIC_LOG(INFO, TAG, "Skipping Null payload");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ if (OC_STACK_OK != clientResponse->result)
+ {
+ OIC_LOG(INFO, TAG, "Error in response");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ else
+ {
+ if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
+ {
+ OIC_LOG(INFO, TAG, "Unknown payload type");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ OicSecDoxm_t *ptrDoxm = NULL;
+ uint8_t *payload = ((OCSecurityPayload*)clientResponse->payload)->securityData;
+ size_t size = ((OCSecurityPayload*)clientResponse->payload)->payloadSize;
+
+ OCStackResult res = CBORPayloadToDoxm(payload, size, &ptrDoxm);
+ if ((NULL == ptrDoxm) || (OC_STACK_OK != res))
+ {
+ OIC_LOG(INFO, TAG, "Ignoring malformed CBOR");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ else
+ {
+ OIC_LOG(DEBUG, TAG, "Successfully converted doxm cbor to bin.");
+
+ //If this is owend device discovery we have to filter out the responses.
+ DiscoveryInfo* pDInfo = (DiscoveryInfo*)ctx;
+ OCProvisionDev_t **ppDevicesList = pDInfo->ppDevicesList;
+
+ // Get my device ID from doxm resource
+ OicUuid_t myId;
+ memset(&myId, 0, sizeof(myId));
+ OCStackResult res = GetDoxmDevOwnerId(&myId);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Error while getting my device ID.");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ res = GetDoxmDeviceID(&myId);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Error while getting my UUID.");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ //if this is owned discovery and this is PT's reply, discard it
+ if((pDInfo->isOwnedDiscovery) &&
+ (0 == memcmp(&ptrDoxm->deviceID.id, &myId.id, sizeof(myId.id))) )
+ {
+ OIC_LOG(DEBUG, TAG, "discarding provision tool's reply");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ if(pDInfo->isOwnedDiscovery)
+ {
+ OicSecSubOwner_t* subOwner = NULL;
+ LL_FOREACH(ptrDoxm->subOwners, subOwner)
+ {
+ if(memcmp(myId.id, subOwner->uuid.id, sizeof(myId.id)) == 0)
+ {
+ break;
+ }
+ }
+
+ if(subOwner)
+ {
+ res = AddDevice(ppDevicesList, &clientResponse->devAddr,
+ clientResponse->connType, ptrDoxm);
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ res = SecurePortDiscovery(pDInfo, clientResponse);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to SecurePortDiscovery");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "discarding device's reply, because not a SubOwner.");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ }
+ else
+ {
+ if(ptrDoxm->mom && OIC_MULTIPLE_OWNER_DISABLE != ptrDoxm->mom->mode)
+ {
+ res = AddDevice(ppDevicesList, &clientResponse->devAddr,
+ clientResponse->connType, ptrDoxm);
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ res = SecurePortDiscovery(pDInfo, clientResponse);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to SecurePortDiscovery");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "discarding mom disabled device's reply");
+ DeleteDoxmBinData(ptrDoxm);
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ }
+
+ OIC_LOG(INFO, TAG, "Exiting ProvisionDiscoveryHandler.");
+ }
+
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+ }
+ else
+ {
+ OIC_LOG(INFO, TAG, "Skiping Null response");
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+/**
+ * Discover multiple OTM enabled devices in the same IP subnet.
+ *
+ * @param[in] waittime Timeout in seconds.
+ * @param[in] ppDevicesList List of OCProvisionDev_t.
+ *
+ * @return OC_STACK_OK on success otherwise error.
+ */
+OCStackResult PMMultipleOwnerDeviceDiscovery(unsigned short waittime, bool isMultipleOwned, OCProvisionDev_t **ppDevicesList)
+{
+ OIC_LOG(DEBUG, TAG, "IN PMMultipleOwnerEnabledDeviceDiscovery");
+
+ if (NULL != *ppDevicesList)
+ {
+ OIC_LOG(ERROR, TAG, "List is not null can cause memory leak");
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ const char *DOXM_MOM_ENABLE_MULTICAST_QUERY = "/oic/sec/doxm?mom!=0&owned=TRUE";
+ const char *DOXM_MULTIPLE_OWNED_MULTICAST_QUERY = "/oic/sec/doxm?owned=TRUE";
+
+ DiscoveryInfo *pDInfo = OICCalloc(1, sizeof(DiscoveryInfo));
+ if(NULL == pDInfo)
+ {
+ OIC_LOG(ERROR, TAG, "PMDeviceDiscovery : Memory allocation failed.");
+ return OC_STACK_NO_MEMORY;
+ }
+
+ pDInfo->ppDevicesList = ppDevicesList;
+ pDInfo->isOwnedDiscovery = isMultipleOwned;
+
+ OCCallbackData cbData;
+ cbData.cb = &MOTDeviceDiscoveryHandler;
+ cbData.context = (void *)pDInfo;
+ cbData.cd = NULL;
+ OCStackResult res = OC_STACK_ERROR;
+
+ const char* query = isMultipleOwned ? DOXM_MULTIPLE_OWNED_MULTICAST_QUERY :
+ DOXM_MOM_ENABLE_MULTICAST_QUERY;
+
+ OCDoHandle handle = NULL;
+ res = OCDoResource(&handle, OC_REST_DISCOVER, query, 0, 0,
+ CT_DEFAULT, OC_HIGH_QOS, &cbData, NULL, 0);
+ if (res != OC_STACK_OK)
+ {
+ OIC_LOG(ERROR, TAG, "OCStack resource error");
+ OICFree(pDInfo);
+ return res;
+ }
+
+ //Waiting for each response.
+ res = PMTimeout(waittime, true);
+ if(OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to wait response for secure discovery.");
+ OICFree(pDInfo);
+ OCStackResult resCancel = OCCancel(handle, OC_HIGH_QOS, NULL, 0);
+ if(OC_STACK_OK != resCancel)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
+ }
+ return res;
+ }
+ res = OCCancel(handle,OC_HIGH_QOS,NULL,0);
+ if (OC_STACK_OK != res)
+ {
+ OIC_LOG(ERROR, TAG, "Failed to remove registered callback");
+ OICFree(pDInfo);
+ return res;
+ }
+ OIC_LOG(DEBUG, TAG, "OUT PMMultipleOwnerEnabledDeviceDiscovery");
+ OICFree(pDInfo);
+ return res;
+}
+
+#endif //_ENABLE_MULTIPLE_OWNER_
+
static OCStackResult SecurePortDiscovery(DiscoveryInfo* discoveryInfo,
const OCClientResponse *clientResponse)
{
if not sptest_env.get('RELEASE'):
sptest_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+if sptest_env.get('MULTIPLE_OWNER') == '1':
+ sptest_env.AppendUnique(CPPDEFINES=['_ENABLE_MULTIPLE_OWNER_'])
+
if target_os in ['msys_nt', 'windows']:
sptest_env.AppendUnique(LINKFLAGS = ['/subsystem:CONSOLE'])
sptest_env.AppendUnique(LIBS = ['ws2_32',
#include "oxmrandompin.h"
#include "securevirtualresourcetypes.h"
#include "provisioningdatabasemanager.h"
+#ifdef _ENABLE_MULTIPLE_OWNER_
+#include "multipleownershiptransfermanager.h"
+#endif //_ENABLE_MULTIPLE_OWNER_
#include "srmutility.h"
#include "doxmresource.h"
#include "pmtypes.h"
static const char* g_otmCtx = "Test User Context";
static OCProvisionDev_t* g_unownedDevices = NULL;
static OCProvisionDev_t* g_ownedDevices = NULL;
+#ifdef _ENABLE_MULTIPLE_OWNER_
+static OCProvisionDev_t* g_motEnabledDevices = NULL;
+static OCProvisionDev_t* g_multiplOwnedDevices = NULL;
+#endif //_ENABLE_MULTIPLE_OWNER_
static void GetCurrentWorkingDirectory(char* buf, size_t bufsize)
{
g_doneCB = true;
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+static void updateDoxmForMOTCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+ if(!hasError)
+ {
+ OIC_LOG_V(INFO, TAG, "POST 'doxm' SUCCEEDED - ctx: %s", (char*) ctx);
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "POST 'doxm' FAILED - ctx: %s", (char*) ctx);
+ }
+ g_callbackResult = !hasError;
+ g_doneCB = true;
+}
+
+static void provisionPreconfiguredPinCB(void* ctx, int nOfRes, OCProvisionResult_t* arr, bool hasError)
+{
+ if(!hasError)
+ {
+ OIC_LOG_V(INFO, TAG, "Provision Preconfigured-PIN SUCCEEDED - ctx: %s", (char*) ctx);
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "Provision Preconfigured-PIN FAILED - ctx: %s", (char*) ctx);
+ }
+ g_callbackResult = !hasError;
+ g_doneCB = true;
+}
+#endif //_ENABLE_MULTIPLE_OWNER_
// callback function(s) for provisioning client using C-level provisioning API
static void removeDeviceCB(void* ctx, int UNUSED1, OCProvisionResult_t* UNUSED2, bool hasError)
EXPECT_EQ(OC_STACK_OK, result);
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+TEST(RegisterPreconfiguredPIN, NullParam)
+{
+ OCStackResult result = SetPreconfigPin("12341234", strlen("12341234"));
+ EXPECT_EQ(OC_STACK_OK, result);
+}
+
+TEST(EnableMOT, NullParam)
+{
+ OCStackResult result = OC_STACK_OK;
+
+ if(NULL == g_ownedDevices)
+ {
+ OIC_LOG(INFO, TAG, "Discovering Only Owned Devices on Network..\n");
+ result = OCDiscoverOwnedDevices(DISCOVERY_TIMEOUT, &g_ownedDevices);
+ EXPECT_EQ(OC_STACK_OK, result);
+ RemoveUnknownDeviceFromDevList(g_ownedDevices);
+ }
+ EXPECT_NE((OCProvisionDev_t*)NULL, g_ownedDevices);
+
+ g_doneCB = false;
+ result = MOTChangeMode(NULL, g_ownedDevices, OIC_MULTIPLE_OWNER_ENABLE, updateDoxmForMOTCB);
+ EXPECT_EQ(OC_STACK_OK, result);
+ if(waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OIC_LOG(ERROR, TAG, "OCChangeMOTMode callback error");
+ return;
+ }
+
+ EXPECT_TRUE(g_callbackResult);
+}
+
+TEST(DiscoverMOTEnabledDevices, NullParam)
+{
+ OCStackResult result = OC_STACK_OK;
+
+ if(g_motEnabledDevices)
+ {
+ PMDeleteDeviceList(g_motEnabledDevices);
+ }
+
+ OIC_LOG(INFO, TAG, "Discovering MOT Enabled Devices on Network..\n");
+ result = OCDiscoverMultipleOwnerEnabledDevices(DISCOVERY_TIMEOUT, &g_motEnabledDevices);
+ EXPECT_EQ(OC_STACK_OK, result);
+ RemoveUnknownDeviceFromDevList(g_motEnabledDevices);
+ EXPECT_NE((OCProvisionDev_t*)NULL, g_motEnabledDevices);
+}
+
+TEST(ProvisonPreconfiguredPIN, NullParam)
+{
+ OCStackResult result = OC_STACK_OK;
+
+ g_doneCB = false;
+ result = OCProvisionPreconfPin(NULL, g_motEnabledDevices, "12341234", strlen("12341234"), provisionPreconfiguredPinCB);
+ EXPECT_EQ(OC_STACK_OK, result);
+ if(waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OIC_LOG(ERROR, TAG, "OCProvisionPreconfPin callback error");
+ return;
+ }
+
+ EXPECT_EQ(true, g_callbackResult);
+}
+
+TEST(SelectMOTMethod, NullParam)
+{
+ OCStackResult result = OC_STACK_OK;
+
+ g_doneCB = false;
+ result = MOTSelectMOTMethod(NULL, g_motEnabledDevices, OIC_PRECONFIG_PIN, updateDoxmForMOTCB);
+ EXPECT_EQ(OC_STACK_OK, result);
+ if(waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OIC_LOG(ERROR, TAG, "OCSelectMOTMethod callback error");
+ return;
+ }
+
+ EXPECT_EQ(true, g_callbackResult);
+}
+
+// TODO: Need to new server to perform MOT
+/*
+TEST(PerformMOT, NullParam)
+{
+ OCStackResult result = OC_STACK_OK;
+
+ g_doneCB = false;
+ result = OCDoMultipleOwnershipTransfer(NULL, g_motEnabledDevices, ownershipTransferCB);
+ EXPECT_EQ(OC_STACK_OK, result);
+ if(waitCallbackRet()) // input |g_doneCB| flag implicitly
+ {
+ OIC_LOG(ERROR, TAG, "OCDoMultipleOwnershipTransfer callback error");
+ return;
+ }
+ EXPECT_EQ(true, g_callbackResult);
+}
+
+TEST(DiscoverMultipleOwnedDevices, NullParam)
+{
+ OCStackResult result = OC_STACK_OK;
+
+ if(g_multiplOwnedDevices)
+ {
+ PMDeleteDeviceList(g_multiplOwnedDevices);
+ }
+
+ OIC_LOG(INFO, TAG, "Discovering MOT Enabled Devices on Network..\n");
+ result = OCDiscoverMultipleOwnedDevices(DISCOVERY_TIMEOUT, &g_multiplOwnedDevices);
+ EXPECT_EQ(OC_STACK_OK, result);
+ RemoveUnknownDeviceFromDevList(g_multiplOwnedDevices);
+ EXPECT_TRUE(NULL != g_multiplOwnedDevices);
+}*/
+
+#endif //_ENABLE_MULTIPLE_OWNER_
+
TEST(PerformRemoveDevice, NullParam)
{
OicUuid_t myUuid;
}
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ if(ace->eownerID)
+ {
+ aclMapSize++;
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
+
cborEncoderResult = cbor_encoder_create_map(&acesArray, &oicSecAclMap, aclMapSize);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Creating ACES Map");
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Validities Array.");
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ // Eownerid -- Not Mandatory
+ if(ace->eownerID)
+ {
+ char *eowner = NULL;
+ cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, OIC_JSON_EOWNERID_NAME,
+ strlen(OIC_JSON_EOWNERID_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding eownerId Name Tag.");
+ ret = ConvertUuidToStr(ace->eownerID, &eowner);
+ VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
+ cborEncoderResult = cbor_encode_text_string(&oicSecAclMap, eowner, strlen(eowner));
+ OICFree(eowner);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding eownerId Value.");
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
+
cborEncoderResult = cbor_encoder_close_container(&acesArray, &oicSecAclMap);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing ACES Map.");
}
return NULL;
}
OCStackResult ret = OC_STACK_ERROR;
+ CborValue aclMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
CborValue aclCbor = { .parser = NULL };
CborParser parser = { .end = NULL };
CborError cborFindResult = CborNoError;
+
cbor_parser_init(cborPayload, size, 0, &parser, &aclCbor);
OicSecAcl_t *acl = (OicSecAcl_t *) OICCalloc(1, sizeof(OicSecAcl_t));
+ VERIFY_NON_NULL(TAG, acl, ERROR);
// Enter ACL Map
- CborValue aclMap = { .parser = NULL, .ptr = NULL, .remaining = 0, .extra = 0, .type = 0, .flags = 0 };
cborFindResult = cbor_value_enter_container(&aclCbor, &aclMap);
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACL Map.");
cborFindResult = cbor_value_enter_container(&aclMap, &aclistMap);
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering ACLIST Map.");
-
while (cbor_value_is_valid(&aclistMap))
{
char* acName = NULL;
VERIFY_NON_NULL(TAG, ace, ERROR);
LL_APPEND(acl->aces, ace);
- VERIFY_NON_NULL(TAG, acl, ERROR);
-
while (cbor_value_is_valid(&aceMap))
{
char* name = NULL;
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing a validities Array.");
}
}
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ // eowner uuid -- Not Mandatory
+ if (strcmp(name, OIC_JSON_EOWNERID_NAME) == 0)
+ {
+ char *eowner = NULL;
+ cborFindResult = cbor_value_dup_text_string(&aceMap, &eowner, &len, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding eownerId Value.");
+ if(NULL == ace->eownerID)
+ {
+ ace->eownerID = (OicUuid_t*)OICCalloc(1, sizeof(OicUuid_t));
+ VERIFY_NON_NULL(TAG, ace->eownerID, ERROR);
+ }
+ ret = ConvertStrToUuid(eowner, ace->eownerID);
+ OICFree(eowner);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
OICFree(name);
}
return acl;
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+bool IsValidAclAccessForSubOwner(const OicUuid_t* uuid, const uint8_t *cborPayload, const size_t size)
+{
+ bool retValue = false;
+ OicSecAcl_t* acl = NULL;
+
+ VERIFY_NON_NULL(TAG, uuid, ERROR);
+ VERIFY_NON_NULL(TAG, cborPayload, ERROR);
+ VERIFY_SUCCESS(TAG, 0 != size, ERROR);
+
+ acl = CBORPayloadToAcl(cborPayload, size);
+ VERIFY_NON_NULL(TAG, acl, ERROR);
+
+ OicSecAce_t* ace = NULL;
+ OicSecAce_t* tempAce = NULL;
+ LL_FOREACH_SAFE(acl->aces, ace, tempAce)
+ {
+ OicSecRsrc_t* rsrc = NULL;
+ OicSecRsrc_t* tempRsrc = NULL;
+
+ VERIFY_NON_NULL(TAG, ace->eownerID, ERROR);
+ VERIFY_SUCCESS(TAG, memcmp(ace->eownerID->id, uuid->id, sizeof(uuid->id)) == 0, ERROR);
+
+ LL_FOREACH_SAFE(ace->resources, rsrc, tempRsrc)
+ {
+ VERIFY_SUCCESS(TAG, strcmp(rsrc->href, OIC_RSRC_TYPE_SEC_DOXM) != 0, ERROR);
+ VERIFY_SUCCESS(TAG, strcmp(rsrc->href, OIC_RSRC_TYPE_SEC_CRED) != 0, ERROR);
+ VERIFY_SUCCESS(TAG, strcmp(rsrc->href, OIC_RSRC_TYPE_SEC_ACL) != 0, ERROR);
+ VERIFY_SUCCESS(TAG, strcmp(rsrc->href, OIC_RSRC_TYPE_SEC_PSTAT) != 0, ERROR);
+ VERIFY_SUCCESS(TAG, strcmp(rsrc->href, OIC_RSRC_TYPE_SEC_CRL) != 0, ERROR);
+ }
+ }
+
+ retValue = true;
+
+exit:
+ DeleteACLList(acl);
+
+ return retValue;
+}
+#endif //_ENABLE_MULTIPLE_OWNER_
+
/**
* This method removes ACE for the subject and resource from the ACL
*
//Clean Period
OICFree(cred->period);
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ //Clean eowner
+ OICFree(cred->eownerID);
+#endif
+
//Clean Cred node itself
OICFree(cred);
}
{
mapSize++;
}
+
#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ if(cred->eownerID)
+ {
+ mapSize++;
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
+
if (SIGNED_ASYMMETRIC_KEY == cred->credType && cred->publicData.data)
{
mapSize++;
}
else
{
- OIC_LOG(ERROR, TAG, "Unknow encoding type for optional data.");
+ OIC_LOG(ERROR, TAG, "Unknown encoding type for optional data.");
VERIFY_CBOR_SUCCESS(TAG, CborErrorUnknownType, "Failed Adding optional Encoding Value.");
}
}
else
{
- OIC_LOG(ERROR, TAG, "Unknow encoding type for private data.");
+ OIC_LOG(ERROR, TAG, "Unknown encoding type for private data.");
VERIFY_CBOR_SUCCESS(TAG, CborErrorUnknownType, "Failed Adding Private Encoding Value.");
}
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding Period Name Value.");
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ // Eownerid -- Not Mandatory
+ if(cred->eownerID)
+ {
+ char *eowner = NULL;
+ cborEncoderResult = cbor_encode_text_string(&credMap, OIC_JSON_EOWNERID_NAME,
+ strlen(OIC_JSON_EOWNERID_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding eownerId Name Tag.");
+ ret = ConvertUuidToStr(cred->eownerID, &eowner);
+ VERIFY_SUCCESS(TAG, ret == OC_STACK_OK, ERROR);
+ cborEncoderResult = cbor_encode_text_string(&credMap, eowner, strlen(eowner));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Addding eownerId Value.");
+ OICFree(eowner);
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
cborEncoderResult = cbor_encoder_close_container(&credArray, &credMap);
VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing Cred Map.");
else
{
cborFindResult = CborErrorUnknownType;
- OIC_LOG(ERROR, TAG, "Unknow type for private data.");
+ OIC_LOG(ERROR, TAG, "Unknown type for private data.");
}
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding PrivateData.");
}
{
//For unit test
cred->privateData.encoding = OIC_ENCODING_RAW;
- OIC_LOG(WARNING, TAG, "Unknow encoding type dectected for private data.");
+ OIC_LOG(WARNING, TAG, "Unknown encoding type dectected for private data.");
}
OICFree(strEncoding);
else
{
cborFindResult = CborErrorUnknownType;
- OIC_LOG(ERROR, TAG, "Unknow type for optional data.");
+ OIC_LOG(ERROR, TAG, "Unknown type for optional data.");
}
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding OptionalData.");
}
{
//For unit test
cred->optionalData.encoding = OIC_ENCODING_RAW;
- OIC_LOG(WARNING, TAG, "Unknow encoding type dectected for optional data.");
+ OIC_LOG(WARNING, TAG, "Unknown encoding type dectected for optional data.");
}
OICFree(strEncoding);
}
VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding Period.");
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ // Eowner uuid -- Not Mandatory
+ if (strcmp(OIC_JSON_EOWNERID_NAME, name) == 0 && cbor_value_is_text_string(&credMap))
+ {
+ char *eowner = NULL;
+ cborFindResult = cbor_value_dup_text_string(&credMap, &eowner, &len, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding eownerId Value.");
+ if(NULL == cred->eownerID)
+ {
+ cred->eownerID = (OicUuid_t*)OICCalloc(1, sizeof(OicUuid_t));
+ VERIFY_NON_NULL(TAG, cred->eownerID, ERROR);
+ }
+ ret = ConvertStrToUuid(eowner, cred->eownerID);
+ OICFree(eowner);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
+
if (cbor_value_is_valid(&credMap))
{
cborFindResult = cbor_value_advance(&credMap);
return ret;
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+bool IsValidCredentialAccessForSubOwner(const OicUuid_t* uuid, const uint8_t *cborPayload, size_t size)
+{
+ OicSecCred_t* cred = NULL;
+ bool isValidCred = false;
+
+ OIC_LOG_BUFFER(DEBUG, TAG, cborPayload, size);
+
+ VERIFY_NON_NULL(TAG, uuid, ERROR);
+ VERIFY_NON_NULL(TAG, cborPayload, ERROR);
+ VERIFY_SUCCESS(TAG, 0 != size, ERROR);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == CBORPayloadToCred(cborPayload, size, &cred), ERROR);
+ VERIFY_NON_NULL(TAG, cred, ERROR);
+ VERIFY_NON_NULL(TAG, cred->eownerID, ERROR);
+ VERIFY_SUCCESS(TAG, (memcmp(cred->eownerID->id, uuid->id, sizeof(uuid->id)) == 0), ERROR);
+
+ isValidCred = true;
+
+exit:
+ DeleteCredList(cred);
+
+ return isValidCred;
+
+}
+#endif //_ENABLE_MULTIPLE_OWNER_
+
OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t credType,
const OicSecCert_t * publicData, const OicSecKey_t* privateData,
- const OicUuid_t * rownerID)
+ const OicUuid_t * rownerID, const OicUuid_t * eownerID)
{
(void)publicData;
OCStackResult ret = OC_STACK_ERROR;
VERIFY_NON_NULL(TAG, rownerID, ERROR);
memcpy(&cred->rownerID, rownerID, sizeof(OicUuid_t));
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ if(eownerID)
+ {
+ cred->eownerID = (OicUuid_t*)OICCalloc(1, sizeof(OicUuid_t));
+ VERIFY_NON_NULL(TAG, cred->eownerID, ERROR);
+ memcpy(cred->eownerID->id, eownerID->id, sizeof(eownerID->id));
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
+
ret = OC_STACK_OK;
exit:
if (OC_STACK_OK != ret)
if (cred)
{
uint8_t *payload = NULL;
- // This added '256' is arbitrary value that is added to cover the name of the resource, map addition and ending
+ // This added '512' is arbitrary value that is added to cover the name of the resource, map addition and ending
size_t size = GetCredKeyDataSize(cred);
- size += (256 * OicSecCredCount(cred));
+ size += (512 * OicSecCredCount(cred));
+
int secureFlag = 0;
OCStackResult res = CredToCBORPayload(cred, &payload, &size, secureFlag);
if ((OC_STACK_OK == res) && payload)
}
else
{
- // TODO: error
VERIFY_SUCCESS(TAG, OIC_ENCODING_UNKNOW, ERROR);
}
return false;
}
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * Internal function to fill private data of SubOwner PSK.
+ *
+ * @param receviedCred recevied owner credential from SubOwner
+ * @param ownerAdd address of SubOwner
+ * @param doxm current device's doxm resource
+ *
+ * @return
+ * true successfully done and valid subower psk information
+ * false Invalid subowner psk information or failed to subowner psk generation
+ */
+static bool FillPrivateDataOfSubOwnerPSK(OicSecCred_t* receivedCred, const CAEndpoint_t* ownerAddr,
+ const OicSecDoxm_t* doxm, const OicUuid_t* subOwner)
+{
+ char* b64Buf = NULL;
+ //Derive OwnerPSK locally
+ const char* oxmLabel = GetOxmString(doxm->oxmSel);
+ VERIFY_NON_NULL(TAG, oxmLabel, ERROR);
+
+ uint8_t subOwnerPSK[OWNER_PSK_LENGTH_128] = {0};
+ CAResult_t pskRet = CAGenerateOwnerPSK(ownerAddr,
+ (uint8_t*)oxmLabel, strlen(oxmLabel),
+ subOwner->id, sizeof(subOwner->id),
+ doxm->deviceID.id, sizeof(doxm->deviceID.id),
+ subOwnerPSK, OWNER_PSK_LENGTH_128);
+ VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
+
+ OIC_LOG(DEBUG, TAG, "SubOwnerPSK dump :");
+ OIC_LOG_BUFFER(DEBUG, TAG, subOwnerPSK, OWNER_PSK_LENGTH_128);
+
+ //Generate owner credential based on received credential information
+
+ if(OIC_ENCODING_RAW == receivedCred->privateData.encoding)
+ {
+ receivedCred->privateData.data = (uint8_t *)OICCalloc(1, OWNER_PSK_LENGTH_128);
+ VERIFY_NON_NULL(TAG, receivedCred->privateData.data, ERROR);
+ receivedCred->privateData.len = OWNER_PSK_LENGTH_128;
+ memcpy(receivedCred->privateData.data, subOwnerPSK, OWNER_PSK_LENGTH_128);
+ }
+ else if(OIC_ENCODING_BASE64 == receivedCred->privateData.encoding)
+ {
+ uint32_t b64OutSize = 0;
+ size_t b64BufSize = B64ENCODE_OUT_SAFESIZE((OWNER_PSK_LENGTH_128 + 1));
+ b64Buf = OICCalloc(1, b64BufSize);
+ VERIFY_NON_NULL(TAG, b64Buf, ERROR);
+
+ VERIFY_SUCCESS(TAG, \
+ B64_OK == b64Encode(subOwnerPSK, OWNER_PSK_LENGTH_128, b64Buf, b64BufSize, &b64OutSize), \
+ ERROR);
+
+ receivedCred->privateData.data = (uint8_t *)OICCalloc(1, b64OutSize + 1);
+ VERIFY_NON_NULL(TAG, receivedCred->privateData.data, ERROR);
+ receivedCred->privateData.len = b64OutSize;
+ strncpy((char*)receivedCred->privateData.data, b64Buf, b64OutSize);
+ receivedCred->privateData.data[b64OutSize] = '\0';
+ }
+ else
+ {
+ OIC_LOG(INFO, TAG, "Unknown credential encoding type.");
+ VERIFY_SUCCESS(TAG, OIC_ENCODING_UNKNOW, ERROR);
+ }
+
+ OIC_LOG(INFO, TAG, "PrivateData of SubOwnerPSK was calculated successfully");
+ OICFree(b64Buf);
+ return true;
+exit:
+ //receivedCred->privateData.data will be deallocated when deleting credential.
+ OICFree(b64Buf);
+ return false;
+}
+#endif //_ENABLE_MULTIPLE_OWNER_
#endif // __WITH_DTLS__ or __WITH_TLS__
static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
if(OIC_RANDOM_DEVICE_PIN == doxm->oxmSel)
{
OicUuid_t emptyUuid = { .id={0}};
- SetUuidForRandomPinOxm(&emptyUuid);
+ SetUuidForPinBasedOxm(&emptyUuid);
#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
}
default:
{
- OIC_LOG(WARNING, TAG, "Unknow credential type for owner credential.");
+ OIC_LOG(WARNING, TAG, "Unknown credential type for owner credential.");
ret = OC_EH_ERROR;
break;
}
}
}
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ // In case SubOwner Credential
+ else if(doxm && doxm->owned && doxm->mom &&
+ OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode &&
+ 0 == cred->privateData.len)
+ {
+ switch(cred->credType)
+ {
+ case SYMMETRIC_PAIR_WISE_KEY:
+ {
+ OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
+ if(FillPrivateDataOfSubOwnerPSK(cred, (CAEndpoint_t *)&request->devAddr, doxm, &cred->subject))
+ {
+ if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&cred->subject))
+ {
+ OIC_LOG(WARNING, TAG, "The credential with the same subject ID was detected!");
+ }
+
+ OIC_LOG(ERROR, TAG, "SubOwnerPSK was generated successfully.");
+ if(OC_STACK_OK == AddCredential(cred))
+ {
+ ret = OC_EH_CHANGED;
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Failed to save the SubOwnerPSK as cred resource");
+ ret = OC_EH_ERROR;
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Failed to verify receviced SubOwner PSK.");
+ ret = OC_EH_ERROR;
+ }
+ }
+ break;
+
+ case SYMMETRIC_GROUP_KEY:
+ case ASYMMETRIC_KEY:
+ case SIGNED_ASYMMETRIC_KEY:
+ case PIN_PASSWORD:
+ case ASYMMETRIC_ENCRYPTION_KEY:
+ {
+ OIC_LOG(WARNING, TAG, "Unsupported credential type for SubOwner credential.");
+ ret = OC_EH_ERROR;
+ break;
+ }
+ default:
+ {
+ OIC_LOG(WARNING, TAG, "Unknown credential type for SubOwner credential.");
+ ret = OC_EH_ERROR;
+ break;
+ }
+ }
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
else
{
/*
OicSecCred_t* GetCredResourceDataByCredId(const uint16_t credId)
{
OicSecCred_t *cred = NULL;
-
- if ( 1 > credId)
+ if ( 1 > credId)
{
return NULL;
}
uint32_t outKeySize;
if(NULL == outKey)
{
- OIC_LOG (ERROR, TAG, "Failed to memoray allocation.");
+ OIC_LOG (ERROR, TAG, "Failed to allocate memory.");
return ret;
}
return ret;
}
}
+ OIC_LOG(DEBUG, TAG, "Can not find subject matched credential.");
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ const OicSecDoxm_t* doxm = GetDoxmResourceData();
+ if(doxm && doxm->mom && OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode)
+ {
+ // in case of multiple owner transfer authentication
+ if(OIC_PRECONFIG_PIN == doxm->oxmSel)
+ {
+ OicSecCred_t* wildCardCred = GetCredResourceData(&WILDCARD_SUBJECT_ID);
+ if(wildCardCred)
+ {
+ OIC_LOG(DEBUG, TAG, "Detected wildcard credential.");
+ if(PIN_PASSWORD == wildCardCred->credType)
+ {
+ //Read PIN/PW
+ char* pinBuffer = NULL;
+ uint32_t pinLength = 0;
+ if(OIC_ENCODING_RAW == wildCardCred->privateData.encoding)
+ {
+ pinBuffer = OICCalloc(1, wildCardCred->privateData.len + 1);
+ if(NULL == pinBuffer)
+ {
+ OIC_LOG (ERROR, TAG, "Failed to allocate memory.");
+ return ret;
+ }
+ pinLength = wildCardCred->privateData.len;
+ memcpy(pinBuffer, wildCardCred->privateData.data, pinLength);
+ }
+ else if(OIC_ENCODING_BASE64 == wildCardCred->privateData.encoding)
+ {
+ size_t pinBufSize = B64DECODE_OUT_SAFESIZE((wildCardCred->privateData.len + 1));
+ pinBuffer = OICCalloc(1, pinBufSize);
+ if(NULL == pinBuffer)
+ {
+ OIC_LOG (ERROR, TAG, "Failed to allocate memory.");
+ return ret;
+ }
+
+ if(B64_OK != b64Decode((char*)wildCardCred->privateData.data, wildCardCred->privateData.len, pinBuffer, pinBufSize, &pinLength))
+ {
+ OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
+ return ret;
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
+ return ret;
+ }
+
+ //Set the PIN/PW to derive PSK
+ if(OC_STACK_OK != SetPreconfigPin(pinBuffer, pinLength))
+ {
+ OICFree(pinBuffer);
+ OIC_LOG(ERROR, TAG, "Failed to load PIN data.");
+ return ret;
+ }
+ OICFree(pinBuffer);
+
+ OicUuid_t myUuid;
+ if(OC_STACK_OK != GetDoxmDeviceID(&myUuid))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to read device ID");
+ return ret;
+ }
+ SetUuidForPinBasedOxm(&myUuid);
+
+ //Calculate PSK using PIN/PW
+ if(0 == DerivePSKUsingPIN((uint8_t*)result))
+ {
+ ret = OWNER_PSK_LENGTH_128;
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN");
+ }
+
+ if(CA_STATUS_OK != CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB))
+ {
+ OIC_LOG(WARNING, TAG, "Error while bind the DTLS Handshake Callback.");
+ }
+ }
+ }
+ }
+ else if(OIC_RANDOM_DEVICE_PIN == doxm->oxmSel)
+ {
+ if(0 == DerivePSKUsingPIN((uint8_t*)result))
+ {
+ ret = OWNER_PSK_LENGTH_128;
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
+ ret = -1;
+ }
+ }
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
}
break;
}
VERIFY_SUCCESS(TAG, (0 == dtlsRes) , ERROR);
cred = GenerateCredential(tmpSubject, credType, NULL,
- &privKey, rownerID);
+ &privKey, rownerID, NULL);
if(NULL == cred)
{
OIC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
{
switch (temp->credType)
{
+ case PIN_PASSWORD:
+ {
+ list[0] = true;
+ OIC_LOG(DEBUG, TAG, "PIN_PASSWORD found");
+ break;
+ }
case SYMMETRIC_PAIR_WISE_KEY:
{
list[0] = true;
}
case SYMMETRIC_GROUP_KEY:
case ASYMMETRIC_KEY:
- case PIN_PASSWORD:
case ASYMMETRIC_ENCRYPTION_KEY:
{
OIC_LOG(WARNING, TAG, "Unsupported credential type for TLS.");
}
default:
{
- OIC_LOG(WARNING, TAG, "Unknow credential type for TLS.");
+ OIC_LOG(WARNING, TAG, "Unknown credential type for TLS.");
break;
}
}
#include "pinoxmcommon.h"
#define TAG "SRM-DOXM"
+#define CHAR_ZERO ('0')
/** Default cbor payload size. This value is increased in case of CborErrorOutOfMemory.
* The value of payload size is increased until reaching belox max cbor size. */
{.id = {0}}, /* OicUuid_t deviceID */
false, /* bool dpc */
{.id = {0}}, /* OicUuid_t owner */
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ NULL, /* OicSecSubOwner_t sub-owner list */
+ NULL, /* OicSecMomType_t multiple owner mode */
+#endif //_ENABLE_MULTIPLE_OWNER_
{.id = {0}}, /* OicUuid_t rownerID */
};
//clean oxm
OICFree(doxm->oxm);
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ //clean mom
+ OICFree(doxm->mom);
+
+ //clean sub-owner list
+ if(NULL != doxm->subOwners)
+ {
+ OicSecSubOwner_t* subowner = NULL;
+ OicSecSubOwner_t* temp = NULL;
+ LL_FOREACH_SAFE(doxm->subOwners, subowner, temp)
+ {
+ LL_DELETE(doxm->subOwners, subowner);
+ OICFree(subowner);
+ }
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
+
//Clean doxm itself
OICFree(doxm);
}
strUuid = NULL;
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ //Device SubOwnerID -- Not Mandatory
+ if(doxm->subOwners)
+ {
+ size_t subOwnerLen = 0;
+ OicSecSubOwner_t* subOwner = NULL;
+ LL_FOREACH(doxm->subOwners, subOwner)
+ {
+ subOwnerLen++;
+ }
+
+ CborEncoder subOwners;
+ cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_SUBOWNERID_NAME,
+ strlen(OIC_JSON_SUBOWNERID_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Tag.");
+ cborEncoderResult = cbor_encoder_create_array(&doxmMap, &subOwners, subOwnerLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwner Array.");
+
+ subOwner = NULL;
+ LL_FOREACH(doxm->subOwners, subOwner)
+ {
+ char* strUuid = NULL;
+ ret = ConvertUuidToStr(&subOwner->uuid, &strUuid);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == ret , ERROR);
+ cborEncoderResult = cbor_encode_text_string(&subOwners, strUuid, strlen(strUuid));
+ OICFree(strUuid);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding SubOwnerId Value");
+ }
+ cborEncoderResult = cbor_encoder_close_container(&doxmMap, &subOwners);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Closing SubOwnerId.");
+ }
+
+ //Multiple Owner Mode -- Not Mandatory
+ if(doxm->mom)
+ {
+ cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_MOM_NAME,
+ strlen(OIC_JSON_MOM_NAME));
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Tag");
+ cborEncoderResult = cbor_encode_int(&doxmMap, (int64_t)doxm->mom->mode);
+ VERIFY_CBOR_SUCCESS(TAG, cborEncoderResult, "Failed Adding mom Value.");
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
+
//devownerid -- Mandatory
cborEncoderResult = cbor_encode_text_string(&doxmMap, OIC_JSON_DEVOWNERID_NAME,
strlen(OIC_JSON_DEVOWNERID_NAME));
CborValue oxmType;
cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmTypeLen);
- VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmTypeLen.")
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmTypeLen.");
VERIFY_SUCCESS(TAG, doxm->oxmTypeLen != 0, ERROR);
doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(*doxm->oxmType));
{
cborFindResult = cbor_value_dup_text_string(&oxmType, &doxm->oxmType[i++],
&len, NULL);
- VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding omxType text string.")
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding omxType text string.");
cborFindResult = cbor_value_advance(&oxmType);
- VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmType.")
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing oxmType.");
}
}
{
CborValue oxm;
cborFindResult = cbor_value_get_array_length(&doxmMap, &doxm->oxmLen);
- VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName array Length.")
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding oxmName array Length.");
VERIFY_SUCCESS(TAG, doxm->oxmLen != 0, ERROR);
doxm->oxm = (OicSecOxm_t *)OICCalloc(doxm->oxmLen, sizeof(*doxm->oxm));
memcpy(doxm->owner.id, gDoxm->owner.id, sizeof(doxm->owner.id));
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_MOM_NAME, &doxmMap);
+ if(CborNoError == cborFindResult && cbor_value_is_integer(&doxmMap))
+ {
+ int mode = 0;
+ cborFindResult = cbor_value_get_int(&doxmMap, &mode);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding mom Name Value.")
+ if(NULL == doxm->mom)
+ {
+ doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
+ VERIFY_NON_NULL(TAG, doxm->mom, ERROR);
+ }
+ doxm->mom->mode = (OicSecMomType_t)mode;
+ }
+ else if(NULL != gDoxm && NULL != gDoxm->mom)
+ {
+ // PUT/POST JSON may not have 'mom' so set it to the gDomx->mom
+ if(NULL == doxm->mom)
+ {
+ doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
+ VERIFY_NON_NULL(TAG, doxm->mom, ERROR);
+ }
+ doxm->mom->mode = gDoxm->mom->mode;
+ }
+
+ cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_SUBOWNERID_NAME, &doxmMap);
+ if(CborNoError == cborFindResult && cbor_value_is_array(&doxmMap))
+ {
+ size_t subOwnerLen = 0;
+ CborValue subOwnerCbor;
+ cborFindResult = cbor_value_get_array_length(&doxmMap, &subOwnerLen);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwner array Length.");
+ VERIFY_SUCCESS(TAG, 0 != subOwnerLen, ERROR);
+
+ cborFindResult = cbor_value_enter_container(&doxmMap, &subOwnerCbor);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Entering SubOwner Array.")
+
+ while (cbor_value_is_valid(&subOwnerCbor) && cbor_value_is_text_string(&subOwnerCbor))
+ {
+ OCStackResult convertRes = OC_STACK_ERROR;
+ OicSecSubOwner_t* subOwner = NULL;
+ char* strUuid = NULL;
+ size_t uuidLen = 0;
+
+ cborFindResult = cbor_value_dup_text_string(&subOwnerCbor, &strUuid, &uuidLen, NULL);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Finding SubOwnerId Value");
+
+ subOwner = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
+ VERIFY_NON_NULL(TAG, subOwner, ERROR);
+
+ convertRes = ConvertStrToUuid(strUuid, &subOwner->uuid);
+ VERIFY_SUCCESS(TAG, OC_STACK_OK == convertRes, ERROR);
+ subOwner->status = MOT_STATUS_DONE;
+ LL_APPEND(doxm->subOwners, subOwner);
+
+ cborFindResult = cbor_value_advance(&subOwnerCbor);
+ VERIFY_CBOR_SUCCESS(TAG, cborFindResult, "Failed Advancing SubOwnerId.")
+ }
+ }
+ else if(NULL != gDoxm && NULL != gDoxm->subOwners)
+ {
+ // PUT/POST JSON may not have 'subOwners' so set it to the gDomx->subOwners
+ OicSecSubOwner_t* subOwnerItor = NULL;
+ LL_FOREACH(gDoxm->subOwners, subOwnerItor)
+ {
+ OicSecSubOwner_t* subOwnerId = (OicSecSubOwner_t*)OICCalloc(1, sizeof(OicSecSubOwner_t));
+ VERIFY_NON_NULL(TAG, subOwnerId, ERROR);
+
+ memcpy(&subOwnerId->uuid, &subOwnerItor->uuid, sizeof(OicUuid_t));
+ subOwnerId->status = MOT_STATUS_DONE;
+
+ LL_APPEND(doxm->subOwners, subOwnerId);
+ }
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
+
cborFindResult = cbor_value_map_find_value(&doxmCbor, OIC_JSON_ROWNERID_NAME, &doxmMap);
if (CborNoError == cborFindResult && cbor_value_is_text_string(&doxmMap))
{
bool bDeviceIDMatch = false; // does 'deviceid' query matches with doxm.deviceid ?
bool bInterfaceQry = false; // does querystring contains 'if' query ?
bool bInterfaceMatch = false; // does 'if' query matches with oic.if.baseline ?
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ bool bMotQry = false; // does querystring contains 'mom' and 'owned' query ?
+ bool bMotMatch = false; // does 'mom' query value is not '0' && does query value matches with doxm.owned status?
+#endif //_ENABLE_MULTIPLE_OWNER_
OicParseQueryIter_t parseIter = {.attrPos = NULL};
}
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_MOM_NAME, strlen(OIC_JSON_MOM_NAME)) == 0)
+ {
+ bMotQry = true;
+ OicSecMomType_t momMode = (OicSecMomType_t)(parseIter.valPos[0] - CHAR_ZERO);
+ if(NULL != gDoxm->mom && momMode != gDoxm->mom->mode)
+ {
+ if(GetNextQuery(&parseIter))
+ {
+ if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_OWNED_NAME, parseIter.attrLen) == 0)
+ {
+ if ((strncasecmp((char *)parseIter.valPos, OIC_SEC_TRUE, parseIter.valLen) == 0) &&
+ (gDoxm->owned))
+ {
+ bMotMatch = true;
+ }
+ }
+ }
+ }
+ return bMotMatch;
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
+
if (strncasecmp((char *)parseIter.attrPos, OIC_JSON_DEVICE_ID_NAME, parseIter.attrLen) == 0)
{
bDeviceIDQry = true;
}
}
- return ((bOwnedQry ? bOwnedMatch : true) && (bDeviceIDQry ? bDeviceIDMatch : true));
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ return ((bOwnedQry ? bOwnedMatch : true) &&
+ (bDeviceIDQry ? bDeviceIDMatch : true) &&
+ (bMotQry ? bMotMatch : true));
+#else
+ return ((bOwnedQry ? bOwnedMatch : true) &&
+ (bDeviceIDQry ? bDeviceIDMatch : true));
+#endif //_ENABLE_MULTIPLE_OWNER_
}
static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehRequest)
return ehRet;
}
+static void updateWriteableProperty(const OicSecDoxm_t* src, OicSecDoxm_t* dst)
+{
+ if(src && dst)
+ {
+ // update oxmsel
+ dst->oxmSel = src->oxmSel;
+
+ //update owner
+ memcpy(&(dst->owner), &(src->owner), sizeof(OicUuid_t));
+
+ //update rowner
+ memcpy(&(dst->rownerID), &(src->rownerID), sizeof(OicUuid_t));
+
+ //Update owned status
+ if(dst->owned != src->owned)
+ {
+ dst->owned = src->owned;
+ }
+
+ //update oxms
+ if(0 < src->oxmLen)
+ {
+ OicSecOxm_t* tempOxm = (OicSecOxm_t*)OICMalloc(sizeof(OicSecOxm_t) * src->oxmLen);
+ if(NULL != tempOxm)
+ {
+ for(size_t i = 0; i < src->oxmLen; i++)
+ {
+ tempOxm[i] = src->oxm[i];
+ }
+ OICFree(dst->oxm);
+
+ dst->oxm = tempOxm;
+ dst->oxmLen = src->oxmLen;
+ }
+ }
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ if(src->mom)
+ {
+ OIC_LOG(DEBUG, TAG, "dectected 'mom' property");
+ if(NULL == dst->mom)
+ {
+ dst->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
+ if(NULL != dst->mom)
+ {
+ dst->mom->mode = src->mom->mode;
+ }
+ }
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
+ }
+}
+
+#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * Callback function to handle MOT DTLS handshake result.
+ * @param[out] object remote device information.
+ * @param[out] errorInfo CA Error information.
+ */
+void MultipleOwnerDTLSHandshakeCB(const CAEndpoint_t *object,
+ const CAErrorInfo_t *errorInfo)
+{
+ OIC_LOG(DEBUG, TAG, "IN MultipleOwnerDTLSHandshakeCB");
+
+ if(CA_STATUS_OK == errorInfo->result)
+ {
+ const CASecureEndpoint_t* authenticatedSubOwnerInfo = CAGetSecureEndpointData(object);
+ if(authenticatedSubOwnerInfo)
+ {
+ OicSecSubOwner_t* subOwnerInst = (OicSecSubOwner_t*)OICMalloc(sizeof(OicSecSubOwner_t));
+ if(subOwnerInst)
+ {
+ OIC_LOG(DEBUG, TAG, "Adding New SubOwner");
+ memcpy(subOwnerInst->uuid.id, authenticatedSubOwnerInfo->identity.id, authenticatedSubOwnerInfo->identity.id_length);
+ LL_APPEND(gDoxm->subOwners, subOwnerInst);
+ if(!UpdatePersistentStorage(gDoxm))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to register SubOwner UUID into Doxm");
+ }
+ }
+ }
+ }
+
+ if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskCredentials))
+ {
+ OIC_LOG(WARNING, TAG, "Failed to revert the DTLS credential handler");
+ }
+
+ OIC_LOG(DEBUG, TAG, "OUT MultipleOwnerDTLSHandshakeCB");
+}
+#endif //_ENABLE_MULTIPLE_OWNER_
+#endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+
static OCEntityHandlerResult HandleDoxmPostRequest(const OCEntityHandlerRequest * ehRequest)
{
OIC_LOG (DEBUG, TAG, "Doxm EntityHandle processing POST request");
// in owned state
if (true == gDoxm->owned)
{
- // update writable properties
- gDoxm->oxmSel = newDoxm->oxmSel;
- memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
- memcpy(&(gDoxm->rownerID), &(newDoxm->rownerID), sizeof(OicUuid_t));
+ //Update gDoxm based on newDoxm
+ updateWriteableProperty(newDoxm, gDoxm);
+
+#if defined(__WITH_DTLS__) || defined (__WITH_TLS__)
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ //handle mom
+ if(gDoxm->mom)
+ {
+ if(OIC_MULTIPLE_OWNER_DISABLE != gDoxm->mom->mode)
+ {
+ CAResult_t caRes = CA_STATUS_FAILED;
+ if(OIC_PRECONFIG_PIN == gDoxm->oxmSel || OIC_RANDOM_DEVICE_PIN == gDoxm->oxmSel)
+ {
+ caRes = CAEnableAnonECDHCipherSuite(false);
+ VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+ OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
+
+ caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, ehRequest->devAddr.adapter);
+ VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+ OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
+
+ //Set the device id to derive temporal PSK
+ SetUuidForPinBasedOxm(&gDoxm->deviceID);
+ }
+ else
+ {
+ OIC_LOG(WARNING, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
+ }
+
+ CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
+ }
+ else
+ {
+ //if MOM is disabled, revert the DTLS handshake callback
+ if(CA_STATUS_OK != CAregisterSslHandshakeCallback(NULL))
+ {
+ OIC_LOG(WARNING, TAG, "Error while revert the DTLS Handshake Callback.");
+ }
+ }
+ }
- if(gDoxm->owned != newDoxm->owned)
+ if(newDoxm->subOwners)
{
- gDoxm->owned = newDoxm->owned;
+ OicSecSubOwner_t* subowner = NULL;
+ OicSecSubOwner_t* temp = NULL;
+
+ OIC_LOG(DEBUG, TAG, "dectected 'subowners' property");
+
+ if(gDoxm->subOwners)
+ {
+ LL_FOREACH_SAFE(gDoxm->subOwners, subowner, temp)
+ {
+ LL_DELETE(gDoxm->subOwners, subowner);
+ OICFree(subowner);
+ }
+ }
+
+ subowner = NULL;
+ temp = NULL;
+ LL_FOREACH_SAFE(newDoxm->subOwners, subowner, temp)
+ {
+ LL_DELETE(newDoxm->subOwners, subowner);
+ LL_APPEND(gDoxm->subOwners, subowner);
+ }
}
+#endif //_ENABLE_MULTIPLE_OWNER_
+#endif // defined(__WITH_DTLS__) || defined (__WITH_TLS__)
//Update new state in persistent storage
if (UpdatePersistentStorage(gDoxm) == true)
if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
{
//Set the device id to derive temporal PSK
- SetUuidForRandomPinOxm(&gDoxm->deviceID);
+ SetUuidForPinBasedOxm(&gDoxm->deviceID);
/**
* Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
ehRet = OC_EH_ERROR;
}
}
- else
+ else if(previousMsgId != ehRequest->messageID)
{
if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
{
//Set the device id to derive temporal PSK
- SetUuidForRandomPinOxm(&gDoxm->deviceID);
+ SetUuidForPinBasedOxm(&gDoxm->deviceID);
/**
* Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
* Credential should not be saved into SVR.
* For this reason, use a temporary get_psk_info callback to random PIN OxM.
*/
-#ifdef __WITH_TLS__
caRes = CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm);
-#endif
VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
ehRet = OC_EH_OK;
}
}
#endif // __WITH_DTLS__ or __WITH_TLS__
}
+#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
else
{
-#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
//Save the owner's UUID to derive owner credential
memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
OIC_LOG(ERROR, TAG, "Failed to update DOXM in persistent storage");
ehRet = OC_EH_ERROR;
}
-#endif // __WITH_DTLS__ or __WITH_TLS__
}
+#endif // __WITH_DTLS__ or __WITH_TLS__
}
}
return gDoxm;
}
+#if defined(__WITH_DTLS__) && defined(_ENABLE_MULTIPLE_OWNER_)
+/**
+ * Internal API to prepare MOT
+ */
+static void PrepareMOT(const OicSecDoxm_t* doxm)
+{
+ OIC_LOG(INFO, TAG, "IN PrepareMOT");
+ VERIFY_NON_NULL(TAG, doxm, ERROR);
+
+ if(true == doxm->owned && NULL != doxm->mom && OIC_MULTIPLE_OWNER_DISABLE != doxm->mom->mode)
+ {
+ CAResult_t caRes = CA_STATUS_FAILED;
+
+ OIC_LOG(INFO, TAG, "Multiple Ownership Transfer Enabled!");
+
+ if(OIC_PRECONFIG_PIN == doxm->oxmSel)
+ {
+ caRes = CAEnableAnonECDHCipherSuite(false);
+ VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+ OIC_LOG(INFO, TAG, "ECDH_ANON CipherSuite is DISABLED");
+
+ caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, CA_ADAPTER_IP);
+ VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+#ifdef __WITH_TLS__
+ caRes = CASelectCipherSuite((uint16_t)TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256, CA_ADAPTER_TCP);
+ VERIFY_SUCCESS(TAG, caRes == CA_STATUS_OK, ERROR);
+#endif
+ OIC_LOG(INFO, TAG, "ECDHE_PSK CipherSuite will be used for MOT");
+
+ //Set the device id to derive temporal PSK
+ SetUuidForPinBasedOxm(&doxm->deviceID);
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Unsupported OxM for Multiple Ownership Transfer.");
+ return;
+ }
+
+ CAregisterSslHandshakeCallback(MultipleOwnerDTLSHandshakeCB);
+ }
+
+ OIC_LOG(INFO, TAG, "OUT PrepareMOT");
+ return;
+exit:
+ OIC_LOG(WARNING, TAG, "Error in PrepareMOT");
+}
+#endif //defined(__WITH_DTLS__) && defined(_ENABLE_MULTIPLE_OWNER_)
+
OCStackResult InitDoxmResource()
{
OCStackResult ret = OC_STACK_ERROR;
OIC_LOG (ERROR, TAG, "CheckDeviceID failed");
}
OICFree(data);
+
+#if defined(__WITH_DTLS__) && defined(_ENABLE_MULTIPLE_OWNER_)
+ //if MOT is enabled, MOT should be prepared.
+ if(gDoxm && gDoxm->owned)
+ {
+ PrepareMOT(gDoxm);
+ }
+#endif // defined(__WITH_DTLS__) && defined(_ENABLE_MULTIPLE_OWNER_)
+
return ret;
}
return retVal;
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * Compare the UUID to SubOwner.
+ *
+ * @param[in] uuid device UUID
+ *
+ * @return true if context->subjectId exist subowner list, else false.
+ */
+bool IsSubOwner(const OicUuid_t* uuid)
+{
+ bool retVal = false;
+
+ if(NULL == uuid)
+ {
+ return retVal;
+ }
+
+ if (gDoxm && gDoxm->subOwners)
+ {
+ OicSecSubOwner_t* subOwner = NULL;
+ LL_FOREACH(gDoxm->subOwners, subOwner)
+ {
+ if(memcmp(subOwner->uuid.id, uuid->id, sizeof(uuid->id)) == 0)
+ {
+ return true;
+ }
+ }
+ }
+ return retVal;
+}
+#endif //_ENABLE_MULTIPLE_OWNER_
+
/**
* Function to restore doxm resurce to initial status.
* This function will use in case of error while ownership transfer
OicSecCred_t *cred = GenerateCredential(peerDevID,
SYMMETRIC_PAIR_WISE_KEY, NULL,
- &pairingKey, owner);
+ &pairingKey, owner, NULL);
VERIFY_NON_NULL(TAG, cred, ERROR);
res = AddCredential(cred);
#include "logger.h"
#include "pinoxmcommon.h"
#include "pbkdf2.h"
+#include "base64.h"
#include "securevirtualresourcetypes.h"
+#include "srmresourcestrings.h"
+#include "doxmresource.h"
+#include "credresource.h"
+#include "cainterface.h"
#define TAG "PIN_OXM_COMMON"
return OC_STACK_ERROR;
}
+ OicUuid_t deviceID;
+ if(OC_STACK_OK == GetDoxmDeviceID(&deviceID))
+ {
+ //Set the device id to derive temporal PSK
+ SetUuidForPinBasedOxm(&deviceID);
+
+ /**
+ * Since PSK will be used directly by DTLS layer while PIN based ownership transfer,
+ * Credential should not be saved into SVR.
+ * For this reason, use a temporary get_psk_info callback to random PIN OxM.
+ */
+ if(CA_STATUS_OK != CAregisterPskCredentialsHandler(GetDtlsPskForRandomPinOxm))
+ {
+ OIC_LOG(ERROR, TAG, "Failed to register DTLS credential handler for Random PIN OxM.");
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Failed to read device ID");
+ return OC_STACK_ERROR;
+ }
+
return OC_STACK_OK;
}
-
OCStackResult InputPin(char* pinBuffer, size_t bufferSize)
{
if(!pinBuffer)
else
{
OIC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
- OIC_LOG(ERROR, TAG, "Callback for input PIN should be registered to use PIN based OxM.");
+ OIC_LOG(ERROR, TAG, "Callback for input PIN should be registered to use Random PIN based OxM.");
return OC_STACK_ERROR;
}
return OC_STACK_OK;
}
-#if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
+#ifdef _ENABLE_MULTIPLE_OWNER_
+OCStackResult SetPreconfigPin(const char* pinBuffer, size_t pinLength)
+{
+ if(NULL == pinBuffer || OXM_PRECONFIG_PIN_SIZE < pinLength)
+ {
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
+ g_PinOxmData.pinData[pinLength] = '\0';
-void SetUuidForRandomPinOxm(const OicUuid_t* uuid)
+ return OC_STACK_OK;
+}
+#endif //_ENABLE_MULTIPLE_OWNER_
+
+#ifdef __WITH_DTLS__
+
+void SetUuidForPinBasedOxm(const OicUuid_t* uuid)
{
if(NULL != uuid)
{
}
}
+int DerivePSKUsingPIN(uint8_t* result)
+{
+ int dtlsRes = DeriveCryptoKeyFromPassword(
+ (const unsigned char *)g_PinOxmData.pinData,
+ OXM_RANDOM_PIN_SIZE,
+ g_PinOxmData.newDevice.id,
+ UUID_LENGTH, PBKDF_ITERATIONS,
+ OWNER_PSK_LENGTH_128, result);
+
+ OIC_LOG_V(DEBUG, TAG, "DeriveCryptoKeyFromPassword Completed (%d)", dtlsRes);
+ OIC_LOG_V(DEBUG, TAG, "PIN : %s", g_PinOxmData.pinData);
+ OIC_LOG(DEBUG, TAG, "UUID : ");
+ OIC_LOG_BUFFER(DEBUG, TAG, g_PinOxmData.newDevice.id, UUID_LENGTH);
+
+ return dtlsRes;
+}
+
int32_t GetDtlsPskForRandomPinOxm( CADtlsPskCredType_t type,
const unsigned char *UNUSED1, size_t UNUSED2,
unsigned char *result, size_t result_length)
{
case CA_DTLS_PSK_HINT:
case CA_DTLS_PSK_IDENTITY:
- /**
- * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
- *
- * At this point, The server generate random hint and
- * provide it to client through server key exchange message.
- */
- OCFillRandomMem(result, result_length);
- ret = result_length;
-
- OIC_LOG(DEBUG, TAG, "PSK HINT : ");
- OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
+ {
+ /**
+ * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
+ *
+ * At this point, The server generate random hint and
+ * provide it to client through server key exchange message.
+ */
+ OCFillRandomMem(result, result_length);
+ ret = result_length;
+
+ OIC_LOG(DEBUG, TAG, "PSK HINT : ");
+ OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
+ }
break;
case CA_DTLS_PSK_KEY:
{
- int dtlsRes = DeriveCryptoKeyFromPassword(
- (const unsigned char *)g_PinOxmData.pinData,
- OXM_RANDOM_PIN_SIZE,
- g_PinOxmData.newDevice.id,
- UUID_LENGTH, PBKDF_ITERATIONS,
- OWNER_PSK_LENGTH_128, (uint8_t*)result);
-
- OIC_LOG_V(DEBUG, TAG, "DeriveCryptoKeyFromPassword Completed (%d)", dtlsRes);
- OIC_LOG_V(DEBUG, TAG, "PIN : %s", g_PinOxmData.pinData);
- OIC_LOG(DEBUG, TAG, "UUID : ");
- OIC_LOG_BUFFER(DEBUG, TAG, g_PinOxmData.newDevice.id, UUID_LENGTH);
-
- if(0 == dtlsRes)
+ if(0 == DerivePSKUsingPIN((uint8_t*)result))
{
ret = OWNER_PSK_LENGTH_128;
}
else
{
- OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result=%d", dtlsRes);
+ OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN");
ret = -1;
}
}
return ret;
}
-#endif // __WITH_DTLS__ or __WITH_TLS__
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+int32_t GetDtlsPskForMotRandomPinOxm( CADtlsPskCredType_t type,
+ const unsigned char *UNUSED1, size_t UNUSED2,
+ unsigned char *result, size_t result_length)
+{
+ int32_t ret = -1;
+
+ (void)UNUSED1;
+ (void)UNUSED2;
+
+ if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
+ {
+ return ret;
+ }
+
+ const OicSecDoxm_t* doxm = GetDoxmResourceData();
+ if(doxm)
+ {
+ switch (type)
+ {
+ case CA_DTLS_PSK_HINT:
+ case CA_DTLS_PSK_IDENTITY:
+ {
+ memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
+ return (sizeof(doxm->deviceID.id));
+ }
+ break;
+
+ case CA_DTLS_PSK_KEY:
+ {
+ if(0 == DerivePSKUsingPIN((uint8_t*)result))
+ {
+ ret = OWNER_PSK_LENGTH_128;
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
+ ret = -1;
+ }
+ }
+ break;
+
+ default:
+ {
+ OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
+ ret = -1;
+ }
+ break;
+ }
+ }
+
+ return ret;
+}
+
+
+int32_t GetDtlsPskForPreconfPinOxm( CADtlsPskCredType_t type,
+ const unsigned char *UNUSED1, size_t UNUSED2,
+ unsigned char *result, size_t result_length)
+{
+ int32_t ret = -1;
+
+ (void)UNUSED1;
+ (void)UNUSED2;
+
+ if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
+ {
+ return ret;
+ }
+
+ const OicSecDoxm_t* doxm = GetDoxmResourceData();
+ if(doxm)
+ {
+ switch (type)
+ {
+ case CA_DTLS_PSK_HINT:
+ case CA_DTLS_PSK_IDENTITY:
+ {
+ /**
+ * The server will provide PSK hint to identify PSK according to RFC 4589 and RFC 4279.
+ *
+ * At this point, The server generate random hint and
+ * provide it to client through server key exchange message.
+ */
+ OCFillRandomMem(result, result_length);
+ ret = result_length;
+
+ OIC_LOG(DEBUG, TAG, "PSK HINT : ");
+ OIC_LOG_BUFFER(DEBUG, TAG, result, result_length);
+ }
+ break;
+
+ case CA_DTLS_PSK_KEY:
+ {
+ OicUuid_t uuid;
+ memset(&uuid, 0x00, sizeof(uuid));
+ OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
+
+ //Load PreConfigured-PIN
+ const OicSecCred_t* cred = GetCredResourceData(&uuid);
+ if(cred)
+ {
+ char* pinBuffer = NULL;
+ uint32_t pinLength = 0;
+ if(OIC_ENCODING_RAW == cred->privateData.encoding)
+ {
+ pinBuffer = OICCalloc(1, cred->privateData.len + 1);
+ if(NULL == pinBuffer)
+ {
+ OIC_LOG (ERROR, TAG, "Failed to allocate memory");
+ return ret;
+ }
+ pinLength = cred->privateData.len;
+ memcpy(pinBuffer, cred->privateData.data, pinLength);
+ }
+ else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
+ {
+ size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
+ pinBuffer = OICCalloc(1, pinBufSize);
+ if(NULL == pinBuffer)
+ {
+ OIC_LOG (ERROR, TAG, "Failed to allocate memory");
+ return ret;
+ }
+
+ if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength))
+ {
+ OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
+ return ret;
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
+ return ret;
+ }
+
+ memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
+ OICFree(pinBuffer);
+ }
+
+ if(0 == DerivePSKUsingPIN((uint8_t*)result))
+ {
+ ret = OWNER_PSK_LENGTH_128;
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
+ ret = -1;
+ }
+ }
+ break;
+
+ default:
+ {
+ OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
+ ret = -1;
+ }
+ break;
+ }
+ }
+
+ return ret;
+}
+
+
+int32_t GetDtlsPskForMotPreconfPinOxm( CADtlsPskCredType_t type,
+ const unsigned char *UNUSED1, size_t UNUSED2,
+ unsigned char *result, size_t result_length)
+{
+ int32_t ret = -1;
+
+ (void)UNUSED1;
+ (void)UNUSED2;
+
+ if (NULL == result || result_length < OWNER_PSK_LENGTH_128)
+ {
+ return ret;
+ }
+
+ const OicSecDoxm_t* doxm = GetDoxmResourceData();
+ if(doxm)
+ {
+ switch (type)
+ {
+ case CA_DTLS_PSK_HINT:
+ case CA_DTLS_PSK_IDENTITY:
+ {
+ memcpy(result, doxm->deviceID.id, sizeof(doxm->deviceID.id));
+ return (sizeof(doxm->deviceID.id));
+ }
+ break;
+ case CA_DTLS_PSK_KEY:
+ {
+ OicUuid_t uuid;
+ memset(&uuid, 0x00, sizeof(uuid));
+ OICStrcpy(uuid.id, sizeof(uuid.id), WILDCARD_SUBJECT_ID.id);
+
+ //Load PreConfigured-PIN
+ const OicSecCred_t* cred = GetCredResourceData(&uuid);
+ if(cred)
+ {
+ char* pinBuffer = NULL;
+ uint32_t pinLength = 0;
+ if(OIC_ENCODING_RAW == cred->privateData.encoding)
+ {
+ pinBuffer = OICCalloc(1, cred->privateData.len + 1);
+ if(NULL == pinBuffer)
+ {
+ OIC_LOG (ERROR, TAG, "Failed to allocate memory");
+ return ret;
+ }
+ pinLength = cred->privateData.len;
+ memcpy(pinBuffer, cred->privateData.data, pinLength);
+ }
+ else if(OIC_ENCODING_BASE64 == cred->privateData.encoding)
+ {
+ size_t pinBufSize = B64DECODE_OUT_SAFESIZE((cred->privateData.len + 1));
+ pinBuffer = OICCalloc(1, pinBufSize);
+ if(NULL == pinBuffer)
+ {
+ OIC_LOG (ERROR, TAG, "Failed to allocate memory");
+ return ret;
+ }
+
+ if(B64_OK != b64Decode((char*)cred->privateData.data, cred->privateData.len, pinBuffer, pinBufSize, &pinLength))
+ {
+ OIC_LOG (ERROR, TAG, "Failed to base64 decoding.");
+ return ret;
+ }
+ }
+ else
+ {
+ OIC_LOG(ERROR, TAG, "Unknown encoding type of PIN/PW credential.");
+ return ret;
+ }
+
+ memcpy(g_PinOxmData.pinData, pinBuffer, pinLength);
+ OICFree(pinBuffer);
+ }
+
+ if(0 == DerivePSKUsingPIN((uint8_t*)result))
+ {
+ ret = OWNER_PSK_LENGTH_128;
+ }
+ else
+ {
+ OIC_LOG_V(ERROR, TAG, "Failed to derive crypto key from PIN : result");
+ ret = -1;
+ }
+ }
+ break;
+
+ default:
+ {
+ OIC_LOG (ERROR, TAG, "Wrong value passed for CADtlsPskCredType_t.");
+ ret = -1;
+ }
+ break;
+ }
+ }
+
+ return ret;
+}
+#endif //_ENABLE_MULTIPLE_OWNER_
+
+#endif //__WITH_DTLS__
return retVal;
}
+
+#ifdef _ENABLE_MULTIPLE_OWNER_
+/**
+ * Compare the request's subject to SubOwner.
+ *
+ * @return true if context->subjectId exist subowner list, else false.
+ */
+static bool IsRequestFromSubOwner(PEContext_t *context)
+{
+ bool retVal = false;
+
+ if(NULL == context)
+ {
+ return retVal;
+ }
+
+ if(IsSubOwner(&context->subject))
+ {
+ retVal = true;
+ }
+
+ if(true == retVal)
+ {
+ OIC_LOG(INFO, TAG, "PE.IsRequestFromSubOwner(): returning true");
+ }
+ else
+ {
+ OIC_LOG(INFO, TAG, "PE.IsRequestFromSubOwner(): returning false");
+ }
+
+ return retVal;
+}
+
+
+/**
+ * Verify the SubOwner's request.
+ *
+ * @return true if request is valid, else false.
+ */
+static bool IsValidRequestFromSubOwner(PEContext_t *context)
+{
+ bool isValidRequest = false;
+
+ if(NULL == context)
+ {
+ return isValidRequest;
+ }
+
+ switch(context->resourceType)
+ {
+ case OIC_R_DOXM_TYPE:
+ //SubOwner has READ permission only for DOXM
+ if(PERMISSION_READ == context->permission)
+ {
+ isValidRequest = true;
+ }
+ break;
+ case OIC_R_PSTAT_TYPE:
+ //SubOwner has full permsion for PSTAT
+ isValidRequest = true;
+ break;
+ case OIC_R_CRED_TYPE:
+ //SubOwner can only access the credential which is registered as the eowner.
+ isValidRequest = IsValidCredentialAccessForSubOwner(&context->subject, context->payload, context->payloadSize);
+ break;
+ case OIC_R_ACL_TYPE:
+ //SubOwner can only access the ACL which is registered as the eowner.
+ isValidRequest = IsValidAclAccessForSubOwner(&context->subject, context->payload, context->payloadSize);
+ break;
+ default:
+ //SubOwner has full permission for all resource except the security resource
+ isValidRequest = true;
+ break;
+ }
+
+ if(isValidRequest)
+ {
+ OIC_LOG(INFO, TAG, "PE.IsValidRequestFromSubOwner(): returning true");
+ }
+ else
+ {
+ OIC_LOG(INFO, TAG, "PE.IsValidRequestFromSubOwner(): returning false");
+ }
+
+ return isValidRequest;
+}
+#endif //_ENABLE_MULTIPLE_OWNER_
+
+
// TODO - remove these function placeholders as they are implemented
// in the resource entity handler code.
// Note that because many SVRs do not have a rowner, in those cases we
{
context->retVal = ACCESS_GRANTED;
}
- // If not granted via DevOwner status,
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ //Then check if request from SubOwner
+ else if(IsRequestFromSubOwner(context))
+ {
+ if(IsValidRequestFromSubOwner(context))
+ {
+ context->retVal = ACCESS_GRANTED;
+ }
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
+ // If not granted via DevOwner status and not a subowner,
// then check if request is for a SVR and coming from rowner
else if (IsRequestFromResourceOwner(context))
{
}
}
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ /*
+ * In case of ACL and CRED, The payload required to verify the payload.
+ * Payload information will be used for subowner's permission verification.
+ */
+ g_policyEngineContext.payload = (uint8_t*)requestInfo->info.payload;
+ g_policyEngineContext.payloadSize = requestInfo->info.payloadSize;
+#endif //_ENABLE_MULTIPLE_OWNER_
//New request are only processed if the policy engine state is AWAITING_REQUEST.
if (AWAITING_REQUEST == g_policyEngineContext.state)
const char * OIC_JSON_OWNERS_NAME = "ownrs";
const char * OIC_JSON_OWNER_NAME = "ownr";
const char * OIC_JSON_DEVOWNERID_NAME = "devowneruuid";
+#ifdef _ENABLE_MULTIPLE_OWNER_
+const char * OIC_JSON_SUBOWNERID_NAME = "x.org.iotivity.subowneruuid";
+#endif //_ENABLE_MULTIPLE_OWNER_
const char * OIC_JSON_OWNED_NAME = "owned";
const char * OIC_JSON_OXM_NAME = "oxm";
const char * OIC_JSON_OXMS_NAME = "oxms";
+#ifdef _ENABLE_MULTIPLE_OWNER_
+const char * OIC_JSON_MOM_NAME = "x.org.iotivity.mom";
+#endif //_ENABLE_MULTIPLE_OWNER_
const char * OIC_JSON_OXM_TYPE_NAME = "oxmtype";
const char * OIC_JSON_OXM_SEL_NAME = "oxmsel";
const char * OIC_JSON_DEVICE_ID_FORMAT_NAME = "didformat";
const char * OIC_JSON_RT_NAME = OC_RSRVD_RESOURCE_TYPE;
const char * OIC_JSON_IF_NAME = OC_RSRVD_INTERFACE;
const char * OIC_JSON_ROWNERID_NAME = "rowneruuid";
+#ifdef _ENABLE_MULTIPLE_OWNER_
+const char * OIC_JSON_EOWNERID_NAME = "x.org.iotivity.eowneruuid";
+#endif //_ENABLE_MULTIPLE_OWNER_
const char * OIC_JSON_ENCODING_NAME = "encoding";
const char * OIC_JSON_DATA_NAME = "data";
const char * OIC_JSON_SEC_V_NAME = "secv";
const char * OXM_JUST_WORKS = "oic.sec.doxm.jw";
const char * OXM_RANDOM_DEVICE_PIN = "oic.sec.doxm.rdp";
const char * OXM_MANUFACTURER_CERTIFICATE = "oic.sec.doxm.mfgcert";
+#ifdef _ENABLE_MULTIPLE_OWNER_
+const char * OXM_PRECONF_PIN = "oic.sec.doxm.pcp";
+#endif //_ENABLE_MULTIPLE_OWNER_
//Credential data encoding methods
const char * OIC_SEC_ENCODING_BASE64 = "oic.sec.encoding.base64";
return OXM_RANDOM_DEVICE_PIN;
case OIC_MANUFACTURER_CERTIFICATE:
return OXM_MANUFACTURER_CERTIFICATE;
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ case OIC_PRECONFIG_PIN:
+ return OXM_PRECONF_PIN;
+#endif //_ENABLE_MULTIPLE_OWNER_
default:
return NULL;
}
doxm->dpc = jsonObj->valueint;
}
+#ifdef _ENABLE_MULTIPLE_OWNER_
+ //mom -- Not Mandatory
+ jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_MOM_NAME);
+ if (jsonObj)
+ {
+ VERIFY_SUCCESS(TAG, (cJSON_Number == jsonObj->type), ERROR);
+ doxm->mom = (OicSecMom_t*)OICCalloc(1, sizeof(OicSecMom_t));
+ VERIFY_NON_NULL(TAG, doxm->mom, ERROR);
+ doxm->mom->mode = (OicSecMomType_t)jsonObj->valueint;
+ }
+#endif //_ENABLE_MULTIPLE_OWNER_
+
//DeviceId -- Mandatory
jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_DEVICE_ID_NAME);
if (jsonObj)
if srmtest_env.get('LOGGING') == '1':
srmtest_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+if srmtest_env.get('MULTIPLE_OWNER') == '1':
+ srmtest_env.AppendUnique(CPPDEFINES=['_ENABLE_MULTIPLE_OWNER_'])
+
if target_os == 'windows':
srmtest_env.AppendUnique(LINKFLAGS = ['/subsystem:CONSOLE'])
srmtest_env.AppendUnique(LIBS = ['advapi32', 'bcrypt', 'kernel32', 'ws2_32', 'iphlpapi', 'octbstack_static'])
unittest_src_dir + 'oic_svr_db_prov.dat'))
srmtest_env.Alias("install", srmtest_env.Install( unittest_build_dir,
unittest_src_dir + 'oic_svr_db.dat'))
-
+
srmtest_env.AppendTarget('test')
if srmtest_env.get('TEST') == '1':
if target_os in ['linux', 'windows']:
OicSecCred_t * cred = NULL;
cred = GenerateCredential(&subject, SYMMETRIC_PAIR_WISE_KEY, NULL,
- &key, &rownerID);
+ &key, &rownerID, NULL);
printCred(cred);
ASSERT_TRUE(NULL != cred);
OicSecCred_t *headCred = NULL;
cred1 = GenerateCredential(&subject, SYMMETRIC_PAIR_WISE_KEY, NULL,
- &key, &rownerID);
+ &key, &rownerID, NULL);
EXPECT_EQ(OC_STACK_OK, AddCredential(cred1));
headCred = cred1;
OICStrcpy((char *)rownerID.id, sizeof(rownerID.id), "ownersId22");
OICStrcpy((char *)subject.id, sizeof(subject.id), "subject22");
cred1 = GenerateCredential(&subject, SYMMETRIC_PAIR_WISE_KEY, NULL,
- &key, &rownerID);
+ &key, &rownerID, NULL);
EXPECT_EQ(OC_STACK_OK, AddCredential(cred1));
OICStrcpy((char *)rownerID.id, sizeof(rownerID.id), "ownersId33");
OICStrcpy((char *)subject.id, sizeof(subject.id), "subject33");
cred1 = GenerateCredential(&subject, SYMMETRIC_PAIR_WISE_KEY, NULL,
- &key, &rownerID);
+ &key, &rownerID, NULL);
EXPECT_EQ(OC_STACK_OK, AddCredential(cred1));
const OicSecCred_t* credList = GetCredResourceData(&headCred->subject);
int request = 0;
scanf("%d", &request);
- getchar();
+ for( ; 0x20<=getchar(); );
switch (request)
{