merge master code to build iotivity
authorhyuna0213.jo <hyuna0213.jo@samsung.com>
Tue, 25 Aug 2015 06:12:39 +0000 (15:12 +0900)
committerJon A. Cruz <jonc@osg.samsung.com>
Tue, 25 Aug 2015 18:55:18 +0000 (18:55 +0000)
current cloud-interface branch code failed to build iotivity stack.
so I merge latest master code that the build issue is resolved
to build full source code.

Change-Id: I6f6393806f3d4b5c5b861fe61941cea13bb45904
Signed-off-by: hyuna0213.jo <hyuna0213.jo@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/2265
Reviewed-by: Jaehong Jo <jaehong.jo@samsung.com>
Reviewed-by: Jon A. Cruz <jonc@osg.samsung.com>
Tested-by: Jon A. Cruz <jonc@osg.samsung.com>
109 files changed:
auto_build.sh
build_common/darwin/SConscript
extlibs/tinydtls/0001-Add-TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256-cipher-su.patch [new file with mode: 0644]
extlibs/tinydtls/0001-Fix-the-wrong-implementation-about-the-anonymous-cip.patch [new file with mode: 0644]
extlibs/tinydtls/crypto.c
extlibs/tinydtls/crypto.h
extlibs/tinydtls/dtls.c
extlibs/tinydtls/dtls.h
extlibs/tinydtls/global.h
extlibs/tinydtls/tests/dtls-client.c
extlibs/tinydtls/tests/dtls-server.c
resource/csdk/connectivity/api/cacommon.h
resource/csdk/connectivity/common/src/caremotehandler.c
resource/csdk/connectivity/common/src/logger.c
resource/csdk/connectivity/inc/caadapternetdtls.h
resource/csdk/connectivity/inc/caipinterface.h
resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c
resource/csdk/connectivity/src/bt_edr_adapter/android/caedrserver.c
resource/csdk/connectivity/src/bt_edr_adapter/caedradapter.c
resource/csdk/connectivity/src/camessagehandler.c
resource/csdk/connectivity/src/caprotocolmessage.c
resource/csdk/connectivity/src/ip_adapter/android/caipnwmonitor.c
resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_eth.cpp
resource/csdk/connectivity/src/ip_adapter/arduino/caipnwmonitor_wifi.cpp
resource/csdk/connectivity/src/ip_adapter/caipadapter.c
resource/csdk/connectivity/src/ip_adapter/caipserver.c
resource/csdk/connectivity/src/ip_adapter/linux/caipnwmonitor.c
resource/csdk/connectivity/src/ip_adapter/tizen/caipnwmonitor.c
resource/csdk/security/SConscript
resource/csdk/security/include/internal/amaclresource.h [new file with mode: 0755]
resource/csdk/security/include/internal/credresource.h
resource/csdk/security/include/internal/doxmresource.h
resource/csdk/security/include/internal/srmresourcestrings.h
resource/csdk/security/include/internal/svcresource.h [new file with mode: 0644]
resource/csdk/security/include/iotvticalendar.h [new file with mode: 0644]
resource/csdk/security/include/pbkdf2.h [new file with mode: 0644]
resource/csdk/security/include/pinoxmcommon.h [new file with mode: 0644]
resource/csdk/security/include/securevirtualresourcetypes.h
resource/csdk/security/include/srmutility.h
resource/csdk/security/provisioning/README.txt [new file with mode: 0644]
resource/csdk/security/provisioning/SConscript
resource/csdk/security/provisioning/include/internal/credentialgenerator.h
resource/csdk/security/provisioning/include/internal/ownershiptransfermanager.h [new file with mode: 0644]
resource/csdk/security/provisioning/include/internal/secureresourceprovider.h [new file with mode: 0644]
resource/csdk/security/provisioning/include/ocprovisioningmanager.h [new file with mode: 0644]
resource/csdk/security/provisioning/include/oxm/oxmjustworks.h [new file with mode: 0644]
resource/csdk/security/provisioning/include/oxm/oxmrandompin.h [new file with mode: 0644]
resource/csdk/security/provisioning/include/pmtypes.h [new file with mode: 0644]
resource/csdk/security/provisioning/include/pmutility.h [new file with mode: 0644]
resource/csdk/security/provisioning/include/provisioningmanager.h [deleted file]
resource/csdk/security/provisioning/sample/SConscript
resource/csdk/security/provisioning/sample/oic_svr_db_client.json [new file with mode: 0644]
resource/csdk/security/provisioning/sample/oic_svr_db_server_justworks.json [new file with mode: 0644]
resource/csdk/security/provisioning/sample/oic_svr_db_server_randompin.json [new file with mode: 0644]
resource/csdk/security/provisioning/sample/provisioningclient.c
resource/csdk/security/provisioning/sample/sampleserver_justworks.cpp [new file with mode: 0644]
resource/csdk/security/provisioning/sample/sampleserver_randompin.cpp [new file with mode: 0644]
resource/csdk/security/provisioning/src/credentialgenerator.c
resource/csdk/security/provisioning/src/ocprovisioningmanager.c [new file with mode: 0644]
resource/csdk/security/provisioning/src/ownershiptransfermanager.c [new file with mode: 0644]
resource/csdk/security/provisioning/src/oxmjustworks.c [new file with mode: 0644]
resource/csdk/security/provisioning/src/oxmrandompin.c [new file with mode: 0644]
resource/csdk/security/provisioning/src/pmutility.c [new file with mode: 0644]
resource/csdk/security/provisioning/src/provisioningmanager.c [deleted file]
resource/csdk/security/provisioning/src/secureresourceprovider.c [new file with mode: 0644]
resource/csdk/security/provisioning/unittest/SConscript
resource/csdk/security/provisioning/unittest/otmunittest.cpp [new file with mode: 0644]
resource/csdk/security/provisioning/unittest/pmutilitytest.cpp [new file with mode: 0644]
resource/csdk/security/provisioning/unittest/provisioningmanager.cpp [deleted file]
resource/csdk/security/provisioning/unittest/secureresourceprovider.cpp [new file with mode: 0644]
resource/csdk/security/src/aclresource.c
resource/csdk/security/src/amaclresource.c [new file with mode: 0644]
resource/csdk/security/src/credresource.c
resource/csdk/security/src/doxmresource.c
resource/csdk/security/src/iotvticalendar.c [new file with mode: 0644]
resource/csdk/security/src/oxmpincommon.c [new file with mode: 0644]
resource/csdk/security/src/pbkdf2.c [new file with mode: 0644]
resource/csdk/security/src/policyengine.c
resource/csdk/security/src/psinterface.c
resource/csdk/security/src/pstatresource.c
resource/csdk/security/src/resourcemanager.c
resource/csdk/security/src/secureresourcemanager.c
resource/csdk/security/src/srmresourcestrings.c
resource/csdk/security/src/srmutility.c
resource/csdk/security/src/svcresource.c [new file with mode: 0644]
resource/csdk/security/unittest/SConscript
resource/csdk/security/unittest/aclresourcetest.cpp
resource/csdk/security/unittest/credentialresource.cpp
resource/csdk/security/unittest/doxmresource.cpp
resource/csdk/security/unittest/iotvticalendartest.cpp [new file with mode: 0644]
resource/csdk/security/unittest/oic_unittest.json
resource/csdk/security/unittest/pstatresource.cpp
resource/csdk/security/unittest/srmtestcommon.cpp [new file with mode: 0644]
resource/csdk/security/unittest/srmtestcommon.h [new file with mode: 0644]
resource/csdk/security/unittest/srmutility.cpp
resource/csdk/security/unittest/svcresourcetest.cpp [new file with mode: 0644]
resource/csdk/stack/samples/linux/secure/occlientbasicops.h
resource/csdk/stack/samples/linux/secure/ocserverbasicops.cpp
resource/csdk/stack/samples/linux/secure/oic_svr_db_client.json
resource/csdk/stack/samples/linux/secure/oic_svr_db_server.json
resource/csdk/stack/samples/tizen/build/packaging/com.oic.ri.spec
resource/csdk/stack/src/ocserverrequest.c
resource/csdk/stack/src/ocstack.c
resource/csdk/stack/src/oicgroup.c
resource/include/OCPlatform.h
resource/include/OCPlatform_impl.h
service/resource-encapsulation/src/resourceBroker/include/DevicePresence.h
service/resource-encapsulation/src/resourceBroker/src/DevicePresence.cpp
service/resource-encapsulation/src/resourceContainer/SConscript

index 750f641..352f3b6 100755 (executable)
@@ -63,27 +63,41 @@ function build_android()
        # Note: for android, as oic-resource uses C++11 feature stoi and to_string,
        # it requires gcc-4.9, currently only android-ndk-r10(for linux)
        # and windows android-ndk-r10(64bit target version) support these features.
-       echo "*********** Build Boost for android ***********"
-       # disable parallel build for android as gradle depends on scons to finish first
-       export SCONSFLAGS="-Q"
 
+    # Parallel builds for android are disabled as gradle depends on
+    # scons to finish first
+    SCONSFLAGS="-Q" build_android_x86 $1 $2
+    SCONSFLAGS="-Q" build_android_armeabi $1 $2
+}
+
+function build_android_x86()
+{
        echo "*********** Build for android x86 *************"
        scons TARGET_OS=android TARGET_ARCH=x86 RELEASE=$1 TARGET_TRANSPORT=IP $2
        scons TARGET_OS=android TARGET_ARCH=x86 RELEASE=$1 TARGET_TRANSPORT=BT $2
        scons TARGET_OS=android TARGET_ARCH=x86 RELEASE=$1 TARGET_TRANSPORT=BLE $2
+<<<<<<< HEAD
 
        echo "*********** Build for android x86_64 *************"
        scons TARGET_OS=android TARGET_ARCH=x86_64 RELEASE=$1 TARGET_TRANSPORT=IP $2
        scons TARGET_OS=android TARGET_ARCH=x86_64 RELEASE=$1 TARGET_TRANSPORT=BT $2
        scons TARGET_OS=android TARGET_ARCH=x86_64 RELEASE=$1 TARGET_TRANSPORT=BLE $2
+=======
+}
+>>>>>>> origin/master
 
+function build_android_armeabi()
+{
        echo "*********** Build for android armeabi *************"
        scons TARGET_OS=android TARGET_ARCH=armeabi RELEASE=$1 TARGET_TRANSPORT=IP $2
        scons TARGET_OS=android TARGET_ARCH=armeabi RELEASE=$1 TARGET_TRANSPORT=BT $2
        scons TARGET_OS=android TARGET_ARCH=armeabi RELEASE=$1 TARGET_TRANSPORT=BLE $2
+<<<<<<< HEAD
 
        # enable parallel build
        export SCONSFLAGS="-Q -j 4"
+=======
+>>>>>>> origin/master
 }
 
 function build_arduino()
@@ -191,6 +205,14 @@ then
        then
                build_android true
                build_android false
+       elif [ $1 = 'android_x86' ]
+       then
+        build_android_x86 true
+        build_android_x86 false
+       elif [ $1 = 'android_armeabi' ]
+       then
+        build_android_armeabi true
+        build_android_armeabi false
        elif [ $1 = 'arduino' ]
        then
                build_arduino true
index 4cbb981..73bb047 100644 (file)
@@ -58,6 +58,9 @@ else:
        env.AppendUnique(CCFLAGS = ['-g'])
        env.AppendUnique(LINKFLAGS = ['-g'])
 
+if env.get('LOGGING'):
+    env.AppendUnique(CPPDEFINES = ['-DTB_LOG'])
+
 if target_os == 'darwin':
        sys_root = tc_path + '/Platforms/MacOSX.platform/Developer/SDKs/MacOSX' + sys_version + '.sdk/'
 else:
diff --git a/extlibs/tinydtls/0001-Add-TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256-cipher-su.patch b/extlibs/tinydtls/0001-Add-TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256-cipher-su.patch
new file mode 100644 (file)
index 0000000..5221174
--- /dev/null
@@ -0,0 +1,746 @@
+From 947179cd0d3646359272cc0645e5049e2426f9e0 Mon Sep 17 00:00:00 2001
+From: Sachin Agrawal <sachin.agrawal@intel.com>
+Date: Thu, 6 Aug 2015 15:13:29 -0700
+Subject: [PATCH 1/1] Add TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 cipher suite
+ in tinydtls
+
+[Patch #1] Initial upload
+[Patch #2] Add function to calculate the pre-master key of ECDHE_PSK cipher suite.
+[Patch #3] Update codes according to review comments
+[Patch #4] Modify code alignment.
+
+Change-Id: I70be3a8e9469cc1913373d820b4a3d4f4a6d6d0d
+Signed-off-by: leechul <chuls.lee@samsung.com>
+Signed-off-by: Sachin Agrawal <sachin.agrawal@intel.com>
+---
+ extlibs/tinydtls/crypto.c            |   41 +++-
+ extlibs/tinydtls/crypto.h            |    9 +
+ extlibs/tinydtls/dtls.c              |  401 ++++++++++++++++++++++++++++++++--
+ extlibs/tinydtls/global.h            |    1 +
+ extlibs/tinydtls/tests/dtls-client.c |    8 +-
+ 5 files changed, 444 insertions(+), 16 deletions(-)
+
+diff --git a/extlibs/tinydtls/crypto.c b/extlibs/tinydtls/crypto.c
+index 3fbb993..deaf581 100644
+--- a/extlibs/tinydtls/crypto.c
++++ b/extlibs/tinydtls/crypto.c
+@@ -641,6 +641,41 @@ dtls_ecdsa_verify_sig(const unsigned char *pub_key_x,
+ }
+ #endif /* DTLS_ECC */
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++int dtls_ecdhe_psk_pre_master_secret(unsigned char *psk, size_t psklen,
++                                     unsigned char *ecc_priv_key,
++                                     unsigned char *ecc_pub_key_x,
++                                     unsigned char *ecc_pub_key_y,
++                                     size_t ecc_key_size,
++                                     unsigned char *result,
++                                     size_t result_len)
++{
++  uint8_t eccPublicKey[64];
++  uint8_t eccPrivateKey[32];
++  unsigned char *p = result;
++
++  if (result_len < uECC_BYTES + psklen + (sizeof(uint16) * 2)) {
++    return -1;
++  }
++
++  dtls_int_to_uint16(p, uECC_BYTES);
++  p += sizeof(uint16);
++
++  memcpy(eccPublicKey, ecc_pub_key_x, 32);
++  memcpy(eccPublicKey + 32, ecc_pub_key_y, 32);
++  memcpy(eccPrivateKey, ecc_priv_key, 32);
++  uECC_shared_secret(eccPublicKey, eccPrivateKey, p);
++  p += uECC_BYTES;
++
++  dtls_int_to_uint16(p, psklen);
++  p += sizeof(uint16);
++
++  memcpy(p, psk, psklen);
++
++  return uECC_BYTES + psklen + (sizeof(uint16) * 2);
++}
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
++
+ int
+ dtls_encrypt(const unsigned char *src, size_t length,
+            unsigned char *buf,
+@@ -665,7 +700,8 @@ dtls_encrypt(const unsigned char *src, size_t length,
+         memmove(buf, src, length);
+       ret = dtls_ccm_encrypt(&ctx->data, src, length, buf, nounce, aad, la);
+   }
+-  if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256) {
++  if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 ||
++     cipher == TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256) {
+       ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
+       if (ret < 0) {
+         /* cleanup everything in case the key has the wrong size */
+@@ -708,7 +744,8 @@ dtls_decrypt(const unsigned char *src, size_t length,
+       ret = dtls_ccm_decrypt(&ctx->data, src, length, buf, nounce, aad, la);
+   }
+-  if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256) {
++  if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 ||
++     cipher == TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256) {
+       ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
+       if (ret < 0) {
+         /* cleanup everything in case the key has the wrong size */
+diff --git a/extlibs/tinydtls/crypto.h b/extlibs/tinydtls/crypto.h
+index a81d306..f4cfc66 100644
+--- a/extlibs/tinydtls/crypto.h
++++ b/extlibs/tinydtls/crypto.h
+@@ -39,6 +39,7 @@
+ #include "numeric.h"
+ #include "hmac.h"
+ #include "ccm.h"
++#include "ecc/ecc.h"
+ /* TLS_PSK_WITH_AES_128_CCM_8 */
+ #define DTLS_MAC_KEY_LENGTH    0
+@@ -129,6 +130,13 @@ typedef struct {
+   dtls_compression_t compression;             /**< compression method */
+   dtls_cipher_t cipher;               /**< cipher type */
+   unsigned int do_client_auth:1;
++
++#ifdef DTLS_ECC && DTLS_PSK
++  struct keyx_t {
++    dtls_handshake_parameters_ecc_t ecc;
++    dtls_handshake_parameters_psk_t psk;
++  } keyx;
++#else /* DTLS_ECC && DTLS_PSK */
+   union {
+ #ifdef DTLS_ECC
+     dtls_handshake_parameters_ecc_t ecc;
+@@ -137,6 +145,7 @@ typedef struct {
+     dtls_handshake_parameters_psk_t psk;
+ #endif /* DTLS_PSK */
+   } keyx;
++#endif /* DTLS_ECC && DTLS_PSK */
+ } dtls_handshake_parameters_t;
+ /* The following macros provide access to the components of the
+diff --git a/extlibs/tinydtls/dtls.c b/extlibs/tinydtls/dtls.c
+index b5b8fd1..6104a08 100644
+--- a/extlibs/tinydtls/dtls.c
++++ b/extlibs/tinydtls/dtls.c
+@@ -506,6 +506,17 @@ static inline int is_tls_ecdh_anon_with_aes_128_cbc_sha_256(dtls_cipher_t cipher
+ #endif
+ }
++/** returns true if the cipher matches TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 */
++static inline int is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(dtls_cipher_t cipher)
++{
++#if defined(DTLS_ECC) && defined(DTLS_PSK)
++  return cipher == TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256;
++#else
++  return 0;
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
++}
++
++
+ /** returns true if the application is configured for psk */
+ static inline int is_psk_supported(dtls_context_t *ctx)
+@@ -549,6 +560,17 @@ static inline int is_ecdh_anon_supported(dtls_context_t *ctx)
+ #endif
+ }
++/** returns true if ecdhe_psk_with_aes_128_cbc_sha_256 is supported */
++static inline int is_ecdhe_psk_supported(dtls_context_t *ctx)
++{
++#if defined(DTLS_ECC) && defined(DTLS_PSK)
++    return is_psk_supported(ctx);
++#else
++    return 0;
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
++}
++
++
+ /**
+  * Returns @c 1 if @p code is a cipher suite other than @c
+  * TLS_NULL_WITH_NULL_NULL that we recognize.
+@@ -563,14 +585,17 @@ known_cipher(dtls_context_t *ctx, dtls_cipher_t code, int is_client) {
+   int psk;
+   int ecdsa;
+   int ecdh_anon;
++  int ecdhe_psk;
+   psk = is_psk_supported(ctx);
+   ecdsa = is_ecdsa_supported(ctx, is_client);
+   ecdh_anon = is_ecdh_anon_supported(ctx);
++  ecdhe_psk = is_ecdhe_psk_supported(ctx);
+   return (psk && is_tls_psk_with_aes_128_ccm_8(code)) ||
+        (ecdsa && is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(code)) ||
+-       (ecdh_anon && is_tls_ecdh_anon_with_aes_128_cbc_sha_256(code));
++       (ecdh_anon && is_tls_ecdh_anon_with_aes_128_cbc_sha_256(code)) ||
++       (ecdhe_psk && is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(code));
+ }
+ /**
+@@ -676,7 +701,11 @@ calculate_key_block(dtls_context_t *ctx,
+                   dtls_peer_t *peer,
+                   session_t *session,
+                   dtls_peer_type role) {
+-  unsigned char *pre_master_secret;
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++  unsigned char pre_master_secret[MAX_KEYBLOCK_LENGTH + uECC_BYTES];
++#else
++  unsigned char pre_master_secret[MAX_KEYBLOCK_LENGTH];
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+   int pre_master_len = 0;
+   dtls_security_parameters_t *security = dtls_security_params_next(peer);
+   uint8 master_secret[DTLS_MASTER_SECRET_LENGTH];
+@@ -685,8 +714,6 @@ calculate_key_block(dtls_context_t *ctx,
+     return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+   }
+-  pre_master_secret = security->key_block;
+-
+   switch (handshake->cipher) {
+ #ifdef DTLS_PSK
+   case TLS_PSK_WITH_AES_128_CCM_8: {
+@@ -733,6 +760,35 @@ calculate_key_block(dtls_context_t *ctx,
+     break;
+   }
+ #endif /* DTLS_ECC */
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++    case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256: {
++      unsigned char psk[DTLS_PSK_MAX_KEY_LEN];
++      int psklen;
++
++      psklen = CALL(ctx, get_psk_info, session, DTLS_PSK_KEY,
++             handshake->keyx.psk.identity,
++             handshake->keyx.psk.id_length,
++             psk, DTLS_PSK_MAX_KEY_LEN);
++      if (psklen < 0) {
++        dtls_crit("no psk key for session available\n");
++        return psklen;
++      }
++
++      pre_master_len = dtls_ecdhe_psk_pre_master_secret(psk, psklen,
++                           handshake->keyx.ecc.own_eph_priv,
++                           handshake->keyx.ecc.other_eph_pub_x,
++                           handshake->keyx.ecc.other_eph_pub_y,
++                           sizeof(handshake->keyx.ecc.own_eph_priv),
++                           pre_master_secret,
++                           MAX_KEYBLOCK_LENGTH + uECC_BYTES);
++
++      if (pre_master_len < 0) {
++        dtls_crit("the curve was too long, for the pre master secret\n");
++        return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
++      }
++      break;
++    }
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC)  */
+   default:
+     dtls_crit("calculate_key_block: unknown cipher\n");
+     return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+@@ -1113,6 +1169,56 @@ check_client_keyexchange(dtls_context_t *ctx,
+     data += sizeof(handshake->keyx.ecc.other_eph_pub_y);
+   }
+ #endif /* DTLS_ECC */
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++  if (is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(handshake->cipher)) {
++    int id_length;
++
++    if (length < DTLS_HS_LENGTH + DTLS_CKXEC_LENGTH) {
++      dtls_debug("The client key exchange is too short\n");
++      return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
++    }
++    data += DTLS_HS_LENGTH;
++
++    //PSK hint
++    id_length = dtls_uint16_to_int(data);
++    data += sizeof(uint16);
++
++    if (DTLS_HS_LENGTH + DTLS_CKXPSK_LENGTH_MIN + DTLS_CKXEC_LENGTH + id_length != length) {
++      dtls_debug("The identity has a wrong length\n");
++      return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
++    }
++
++    if (id_length > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) {
++      dtls_warn("please use a smaller client identity\n");
++      return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
++    }
++
++    handshake->keyx.psk.id_length = id_length;
++    memcpy(handshake->keyx.psk.identity, data, id_length);
++    data += id_length;
++
++    //ECDH public
++    if (dtls_uint8_to_int(data) != 1 + 2 * DTLS_EC_KEY_SIZE) {
++      dtls_alert("expected 65 bytes long public point\n");
++      return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
++    }
++    data += sizeof(uint8);
++
++    if (dtls_uint8_to_int(data) != 4) {
++      dtls_alert("expected uncompressed public point\n");
++      return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
++    }
++    data += sizeof(uint8);
++
++    memcpy(handshake->keyx.ecc.other_eph_pub_x, data,
++       sizeof(handshake->keyx.ecc.other_eph_pub_x));
++    data += sizeof(handshake->keyx.ecc.other_eph_pub_x);
++
++    memcpy(handshake->keyx.ecc.other_eph_pub_y, data,
++       sizeof(handshake->keyx.ecc.other_eph_pub_y));
++    data += sizeof(handshake->keyx.ecc.other_eph_pub_y);
++  }
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+ #ifdef DTLS_PSK
+   if (is_tls_psk_with_aes_128_ccm_8(handshake->cipher)) {
+     int id_length;
+@@ -1286,7 +1392,8 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
+       p += data_len_array[i];
+       res += data_len_array[i];
+     }
+-  } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(security->cipher)) {
++  } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(security->cipher) ||
++             is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(security->cipher)) {
+     unsigned char nonce[DTLS_CBC_IV_LENGTH];
+@@ -2116,6 +2223,80 @@ dtls_send_server_key_exchange_ecdh(dtls_context_t *ctx, dtls_peer_t *peer,
+ }
+ #endif /* DTLS_ECC */
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++static int dtls_send_server_key_exchange_ecdhe_psk(dtls_context_t *ctx, dtls_peer_t *peer,
++                                const unsigned char *psk_hint, size_t psk_hint_len)
++{
++  /* The ASN.1 Integer representation of an 32 byte unsigned int could be
++   * 33 bytes long add space for that */
++  uint8 buf[DTLS_SKEXEC_LENGTH + DTLS_SKEXECPSK_LENGTH_MAX + 2];
++  uint8 *p;
++  uint8 *ephemeral_pub_x;
++  uint8 *ephemeral_pub_y;
++  dtls_handshake_parameters_t *config = peer->handshake_params;
++
++  /* ServerKeyExchange
++    * Please see Session 2, RFC 5489.
++
++         struct {
++          select (KeyExchangeAlgorithm) {
++              //other cases for rsa, diffie_hellman, etc.
++              case ec_diffie_hellman_psk:  // NEW
++                  opaque psk_identity_hint<0..2^16-1>;
++                  ServerECDHParams params;
++          };
++      } ServerKeyExchange; */
++  p = buf;
++
++  assert(psk_hint_len <= DTLS_PSK_MAX_CLIENT_IDENTITY_LEN);
++  if (psk_hint_len > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) {
++    // should never happen
++    dtls_warn("psk identity hint is too long\n");
++    return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
++  }
++
++  // psk_identity_hint
++  dtls_int_to_uint16(p, psk_hint_len);
++  p += sizeof(uint16);
++
++  memcpy(p, psk_hint, psk_hint_len);
++  p += psk_hint_len;
++
++  /* ServerECDHParams. */
++  /* ECCurveType curve_type: named_curve */
++  dtls_int_to_uint8(p, TLS_EC_CURVE_TYPE_NAMED_CURVE);
++  p += sizeof(uint8);
++
++  /* NamedCurve namedcurve: secp256r1 */
++  dtls_int_to_uint16(p, TLS_EXT_ELLIPTIC_CURVES_SECP256R1);
++  p += sizeof(uint16);
++
++  dtls_int_to_uint8(p, 1 + 2 * DTLS_EC_KEY_SIZE);
++  p += sizeof(uint8);
++
++  /* This should be an uncompressed point, but I do not have access to the spec. */
++  dtls_int_to_uint8(p, 4);
++  p += sizeof(uint8);
++
++  /* store the pointer to the x component of the pub key and make space */
++  ephemeral_pub_x = p;
++  p += DTLS_EC_KEY_SIZE;
++
++  /* store the pointer to the y component of the pub key and make space */
++  ephemeral_pub_y = p;
++  p += DTLS_EC_KEY_SIZE;
++
++  dtls_ecdsa_generate_key(config->keyx.ecc.own_eph_priv,
++              ephemeral_pub_x, ephemeral_pub_y,
++              DTLS_EC_KEY_SIZE);
++
++  assert(p - buf <= sizeof(buf));
++
++  return dtls_send_handshake_msg(ctx, peer, DTLS_HT_SERVER_KEY_EXCHANGE,
++                               buf, p - buf);
++}
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
++
+ #ifdef DTLS_PSK
+ static int
+ dtls_send_server_key_exchange_psk(dtls_context_t *ctx, dtls_peer_t *peer,
+@@ -2207,6 +2388,7 @@ dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
+   int res;
+   int ecdsa;
+   int ecdh_anon;
++  int ecdhe_psk;
+   res = dtls_send_server_hello(ctx, peer);
+@@ -2217,6 +2399,7 @@ dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
+   ecdsa = is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher);
+   ecdh_anon = is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher);
++  ecdhe_psk = is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(peer->handshake_params->cipher);
+ #ifdef DTLS_ECC
+   if(ecdh_anon) {
+@@ -2261,7 +2444,31 @@ dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
+     }
+   }
+ #endif /* DTLS_ECC */
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++  else if(ecdhe_psk) {
++    unsigned char psk_hint[DTLS_PSK_MAX_CLIENT_IDENTITY_LEN];
++    int psk_len;
++
++    /* The identity hint is optional, therefore we ignore the result
++     * and check psk only. */
++    psk_len = CALL(ctx, get_psk_info, &peer->session, DTLS_PSK_HINT,
++             NULL, 0, psk_hint, DTLS_PSK_MAX_CLIENT_IDENTITY_LEN);
++    if (psk_len < 0) {
++      dtls_debug("dtls_server_hello: cannot create ServerKeyExchange\n");
++      return psk_len;
++    }
++
++    if (psk_len > 0) {
++      res = dtls_send_server_key_exchange_ecdhe_psk(ctx, peer, psk_hint, (size_t)psk_len);
++
++      if (res < 0) {
++        dtls_debug("dtls_server_hello(with ECDHE): cannot prepare Server Key Exchange record\n");
++        return res;
++      }
++    }
++  }
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+ #ifdef DTLS_PSK
+   if (is_tls_psk_with_aes_128_ccm_8(peer->handshake_params->cipher)) {
+     unsigned char psk_hint[DTLS_PSK_MAX_CLIENT_IDENTITY_LEN];
+@@ -2308,7 +2515,11 @@ dtls_send_ccs(dtls_context_t *ctx, dtls_peer_t *peer) {
+ static int
+ dtls_send_client_key_exchange(dtls_context_t *ctx, dtls_peer_t *peer)
+ {
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++  uint8 buf[DTLS_CKXEC_LENGTH + 2 + DTLS_PSK_MAX_CLIENT_IDENTITY_LEN];
++#else
+   uint8 buf[DTLS_CKXEC_LENGTH];
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+   uint8 client_id[DTLS_PSK_MAX_CLIENT_IDENTITY_LEN];
+   uint8 *p;
+   dtls_handshake_parameters_t *handshake = peer->handshake_params;
+@@ -2368,6 +2579,60 @@ dtls_send_client_key_exchange(dtls_context_t *ctx, dtls_peer_t *peer)
+     break;
+   }
+ #endif /* DTLS_ECC */
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++  case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256: {
++      int psk_len;
++      uint8 *ephemeral_pub_x;
++      uint8 *ephemeral_pub_y;
++
++    /* Please see Session 2, RFC 5489.
++         struct {
++            select (KeyExchangeAlgorithm) {
++                // other cases for rsa, diffie_hellman, etc.
++                case ec_diffie_hellman_psk:
++                    opaque psk_identity<0..2^16-1>;
++                    ClientECDiffieHellmanPublic public;
++            } exchange_keys;
++        } ClientKeyExchange;
++    */
++
++    psk_len = CALL(ctx, get_psk_info, &peer->session, DTLS_PSK_IDENTITY,
++               NULL, 0,
++               client_id,
++               sizeof(client_id));
++    if (psk_len < 0) {
++      dtls_crit("no psk identity set in kx\n");
++      return psk_len;
++    }
++
++    if (psk_len + sizeof(uint16) > DTLS_CKXEC_LENGTH) {
++      dtls_warn("the psk identity is too long\n");
++      return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
++    }
++
++    dtls_int_to_uint16(p, psk_len);
++    p += sizeof(uint16);
++
++    memcpy(p, client_id, psk_len);
++    p += psk_len;
++
++    dtls_int_to_uint8(p, 1 + 2 * DTLS_EC_KEY_SIZE);
++    p += sizeof(uint8);
++
++    dtls_int_to_uint8(p, 4);
++    p += sizeof(uint8);
++
++    ephemeral_pub_x = p;
++    p += DTLS_EC_KEY_SIZE;
++    ephemeral_pub_y = p;
++    p += DTLS_EC_KEY_SIZE;
++
++    dtls_ecdsa_generate_key(peer->handshake_params->keyx.ecc.own_eph_priv,
++                          ephemeral_pub_x, ephemeral_pub_y,
++                          DTLS_EC_KEY_SIZE);
++    break;
++  }
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+   default:
+     dtls_crit("cipher not supported\n");
+     return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+@@ -2457,6 +2722,7 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
+   int psk = 0;
+   int ecdsa = 0;
+   int ecdh_anon = 0;
++  int ecdhe_psk = 0;
+   dtls_handshake_parameters_t *handshake = peer->handshake_params;
+   dtls_tick_t now;
+@@ -2471,14 +2737,18 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
+       case TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256:
+         ecdh_anon = is_ecdh_anon_supported(ctx);
+         break;
++      case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256:
++        ecdhe_psk = is_ecdhe_psk_supported(ctx);
++        break;
+       default:
+         psk = is_psk_supported(ctx);
+         ecdsa = is_ecdsa_supported(ctx, 1);
+         ecdh_anon = is_ecdh_anon_supported(ctx);
++        ecdhe_psk = is_ecdhe_psk_supported(ctx);
+         break;
+    }
+-  cipher_size = 2 + (ecdsa ? 2 : 0) + (psk ? 2 : 0) + (ecdh_anon ? 2 : 0);
++  cipher_size = 2 + (ecdsa ? 2 : 0) + (psk ? 2 : 0) + (ecdh_anon ? 2 : 0) + (ecdhe_psk ? 2 : 0);
+   extension_size = (ecdsa) ? (2 + 6 + 6 + 8 + 6) : 0;
+   if (cipher_size == 0) {
+@@ -2533,6 +2803,10 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
+     dtls_int_to_uint16(p, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
+     p += sizeof(uint16);
+   }
++  if (ecdhe_psk) {
++      dtls_int_to_uint16(p, TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);
++      p += sizeof(uint16);
++  }
+   /* compression method */
+   dtls_int_to_uint8(p, 1);
+@@ -2900,8 +3174,97 @@ check_server_key_exchange_ecdh(dtls_context_t *ctx,
+   return 0;
+ }
+-
+ #endif /* DTLS_ECC */
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++check_server_key_exchange_ecdhe_psk(dtls_context_t *ctx,
++                            dtls_peer_t *peer,
++                            uint8 *data, size_t data_length)
++{
++  dtls_handshake_parameters_t *config = peer->handshake_params;
++  uint16_t psk_len = 0;
++
++  /* ServerKeyExchange
++    * Please see Session 2, RFC 5489.
++
++         struct {
++          select (KeyExchangeAlgorithm) {
++              //other cases for rsa, diffie_hellman, etc.
++              case ec_diffie_hellman_psk:  // NEW
++                  opaque psk_identity_hint<0..2^16-1>;
++                  ServerECDHParams params;
++          };
++      } ServerKeyExchange; */
++
++  update_hs_hash(peer, data, data_length);
++
++  assert(is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(config->cipher));
++
++  data += DTLS_HS_LENGTH;
++
++  psk_len = dtls_uint16_to_int(data);
++  data += sizeof(uint16);
++
++  if (psk_len != data_length - DTLS_HS_LENGTH - DTLS_SKEXEC_ECDH_ANON_LENGTH - sizeof(uint16)) {
++    dtls_warn("the length of the server identity hint is worng\n");
++    return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
++  }
++
++  if (psk_len > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) {
++    dtls_warn("please use a smaller server identity hint\n");
++    return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
++  }
++
++  // store the psk_identity_hint in config->keyx.psk for later use
++  config->keyx.psk.id_length = psk_len;
++  memcpy(config->keyx.psk.identity, data, psk_len);
++
++  data += psk_len;
++  data_length -= psk_len;
++
++  if (data_length < DTLS_HS_LENGTH + DTLS_SKEXEC_ECDH_ANON_LENGTH) {
++    dtls_alert("the packet length does not match the expected\n");
++    return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
++  }
++
++  if (dtls_uint8_to_int(data) != TLS_EC_CURVE_TYPE_NAMED_CURVE) {
++    dtls_alert("Only named curves supported\n");
++    return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
++  }
++  data += sizeof(uint8);
++  data_length -= sizeof(uint8);
++
++  if (dtls_uint16_to_int(data) != TLS_EXT_ELLIPTIC_CURVES_SECP256R1) {
++    dtls_alert("secp256r1 supported\n");
++    return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
++  }
++  data += sizeof(uint16);
++  data_length -= sizeof(uint16);
++
++  if (dtls_uint8_to_int(data) != 1 + 2 * DTLS_EC_KEY_SIZE) {
++    dtls_alert("expected 65 bytes long public point\n");
++    return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
++  }
++  data += sizeof(uint8);
++  data_length -= sizeof(uint8);
++
++  if (dtls_uint8_to_int(data) != 4) {
++    dtls_alert("expected uncompressed public point\n");
++    return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
++  }
++  data += sizeof(uint8);
++  data_length -= sizeof(uint8);
++
++  memcpy(config->keyx.ecc.other_eph_pub_x, data, sizeof(config->keyx.ecc.other_eph_pub_x));
++  data += sizeof(config->keyx.ecc.other_eph_pub_x);
++  data_length -= sizeof(config->keyx.ecc.other_eph_pub_x);
++
++  memcpy(config->keyx.ecc.other_eph_pub_y, data, sizeof(config->keyx.ecc.other_eph_pub_y));
++  data += sizeof(config->keyx.ecc.other_eph_pub_y);
++  data_length -= sizeof(config->keyx.ecc.other_eph_pub_y);
++
++  return 0;
++}
++#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+ #ifdef DTLS_PSK
+ static int
+@@ -3113,7 +3476,8 @@ decrypt_verify(dtls_peer_t *peer, uint8 *packet, size_t length,
+   if (security->cipher == TLS_NULL_WITH_NULL_NULL) {
+     /* no cipher suite selected */
+     return clen;
+-  } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(security->cipher)) {
++  } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(security->cipher) ||
++             is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(security->cipher)) {
+     unsigned char nonce[DTLS_CBC_IV_LENGTH];
+@@ -3169,17 +3533,17 @@ decrypt_verify(dtls_peer_t *peer, uint8 *packet, size_t length,
+                      dtls_kb_remote_write_key(security, peer->role),
+                      dtls_kb_key_size(security, peer->role),
+                      A_DATA, A_DATA_LEN,
+-                     security->cipher);
++                     security->cipher);
+   }
+   if (clen < 0)
+     dtls_warn("decryption failed\n");
+   else {
+ #ifndef NDEBUG
+-      dtls_debug("decrypt_verify(): found %i bytes cleartext\n", clen);
++    dtls_debug("decrypt_verify(): found %i bytes cleartext\n", clen);
+ #endif
+-      dtls_security_params_free_other(peer);
+-      dtls_debug_dump("cleartext", *cleartext, clen);
++    dtls_security_params_free_other(peer);
++    dtls_debug_dump("cleartext", *cleartext, clen);
+   }
+   return clen;
+@@ -3282,7 +3646,8 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, session_t *session,
+     }
+     if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher))
+       peer->state = DTLS_STATE_WAIT_SERVERCERTIFICATE; //ecdsa
+-    else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher))
++    else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher) ||
++        is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(peer->handshake_params->cipher))
+         peer->state = DTLS_STATE_WAIT_SERVERKEYEXCHANGE; //ecdh
+     else
+       peer->state = DTLS_STATE_WAIT_SERVERHELLODONE; //psk
+@@ -3329,6 +3694,16 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, session_t *session,
+       err = check_server_key_exchange_ecdh(ctx, peer, data, data_length);
+     }
+ #endif /* DTLS_ECC */
++
++#if defined(DTLS_PSK) && defined(DTLS_ECC)
++    if (is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(peer->handshake_params->cipher)) {
++        if (state != DTLS_STATE_WAIT_SERVERKEYEXCHANGE) {
++          return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
++        }
++      err = check_server_key_exchange_ecdhe_psk(ctx, peer, data, data_length);
++    }
++#endif defined(DTLS_PSK) && defined(DTLS_ECC)
++
+ #ifdef DTLS_PSK
+     if (is_tls_psk_with_aes_128_ccm_8(peer->handshake_params->cipher)) {
+       if (state != DTLS_STATE_WAIT_SERVERHELLODONE) {
+diff --git a/extlibs/tinydtls/global.h b/extlibs/tinydtls/global.h
+index 169c726..8b3c518 100644
+--- a/extlibs/tinydtls/global.h
++++ b/extlibs/tinydtls/global.h
+@@ -75,6 +75,7 @@ typedef enum {
+   TLS_NULL_WITH_NULL_NULL = 0x0000,   /**< NULL cipher  */
+   TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 = 0xC018, /**< see RFC 4492 */
+   TLS_PSK_WITH_AES_128_CCM_8 = 0xC0A8, /**< see RFC 6655 */
++  TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 = 0xC037, /**< see RFC 5489 */
+   TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xC0AE /**< see RFC 7251 */
+ } dtls_cipher_t;
+diff --git a/extlibs/tinydtls/tests/dtls-client.c b/extlibs/tinydtls/tests/dtls-client.c
+index dfc822a..dfd34c8 100644
+--- a/extlibs/tinydtls/tests/dtls-client.c
++++ b/extlibs/tinydtls/tests/dtls-client.c
+@@ -311,7 +311,8 @@ usage( const char *program, const char *version) {
+           "\t-c num\t\tcipher suite (default: 1)\n"
+           "\t\t\t1: TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 \n"
+           "\t\t\t2: TLS_PSK_WITH_AES_128_CCM_8\n"
+-          "\t\t\t3: TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8\n",
++          "\t\t\t3: TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8\n"
++          "\t\t\t4: TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256\n",
+          program, version, program, DEFAULT_PORT);
+ }
+@@ -430,6 +431,11 @@ main(int argc, char **argv) {
+           selected_cipher = TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ;
+           ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
+       }
++      else if( strcmp(optarg, "4") == 0)
++      {
++          selected_cipher = TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256;
++          ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
++      }
+       break;
+     default:
+       usage(argv[0], dtls_package_version());
+-- 
+1.7.9.5
+
diff --git a/extlibs/tinydtls/0001-Fix-the-wrong-implementation-about-the-anonymous-cip.patch b/extlibs/tinydtls/0001-Fix-the-wrong-implementation-about-the-anonymous-cip.patch
new file mode 100644 (file)
index 0000000..e2b8e65
--- /dev/null
@@ -0,0 +1,690 @@
+From 1ee27820ccad59423711c83fb01ff58939511f3b Mon Sep 17 00:00:00 2001
+From: Sachin Agrawal <sachin.agrawal@intel.com>
+Date: Mon, 29 Jun 2015 22:26:21 -0700
+Subject: [PATCH 1/1] Fix the wrong implementation about the anonymous cipher
+ suite of tinydtls. (NOTE : This patch has been modified
+ based on RFC 5246)
+
+1. IV for CBC block operation
+   - Apply the random IV for CBC block operations according to section 6.2.3.2 of RFC 5246.
+
+2. MAC calculation
+   - Apply HMAC for DTLS MAC calculation according to section 6.2.3.1 of RFC 5246.
+
+3. CBC padding
+   - Apply PKCS#5 padding for CBC block cipher accroding to section 6.2.3.2 of RFC 5246.
+
+4. Change the cipher suite name TLS_ECDH_anon_WITH_AES_128_CBC_SHA
+   to TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256.
+
+5. Fix the minor bug in dtls sample.
+
+Change-Id: I8783caa6ac04fe2d46e242efe56e3205646b1038
+Signed-off-by: leechul <chuls.lee@samsung.com>
+Signed-off-by: Sachin Agrawal <sachin.agrawal@intel.com>
+---
+ extlibs/tinydtls/crypto.c                          |  100 +++++++++++++-----
+ extlibs/tinydtls/crypto.h                          |    1 +
+ extlibs/tinydtls/dtls.c                            |  111 +++++++++++++++-----
+ extlibs/tinydtls/dtls.h                            |    6 +-
+ extlibs/tinydtls/global.h                          |    2 +-
+ extlibs/tinydtls/tests/dtls-client.c               |    8 +-
+ extlibs/tinydtls/tests/dtls-server.c               |    8 +-
+ resource/csdk/connectivity/api/cainterface.h       |    4 +-
+ resource/csdk/connectivity/inc/caadapternetdtls.h  |    2 +-
+ .../src/adapter_util/caadapternetdtls.c            |    2 +-
+ .../provisioning/src/provisioningmanager.c         |    2 +-
+ 11 files changed, 180 insertions(+), 66 deletions(-)
+
+diff --git a/extlibs/tinydtls/crypto.c b/extlibs/tinydtls/crypto.c
+index 5082535..3fbb993 100644
+--- a/extlibs/tinydtls/crypto.c
++++ b/extlibs/tinydtls/crypto.c
+@@ -58,6 +58,7 @@
+ #include "sha2/sha2.h"
+ #include "prng.h"
+ #include "netq.h"
++#include "hmac.h"
+ #ifndef WITH_CONTIKI
+ #include <pthread.h>
+@@ -329,6 +330,7 @@ dtls_ccm_decrypt(aes128_t *ccm_ctx, const unsigned char *src,
+ static size_t
+ dtls_cbc_encrypt(aes128_t *aes_ctx,
++                 unsigned char *key, size_t keylen,
+                  const unsigned char *iv,
+                  const unsigned char *src, size_t srclen,
+                  unsigned char *buf) {
+@@ -336,18 +338,35 @@ dtls_cbc_encrypt(aes128_t *aes_ctx,
+     unsigned char cbc[DTLS_BLK_LENGTH];
+     unsigned char tmp[DTLS_BLK_LENGTH];
+     unsigned char *pos;
+-    dtls_hash_ctx shactx;
++    const unsigned char *dtls_hdr = NULL;
+     int i, j;
+     int blocks;
++    dtls_hmac_context_t* hmac_ctx = NULL;
++    int paddinglen = 0;
+     pos = buf;
+-    dtls_hash_init(&shactx);
+-    dtls_hash_update(&shactx, src, srclen);
+-    dtls_hash_finalize(pos + srclen, &shactx);
++    dtls_hdr = src - DTLS_CBC_IV_LENGTH - sizeof(dtls_record_header_t);
++
++    //Calculate MAC : Append the MAC code to end of content
++    hmac_ctx = dtls_hmac_new(key, keylen);
++    dtls_mac(hmac_ctx,
++             dtls_hdr,
++             src, srclen,
++             buf + srclen);
++    dtls_hmac_free(hmac_ctx);
++    
++    dtls_debug_dump("[MAC]",
++                    buf + srclen,
++                    DTLS_HMAC_DIGEST_SIZE);
++
++    paddinglen = DTLS_BLK_LENGTH - ((srclen + DTLS_HMAC_DIGEST_SIZE) % DTLS_BLK_LENGTH);
++    
++    //TLS padding
++    memset(buf + (srclen + DTLS_HMAC_DIGEST_SIZE), paddinglen - 1, paddinglen);
+     memcpy(cbc, iv, DTLS_BLK_LENGTH);
+-    blocks = (srclen + SHA256_DIGEST_LENGTH) / DTLS_BLK_LENGTH;
++    blocks = (srclen + DTLS_HMAC_DIGEST_SIZE + paddinglen) / DTLS_BLK_LENGTH;
+     for (i = 0; i < blocks; i++) {
+         for (j = 0; j < DTLS_BLK_LENGTH; j++) {
+@@ -360,14 +379,17 @@ dtls_cbc_encrypt(aes128_t *aes_ctx,
+         pos += DTLS_BLK_LENGTH;
+     }
+-    dtls_debug_dump("Encrypted Data:", buf, srclen + SHA256_DIGEST_LENGTH);
+-
+-    return srclen + SHA256_DIGEST_LENGTH;
++    dtls_debug_dump("[Encrypted Data]",
++                    buf,
++                    srclen + DTLS_HMAC_DIGEST_SIZE + paddinglen);
++    
++    return srclen + DTLS_HMAC_DIGEST_SIZE + paddinglen;
+ }
+ static size_t
+ dtls_cbc_decrypt(aes128_t *aes_ctx,
++                 unsigned char *key, size_t keylen,
+                  const unsigned char *iv,
+                  const unsigned char *src, size_t srclen,
+                  unsigned char *buf) {
+@@ -375,14 +397,17 @@ dtls_cbc_decrypt(aes128_t *aes_ctx,
+     unsigned char cbc[DTLS_BLK_LENGTH];
+     unsigned char tmp[DTLS_BLK_LENGTH];
+     unsigned char tmp2[DTLS_BLK_LENGTH];
+-    unsigned char msg_hash[SHA256_DIGEST_LENGTH];
++    unsigned char mac_buf[DTLS_HMAC_DIGEST_SIZE] = {0,};
++    const unsigned char *dtls_hdr = NULL;
+     unsigned char *pos;
+-    dtls_hash_ctx shactx;
+     int i, j;
+     int blocks;
++    int depaddinglen = 0;
++    dtls_hmac_context_t* hmac_ctx = NULL;
+     pos = buf;
+-    memcpy(pos, src, srclen);
++
++    dtls_hdr = src - DTLS_CBC_IV_LENGTH - sizeof(dtls_record_header_t);
+     memcpy(cbc, iv, DTLS_BLK_LENGTH);
+     blocks = srclen / DTLS_BLK_LENGTH;
+@@ -401,19 +426,46 @@ dtls_cbc_decrypt(aes128_t *aes_ctx,
+         pos += DTLS_BLK_LENGTH;
+     }
+-    dtls_hash_init(&shactx);
+-    dtls_hash_update(&shactx, buf, srclen - SHA256_DIGEST_LENGTH);
+-    dtls_hash_finalize(msg_hash, &shactx);
+-
+-    dtls_debug_dump("decrypted data:", buf, srclen);
++    //de-padding
++    depaddinglen = buf[srclen -1];
+-    if(memcmp(msg_hash, buf + (srclen - SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH) != 0)
++    //Calculate MAC
++    hmac_ctx = dtls_hmac_new(key, keylen);
++    if(!hmac_ctx) {
++        return -1;
++    }
++    dtls_mac(hmac_ctx, dtls_hdr, buf,
++             srclen - DTLS_HMAC_DIGEST_SIZE - depaddinglen - 1,
++             mac_buf);
++    dtls_hmac_free(hmac_ctx);
++
++    dtls_debug_dump("[MAC]",
++                    mac_buf,
++                    DTLS_HMAC_DIGEST_SIZE);
++    dtls_debug_dump("[Decrypted data]",
++                    buf,
++                    srclen - DTLS_HMAC_DIGEST_SIZE - depaddinglen - 1);
++
++    //verify the MAC
++    if(memcmp(mac_buf,
++              buf + (srclen - DTLS_HMAC_DIGEST_SIZE - depaddinglen - 1),
++              DTLS_HMAC_DIGEST_SIZE) != 0)
+     {
+-        dtls_warn("message is broken\n");
++        dtls_crit("Failed to verification of MAC\n");
+         return -1;
+     }
+-    return srclen - SHA256_DIGEST_LENGTH;
++    //verify the padding bytes
++    for (i =0; i < depaddinglen; i++)
++    {
++        if (buf[srclen - depaddinglen - 1 + i] != depaddinglen)
++        {
++            dtls_crit("Failed to verify padding bytes\n");
++            return -1;
++        }
++    }
++
++    return srclen - DTLS_HMAC_DIGEST_SIZE - depaddinglen - 1;
+ }
+ #ifdef DTLS_PSK
+@@ -523,8 +575,6 @@ void
+ dtls_ecdsa_create_sig_hash(const unsigned char *priv_key, size_t key_size,
+                          const unsigned char *sign_hash, size_t sign_hash_size,
+                          uint32_t point_r[9], uint32_t point_s[9]) {
+-  int ret;
+-
+   uint8_t privateKey[32];
+   uint8_t hashValue[32];
+   uint8_t sign[64];
+@@ -615,7 +665,7 @@ dtls_encrypt(const unsigned char *src, size_t length,
+         memmove(buf, src, length);
+       ret = dtls_ccm_encrypt(&ctx->data, src, length, buf, nounce, aad, la);
+   }
+-  if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA) {
++  if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256) {
+       ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
+       if (ret < 0) {
+         /* cleanup everything in case the key has the wrong size */
+@@ -625,7 +675,7 @@ dtls_encrypt(const unsigned char *src, size_t length,
+       if (src != buf)
+         memmove(buf, src, length);
+-      ret = dtls_cbc_encrypt(&ctx->data, nounce, src, length, buf);
++      ret = dtls_cbc_encrypt(&ctx->data, key, keylen, nounce, src, length, buf);
+   }
+ error:
+@@ -658,7 +708,7 @@ dtls_decrypt(const unsigned char *src, size_t length,
+       ret = dtls_ccm_decrypt(&ctx->data, src, length, buf, nounce, aad, la);
+   }
+-  if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA) {
++  if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256) {
+       ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
+       if (ret < 0) {
+         /* cleanup everything in case the key has the wrong size */
+@@ -668,7 +718,7 @@ dtls_decrypt(const unsigned char *src, size_t length,
+       if (src != buf)
+         memmove(buf, src, length);
+-      ret = dtls_cbc_decrypt(&ctx->data, nounce, src, length, buf);
++      ret = dtls_cbc_decrypt(&ctx->data, key, keylen, nounce, src, length, buf);
+     }
+ error:
+diff --git a/extlibs/tinydtls/crypto.h b/extlibs/tinydtls/crypto.h
+index dd13ffa..a81d306 100644
+--- a/extlibs/tinydtls/crypto.h
++++ b/extlibs/tinydtls/crypto.h
+@@ -46,6 +46,7 @@
+ #define DTLS_BLK_LENGTH        16 /* AES-128 */
+ #define DTLS_MAC_LENGTH        DTLS_HMAC_DIGEST_SIZE
+ #define DTLS_IV_LENGTH         4  /* length of nonce_explicit */
++#define DTLS_CBC_IV_LENGTH     16
+ /** 
+  * Maximum size of the generated keyblock. Note that MAX_KEYBLOCK_LENGTH must 
+diff --git a/extlibs/tinydtls/dtls.c b/extlibs/tinydtls/dtls.c
+index 41e68a5..b5b8fd1 100644
+--- a/extlibs/tinydtls/dtls.c
++++ b/extlibs/tinydtls/dtls.c
+@@ -496,11 +496,11 @@ static inline int is_tls_psk_with_aes_128_ccm_8(dtls_cipher_t cipher)
+ #endif /* DTLS_PSK */
+ }
+-/** returns true if the cipher matches TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
+-static inline int is_tls_ecdh_anon_with_aes_128_cbc_sha(dtls_cipher_t cipher)
++/** returns true if the cipher matches TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 */
++static inline int is_tls_ecdh_anon_with_aes_128_cbc_sha_256(dtls_cipher_t cipher)
+ {
+ #ifdef DTLS_ECC
+-    return cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
++    return cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256;
+ #else
+     return 0;
+ #endif
+@@ -570,7 +570,7 @@ known_cipher(dtls_context_t *ctx, dtls_cipher_t code, int is_client) {
+   return (psk && is_tls_psk_with_aes_128_ccm_8(code)) ||
+        (ecdsa && is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(code)) ||
+-       (ecdh_anon && is_tls_ecdh_anon_with_aes_128_cbc_sha(code));
++       (ecdh_anon && is_tls_ecdh_anon_with_aes_128_cbc_sha_256(code));
+ }
+ /**
+@@ -719,7 +719,7 @@ calculate_key_block(dtls_context_t *ctx,
+ #endif /* DTLS_PSK */
+ #ifdef DTLS_ECC
+   case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
+-  case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: {
++  case TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256: {
+     pre_master_len = dtls_ecdh_pre_master_secret(handshake->keyx.ecc.own_eph_priv,
+                                                handshake->keyx.ecc.other_eph_pub_x,
+                                                handshake->keyx.ecc.other_eph_pub_y,
+@@ -1084,7 +1084,7 @@ check_client_keyexchange(dtls_context_t *ctx,
+ #ifdef DTLS_ECC
+   if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher) ||
+-       is_tls_ecdh_anon_with_aes_128_cbc_sha(handshake->cipher) ) {
++       is_tls_ecdh_anon_with_aes_128_cbc_sha_256(handshake->cipher) ) {
+     if (length < DTLS_HS_LENGTH + DTLS_CKXEC_LENGTH) {
+       dtls_debug("The client key exchange is too short\n");
+@@ -1286,6 +1286,51 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
+       p += data_len_array[i];
+       res += data_len_array[i];
+     }
++  } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(security->cipher)) {
++
++    unsigned char nonce[DTLS_CBC_IV_LENGTH];
++
++    /** Add IV into body of packet in case of AES CBC mode according to RFC 5246, Section 6.2.3.2
++     *
++     *    opaque IV[SecurityParameters.record_iv_length];
++     *    block-ciphered struct {
++     *        opaque content[TLSCompressed.length];
++     *        opaque MAC[SecurityParameters.mac_length];
++     *        uint8 padding[GenericBlockCipher.padding_length];
++     *        uint8 padding_length;
++     * };
++     *
++     */
++
++    res = 0;
++    dtls_prng(nonce, DTLS_CBC_IV_LENGTH);
++    memcpy(p , nonce, DTLS_CBC_IV_LENGTH);
++    p += DTLS_CBC_IV_LENGTH;
++    res += DTLS_CBC_IV_LENGTH;
++
++    for (i = 0; i < data_array_len; i++) {
++        /* check the minimum that we need for packets that are not encrypted */
++        if (*rlen < res + DTLS_RH_LENGTH + data_len_array[i]) {
++            dtls_debug("dtls_prepare_record: send buffer too small\n");
++            return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
++        }
++
++        memcpy(p, data_array[i], data_len_array[i]);
++        p += data_len_array[i];
++        res += data_len_array[i];
++     }
++
++     res = dtls_encrypt(start + DTLS_CBC_IV_LENGTH, res - DTLS_CBC_IV_LENGTH,
++               start + DTLS_CBC_IV_LENGTH, nonce,
++               dtls_kb_local_write_key(security, peer->role),
++               dtls_kb_key_size(security, peer->role),
++               NULL, 0,
++               security->cipher);
++     if (res < 0)
++       return res;
++
++     res += DTLS_CBC_IV_LENGTH;
++
+   } else { /* TLS_PSK_WITH_AES_128_CCM_8 or TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 */   
+     /** 
+      * length of additional_data for the AEAD cipher which consists of
+@@ -1299,8 +1344,6 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
+       dtls_debug("dtls_prepare_record(): encrypt using TLS_PSK_WITH_AES_128_CCM_8\n");
+     } else if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(security->cipher)) {
+       dtls_debug("dtls_prepare_record(): encrypt using TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8\n");
+-    } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha(security->cipher)) {
+-        dtls_debug("dtls_prepare_record() : encrypt using TLS_ECDH_anon_WITH_AES_128_CBC_SHA\n");
+     } else {
+       dtls_debug("dtls_prepare_record(): encrypt using unknown cipher\n");
+     }
+@@ -1363,7 +1406,7 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
+     memset(nonce, 0, DTLS_CCM_BLOCKSIZE);
+     memcpy(nonce, dtls_kb_local_iv(security, peer->role),
+-         dtls_kb_iv_size(security, peer->role));
++        dtls_kb_iv_size(security, peer->role));
+     memcpy(nonce + dtls_kb_iv_size(security, peer->role), start, 8); /* epoch + seq_num */
+     dtls_debug_dump("nonce:", nonce, DTLS_CCM_BLOCKSIZE);
+@@ -1378,7 +1421,8 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
+     memcpy(A_DATA, &DTLS_RECORD_HEADER(sendbuf)->epoch, 8); /* epoch and seq_num */
+     memcpy(A_DATA + 8,  &DTLS_RECORD_HEADER(sendbuf)->content_type, 3); /* type and version */
+     dtls_int_to_uint16(A_DATA + 11, res - 8); /* length */
+-    
++
++
+     res = dtls_encrypt(start + 8, res - 8, start + 8, nonce,
+                dtls_kb_local_write_key(security, peer->role),
+                dtls_kb_key_size(security, peer->role),
+@@ -1388,7 +1432,7 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
+     if (res < 0)
+       return res;
+-    res += 8;                 /* increment res by size of nonce_explicit */
++    res += 8; /* increment res by size of nonce_explicit */
+     dtls_debug_dump("message:", start, res);
+   }
+@@ -2172,7 +2216,7 @@ dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
+   }
+   ecdsa = is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher);
+-  ecdh_anon = is_tls_ecdh_anon_with_aes_128_cbc_sha(peer->handshake_params->cipher);
++  ecdh_anon = is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher);
+ #ifdef DTLS_ECC
+   if(ecdh_anon) {
+@@ -2301,7 +2345,7 @@ dtls_send_client_key_exchange(dtls_context_t *ctx, dtls_peer_t *peer)
+ #endif /* DTLS_PSK */
+ #ifdef DTLS_ECC
+   case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
+-  case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: {
++  case TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256: {
+     uint8 *ephemeral_pub_x;
+     uint8 *ephemeral_pub_y;
+@@ -2424,7 +2468,7 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
+       case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
+         ecdsa = is_ecdsa_supported(ctx, 1);
+         break;
+-      case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
++      case TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256:
+         ecdh_anon = is_ecdh_anon_supported(ctx);
+         break;
+       default:
+@@ -2478,7 +2522,7 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
+   p += sizeof(uint16);
+   if (ecdh_anon) {
+-    dtls_int_to_uint16(p, TLS_ECDH_anon_WITH_AES_128_CBC_SHA);
++    dtls_int_to_uint16(p, TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256);
+     p += sizeof(uint16);
+   }
+   if (psk) {
+@@ -2809,7 +2853,7 @@ check_server_key_exchange_ecdh(dtls_context_t *ctx,
+   update_hs_hash(peer, data, data_length);
+-  assert(is_tls_ecdh_anon_with_aes_128_cbc_sha(config->cipher));
++  assert(is_tls_ecdh_anon_with_aes_128_cbc_sha_256(config->cipher));
+   data += DTLS_HS_LENGTH;
+@@ -3069,6 +3113,23 @@ decrypt_verify(dtls_peer_t *peer, uint8 *packet, size_t length,
+   if (security->cipher == TLS_NULL_WITH_NULL_NULL) {
+     /* no cipher suite selected */
+     return clen;
++  } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(security->cipher)) {
++
++    unsigned char nonce[DTLS_CBC_IV_LENGTH];
++
++    if (clen < (DTLS_CBC_IV_LENGTH + DTLS_HMAC_DIGEST_SIZE))          /* need at least IV and MAC */
++      return -1;
++
++    memcpy(nonce, *cleartext , DTLS_CBC_IV_LENGTH);
++    clen -= DTLS_CBC_IV_LENGTH;
++    *cleartext += DTLS_CBC_IV_LENGTH ;
++
++    clen = dtls_decrypt(*cleartext, clen, *cleartext, nonce,
++                     dtls_kb_remote_write_key(security, peer->role),
++                     dtls_kb_key_size(security, peer->role),
++                     NULL, 0,
++                     security->cipher);
++
+   } else { /* TLS_PSK_WITH_AES_128_CCM_8 or TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 */
+     /** 
+      * length of additional_data for the AEAD cipher which consists of
+@@ -3083,7 +3144,7 @@ decrypt_verify(dtls_peer_t *peer, uint8 *packet, size_t length,
+     memset(nonce, 0, DTLS_CCM_BLOCKSIZE);
+     memcpy(nonce, dtls_kb_remote_iv(security, peer->role),
+-         dtls_kb_iv_size(security, peer->role));
++        dtls_kb_iv_size(security, peer->role));
+     /* read epoch and seq_num from message */
+     memcpy(nonce + dtls_kb_iv_size(security, peer->role), *cleartext, 8);
+@@ -3108,17 +3169,19 @@ decrypt_verify(dtls_peer_t *peer, uint8 *packet, size_t length,
+                      dtls_kb_remote_write_key(security, peer->role),
+                      dtls_kb_key_size(security, peer->role),
+                      A_DATA, A_DATA_LEN,
+-               security->cipher);
+-    if (clen < 0)
+-      dtls_warn("decryption failed\n");
+-    else {
++                     security->cipher);
++  }
++
++  if (clen < 0)
++    dtls_warn("decryption failed\n");
++  else {
+ #ifndef NDEBUG
+       dtls_debug("decrypt_verify(): found %i bytes cleartext\n", clen);
+ #endif
+       dtls_security_params_free_other(peer);
+       dtls_debug_dump("cleartext", *cleartext, clen);
+-    }
+   }
++
+   return clen;
+ }
+@@ -3219,7 +3282,7 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, session_t *session,
+     }
+     if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher))
+       peer->state = DTLS_STATE_WAIT_SERVERCERTIFICATE; //ecdsa
+-    else if (is_tls_ecdh_anon_with_aes_128_cbc_sha(peer->handshake_params->cipher))
++    else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher))
+         peer->state = DTLS_STATE_WAIT_SERVERKEYEXCHANGE; //ecdh
+     else
+       peer->state = DTLS_STATE_WAIT_SERVERHELLODONE; //psk
+@@ -3259,7 +3322,7 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, session_t *session,
+       err = check_server_key_exchange_ecdsa(ctx, peer, data, data_length);
+     }
+-    if (is_tls_ecdh_anon_with_aes_128_cbc_sha(peer->handshake_params->cipher)) {
++    if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher)) {
+       if (state != DTLS_STATE_WAIT_SERVERKEYEXCHANGE) {
+         return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
+       }
+diff --git a/extlibs/tinydtls/dtls.h b/extlibs/tinydtls/dtls.h
+index a2ab86e..7d2bc19 100644
+--- a/extlibs/tinydtls/dtls.h
++++ b/extlibs/tinydtls/dtls.h
+@@ -238,7 +238,7 @@ typedef struct dtls_context_t {
+   dtls_handler_t *h;          /**< callback handlers */
+-  dtls_cipher_enable_t is_anon_ecdh_eabled;    /**< enable/disable the TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
++  dtls_cipher_enable_t is_anon_ecdh_eabled;    /**< enable/disable the TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 */
+   dtls_cipher_t selected_cipher; /**< selected ciper suite for handshake */
+@@ -268,7 +268,7 @@ static inline void dtls_set_handler(dtls_context_t *ctx, dtls_handler_t *h) {
+ }
+  /**
+-  * @brief Enabling the TLS_ECDH_anon_WITH_AES_128_CBC_SHA
++  * @brief Enabling the TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256
+   *
+   * @param ctx              The DTLS context to use.
+   * @param is_enable    DTLS_CIPHER_ENABLE(1) or DTLS_CIPHER_DISABLE(0)
+@@ -279,7 +279,7 @@ void dtls_enables_anon_ecdh(dtls_context_t* ctx, dtls_cipher_enable_t is_enable)
+  * @brief Select the cipher suite for handshake
+  *
+  * @param ctx              The DTLS context to use.
+- * @param cipher         TLS_ECDH_anon_WITH_AES_128_CBC_SHA (0xC018)
++ * @param cipher         TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 (0xC018)
+  *                                  TLS_PSK_WITH_AES_128_CCM_8 (0xX0A8)
+  *                                  TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 (0xC0AE)
+  */
+diff --git a/extlibs/tinydtls/global.h b/extlibs/tinydtls/global.h
+index 441710f..169c726 100644
+--- a/extlibs/tinydtls/global.h
++++ b/extlibs/tinydtls/global.h
+@@ -73,7 +73,7 @@ typedef unsigned char uint48[6];
+ /** Known cipher suites.*/
+ typedef enum { 
+   TLS_NULL_WITH_NULL_NULL = 0x0000,   /**< NULL cipher  */
+-  TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018, /**< see RFC 4492 */
++  TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 = 0xC018, /**< see RFC 4492 */
+   TLS_PSK_WITH_AES_128_CCM_8 = 0xC0A8, /**< see RFC 6655 */
+   TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xC0AE /**< see RFC 7251 */
+ } dtls_cipher_t;
+diff --git a/extlibs/tinydtls/tests/dtls-client.c b/extlibs/tinydtls/tests/dtls-client.c
+index 35521e9..dfc822a 100644
+--- a/extlibs/tinydtls/tests/dtls-client.c
++++ b/extlibs/tinydtls/tests/dtls-client.c
+@@ -309,7 +309,7 @@ usage( const char *program, const char *version) {
+         "\t-p port\t\tlisten on specified port (default is %d)\n"
+         "\t-v num\t\tverbosity level (default: 3)\n"
+           "\t-c num\t\tcipher suite (default: 1)\n"
+-          "\t\t\t1: TLS_ECDH_anon_WITH_AES_128_CBC_SHA \n"
++          "\t\t\t1: TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 \n"
+           "\t\t\t2: TLS_PSK_WITH_AES_128_CCM_8\n"
+           "\t\t\t3: TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8\n",
+          program, version, program, DEFAULT_PORT);
+@@ -347,7 +347,7 @@ main(int argc, char **argv) {
+   log_t log_level = DTLS_LOG_WARN;
+   int fd, result;
+   int on = 1;
+-  dtls_cipher_t selected_cipher = TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
++  dtls_cipher_t selected_cipher = TLS_NULL_WITH_NULL_NULL;
+   dtls_cipher_enable_t ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
+   int opt, res;
+   session_t dst;
+@@ -417,7 +417,7 @@ main(int argc, char **argv) {
+     case 'c':
+       if( strcmp(optarg, "1") == 0)
+       {
+-          selected_cipher = TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
++          selected_cipher = TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256;
+           ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
+       }
+       else if( strcmp(optarg, "2") == 0)
+@@ -500,7 +500,7 @@ main(int argc, char **argv) {
+   /* select cipher suite */
+   dtls_select_cipher(dtls_context, selected_cipher);
+-  /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha */
++  /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha_256 */
+   dtls_enables_anon_ecdh(dtls_context, ecdh_anon_enalbe);
+   dtls_set_handler(dtls_context, &cb);
+diff --git a/extlibs/tinydtls/tests/dtls-server.c b/extlibs/tinydtls/tests/dtls-server.c
+index d3da1a7..5893084 100644
+--- a/extlibs/tinydtls/tests/dtls-server.c
++++ b/extlibs/tinydtls/tests/dtls-server.c
+@@ -254,8 +254,8 @@ usage(const char *program, const char *version) {
+         "\t-p port\t\tlisten on specified port (default is %d)\n"
+         "\t-v num\t\tverbosity level (default: 3)\n"
+         "\t-a enable|disable\t(default: disable)\n"
+-        "\t\t\t\tenable:enable TLS_ECDH_anon_with_AES_128_CBC_SHA\n"
+-        "\t\t\t\tdisable:disable TLS_ECDH_anon_with_AES_128_CBC_SHA\n",
++        "\t\t\t\tenable:enable TLS_ECDH_anon_with_AES_128_CBC_SHA_256\n"
++        "\t\t\t\tdisable:disable TLS_ECDH_anon_with_AES_128_CBC_SHA_256\n",
+          program, version, program, DEFAULT_PORT);
+ }
+@@ -280,7 +280,7 @@ main(int argc, char **argv) {
+   struct timeval timeout;
+   int fd, opt, result;
+   int on = 1;
+-  int ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
++  dtls_cipher_enable_t ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
+   struct sockaddr_in6 listen_addr;
+   memset(&listen_addr, 0, sizeof(struct sockaddr_in6));
+@@ -356,7 +356,7 @@ main(int argc, char **argv) {
+   the_context = dtls_new_context(&fd);
+-  /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha */
++  /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha_256 */
+   dtls_enables_anon_ecdh(the_context, ecdh_anon_enalbe);
+   dtls_set_handler(the_context, &cb);
+diff --git a/resource/csdk/connectivity/api/cainterface.h b/resource/csdk/connectivity/api/cainterface.h
+index 760df09..2f10fd5 100644
+--- a/resource/csdk/connectivity/api/cainterface.h
++++ b/resource/csdk/connectivity/api/cainterface.h
+@@ -290,7 +290,7 @@ CAResult_t CAHandleRequestResponse();
+  * Select the cipher suite for dtls handshake
+  *
+  * @param[IN] cipher  cipher suite (Note : Make sure endianness)
+- *                               0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA
++ *                               0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256
+  *                               0xC0A8 : TLS_PSK_WITH_AES_128_CCM_8
+  *                               0xC0AE : TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+  *
+@@ -301,7 +301,7 @@ CAResult_t CAHandleRequestResponse();
+ CAResult_t CASelectCipherSuite(const uint16_t cipher);
+ /**
+- * Enable TLS_ECDH_anon_WITH_AES_128_CBC_SHA cipher suite in dtls
++ * Enable TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 cipher suite in dtls
+  *
+  * @param[IN] enable  TRUE/FALSE enables/disables anonymous cipher suite
+  *
+diff --git a/resource/csdk/connectivity/inc/caadapternetdtls.h b/resource/csdk/connectivity/inc/caadapternetdtls.h
+index f9f99d8..274321e 100644
+--- a/resource/csdk/connectivity/inc/caadapternetdtls.h
++++ b/resource/csdk/connectivity/inc/caadapternetdtls.h
+@@ -160,7 +160,7 @@ void CADTLSSetCredentialsCallback(CAGetDTLSCredentialsHandler credCallback);
+  * Select the cipher suite for dtls handshake
+  *
+  * @param[in] cipher    cipher suite
+- *                             0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA
++ *                             0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256
+  *                             0xC0A8 : TLS_PSK_WITH_AES_128_CCM_8
+  *                             0xC0AE : TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+  *
+diff --git a/resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c b/resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c
+index 8f01c06..6fd83e8 100644
+--- a/resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c
++++ b/resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c
+@@ -598,7 +598,7 @@ CAResult_t CADtlsEnableAnonECDHCipherSuite(const bool enable)
+     dtls_enables_anon_ecdh(g_caDtlsContext->dtlsContext,
+         enable == true ? DTLS_CIPHER_ENABLE : DTLS_CIPHER_DISABLE);
+     ca_mutex_unlock(g_dtlsContextMutex);
+-    OIC_LOG_V(DEBUG, NET_DTLS_TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA  is %s",
++    OIC_LOG_V(DEBUG, NET_DTLS_TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256  is %s",
+         enable ? "enabled" : "disabled");
+     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsEnablesAnonEcdh");
+diff --git a/resource/csdk/security/provisioning/src/provisioningmanager.c b/resource/csdk/security/provisioning/src/provisioningmanager.c
+index defe4e6..301614d 100644
+--- a/resource/csdk/security/provisioning/src/provisioningmanager.c
++++ b/resource/csdk/security/provisioning/src/provisioningmanager.c
+@@ -1031,7 +1031,7 @@ static SPResult updateOperationMode(unsigned short timeout, SPTargetDeviceInfo_t
+  */
+ static SPResult initiateDtlsHandshake(const SPTargetDeviceInfo_t *deviceInfo)
+ {
+-    CAResult_t caresult = CASelectCipherSuite(TLS_ECDH_anon_WITH_AES_128_CBC_SHA);
++    CAResult_t caresult = CASelectCipherSuite(TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256);
+     if (CA_STATUS_OK != caresult)
+     {
+-- 
+1.7.9.5
+
index 5082535..deaf581 100644 (file)
@@ -58,6 +58,7 @@
 #include "sha2/sha2.h"
 #include "prng.h"
 #include "netq.h"
+#include "hmac.h"
 
 #ifndef WITH_CONTIKI
 #include <pthread.h>
@@ -329,6 +330,7 @@ dtls_ccm_decrypt(aes128_t *ccm_ctx, const unsigned char *src,
 
 static size_t
 dtls_cbc_encrypt(aes128_t *aes_ctx,
+                 unsigned char *key, size_t keylen,
                  const unsigned char *iv,
                  const unsigned char *src, size_t srclen,
                  unsigned char *buf) {
@@ -336,18 +338,35 @@ dtls_cbc_encrypt(aes128_t *aes_ctx,
     unsigned char cbc[DTLS_BLK_LENGTH];
     unsigned char tmp[DTLS_BLK_LENGTH];
     unsigned char *pos;
-    dtls_hash_ctx shactx;
+    const unsigned char *dtls_hdr = NULL;
     int i, j;
     int blocks;
+    dtls_hmac_context_t* hmac_ctx = NULL;
+    int paddinglen = 0;
 
     pos = buf;
 
-    dtls_hash_init(&shactx);
-    dtls_hash_update(&shactx, src, srclen);
-    dtls_hash_finalize(pos + srclen, &shactx);
+    dtls_hdr = src - DTLS_CBC_IV_LENGTH - sizeof(dtls_record_header_t);
+
+    //Calculate MAC : Append the MAC code to end of content
+    hmac_ctx = dtls_hmac_new(key, keylen);
+    dtls_mac(hmac_ctx,
+             dtls_hdr,
+             src, srclen,
+             buf + srclen);
+    dtls_hmac_free(hmac_ctx);
+    
+    dtls_debug_dump("[MAC]",
+                    buf + srclen,
+                    DTLS_HMAC_DIGEST_SIZE);
+
+    paddinglen = DTLS_BLK_LENGTH - ((srclen + DTLS_HMAC_DIGEST_SIZE) % DTLS_BLK_LENGTH);
+    
+    //TLS padding
+    memset(buf + (srclen + DTLS_HMAC_DIGEST_SIZE), paddinglen - 1, paddinglen);
 
     memcpy(cbc, iv, DTLS_BLK_LENGTH);
-    blocks = (srclen + SHA256_DIGEST_LENGTH) / DTLS_BLK_LENGTH;
+    blocks = (srclen + DTLS_HMAC_DIGEST_SIZE + paddinglen) / DTLS_BLK_LENGTH;
 
     for (i = 0; i < blocks; i++) {
         for (j = 0; j < DTLS_BLK_LENGTH; j++) {
@@ -360,14 +379,17 @@ dtls_cbc_encrypt(aes128_t *aes_ctx,
         pos += DTLS_BLK_LENGTH;
     }
 
-    dtls_debug_dump("Encrypted Data:", buf, srclen + SHA256_DIGEST_LENGTH);
-
-    return srclen + SHA256_DIGEST_LENGTH;
+    dtls_debug_dump("[Encrypted Data]",
+                    buf,
+                    srclen + DTLS_HMAC_DIGEST_SIZE + paddinglen);
+    
+    return srclen + DTLS_HMAC_DIGEST_SIZE + paddinglen;
 }
 
 
 static size_t
 dtls_cbc_decrypt(aes128_t *aes_ctx,
+                 unsigned char *key, size_t keylen,
                  const unsigned char *iv,
                  const unsigned char *src, size_t srclen,
                  unsigned char *buf) {
@@ -375,14 +397,17 @@ dtls_cbc_decrypt(aes128_t *aes_ctx,
     unsigned char cbc[DTLS_BLK_LENGTH];
     unsigned char tmp[DTLS_BLK_LENGTH];
     unsigned char tmp2[DTLS_BLK_LENGTH];
-    unsigned char msg_hash[SHA256_DIGEST_LENGTH];
+    unsigned char mac_buf[DTLS_HMAC_DIGEST_SIZE] = {0,};
+    const unsigned char *dtls_hdr = NULL;
     unsigned char *pos;
-    dtls_hash_ctx shactx;
     int i, j;
     int blocks;
+    int depaddinglen = 0;
+    dtls_hmac_context_t* hmac_ctx = NULL;
 
     pos = buf;
-    memcpy(pos, src, srclen);
+
+    dtls_hdr = src - DTLS_CBC_IV_LENGTH - sizeof(dtls_record_header_t);
 
     memcpy(cbc, iv, DTLS_BLK_LENGTH);
     blocks = srclen / DTLS_BLK_LENGTH;
@@ -401,19 +426,46 @@ dtls_cbc_decrypt(aes128_t *aes_ctx,
         pos += DTLS_BLK_LENGTH;
     }
 
-    dtls_hash_init(&shactx);
-    dtls_hash_update(&shactx, buf, srclen - SHA256_DIGEST_LENGTH);
-    dtls_hash_finalize(msg_hash, &shactx);
-
-    dtls_debug_dump("decrypted data:", buf, srclen);
+    //de-padding
+    depaddinglen = buf[srclen -1];
 
-    if(memcmp(msg_hash, buf + (srclen - SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH) != 0)
+    //Calculate MAC
+    hmac_ctx = dtls_hmac_new(key, keylen);
+    if(!hmac_ctx) {
+        return -1;
+    }
+    dtls_mac(hmac_ctx, dtls_hdr, buf,
+             srclen - DTLS_HMAC_DIGEST_SIZE - depaddinglen - 1,
+             mac_buf);
+    dtls_hmac_free(hmac_ctx);
+
+    dtls_debug_dump("[MAC]",
+                    mac_buf,
+                    DTLS_HMAC_DIGEST_SIZE);
+    dtls_debug_dump("[Decrypted data]",
+                    buf,
+                    srclen - DTLS_HMAC_DIGEST_SIZE - depaddinglen - 1);
+
+    //verify the MAC
+    if(memcmp(mac_buf,
+              buf + (srclen - DTLS_HMAC_DIGEST_SIZE - depaddinglen - 1),
+              DTLS_HMAC_DIGEST_SIZE) != 0)
     {
-        dtls_warn("message is broken\n");
+        dtls_crit("Failed to verification of MAC\n");
         return -1;
     }
 
-    return srclen - SHA256_DIGEST_LENGTH;
+    //verify the padding bytes
+    for (i =0; i < depaddinglen; i++)
+    {
+        if (buf[srclen - depaddinglen - 1 + i] != depaddinglen)
+        {
+            dtls_crit("Failed to verify padding bytes\n");
+            return -1;
+        }
+    }
+
+    return srclen - DTLS_HMAC_DIGEST_SIZE - depaddinglen - 1;
 }
 
 #ifdef DTLS_PSK
@@ -523,8 +575,6 @@ void
 dtls_ecdsa_create_sig_hash(const unsigned char *priv_key, size_t key_size,
                           const unsigned char *sign_hash, size_t sign_hash_size,
                           uint32_t point_r[9], uint32_t point_s[9]) {
-  int ret;
-
   uint8_t privateKey[32];
   uint8_t hashValue[32];
   uint8_t sign[64];
@@ -591,6 +641,41 @@ dtls_ecdsa_verify_sig(const unsigned char *pub_key_x,
 }
 #endif /* DTLS_ECC */
 
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+int dtls_ecdhe_psk_pre_master_secret(unsigned char *psk, size_t psklen,
+                                     unsigned char *ecc_priv_key,
+                                     unsigned char *ecc_pub_key_x,
+                                     unsigned char *ecc_pub_key_y,
+                                     size_t ecc_key_size,
+                                     unsigned char *result,
+                                     size_t result_len)
+{
+  uint8_t eccPublicKey[64];
+  uint8_t eccPrivateKey[32];
+  unsigned char *p = result;
+
+  if (result_len < uECC_BYTES + psklen + (sizeof(uint16) * 2)) {
+    return -1;
+  }
+
+  dtls_int_to_uint16(p, uECC_BYTES);
+  p += sizeof(uint16);
+
+  memcpy(eccPublicKey, ecc_pub_key_x, 32);
+  memcpy(eccPublicKey + 32, ecc_pub_key_y, 32);
+  memcpy(eccPrivateKey, ecc_priv_key, 32);
+  uECC_shared_secret(eccPublicKey, eccPrivateKey, p);
+  p += uECC_BYTES;
+
+  dtls_int_to_uint16(p, psklen);
+  p += sizeof(uint16);
+
+  memcpy(p, psk, psklen);
+
+  return uECC_BYTES + psklen + (sizeof(uint16) * 2);
+}
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+
 int
 dtls_encrypt(const unsigned char *src, size_t length,
             unsigned char *buf,
@@ -615,7 +700,8 @@ dtls_encrypt(const unsigned char *src, size_t length,
         memmove(buf, src, length);
       ret = dtls_ccm_encrypt(&ctx->data, src, length, buf, nounce, aad, la);
   }
-  if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA) {
+  if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 ||
+     cipher == TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256) {
       ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
       if (ret < 0) {
         /* cleanup everything in case the key has the wrong size */
@@ -625,7 +711,7 @@ dtls_encrypt(const unsigned char *src, size_t length,
 
       if (src != buf)
         memmove(buf, src, length);
-      ret = dtls_cbc_encrypt(&ctx->data, nounce, src, length, buf);
+      ret = dtls_cbc_encrypt(&ctx->data, key, keylen, nounce, src, length, buf);
   }
 
 error:
@@ -658,7 +744,8 @@ dtls_decrypt(const unsigned char *src, size_t length,
       ret = dtls_ccm_decrypt(&ctx->data, src, length, buf, nounce, aad, la);
   }
 
-  if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA) {
+  if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 ||
+     cipher == TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256) {
       ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
       if (ret < 0) {
         /* cleanup everything in case the key has the wrong size */
@@ -668,7 +755,7 @@ dtls_decrypt(const unsigned char *src, size_t length,
 
       if (src != buf)
         memmove(buf, src, length);
-      ret = dtls_cbc_decrypt(&ctx->data, nounce, src, length, buf);
+      ret = dtls_cbc_decrypt(&ctx->data, key, keylen, nounce, src, length, buf);
     }
 
 error:
index dd13ffa..f4cfc66 100644 (file)
@@ -39,6 +39,7 @@
 #include "numeric.h"
 #include "hmac.h"
 #include "ccm.h"
+#include "ecc/ecc.h"
 
 /* TLS_PSK_WITH_AES_128_CCM_8 */
 #define DTLS_MAC_KEY_LENGTH    0
@@ -46,6 +47,7 @@
 #define DTLS_BLK_LENGTH        16 /* AES-128 */
 #define DTLS_MAC_LENGTH        DTLS_HMAC_DIGEST_SIZE
 #define DTLS_IV_LENGTH         4  /* length of nonce_explicit */
+#define DTLS_CBC_IV_LENGTH     16
 
 /** 
  * Maximum size of the generated keyblock. Note that MAX_KEYBLOCK_LENGTH must 
@@ -128,6 +130,13 @@ typedef struct {
   dtls_compression_t compression;              /**< compression method */
   dtls_cipher_t cipher;                /**< cipher type */
   unsigned int do_client_auth:1;
+
+#ifdef DTLS_ECC && DTLS_PSK
+  struct keyx_t {
+    dtls_handshake_parameters_ecc_t ecc;
+    dtls_handshake_parameters_psk_t psk;
+  } keyx;
+#else /* DTLS_ECC && DTLS_PSK */
   union {
 #ifdef DTLS_ECC
     dtls_handshake_parameters_ecc_t ecc;
@@ -136,6 +145,7 @@ typedef struct {
     dtls_handshake_parameters_psk_t psk;
 #endif /* DTLS_PSK */
   } keyx;
+#endif /* DTLS_ECC && DTLS_PSK */
 } dtls_handshake_parameters_t;
 
 /* The following macros provide access to the components of the
index 41e68a5..6104a08 100644 (file)
@@ -496,16 +496,27 @@ static inline int is_tls_psk_with_aes_128_ccm_8(dtls_cipher_t cipher)
 #endif /* DTLS_PSK */
 }
 
-/** returns true if the cipher matches TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
-static inline int is_tls_ecdh_anon_with_aes_128_cbc_sha(dtls_cipher_t cipher)
+/** returns true if the cipher matches TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 */
+static inline int is_tls_ecdh_anon_with_aes_128_cbc_sha_256(dtls_cipher_t cipher)
 {
 #ifdef DTLS_ECC
-    return cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
+    return cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256;
 #else
     return 0;
 #endif
 }
 
+/** returns true if the cipher matches TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 */
+static inline int is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(dtls_cipher_t cipher)
+{
+#if defined(DTLS_ECC) && defined(DTLS_PSK)
+  return cipher == TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256;
+#else
+  return 0;
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+}
+
+
 
 /** returns true if the application is configured for psk */
 static inline int is_psk_supported(dtls_context_t *ctx)
@@ -549,6 +560,17 @@ static inline int is_ecdh_anon_supported(dtls_context_t *ctx)
 #endif
 }
 
+/** returns true if ecdhe_psk_with_aes_128_cbc_sha_256 is supported */
+static inline int is_ecdhe_psk_supported(dtls_context_t *ctx)
+{
+#if defined(DTLS_ECC) && defined(DTLS_PSK)
+    return is_psk_supported(ctx);
+#else
+    return 0;
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+}
+
+
 /**
  * Returns @c 1 if @p code is a cipher suite other than @c
  * TLS_NULL_WITH_NULL_NULL that we recognize.
@@ -563,14 +585,17 @@ known_cipher(dtls_context_t *ctx, dtls_cipher_t code, int is_client) {
   int psk;
   int ecdsa;
   int ecdh_anon;
+  int ecdhe_psk;
 
   psk = is_psk_supported(ctx);
   ecdsa = is_ecdsa_supported(ctx, is_client);
   ecdh_anon = is_ecdh_anon_supported(ctx);
+  ecdhe_psk = is_ecdhe_psk_supported(ctx);
 
   return (psk && is_tls_psk_with_aes_128_ccm_8(code)) ||
         (ecdsa && is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(code)) ||
-        (ecdh_anon && is_tls_ecdh_anon_with_aes_128_cbc_sha(code));
+        (ecdh_anon && is_tls_ecdh_anon_with_aes_128_cbc_sha_256(code)) ||
+        (ecdhe_psk && is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(code));
 }
 
 /**
@@ -676,7 +701,11 @@ calculate_key_block(dtls_context_t *ctx,
                    dtls_peer_t *peer,
                    session_t *session,
                    dtls_peer_type role) {
-  unsigned char *pre_master_secret;
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+  unsigned char pre_master_secret[MAX_KEYBLOCK_LENGTH + uECC_BYTES];
+#else
+  unsigned char pre_master_secret[MAX_KEYBLOCK_LENGTH];
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
   int pre_master_len = 0;
   dtls_security_parameters_t *security = dtls_security_params_next(peer);
   uint8 master_secret[DTLS_MASTER_SECRET_LENGTH];
@@ -685,8 +714,6 @@ calculate_key_block(dtls_context_t *ctx,
     return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
   }
 
-  pre_master_secret = security->key_block;
-
   switch (handshake->cipher) {
 #ifdef DTLS_PSK
   case TLS_PSK_WITH_AES_128_CCM_8: {
@@ -719,7 +746,7 @@ calculate_key_block(dtls_context_t *ctx,
 #endif /* DTLS_PSK */
 #ifdef DTLS_ECC
   case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
-  case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: {
+  case TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256: {
     pre_master_len = dtls_ecdh_pre_master_secret(handshake->keyx.ecc.own_eph_priv,
                                                 handshake->keyx.ecc.other_eph_pub_x,
                                                 handshake->keyx.ecc.other_eph_pub_y,
@@ -733,6 +760,35 @@ calculate_key_block(dtls_context_t *ctx,
     break;
   }
 #endif /* DTLS_ECC */
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+    case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256: {
+      unsigned char psk[DTLS_PSK_MAX_KEY_LEN];
+      int psklen;
+
+      psklen = CALL(ctx, get_psk_info, session, DTLS_PSK_KEY,
+             handshake->keyx.psk.identity,
+             handshake->keyx.psk.id_length,
+             psk, DTLS_PSK_MAX_KEY_LEN);
+      if (psklen < 0) {
+        dtls_crit("no psk key for session available\n");
+        return psklen;
+      }
+
+      pre_master_len = dtls_ecdhe_psk_pre_master_secret(psk, psklen,
+                           handshake->keyx.ecc.own_eph_priv,
+                           handshake->keyx.ecc.other_eph_pub_x,
+                           handshake->keyx.ecc.other_eph_pub_y,
+                           sizeof(handshake->keyx.ecc.own_eph_priv),
+                           pre_master_secret,
+                           MAX_KEYBLOCK_LENGTH + uECC_BYTES);
+
+      if (pre_master_len < 0) {
+        dtls_crit("the curve was too long, for the pre master secret\n");
+        return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+      }
+      break;
+    }
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC)  */
   default:
     dtls_crit("calculate_key_block: unknown cipher\n");
     return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
@@ -1084,7 +1140,7 @@ check_client_keyexchange(dtls_context_t *ctx,
 
 #ifdef DTLS_ECC
   if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher) ||
-       is_tls_ecdh_anon_with_aes_128_cbc_sha(handshake->cipher) ) {
+       is_tls_ecdh_anon_with_aes_128_cbc_sha_256(handshake->cipher) ) {
 
     if (length < DTLS_HS_LENGTH + DTLS_CKXEC_LENGTH) {
       dtls_debug("The client key exchange is too short\n");
@@ -1113,6 +1169,56 @@ check_client_keyexchange(dtls_context_t *ctx,
     data += sizeof(handshake->keyx.ecc.other_eph_pub_y);
   }
 #endif /* DTLS_ECC */
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+  if (is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(handshake->cipher)) {
+    int id_length;
+
+    if (length < DTLS_HS_LENGTH + DTLS_CKXEC_LENGTH) {
+      dtls_debug("The client key exchange is too short\n");
+      return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
+    }
+    data += DTLS_HS_LENGTH;
+
+    //PSK hint
+    id_length = dtls_uint16_to_int(data);
+    data += sizeof(uint16);
+
+    if (DTLS_HS_LENGTH + DTLS_CKXPSK_LENGTH_MIN + DTLS_CKXEC_LENGTH + id_length != length) {
+      dtls_debug("The identity has a wrong length\n");
+      return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
+    }
+
+    if (id_length > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) {
+      dtls_warn("please use a smaller client identity\n");
+      return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+    }
+
+    handshake->keyx.psk.id_length = id_length;
+    memcpy(handshake->keyx.psk.identity, data, id_length);
+    data += id_length;
+
+    //ECDH public
+    if (dtls_uint8_to_int(data) != 1 + 2 * DTLS_EC_KEY_SIZE) {
+      dtls_alert("expected 65 bytes long public point\n");
+      return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
+    }
+    data += sizeof(uint8);
+
+    if (dtls_uint8_to_int(data) != 4) {
+      dtls_alert("expected uncompressed public point\n");
+      return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
+    }
+    data += sizeof(uint8);
+
+    memcpy(handshake->keyx.ecc.other_eph_pub_x, data,
+       sizeof(handshake->keyx.ecc.other_eph_pub_x));
+    data += sizeof(handshake->keyx.ecc.other_eph_pub_x);
+
+    memcpy(handshake->keyx.ecc.other_eph_pub_y, data,
+       sizeof(handshake->keyx.ecc.other_eph_pub_y));
+    data += sizeof(handshake->keyx.ecc.other_eph_pub_y);
+  }
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
 #ifdef DTLS_PSK
   if (is_tls_psk_with_aes_128_ccm_8(handshake->cipher)) {
     int id_length;
@@ -1286,6 +1392,52 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
       p += data_len_array[i];
       res += data_len_array[i];
     }
+  } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(security->cipher) ||
+             is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(security->cipher)) {
+
+    unsigned char nonce[DTLS_CBC_IV_LENGTH];
+
+    /** Add IV into body of packet in case of AES CBC mode according to RFC 5246, Section 6.2.3.2
+     *
+     *    opaque IV[SecurityParameters.record_iv_length];
+     *    block-ciphered struct {
+     *        opaque content[TLSCompressed.length];
+     *        opaque MAC[SecurityParameters.mac_length];
+     *        uint8 padding[GenericBlockCipher.padding_length];
+     *        uint8 padding_length;
+     * };
+     *
+     */
+
+    res = 0;
+    dtls_prng(nonce, DTLS_CBC_IV_LENGTH);
+    memcpy(p , nonce, DTLS_CBC_IV_LENGTH);
+    p += DTLS_CBC_IV_LENGTH;
+    res += DTLS_CBC_IV_LENGTH;
+
+    for (i = 0; i < data_array_len; i++) {
+        /* check the minimum that we need for packets that are not encrypted */
+        if (*rlen < res + DTLS_RH_LENGTH + data_len_array[i]) {
+            dtls_debug("dtls_prepare_record: send buffer too small\n");
+            return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+        }
+
+        memcpy(p, data_array[i], data_len_array[i]);
+        p += data_len_array[i];
+        res += data_len_array[i];
+     }
+
+     res = dtls_encrypt(start + DTLS_CBC_IV_LENGTH, res - DTLS_CBC_IV_LENGTH,
+               start + DTLS_CBC_IV_LENGTH, nonce,
+               dtls_kb_local_write_key(security, peer->role),
+               dtls_kb_key_size(security, peer->role),
+               NULL, 0,
+               security->cipher);
+     if (res < 0)
+       return res;
+
+     res += DTLS_CBC_IV_LENGTH;
+
   } else { /* TLS_PSK_WITH_AES_128_CCM_8 or TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 */   
     /** 
      * length of additional_data for the AEAD cipher which consists of
@@ -1299,8 +1451,6 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
       dtls_debug("dtls_prepare_record(): encrypt using TLS_PSK_WITH_AES_128_CCM_8\n");
     } else if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(security->cipher)) {
       dtls_debug("dtls_prepare_record(): encrypt using TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8\n");
-    } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha(security->cipher)) {
-        dtls_debug("dtls_prepare_record() : encrypt using TLS_ECDH_anon_WITH_AES_128_CBC_SHA\n");
     } else {
       dtls_debug("dtls_prepare_record(): encrypt using unknown cipher\n");
     }
@@ -1363,7 +1513,7 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
 
     memset(nonce, 0, DTLS_CCM_BLOCKSIZE);
     memcpy(nonce, dtls_kb_local_iv(security, peer->role),
-          dtls_kb_iv_size(security, peer->role));
+        dtls_kb_iv_size(security, peer->role));
     memcpy(nonce + dtls_kb_iv_size(security, peer->role), start, 8); /* epoch + seq_num */
 
     dtls_debug_dump("nonce:", nonce, DTLS_CCM_BLOCKSIZE);
@@ -1378,7 +1528,8 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
     memcpy(A_DATA, &DTLS_RECORD_HEADER(sendbuf)->epoch, 8); /* epoch and seq_num */
     memcpy(A_DATA + 8,  &DTLS_RECORD_HEADER(sendbuf)->content_type, 3); /* type and version */
     dtls_int_to_uint16(A_DATA + 11, res - 8); /* length */
-    
+
+
     res = dtls_encrypt(start + 8, res - 8, start + 8, nonce,
                dtls_kb_local_write_key(security, peer->role),
                dtls_kb_key_size(security, peer->role),
@@ -1388,7 +1539,7 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
     if (res < 0)
       return res;
 
-    res += 8;                  /* increment res by size of nonce_explicit */
+    res += 8; /* increment res by size of nonce_explicit */
     dtls_debug_dump("message:", start, res);
   }
 
@@ -2072,6 +2223,80 @@ dtls_send_server_key_exchange_ecdh(dtls_context_t *ctx, dtls_peer_t *peer,
 }
 #endif /* DTLS_ECC */
 
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+static int dtls_send_server_key_exchange_ecdhe_psk(dtls_context_t *ctx, dtls_peer_t *peer,
+                                 const unsigned char *psk_hint, size_t psk_hint_len)
+{
+  /* The ASN.1 Integer representation of an 32 byte unsigned int could be
+   * 33 bytes long add space for that */
+  uint8 buf[DTLS_SKEXEC_LENGTH + DTLS_SKEXECPSK_LENGTH_MAX + 2];
+  uint8 *p;
+  uint8 *ephemeral_pub_x;
+  uint8 *ephemeral_pub_y;
+  dtls_handshake_parameters_t *config = peer->handshake_params;
+
+  /* ServerKeyExchange
+    * Please see Session 2, RFC 5489.
+
+         struct {
+          select (KeyExchangeAlgorithm) {
+              //other cases for rsa, diffie_hellman, etc.
+              case ec_diffie_hellman_psk:  // NEW
+                  opaque psk_identity_hint<0..2^16-1>;
+                  ServerECDHParams params;
+          };
+      } ServerKeyExchange; */
+  p = buf;
+
+  assert(psk_hint_len <= DTLS_PSK_MAX_CLIENT_IDENTITY_LEN);
+  if (psk_hint_len > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) {
+    // should never happen
+    dtls_warn("psk identity hint is too long\n");
+    return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+  }
+
+  // psk_identity_hint
+  dtls_int_to_uint16(p, psk_hint_len);
+  p += sizeof(uint16);
+
+  memcpy(p, psk_hint, psk_hint_len);
+  p += psk_hint_len;
+
+  /* ServerECDHParams. */
+  /* ECCurveType curve_type: named_curve */
+  dtls_int_to_uint8(p, TLS_EC_CURVE_TYPE_NAMED_CURVE);
+  p += sizeof(uint8);
+
+  /* NamedCurve namedcurve: secp256r1 */
+  dtls_int_to_uint16(p, TLS_EXT_ELLIPTIC_CURVES_SECP256R1);
+  p += sizeof(uint16);
+
+  dtls_int_to_uint8(p, 1 + 2 * DTLS_EC_KEY_SIZE);
+  p += sizeof(uint8);
+
+  /* This should be an uncompressed point, but I do not have access to the spec. */
+  dtls_int_to_uint8(p, 4);
+  p += sizeof(uint8);
+
+  /* store the pointer to the x component of the pub key and make space */
+  ephemeral_pub_x = p;
+  p += DTLS_EC_KEY_SIZE;
+
+  /* store the pointer to the y component of the pub key and make space */
+  ephemeral_pub_y = p;
+  p += DTLS_EC_KEY_SIZE;
+
+  dtls_ecdsa_generate_key(config->keyx.ecc.own_eph_priv,
+              ephemeral_pub_x, ephemeral_pub_y,
+              DTLS_EC_KEY_SIZE);
+
+  assert(p - buf <= sizeof(buf));
+
+  return dtls_send_handshake_msg(ctx, peer, DTLS_HT_SERVER_KEY_EXCHANGE,
+                                buf, p - buf);
+}
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
+
 #ifdef DTLS_PSK
 static int
 dtls_send_server_key_exchange_psk(dtls_context_t *ctx, dtls_peer_t *peer,
@@ -2163,6 +2388,7 @@ dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
   int res;
   int ecdsa;
   int ecdh_anon;
+  int ecdhe_psk;
 
   res = dtls_send_server_hello(ctx, peer);
 
@@ -2172,7 +2398,8 @@ dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
   }
 
   ecdsa = is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher);
-  ecdh_anon = is_tls_ecdh_anon_with_aes_128_cbc_sha(peer->handshake_params->cipher);
+  ecdh_anon = is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher);
+  ecdhe_psk = is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(peer->handshake_params->cipher);
 
 #ifdef DTLS_ECC
   if(ecdh_anon) {
@@ -2217,7 +2444,31 @@ dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
     }
   }
 #endif /* DTLS_ECC */
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+  else if(ecdhe_psk) {
+    unsigned char psk_hint[DTLS_PSK_MAX_CLIENT_IDENTITY_LEN];
+    int psk_len;
 
+    /* The identity hint is optional, therefore we ignore the result
+     * and check psk only. */
+    psk_len = CALL(ctx, get_psk_info, &peer->session, DTLS_PSK_HINT,
+              NULL, 0, psk_hint, DTLS_PSK_MAX_CLIENT_IDENTITY_LEN);
+
+    if (psk_len < 0) {
+      dtls_debug("dtls_server_hello: cannot create ServerKeyExchange\n");
+      return psk_len;
+    }
+
+    if (psk_len > 0) {
+      res = dtls_send_server_key_exchange_ecdhe_psk(ctx, peer, psk_hint, (size_t)psk_len);
+
+      if (res < 0) {
+        dtls_debug("dtls_server_hello(with ECDHE): cannot prepare Server Key Exchange record\n");
+        return res;
+      }
+    }
+  }
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
 #ifdef DTLS_PSK
   if (is_tls_psk_with_aes_128_ccm_8(peer->handshake_params->cipher)) {
     unsigned char psk_hint[DTLS_PSK_MAX_CLIENT_IDENTITY_LEN];
@@ -2264,7 +2515,11 @@ dtls_send_ccs(dtls_context_t *ctx, dtls_peer_t *peer) {
 static int
 dtls_send_client_key_exchange(dtls_context_t *ctx, dtls_peer_t *peer)
 {
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+  uint8 buf[DTLS_CKXEC_LENGTH + 2 + DTLS_PSK_MAX_CLIENT_IDENTITY_LEN];
+#else
   uint8 buf[DTLS_CKXEC_LENGTH];
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
   uint8 client_id[DTLS_PSK_MAX_CLIENT_IDENTITY_LEN];
   uint8 *p;
   dtls_handshake_parameters_t *handshake = peer->handshake_params;
@@ -2301,7 +2556,7 @@ dtls_send_client_key_exchange(dtls_context_t *ctx, dtls_peer_t *peer)
 #endif /* DTLS_PSK */
 #ifdef DTLS_ECC
   case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
-  case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: {
+  case TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256: {
     uint8 *ephemeral_pub_x;
     uint8 *ephemeral_pub_y;
 
@@ -2324,6 +2579,60 @@ dtls_send_client_key_exchange(dtls_context_t *ctx, dtls_peer_t *peer)
     break;
   }
 #endif /* DTLS_ECC */
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+  case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256: {
+      int psk_len;
+      uint8 *ephemeral_pub_x;
+      uint8 *ephemeral_pub_y;
+
+    /* Please see Session 2, RFC 5489.
+         struct {
+            select (KeyExchangeAlgorithm) {
+                // other cases for rsa, diffie_hellman, etc.
+                case ec_diffie_hellman_psk:
+                    opaque psk_identity<0..2^16-1>;
+                    ClientECDiffieHellmanPublic public;
+            } exchange_keys;
+        } ClientKeyExchange;
+    */
+
+    psk_len = CALL(ctx, get_psk_info, &peer->session, DTLS_PSK_IDENTITY,
+               NULL, 0,
+               client_id,
+               sizeof(client_id));
+    if (psk_len < 0) {
+      dtls_crit("no psk identity set in kx\n");
+      return psk_len;
+    }
+
+    if (psk_len + sizeof(uint16) > DTLS_CKXEC_LENGTH) {
+      dtls_warn("the psk identity is too long\n");
+      return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+    }
+
+    dtls_int_to_uint16(p, psk_len);
+    p += sizeof(uint16);
+
+    memcpy(p, client_id, psk_len);
+    p += psk_len;
+
+    dtls_int_to_uint8(p, 1 + 2 * DTLS_EC_KEY_SIZE);
+    p += sizeof(uint8);
+
+    dtls_int_to_uint8(p, 4);
+    p += sizeof(uint8);
+
+    ephemeral_pub_x = p;
+    p += DTLS_EC_KEY_SIZE;
+    ephemeral_pub_y = p;
+    p += DTLS_EC_KEY_SIZE;
+
+    dtls_ecdsa_generate_key(peer->handshake_params->keyx.ecc.own_eph_priv,
+                           ephemeral_pub_x, ephemeral_pub_y,
+                           DTLS_EC_KEY_SIZE);
+    break;
+  }
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
   default:
     dtls_crit("cipher not supported\n");
     return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
@@ -2413,6 +2722,7 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
   int psk = 0;
   int ecdsa = 0;
   int ecdh_anon = 0;
+  int ecdhe_psk = 0;
   dtls_handshake_parameters_t *handshake = peer->handshake_params;
   dtls_tick_t now;
 
@@ -2424,17 +2734,21 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
       case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
         ecdsa = is_ecdsa_supported(ctx, 1);
         break;
-      case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
+      case TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256:
         ecdh_anon = is_ecdh_anon_supported(ctx);
         break;
+      case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256:
+        ecdhe_psk = is_ecdhe_psk_supported(ctx);
+        break;
       default:
         psk = is_psk_supported(ctx);
         ecdsa = is_ecdsa_supported(ctx, 1);
         ecdh_anon = is_ecdh_anon_supported(ctx);
+        ecdhe_psk = is_ecdhe_psk_supported(ctx);
         break;
    }
 
-  cipher_size = 2 + (ecdsa ? 2 : 0) + (psk ? 2 : 0) + (ecdh_anon ? 2 : 0);
+  cipher_size = 2 + (ecdsa ? 2 : 0) + (psk ? 2 : 0) + (ecdh_anon ? 2 : 0) + (ecdhe_psk ? 2 : 0);
   extension_size = (ecdsa) ? (2 + 6 + 6 + 8 + 6) : 0;
 
   if (cipher_size == 0) {
@@ -2478,7 +2792,7 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
   p += sizeof(uint16);
 
   if (ecdh_anon) {
-    dtls_int_to_uint16(p, TLS_ECDH_anon_WITH_AES_128_CBC_SHA);
+    dtls_int_to_uint16(p, TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256);
     p += sizeof(uint16);
   }
   if (psk) {
@@ -2489,6 +2803,10 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
     dtls_int_to_uint16(p, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
     p += sizeof(uint16);
   }
+  if (ecdhe_psk) {
+      dtls_int_to_uint16(p, TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);
+      p += sizeof(uint16);
+  }
 
   /* compression method */
   dtls_int_to_uint8(p, 1);
@@ -2809,7 +3127,7 @@ check_server_key_exchange_ecdh(dtls_context_t *ctx,
 
   update_hs_hash(peer, data, data_length);
 
-  assert(is_tls_ecdh_anon_with_aes_128_cbc_sha(config->cipher));
+  assert(is_tls_ecdh_anon_with_aes_128_cbc_sha_256(config->cipher));
 
   data += DTLS_HS_LENGTH;
 
@@ -2856,8 +3174,97 @@ check_server_key_exchange_ecdh(dtls_context_t *ctx,
 
   return 0;
 }
-
 #endif /* DTLS_ECC */
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+check_server_key_exchange_ecdhe_psk(dtls_context_t *ctx,
+                             dtls_peer_t *peer,
+                             uint8 *data, size_t data_length)
+{
+  dtls_handshake_parameters_t *config = peer->handshake_params;
+  uint16_t psk_len = 0;
+
+  /* ServerKeyExchange
+    * Please see Session 2, RFC 5489.
+
+         struct {
+          select (KeyExchangeAlgorithm) {
+              //other cases for rsa, diffie_hellman, etc.
+              case ec_diffie_hellman_psk:  // NEW
+                  opaque psk_identity_hint<0..2^16-1>;
+                  ServerECDHParams params;
+          };
+      } ServerKeyExchange; */
+
+  update_hs_hash(peer, data, data_length);
+
+  assert(is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(config->cipher));
+
+  data += DTLS_HS_LENGTH;
+
+  psk_len = dtls_uint16_to_int(data);
+  data += sizeof(uint16);
+
+  if (psk_len != data_length - DTLS_HS_LENGTH - DTLS_SKEXEC_ECDH_ANON_LENGTH - sizeof(uint16)) {
+    dtls_warn("the length of the server identity hint is worng\n");
+    return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
+  }
+
+  if (psk_len > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) {
+    dtls_warn("please use a smaller server identity hint\n");
+    return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
+  }
+
+  // store the psk_identity_hint in config->keyx.psk for later use
+  config->keyx.psk.id_length = psk_len;
+  memcpy(config->keyx.psk.identity, data, psk_len);
+
+  data += psk_len;
+  data_length -= psk_len;
+
+  if (data_length < DTLS_HS_LENGTH + DTLS_SKEXEC_ECDH_ANON_LENGTH) {
+    dtls_alert("the packet length does not match the expected\n");
+    return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
+  }
+
+  if (dtls_uint8_to_int(data) != TLS_EC_CURVE_TYPE_NAMED_CURVE) {
+    dtls_alert("Only named curves supported\n");
+    return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
+  }
+  data += sizeof(uint8);
+  data_length -= sizeof(uint8);
+
+  if (dtls_uint16_to_int(data) != TLS_EXT_ELLIPTIC_CURVES_SECP256R1) {
+    dtls_alert("secp256r1 supported\n");
+    return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
+  }
+  data += sizeof(uint16);
+  data_length -= sizeof(uint16);
+
+  if (dtls_uint8_to_int(data) != 1 + 2 * DTLS_EC_KEY_SIZE) {
+    dtls_alert("expected 65 bytes long public point\n");
+    return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
+  }
+  data += sizeof(uint8);
+  data_length -= sizeof(uint8);
+
+  if (dtls_uint8_to_int(data) != 4) {
+    dtls_alert("expected uncompressed public point\n");
+    return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
+  }
+  data += sizeof(uint8);
+  data_length -= sizeof(uint8);
+
+  memcpy(config->keyx.ecc.other_eph_pub_x, data, sizeof(config->keyx.ecc.other_eph_pub_x));
+  data += sizeof(config->keyx.ecc.other_eph_pub_x);
+  data_length -= sizeof(config->keyx.ecc.other_eph_pub_x);
+
+  memcpy(config->keyx.ecc.other_eph_pub_y, data, sizeof(config->keyx.ecc.other_eph_pub_y));
+  data += sizeof(config->keyx.ecc.other_eph_pub_y);
+  data_length -= sizeof(config->keyx.ecc.other_eph_pub_y);
+
+  return 0;
+}
+#endif /* defined(DTLS_PSK) && defined(DTLS_ECC) */
 
 #ifdef DTLS_PSK
 static int
@@ -3069,6 +3476,24 @@ decrypt_verify(dtls_peer_t *peer, uint8 *packet, size_t length,
   if (security->cipher == TLS_NULL_WITH_NULL_NULL) {
     /* no cipher suite selected */
     return clen;
+  } else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(security->cipher) ||
+             is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(security->cipher)) {
+
+    unsigned char nonce[DTLS_CBC_IV_LENGTH];
+
+    if (clen < (DTLS_CBC_IV_LENGTH + DTLS_HMAC_DIGEST_SIZE))           /* need at least IV and MAC */
+      return -1;
+
+    memcpy(nonce, *cleartext , DTLS_CBC_IV_LENGTH);
+    clen -= DTLS_CBC_IV_LENGTH;
+    *cleartext += DTLS_CBC_IV_LENGTH ;
+
+    clen = dtls_decrypt(*cleartext, clen, *cleartext, nonce,
+                      dtls_kb_remote_write_key(security, peer->role),
+                      dtls_kb_key_size(security, peer->role),
+                      NULL, 0,
+                      security->cipher);
+
   } else { /* TLS_PSK_WITH_AES_128_CCM_8 or TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 */
     /** 
      * length of additional_data for the AEAD cipher which consists of
@@ -3083,7 +3508,7 @@ decrypt_verify(dtls_peer_t *peer, uint8 *packet, size_t length,
 
     memset(nonce, 0, DTLS_CCM_BLOCKSIZE);
     memcpy(nonce, dtls_kb_remote_iv(security, peer->role),
-          dtls_kb_iv_size(security, peer->role));
+        dtls_kb_iv_size(security, peer->role));
 
     /* read epoch and seq_num from message */
     memcpy(nonce + dtls_kb_iv_size(security, peer->role), *cleartext, 8);
@@ -3108,17 +3533,19 @@ decrypt_verify(dtls_peer_t *peer, uint8 *packet, size_t length,
                       dtls_kb_remote_write_key(security, peer->role),
                       dtls_kb_key_size(security, peer->role),
                       A_DATA, A_DATA_LEN,
-               security->cipher);
-    if (clen < 0)
-      dtls_warn("decryption failed\n");
-    else {
+                      security->cipher);
+  }
+
+  if (clen < 0)
+    dtls_warn("decryption failed\n");
+  else {
 #ifndef NDEBUG
-      dtls_debug("decrypt_verify(): found %i bytes cleartext\n", clen);
+    dtls_debug("decrypt_verify(): found %i bytes cleartext\n", clen);
 #endif
-      dtls_security_params_free_other(peer);
-      dtls_debug_dump("cleartext", *cleartext, clen);
-    }
+    dtls_security_params_free_other(peer);
+    dtls_debug_dump("cleartext", *cleartext, clen);
   }
+
   return clen;
 }
 
@@ -3219,7 +3646,8 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, session_t *session,
     }
     if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher))
       peer->state = DTLS_STATE_WAIT_SERVERCERTIFICATE; //ecdsa
-    else if (is_tls_ecdh_anon_with_aes_128_cbc_sha(peer->handshake_params->cipher))
+    else if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher) ||
+        is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(peer->handshake_params->cipher))
         peer->state = DTLS_STATE_WAIT_SERVERKEYEXCHANGE; //ecdh
     else
       peer->state = DTLS_STATE_WAIT_SERVERHELLODONE; //psk
@@ -3259,13 +3687,23 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, session_t *session,
       err = check_server_key_exchange_ecdsa(ctx, peer, data, data_length);
     }
 
-    if (is_tls_ecdh_anon_with_aes_128_cbc_sha(peer->handshake_params->cipher)) {
+    if (is_tls_ecdh_anon_with_aes_128_cbc_sha_256(peer->handshake_params->cipher)) {
       if (state != DTLS_STATE_WAIT_SERVERKEYEXCHANGE) {
         return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
       }
       err = check_server_key_exchange_ecdh(ctx, peer, data, data_length);
     }
 #endif /* DTLS_ECC */
+
+#if defined(DTLS_PSK) && defined(DTLS_ECC)
+    if (is_tls_ecdhe_psk_with_aes_128_cbc_sha_256(peer->handshake_params->cipher)) {
+        if (state != DTLS_STATE_WAIT_SERVERKEYEXCHANGE) {
+          return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
+        }
+      err = check_server_key_exchange_ecdhe_psk(ctx, peer, data, data_length);
+    }
+#endif defined(DTLS_PSK) && defined(DTLS_ECC)
+
 #ifdef DTLS_PSK
     if (is_tls_psk_with_aes_128_ccm_8(peer->handshake_params->cipher)) {
       if (state != DTLS_STATE_WAIT_SERVERHELLODONE) {
index a2ab86e..7d2bc19 100644 (file)
@@ -238,7 +238,7 @@ typedef struct dtls_context_t {
 
   dtls_handler_t *h;           /**< callback handlers */
 
-  dtls_cipher_enable_t is_anon_ecdh_eabled;    /**< enable/disable the TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
+  dtls_cipher_enable_t is_anon_ecdh_eabled;    /**< enable/disable the TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 */
 
   dtls_cipher_t selected_cipher; /**< selected ciper suite for handshake */
 
@@ -268,7 +268,7 @@ static inline void dtls_set_handler(dtls_context_t *ctx, dtls_handler_t *h) {
 }
 
  /**
-  * @brief Enabling the TLS_ECDH_anon_WITH_AES_128_CBC_SHA
+  * @brief Enabling the TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256
   *
   * @param ctx              The DTLS context to use.
   * @param is_enable    DTLS_CIPHER_ENABLE(1) or DTLS_CIPHER_DISABLE(0)
@@ -279,7 +279,7 @@ void dtls_enables_anon_ecdh(dtls_context_t* ctx, dtls_cipher_enable_t is_enable)
  * @brief Select the cipher suite for handshake
  *
  * @param ctx              The DTLS context to use.
- * @param cipher         TLS_ECDH_anon_WITH_AES_128_CBC_SHA (0xC018)
+ * @param cipher         TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 (0xC018)
  *                                  TLS_PSK_WITH_AES_128_CCM_8 (0xX0A8)
  *                                  TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 (0xC0AE)
  */
index 441710f..8b3c518 100644 (file)
@@ -73,8 +73,9 @@ typedef unsigned char uint48[6];
 /** Known cipher suites.*/
 typedef enum { 
   TLS_NULL_WITH_NULL_NULL = 0x0000,   /**< NULL cipher  */
-  TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018, /**< see RFC 4492 */
+  TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 = 0xC018, /**< see RFC 4492 */
   TLS_PSK_WITH_AES_128_CCM_8 = 0xC0A8, /**< see RFC 6655 */
+  TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256 = 0xC037, /**< see RFC 5489 */
   TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xC0AE /**< see RFC 7251 */
 } dtls_cipher_t;
 
index 35521e9..dfd34c8 100644 (file)
@@ -309,9 +309,10 @@ usage( const char *program, const char *version) {
          "\t-p port\t\tlisten on specified port (default is %d)\n"
          "\t-v num\t\tverbosity level (default: 3)\n"
           "\t-c num\t\tcipher suite (default: 1)\n"
-          "\t\t\t1: TLS_ECDH_anon_WITH_AES_128_CBC_SHA \n"
+          "\t\t\t1: TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256 \n"
           "\t\t\t2: TLS_PSK_WITH_AES_128_CCM_8\n"
-          "\t\t\t3: TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8\n",
+          "\t\t\t3: TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8\n"
+          "\t\t\t4: TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256\n",
           program, version, program, DEFAULT_PORT);
 }
 
@@ -347,7 +348,7 @@ main(int argc, char **argv) {
   log_t log_level = DTLS_LOG_WARN;
   int fd, result;
   int on = 1;
-  dtls_cipher_t selected_cipher = TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
+  dtls_cipher_t selected_cipher = TLS_NULL_WITH_NULL_NULL;
   dtls_cipher_enable_t ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
   int opt, res;
   session_t dst;
@@ -417,7 +418,7 @@ main(int argc, char **argv) {
     case 'c':
       if( strcmp(optarg, "1") == 0)
       {
-          selected_cipher = TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
+          selected_cipher = TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256;
           ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
       }
       else if( strcmp(optarg, "2") == 0)
@@ -430,6 +431,11 @@ main(int argc, char **argv) {
           selected_cipher = TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ;
           ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
       }
+      else if( strcmp(optarg, "4") == 0)
+      {
+          selected_cipher = TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256;
+          ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
+      }
       break;
     default:
       usage(argv[0], dtls_package_version());
@@ -500,7 +506,7 @@ main(int argc, char **argv) {
   /* select cipher suite */
   dtls_select_cipher(dtls_context, selected_cipher);
 
-  /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha */
+  /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha_256 */
   dtls_enables_anon_ecdh(dtls_context, ecdh_anon_enalbe);
 
   dtls_set_handler(dtls_context, &cb);
index d3da1a7..5893084 100644 (file)
@@ -254,8 +254,8 @@ usage(const char *program, const char *version) {
          "\t-p port\t\tlisten on specified port (default is %d)\n"
          "\t-v num\t\tverbosity level (default: 3)\n"
          "\t-a enable|disable\t(default: disable)\n"
-         "\t\t\t\tenable:enable TLS_ECDH_anon_with_AES_128_CBC_SHA\n"
-         "\t\t\t\tdisable:disable TLS_ECDH_anon_with_AES_128_CBC_SHA\n",
+         "\t\t\t\tenable:enable TLS_ECDH_anon_with_AES_128_CBC_SHA_256\n"
+         "\t\t\t\tdisable:disable TLS_ECDH_anon_with_AES_128_CBC_SHA_256\n",
           program, version, program, DEFAULT_PORT);
 }
 
@@ -280,7 +280,7 @@ main(int argc, char **argv) {
   struct timeval timeout;
   int fd, opt, result;
   int on = 1;
-  int ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
+  dtls_cipher_enable_t ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
   struct sockaddr_in6 listen_addr;
 
   memset(&listen_addr, 0, sizeof(struct sockaddr_in6));
@@ -356,7 +356,7 @@ main(int argc, char **argv) {
 
   the_context = dtls_new_context(&fd);
 
-  /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha */
+  /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha_256 */
   dtls_enables_anon_ecdh(the_context, ecdh_anon_enalbe);
 
   dtls_set_handler(the_context, &cb);
index b7a659a..184ef64 100644 (file)
@@ -391,6 +391,7 @@ typedef struct
 {
     CAResponseResult_t result;  /**< Result for response by resource model */
     CAInfo_t info;              /**< Information of the response */
+    bool isMulticast;
 } CAResponseInfo_t;
 
 /**
index cca8bd8..7b6ce44 100644 (file)
@@ -129,6 +129,7 @@ CAResponseInfo_t *CACloneResponseInfo(const CAResponseInfo_t *rep)
         return NULL;
     }
 
+    clone->isMulticast = rep->isMulticast;
     clone->result = rep->result;
     return clone;
 }
index 2a751ff..bcdc905 100644 (file)
@@ -74,7 +74,7 @@ static const char *LEVEL[] =
 static android_LogPriority LEVEL[] =
 {   ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL};
 #endif
-#elif defined __linux__
+#elif defined (__linux__) || defined (__APPLE__)
 static const char *LEVEL[] __attribute__ ((unused)) =
 {   "DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
 #elif defined ARDUINO
@@ -116,7 +116,7 @@ void OICLogInit()
 
 void OICLogShutdown()
 {
-#ifdef __linux__
+#if defined(__linux__) || defined(__APPLE__)
     if (logCtx && logCtx->destroy)
     {
         logCtx->destroy(logCtx);
@@ -147,7 +147,7 @@ void OICLog(LogLevel level, const char *tag, const char *logStr)
     __android_log_write(LEVEL[level], tag, logStr);
 #endif
 
-#elif defined __linux__
+#elif defined __linux__ || defined __APPLE__
     if (logCtx && logCtx->write_level)
     {
         logCtx->write_level(logCtx, LEVEL_XTABLE[level], logStr);
@@ -158,7 +158,7 @@ void OICLog(LogLevel level, const char *tag, const char *logStr)
         int min = 0;
         int sec = 0;
         int ms = 0;
-#ifdef _POSIX_TIMERS
+#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
         struct timespec when = { 0, 0 };
         clockid_t clk = CLOCK_REALTIME;
 #ifdef CLOCK_REALTIME_COARSE
index e6940d8..d766451 100644 (file)
@@ -138,7 +138,7 @@ void CADTLSSetCredentialsCallback(CAGetDTLSCredentialsHandler credCallback);
  * Select the cipher suite for dtls handshake
  *
  * @param[in] cipher    cipher suite
- *                             0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA
+ *                             0xC018 : TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256
  *                             0xC0A8 : TLS_PSK_WITH_AES_128_CCM_8
  *                             0xC0AE : TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
  *
index 677b1f9..7aeb391 100644 (file)
@@ -193,18 +193,18 @@ int CAGetPollingInterval(int interval);
 void CAWakeUpForChange();
 
 /**
- * @brief   Initializes network monitor.
+ * Start network monitor.
  *
  * @return ::CA_STATUS_OK or Appropriate error code.
  */
-CAResult_t CAIPInitializeNetworkMonitor();
+CAResult_t CAIPStartNetworkMonitor();
 
 /**
- * @brief   Terminates network monitor.
+ * Stops network monitor.
  *
  * @return ::CA_STATUS_OK or Appropriate error code.
  */
-CAResult_t CAIPTerminateNetworkMonitor();
+CAResult_t CAIPStopNetworkMonitor();
 
 /**
  * @brief  Set callback for error handling.
index af9ed9a..780a6aa 100644 (file)
@@ -118,9 +118,10 @@ static CAResult_t CAAddIdToPeerInfoList(const char *peerAddr, uint32_t port,
     {
         OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
         OICFree(peer);
+        return CA_STATUS_FAILED;
     }
 
-    return result;
+    return CA_STATUS_OK;
 }
 
 static void CAFreePeerInfoList()
@@ -302,10 +303,11 @@ static CAResult_t CADtlsCacheMsg(stCACacheMessage_t *msg)
     if (!result)
     {
         OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
+        return CA_STATUS_FAILED;
     }
 
     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
-    return result;
+    return CA_STATUS_OK;
 }
 
 
@@ -437,11 +439,13 @@ static int32_t CASendSecureData(dtls_context_t *context,
 
     stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
 
-    CAEndpoint_t endpoint;
+    CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
+
     CAConvertAddrToName(&(addrInfo->addr.st), endpoint.addr, &endpoint.port);
     endpoint.flags = addrInfo->addr.st.ss_family == AF_INET ? CA_IPV4 : CA_IPV6;
     endpoint.flags |= CA_SECURE;
     endpoint.adapter = CA_ADAPTER_IP;
+    endpoint.interface = session->ifindex;
     int type = 0;
 
     //Mutex is not required for g_caDtlsContext. It will be called in same thread.
@@ -644,7 +648,7 @@ CAResult_t CADtlsEnableAnonECDHCipherSuite(const bool enable)
     dtls_enables_anon_ecdh(g_caDtlsContext->dtlsContext,
         enable == true ? DTLS_CIPHER_ENABLE : DTLS_CIPHER_DISABLE);
     ca_mutex_unlock(g_dtlsContextMutex);
-    OIC_LOG_V(DEBUG, NET_DTLS_TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA  is %s",
+    OIC_LOG_V(DEBUG, NET_DTLS_TAG, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA_256  is %s",
         enable ? "enabled" : "disabled");
 
     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsEnablesAnonEcdh");
index 20e0c22..c54411a 100644 (file)
@@ -1145,6 +1145,7 @@ void CAEDRNatvieCloseServerTask(JNIEnv* env)
         jmethodID jni_mid_close = (*env)->GetMethodID(env, jni_cid_InputStream, "close", "()V");
         (*env)->CallVoidMethod(env, g_inputStream, jni_mid_close);
         (*env)->DeleteGlobalRef(env, g_inputStream);
+        g_inputStream = NULL;
     }
 
     if (g_serverSocket)
@@ -1167,6 +1168,7 @@ void CAEDRNatvieCloseServerTask(JNIEnv* env)
         }
         (*env)->CallVoidMethod(env, g_serverSocket, jni_mid_accept);
         (*env)->DeleteGlobalRef(env, g_serverSocket);
+        g_serverSocket = NULL;
 
         OIC_LOG(DEBUG, TAG, "[EDR][Native] close accept obj");
     }
index d1bf5b4..7048867 100644 (file)
@@ -370,8 +370,6 @@ void CATerminateEDR()
 {
     OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
 
-    // Stop EDR adapter
-    CAStopEDR();
     // Terminate EDR Network Monitor
     CAEDRTerminateNetworkMonitor();
 
index f746cac..a4749c9 100644 (file)
@@ -538,21 +538,45 @@ static CAResult_t CAProcessSendData(const CAData_t *data)
                     }
                 }
 #endif
-                CALogPDUInfo(pdu, data->remoteEndpoint->flags);
+            }
+            else
+            {
+                OIC_LOG(ERROR,TAG,"Failed to generate multicast PDU");
+                CASendErrorInfo(data->remoteEndpoint, info, CA_SEND_FAILED);
+                return CA_SEND_FAILED;
+            }
+        }
+        else if (NULL != data->responseInfo)
+        {
+            OIC_LOG(DEBUG, TAG, "responseInfo is available..");
 
-                res = CASendMulticastData(data->remoteEndpoint, pdu->hdr, pdu->length);
-                if (CA_STATUS_OK != res)
+            info = &data->responseInfo->info;
+            pdu = CAGeneratePDU(data->responseInfo->result, info, data->remoteEndpoint);
+
+            if (NULL != pdu)
+            {
+#ifdef WITH_BWT
+                if (CA_ADAPTER_GATT_BTLE != data->remoteEndpoint->adapter
+#ifdef CI_ADAPTER
+                        && CA_IPV4_TCP != data->remoteEndpoint->flags
+#endif
+                        )
                 {
-                    OIC_LOG_V(ERROR, TAG, "send failed:%d", res);
-                    CAErrorHandler(data->remoteEndpoint, pdu->hdr, pdu->length, res);
-                    coap_delete_pdu(pdu);
-                    return res;
+                    // Blockwise transfer
+                    if (NULL != info)
+                    {
+                        CAResult_t res = CAAddBlockOption(&pdu, *info,
+                                data->remoteEndpoint);
+                        if (CA_STATUS_OK != res)
+                        {
+                            OIC_LOG(INFO, TAG, "to write block option has failed");
+                            CAErrorHandler(data->remoteEndpoint, pdu->hdr, pdu->length, res);
+                            coap_delete_pdu(pdu);
+                            return res;
+                        }
+                    }
                 }
-
-                OIC_LOG(DEBUG, TAG, "pdu to send :");
-                OIC_LOG_BUFFER(DEBUG, TAG,  pdu->hdr, pdu->length);
-
-                coap_delete_pdu(pdu);
+#endif
             }
             else
             {
@@ -563,12 +587,27 @@ static CAResult_t CAProcessSendData(const CAData_t *data)
         }
         else
         {
-            OIC_LOG(ERROR, TAG, "request info is empty");
+            OIC_LOG(ERROR, TAG, "request or response info is empty");
             return CA_SEND_FAILED;
         }
+
+        CALogPDUInfo(pdu, data->remoteEndpoint->flags);
+
+        OIC_LOG(DEBUG, TAG, "pdu to send :");
+        OIC_LOG_BUFFER(DEBUG, TAG,  pdu->hdr, pdu->length);
+
+        res = CASendMulticastData(data->remoteEndpoint, pdu->hdr, pdu->length);
+        if (CA_STATUS_OK != res)
+        {
+            OIC_LOG_V(ERROR, TAG, "send failed:%d", res);
+            CAErrorHandler(data->remoteEndpoint, pdu->hdr, pdu->length, res);
+            coap_delete_pdu(pdu);
+            return res;
+        }
+
+        coap_delete_pdu(pdu);
     }
 
-    OIC_LOG(DEBUG, TAG, "OUT");
     return CA_STATUS_OK;
 }
 
@@ -842,7 +881,7 @@ static CAData_t* CAPrepareSendData(const CAEndpoint_t *endpoint, const void *sen
             return NULL;
         }
 
-        cadata->type = SEND_TYPE_UNICAST;
+        cadata->type = response->isMulticast ? SEND_TYPE_MULTICAST : SEND_TYPE_UNICAST;
         cadata->responseInfo = response;
     }
     else
index 23af19c..874d634 100644 (file)
@@ -126,6 +126,9 @@ coap_pdu_t *CAGeneratePDU(uint32_t code, const CAInfo_t *info, const CAEndpoint_
 {
     OIC_LOG(DEBUG, TAG, "IN");
 
+    VERIFY_NON_NULL_RET(info, TAG, "info", NULL);
+    VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", NULL);
+
     coap_pdu_t *pdu = NULL;
 
     // RESET have to use only 4byte (empty message)
@@ -264,6 +267,13 @@ coap_pdu_t *CAParsePDU(const char *data, uint32_t length, uint32_t *outCode,
             coap_delete_pdu(outpdu);
             return NULL;
         }
+        if (outpdu->hdr->coap_hdr_udp_t.token_length > CA_MAX_TOKEN_LEN)
+        {
+            OIC_LOG_V(ERROR, TAG, "token length has been exceed : %d",
+                      outpdu->hdr->coap_hdr_udp_t.token_length);
+            coap_delete_pdu(outpdu);
+            return NULL;
+        }
     }
 
     if (outCode)
@@ -279,7 +289,8 @@ coap_pdu_t *CAGeneratePDUImpl(code_t code, coap_list_t *options, const CAInfo_t
                               const CAEndpoint_t *endpoint)
 {
     OIC_LOG(DEBUG, TAG, "IN");
-    VERIFY_NON_NULL_RET(info, TAG, "info is NULL", NULL);
+    VERIFY_NON_NULL_RET(info, TAG, "info", NULL);
+    VERIFY_NON_NULL_RET(endpoint, TAG, "endpoint", NULL);
 
     coap_transport_type transport;
 
index 7896334..6efe5f0 100755 (executable)
@@ -49,12 +49,12 @@ CAResult_t CAIPJniInit();
 
 #define MAX_INTERFACE_INFO_LENGTH 1024 // allows 32 interfaces from SIOCGIFCONF
 
-CAResult_t CAIPInitializeNetworkMonitor()
+CAResult_t CAIPStartNetworkMonitor()
 {
     return CAIPJniInit();
 }
 
-CAResult_t CAIPTerminateNetworkMonitor()
+CAResult_t CAIPStopNetworkMonitor()
 {
     return CA_STATUS_OK;
 }
index 06fca45..c9ef984 100644 (file)
 // defined & used (as-is defined in the linux socket headers).
 #define AF_INET (2)
 
-CAResult_t CAIPInitializeNetworkMonitor()
+CAResult_t CAIPStartNetworkMonitor()
 {
     return CA_STATUS_OK;
 }
 
-CAResult_t CAIPTerminateNetworkMonitor()
+CAResult_t CAIPStopNetworkMonitor()
 {
     return CA_STATUS_OK;
 }
@@ -104,7 +104,7 @@ u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
         goto exit;
     }
 
-    OIC_LOG_V(ERROR, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family);
+    OIC_LOG_V(DEBUG, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family);
 
     return iflist;
 
index f35de3c..3323c4a 100644 (file)
 // defined & used (as-is defined in the linux socket headers).
 #define AF_INET (2)
 
-CAResult_t CAIPInitializeNetworkMonitor()
+CAResult_t CAIPStartNetworkMonitor()
 {
     return CA_STATUS_OK;
 }
 
-CAResult_t CAIPTerminateNetworkMonitor()
+CAResult_t CAIPStopNetworkMonitor()
 {
     return CA_STATUS_OK;
 }
@@ -108,7 +108,7 @@ u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
         goto exit;
     }
 
-    OIC_LOG_V(ERROR, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family);
+    OIC_LOG_V(DEBUG, TAG, "Added interface: %s (%d)", ifitem->name, ifitem->family);
 
     return iflist;
 
index f2ba419..2528db8 100644 (file)
@@ -264,7 +264,6 @@ CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback,
     caglobals.ip.threadpool = handle;
 
     CAIPSetPacketReceiveCallback(CAIPPacketReceivedCB);
-    CAIPInitializeNetworkMonitor();
 #ifdef __WITH_DTLS__
     CAAdapterNetDtlsInit();
 
@@ -291,6 +290,7 @@ CAResult_t CAStartIP()
 {
     OIC_LOG(DEBUG, TAG, "IN");
 
+    CAIPStartNetworkMonitor();
 #ifdef SINGLE_THREAD
     uint16_t unicastPort = 55555;
     // Address is hardcoded as we are using Single Interface
@@ -418,6 +418,7 @@ CAResult_t CAStopIP()
     CAIPDeinitializeQueueHandles();
 #endif
 
+    CAIPStopNetworkMonitor();
     CAIPStopServer();
 
     OIC_LOG(DEBUG, TAG, "OUT");
@@ -428,8 +429,6 @@ void CATerminateIP()
 {
     OIC_LOG(DEBUG, TAG, "IN");
 
-    CAIPTerminateNetworkMonitor();
-
 #ifdef __WITH_DTLS__
     CADTLSSetAdapterCallbacks(NULL, NULL, 0);
 #endif
index 6ead6a4..fd0f166 100644 (file)
@@ -512,7 +512,15 @@ void CAWakeUpForChange()
 {
     if (caglobals.ip.shutdownFds[1] != -1)
     {
-        write(caglobals.ip.shutdownFds[1], "w", 1);
+        ssize_t len = 0;
+        do
+        {
+            len = write(caglobals.ip.shutdownFds[1], "w", 1);
+        } while ((len == -1) && (errno == EINTR));
+        if ((len == -1) && (errno != EINTR) && (errno != EPIPE))
+        {
+            OIC_LOG_V(DEBUG, TAG, "write failed: %s", strerror(errno));
+        }
     }
 }
 
@@ -625,7 +633,6 @@ static void CAProcessNewInterface(CAInterface_t *ifitem)
     inaddr.s_addr = ifitem->ipv4addr;
     applyMulticastToInterface4(inaddr);
 }
-
 static void CAHandleNetlink()
 {
 #ifdef __linux__
index fd889ee..c70e9cc 100644 (file)
 
 #define TAG "IP_MONITOR"
 
-CAResult_t CAIPInitializeNetworkMonitor()
+CAResult_t CAIPStartNetworkMonitor()
 {
     return CA_STATUS_OK;
 }
 
-CAResult_t CAIPTerminateNetworkMonitor()
+CAResult_t CAIPStopNetworkMonitor()
 {
     return CA_STATUS_OK;
 }
@@ -138,7 +138,7 @@ u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
             goto exit;
         }
 
-        OIC_LOG_V(ERROR, TAG, "Added interface: %s (%d)", ifitem->name, family);
+        OIC_LOG_V(DEBUG, TAG, "Added interface: %s (%d)", ifitem->name, family);
     }
 
     freeifaddrs(ifp);
index b81b357..47e11b4 100644 (file)
@@ -28,6 +28,8 @@
 #include <string.h>
 #include <errno.h>
 #include <unistd.h>
+#include <sys/ioctl.h>
+#include <wifi.h>
 
 #include "caadapterutils.h"
 #include "logger.h"
 #include "oic_string.h"
 
 #define TAG "IP_MONITOR"
+#define MAX_INTERFACE_INFO_LENGTH (1024)
 
-CAResult_t CAIPInitializeNetworkMonitor()
+static CAInterface_t *CANewInterfaceItem(int index, char *name, int family,
+                                         uint32_t addr, int flags);
+
+static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index,
+                                     char *name, int family, uint32_t addr, int flags);
+
+static void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap,
+                                           void *userData);
+
+static void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData);
+
+
+int CAGetPollingInterval(int interval)
 {
-    return CA_STATUS_OK;
+    return interval;
 }
 
-CAResult_t CAIPTerminateNetworkMonitor()
+CAInterface_t *CAFindInterfaceChange()
 {
-    return CA_STATUS_OK;
+    char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 };
+    struct ifconf ifc  = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf };
+
+    int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd;
+    if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
+    {
+        OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno));
+        return NULL;
+    }
+
+    CAInterface_t *foundNewInterface = NULL;
+
+    struct ifreq* ifr = ifc.ifc_req;
+    size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]);
+    size_t ifreqsize = ifc.ifc_len;
+
+    CAIfItem_t *previous = (CAIfItem_t *)OICMalloc(ifreqsize);
+    if (!previous)
+    {
+        OIC_LOG(ERROR, TAG, "OICMalloc failed");
+        return NULL;
+    }
+
+    memcpy(previous, caglobals.ip.nm.ifItems, ifreqsize);
+    size_t numprevious = caglobals.ip.nm.numIfItems;
+
+    if (ifreqsize > caglobals.ip.nm.sizeIfItems)
+    {
+
+        CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize);
+        if (!items)
+        {
+            OIC_LOG(ERROR, TAG, "OICRealloc failed");
+            OICFree(previous);
+            return NULL;
+        }
+        caglobals.ip.nm.ifItems = items;
+        caglobals.ip.nm.sizeIfItems = ifreqsize;
+    }
+
+    caglobals.ip.nm.numIfItems = 0;
+    for (size_t i = 0; i < interfaces; i++)
+    {
+        struct ifreq* item = &ifr[i];
+        char *name = item->ifr_name;
+        struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr;
+        uint32_t ipv4addr = sa4->sin_addr.s_addr;
+
+        if (ioctl(s, SIOCGIFFLAGS, item) < 0)
+        {
+            OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno));
+            continue;
+        }
+        int16_t flags = item->ifr_flags;
+        if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING))
+        {
+            continue;
+        }
+        if (ioctl(s, SIOCGIFINDEX, item) < 0)
+        {
+            OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno));
+            continue;
+        }
+
+        int ifIndex = item->ifr_ifindex;
+        caglobals.ip.nm.ifItems[i].ifIndex = ifIndex;  // refill interface list
+        caglobals.ip.nm.numIfItems++;
+
+        if (foundNewInterface)
+        {
+            continue;   // continue updating interface list
+        }
+
+        // see if this interface didn't previously exist
+        bool found = false;
+        for (size_t j = 0; j < numprevious; j++)
+        {
+            if (ifIndex == previous[j].ifIndex)
+            {
+                found = true;
+                break;
+            }
+        }
+        if (found)
+        {
+            OIC_LOG_V(INFO, TAG, "Interface found: %s", name);
+            continue;
+        }
+
+        foundNewInterface = CANewInterfaceItem(ifIndex, name, AF_INET, ipv4addr, flags);
+    }
+
+    OICFree(previous);
+    return foundNewInterface;
 }
 
-int CAGetPollingInterval(int interval)
+CAResult_t CAIPStartNetworkMonitor()
 {
-    return interval;
+    OIC_LOG(DEBUG, TAG, "IN");
+
+     // Initialize Wifi service
+    wifi_error_e ret = wifi_initialize();
+    if (WIFI_ERROR_NONE != ret)
+    {
+        OIC_LOG(ERROR, TAG, "wifi_initialize failed");
+        return CA_STATUS_FAILED;
+    }
+
+    // Set callback for receiving state changes
+    ret = wifi_set_device_state_changed_cb(CAWIFIDeviceStateChangedCb, NULL);
+    if (WIFI_ERROR_NONE != ret)
+    {
+        OIC_LOG(ERROR, TAG, "wifi_set_device_state_changed_cb failed");
+        return CA_STATUS_FAILED;
+    }
+
+    // Set callback for receiving connection state changes
+    ret = wifi_set_connection_state_changed_cb(CAWIFIConnectionStateChangedCb, NULL);
+    if (WIFI_ERROR_NONE != ret)
+    {
+        OIC_LOG(ERROR, TAG, "wifi_set_connection_state_changed_cb failed");
+        return CA_STATUS_FAILED;
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
 }
 
-CAInterface_t *CAFindInterfaceChange()
+CAResult_t CAIPStopNetworkMonitor()
 {
-    return NULL;
+    OIC_LOG(DEBUG, TAG, "IN");
+
+     // Reset callback for receiving state changes
+    wifi_error_e ret = wifi_unset_device_state_changed_cb();
+    if (WIFI_ERROR_NONE != ret)
+    {
+        OIC_LOG(ERROR, TAG, "wifi_unset_device_state_changed_cb failed");
+    }
+
+    // Reset callback for receiving connection state changes
+    ret = wifi_unset_connection_state_changed_cb();
+    if (WIFI_ERROR_NONE != ret)
+    {
+        OIC_LOG(ERROR, TAG, "wifi_unset_connection_state_changed_cb failed");
+    }
+
+    // Deinitialize Wifi service
+    ret = wifi_deinitialize();
+    if (WIFI_ERROR_NONE != ret)
+    {
+        OIC_LOG(ERROR, TAG, "wifi_deinitialize failed");
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+    return CA_STATUS_OK;
 }
 
 u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
@@ -65,66 +224,168 @@ u_arraylist_t *CAIPGetInterfaceInformation(int desiredIndex)
         return NULL;
     }
 
-    struct ifaddrs *ifp = NULL;
-    if (-1 == getifaddrs(&ifp))
+    char buf[MAX_INTERFACE_INFO_LENGTH] = { 0 };
+    struct ifconf ifc = { .ifc_len = MAX_INTERFACE_INFO_LENGTH, .ifc_buf = buf };
+
+    int s = caglobals.ip.u6.fd != -1 ? caglobals.ip.u6.fd : caglobals.ip.u4.fd;
+    if (ioctl(s, SIOCGIFCONF, &ifc) < 0)
     {
-        OIC_LOG_V(ERROR, TAG, "Failed to get ifaddrs: %s", strerror(errno));
+        OIC_LOG_V(ERROR, TAG, "SIOCGIFCONF failed: %s", strerror(errno));
         u_arraylist_destroy(iflist);
         return NULL;
     }
 
-    struct ifaddrs *ifa = NULL;
-    for (ifa = ifp; ifa; ifa = ifa->ifa_next)
+    struct ifreq* ifr = ifc.ifc_req;
+    size_t interfaces = ifc.ifc_len / sizeof (ifc.ifc_req[0]);
+    size_t ifreqsize = ifc.ifc_len;
+
+    if (ifreqsize > caglobals.ip.nm.sizeIfItems)
     {
-        int family = ifa->ifa_addr->sa_family;
-        if ((ifa->ifa_flags & IFF_LOOPBACK) || (AF_INET != family && AF_INET6 != family))
+        CAIfItem_t *items = (CAIfItem_t *)OICRealloc(caglobals.ip.nm.ifItems, ifreqsize);
+        if (!items)
         {
-            continue;
+            OIC_LOG(ERROR, TAG, "OICRealloc failed");
+            goto exit;
         }
+        caglobals.ip.nm.ifItems = items;
+        caglobals.ip.nm.sizeIfItems = ifreqsize;
+    }
+
+    caglobals.ip.nm.numIfItems = 0;
+    for (size_t i = 0; i < interfaces; i++)
+    {
+        CAResult_t result = CA_STATUS_OK;
+        struct ifreq* item = &ifr[i];
+        char *name = item->ifr_name;
+        struct sockaddr_in *sa4 = (struct sockaddr_in *)&item->ifr_addr;
+        uint32_t ipv4addr = sa4->sin_addr.s_addr;
 
-        int ifindex = if_nametoindex(ifa->ifa_name);
-        int length = u_arraylist_length(iflist);
-        int already = false;
-        for (int i = length-1; i >= 0; i--)
+        if (ioctl(s, SIOCGIFFLAGS, item) < 0)
         {
-            CAInterface_t *ifitem = (CAInterface_t *)u_arraylist_get(iflist, i);
-            if (ifitem->index == ifindex && ifitem->family == family)
-            {
-                already = true;
-                break;
-            }
+            OIC_LOG_V(ERROR, TAG, "SIOCGIFFLAGS failed: %s", strerror(errno));
+            continue;
         }
-        if (already)
+        int16_t flags = item->ifr_flags;
+        if ((flags & IFF_LOOPBACK) || !(flags & IFF_RUNNING))
         {
             continue;
         }
+        if (ioctl(s, SIOCGIFINDEX, item) < 0)
+        {
+            OIC_LOG_V(ERROR, TAG, "SIOCGIFINDEX failed: %s", strerror(errno));
+            continue;
+        }
+
+        int ifindex = item->ifr_ifindex;
+        caglobals.ip.nm.ifItems[i].ifIndex = ifindex;
+        caglobals.ip.nm.numIfItems++;
 
-        CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof(CAInterface_t));
-        if (!ifitem)
+        if (desiredIndex && (ifindex != desiredIndex))
         {
-            OIC_LOG(ERROR, TAG, "Malloc failed");
-            goto exit;
+            continue;
         }
 
-        OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, ifa->ifa_name);
-        ifitem->index = ifindex;
-        ifitem->family = family;
-        ifitem->ipv4addr = ((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr;
-        ifitem->flags = ifa->ifa_flags;
+        // Add IPv4 interface
+        result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET, ipv4addr, flags);
+        if (CA_STATUS_OK != result)
+        {
+            goto exit;
+        }
 
-        bool result = u_arraylist_add(iflist, ifitem);
-        if (!result)
+        // Add IPv6 interface
+        result = CAAddInterfaceItem(iflist, ifindex, name, AF_INET6, ipv4addr, flags);
+        if (CA_STATUS_OK != result)
         {
-            OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
             goto exit;
         }
     }
-
-    freeifaddrs(ifp);
     return iflist;
 
 exit:
-    freeifaddrs(ifp);
     u_arraylist_destroy(iflist);
     return NULL;
 }
+
+static CAResult_t CAAddInterfaceItem(u_arraylist_t *iflist, int index,
+                                     char *name, int family, uint32_t addr, int flags)
+{
+    CAInterface_t *ifitem = CANewInterfaceItem(index, name, family, addr, flags);
+    if (!ifitem)
+    {
+        return CA_STATUS_FAILED;
+    }
+    bool result = u_arraylist_add(iflist, ifitem);
+    if (!result)
+    {
+        OIC_LOG(ERROR, TAG, "u_arraylist_add failed.");
+        OICFree(ifitem);
+        return CA_STATUS_FAILED;
+    }
+
+    return CA_STATUS_OK;
+}
+
+static CAInterface_t *CANewInterfaceItem(int index, char *name, int family,
+                                         uint32_t addr, int flags)
+{
+    CAInterface_t *ifitem = (CAInterface_t *)OICCalloc(1, sizeof (CAInterface_t));
+    if (!ifitem)
+    {
+        OIC_LOG(ERROR, TAG, "Malloc failed");
+        return NULL;
+    }
+
+    OICStrcpy(ifitem->name, INTERFACE_NAME_MAX, name);
+    ifitem->index = index;
+    ifitem->family = family;
+    ifitem->ipv4addr = addr;
+    ifitem->flags = flags;
+
+    return ifitem;
+}
+
+void CAWIFIConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap,
+                                    void *userData)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    if (WIFI_CONNECTION_STATE_ASSOCIATION == state
+        || WIFI_CONNECTION_STATE_CONFIGURATION == state)
+    {
+        OIC_LOG(DEBUG, TAG, "Connection is in Association State");
+        return;
+    }
+
+    if (WIFI_CONNECTION_STATE_CONNECTED == state)
+    {
+        CAWakeUpForChange();
+    }
+    else
+    {
+        u_arraylist_t *iflist = CAIPGetInterfaceInformation(0);
+        if (!iflist)
+        {
+            OIC_LOG_V(ERROR, TAG, "get interface info failed");
+            return;
+        }
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+}
+
+void CAWIFIDeviceStateChangedCb(wifi_device_state_e state, void *userData)
+{
+    OIC_LOG(DEBUG, TAG, "IN");
+
+    if (WIFI_DEVICE_STATE_ACTIVATED == state)
+    {
+        OIC_LOG(DEBUG, TAG, "Wifi is in Activated State");
+    }
+    else
+    {
+        CAWIFIConnectionStateChangedCb(WIFI_CONNECTION_STATE_DISCONNECTED, NULL, NULL);
+        OIC_LOG(DEBUG, TAG, "Wifi is in Deactivated State");
+    }
+
+    OIC_LOG(DEBUG, TAG, "OUT");
+}
index 379aec5..033a4d7 100644 (file)
@@ -40,7 +40,7 @@ if target_os == 'arduino':
 ######################################################################
 libocsrm_env.PrependUnique(CPPPATH = [
                '../../../extlibs/cjson/',
-#              '../../../extlibs/tinydtls/',
+               '../../../extlibs/tinydtls/',
                '../logger/include',
                '../ocrandom/include',
                '../stack/include',
@@ -82,19 +82,44 @@ if not env.get('RELEASE'):
 # Source files and Targets
 ######################################################################
 OCSRM_SRC = 'src/'
-libocsrm_src = [
-       OCSRM_SRC + 'secureresourcemanager.c',
-       OCSRM_SRC + 'resourcemanager.c',
-       OCSRM_SRC + 'aclresource.c',
-       OCSRM_SRC + 'pstatresource.c',
-       OCSRM_SRC + 'doxmresource.c',
-       OCSRM_SRC + 'credresource.c',
-       OCSRM_SRC + 'policyengine.c',
-       OCSRM_SRC + 'psinterface.c',
-       OCSRM_SRC + 'srmresourcestrings.c',
-       OCSRM_SRC + 'srmutility.c',
-       OCSRM_SRC + 'base64.c'
-       ]
+if env.get('SECURED') == '1':
+       libocsrm_src = [
+               OCSRM_SRC + 'secureresourcemanager.c',
+               OCSRM_SRC + 'resourcemanager.c',
+               OCSRM_SRC + 'aclresource.c',
+               OCSRM_SRC + 'amaclresource.c',
+               OCSRM_SRC + 'pstatresource.c',
+               OCSRM_SRC + 'doxmresource.c',
+               OCSRM_SRC + 'credresource.c',
+               OCSRM_SRC + 'svcresource.c',
+               OCSRM_SRC + 'policyengine.c',
+               OCSRM_SRC + 'psinterface.c',
+               OCSRM_SRC + 'srmresourcestrings.c',
+               OCSRM_SRC + 'srmutility.c',
+               OCSRM_SRC + 'iotvticalendar.c',
+               OCSRM_SRC + 'oxmpincommon.c',
+               OCSRM_SRC + 'base64.c',
+               #pbkdf2.c is required to PIN based OxM only.
+               #But we did not use a separate build options to prevent the build command becomes complicated.
+               OCSRM_SRC + 'pbkdf2.c'
+               ]
+else:
+       libocsrm_src = [
+               OCSRM_SRC + 'secureresourcemanager.c',
+               OCSRM_SRC + 'resourcemanager.c',
+               OCSRM_SRC + 'aclresource.c',
+               OCSRM_SRC + 'amaclresource.c',
+               OCSRM_SRC + 'pstatresource.c',
+               OCSRM_SRC + 'doxmresource.c',
+               OCSRM_SRC + 'credresource.c',
+               OCSRM_SRC + 'svcresource.c',
+               OCSRM_SRC + 'policyengine.c',
+               OCSRM_SRC + 'psinterface.c',
+               OCSRM_SRC + 'srmresourcestrings.c',
+               OCSRM_SRC + 'srmutility.c',
+               OCSRM_SRC + 'iotvticalendar.c',
+               OCSRM_SRC + 'base64.c'
+               ]
 
 libocsrm = libocsrm_env.StaticLibrary('libocsrm', libocsrm_src)
 
diff --git a/resource/csdk/security/include/internal/amaclresource.h b/resource/csdk/security/include/internal/amaclresource.h
new file mode 100755 (executable)
index 0000000..e1f4f5b
--- /dev/null
@@ -0,0 +1,79 @@
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef IOTVT_SRM_AMACLR_H
+#define IOTVT_SRM_AMACLR_H
+
+/**
+ * @file
+ *
+ * This file contains the APIs for the /oic/sec/amacl resource is an ACL structure that
+ * specifies which resources will use an Access Manager Service (AMS) to resolve access decisions.
+ * It dynamically obtains an ACL using an AMS.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Initialize Amacl resource by loading data from persistent storage.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitAmaclResource();
+
+/**
+ * Perform cleanup for Amacl resources.
+ *
+ * @retval  none
+ */
+void DeInitAmaclResource();
+
+/**
+ * This method is used by PolicyEngine to retrieve Amacl for a Subject.
+ *
+ * @param subjectId ID of the subject for which Amacl is required.
+ * @param savePtr is used internally by @ref GetAmaclResourceData to maintain index between
+ *                successive calls for same subjectId.
+ *
+ * @retval  reference to @ref OicSecAmacl_t if Amacl is found, else NULL
+ *
+ * @note On the first call to @ref GetAmaclResourceData, savePtr should point to NULL
+ */
+const OicSecAmacl_t* GetAmaclResourceData(const OicUuid_t* subjectId, OicSecAmacl_t **savePtr);
+
+/**
+ * This function converts Amacl data into JSON format.
+ * Caller needs to invoke 'free' when done using
+ * returned string.
+ * @param Amacl  instance of OicSecAmacl_t structure.
+ *
+ * @retval  pointer to Amacl in json format.
+ */
+char* BinToAmaclJSON(const OicSecAmacl_t * amacl);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //IOTVT_SRM_AMACLR_H
+
+
index 9ae31bd..2170521 100644 (file)
@@ -100,6 +100,15 @@ OicSecCred_t * GenerateCredential(const OicUuid_t* subject, OicSecCredType_t cre
  */
 OCStackResult AddCredential(OicSecCred_t * cred);
 
+/**
+ * Function to remove the credential from SVR DB.
+ *
+ * @param credId Credential ID to be deleted.
+ *
+ * @return OC_STACK_OK for success and errorcode otherwise.
+ */
+OCStackResult RemoveCredential(const OicUuid_t* credId);
+
 #if defined(__WITH_DTLS__)
 /**
  * This internal callback is used by lower stack (i.e. CA layer) to
@@ -114,6 +123,24 @@ OCStackResult AddCredential(OicSecCred_t * cred);
  * @retval none
  */
 void GetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo);
+
+/**
+ * Add temporal PSK to PIN based OxM
+ *
+ * @param[in] tmpSubject UUID of target device
+ * @param[in] credType Type of credential to be added
+ * @param[in] pin numeric characters
+ * @param[in] pinSize length of 'pin'
+ * @param[in] ownersLen Number of owners
+ * @param[in] owners Array of owners
+ * @param[out] tmpCredSubject Generated credential's subject.
+ *
+ * @return OC_STACK_OK for success and errorcode otherwise.
+ */
+OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
+                            const char * pin, size_t pinSize,
+                            size_t ownersLen, const OicUuid_t * owners, OicUuid_t* tmpCredSubject);
+
 #endif /* __WITH_DTLS__ */
 
 /**
index cd8477e..e0f2fc9 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef IOTVT_SRM_DOXM_H
 #define IOTVT_SRM_DOXM_H
 
+#include "octypes.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
index 017eb79..9974717 100644 (file)
 extern const char * SVR_DB_FILE_NAME;
 extern const char * OIC_MI_DEF;
 
+//AMACL
+extern const char * OIC_RSRC_TYPE_SEC_AMACL;
+extern const char * OIC_RSRC_AMACL_URI;
+extern const char * OIC_JSON_AMACL_NAME;
+
 //ACL
 extern const char * OIC_RSRC_TYPE_SEC_ACL;
 extern const char * OIC_RSRC_ACL_URI;
@@ -47,8 +52,14 @@ extern const char * OIC_RSRC_TYPE_SEC_CRED;
 extern const char * OIC_RSRC_CRED_URI;
 extern const char * OIC_JSON_CRED_NAME;
 
+//SVC
+extern const char * OIC_RSRC_TYPE_SEC_SVC;
+extern const char * OIC_RSRC_SVC_URI;
+extern const char * OIC_JSON_SVC_NAME;
+
 extern const char * OIC_JSON_SUBJECT_NAME;
 extern const char * OIC_JSON_RESOURCES_NAME;
+extern const char * OIC_JSON_AMSS_NAME;
 extern const char * OIC_JSON_PERMISSION_NAME;
 extern const char * OIC_JSON_OWNERS_NAME;
 extern const char * OIC_JSON_OWNER_NAME;
@@ -63,6 +74,8 @@ extern const char * OIC_JSON_CREDTYPE_NAME;
 extern const char * OIC_JSON_PUBLICDATA_NAME;
 extern const char * OIC_JSON_PRIVATEDATA_NAME;
 extern const char * OIC_JSON_PERIOD_NAME;
+extern const char * OIC_JSON_PERIODS_NAME;
+extern const char * OIC_JSON_RECURRENCES_NAME;
 extern const char * OIC_JSON_ISOP_NAME;
 extern const char * OIC_JSON_COMMIT_HASH_NAME;
 extern const char * OIC_JSON_DEVICE_ID_NAME;
@@ -70,6 +83,8 @@ extern const char * OIC_JSON_CM_NAME;
 extern const char * OIC_JSON_TM_NAME;
 extern const char * OIC_JSON_OM_NAME;
 extern const char * OIC_JSON_SM_NAME;
+extern const char * OIC_JSON_SERVICE_DEVICE_ID;
+extern const char * OIC_JSON_SERVICE_TYPE;
 
 extern OicUuid_t WILDCARD_SUBJECT_ID;
 extern size_t WILDCARD_SUBJECT_ID_LEN;
@@ -78,9 +93,9 @@ extern const char * WILDCARD_RESOURCE_URI;
 //Ownership Transfer Methods
 extern const char * OXM_JUST_WORKS;
 extern const char * OXM_MODE_SWITCH;
-extern const char * RANDOM_DEVICE_PIN;
-extern const char * PRE_PROVISIONED_DEVICE_PIN;
-extern const char * PRE_PROVISIONED_STRONG_CREDENTIAL;
+extern const char * OXM_RANDOM_DEVICE_PIN;
+extern const char * OXM_PRE_PROVISIONED_DEVICE_PIN;
+extern const char * OXM_PRE_PROVISIONED_STRONG_CREDENTIAL;
 
 extern const char * OIC_SEC_TRUE;
 extern const char * OIC_SEC_FALSE;
diff --git a/resource/csdk/security/include/internal/svcresource.h b/resource/csdk/security/include/internal/svcresource.h
new file mode 100644 (file)
index 0000000..9db42c5
--- /dev/null
@@ -0,0 +1,58 @@
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef IOTVT_SRM_SVCR_H
+#define IOTVT_SRM_SVCR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Initialize SVC resource by loading data from persistent storage.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitSVCResource();
+
+/**
+ * Perform cleanup for SVC resources.
+ *
+ * @retval  none
+ */
+void DeInitSVCResource();
+
+/**
+ * This function converts SVC data into JSON format.
+ * Caller needs to invoke 'free' when done using
+ * returned string.
+ * @param svc  instance of OicSecSvc_t structure.
+ *
+ * @retval  pointer to SVC in json format.
+ */
+char* BinToSvcJSON(const OicSecSvc_t * svc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //IOTVT_SRM_SVCR_H
+
+
diff --git a/resource/csdk/security/include/iotvticalendar.h b/resource/csdk/security/include/iotvticalendar.h
new file mode 100644 (file)
index 0000000..2d77be0
--- /dev/null
@@ -0,0 +1,191 @@
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef IOTVT_ICALENDAR_H
+#define IOTVT_ICALENDAR_H
+
+//Not supported on Arduino due lack of absolute time need to implement iCalendar
+#ifndef WITH_ARDUINO
+
+#include <stdint.h> // for uint8_t typedef
+#include <stdbool.h>
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define FREQ_DAILY (1)
+#define MAX_BYDAY_SIZE (7)     //7 days of week
+#define TM_YEAR_OFFSET (1900)  //tm_year field of c-lang tm date-time struct
+                               //represents number of years since 1900.
+#define TM_DST_OFFSET (1)      //c-lang tm struct Daylight Saving Time offset.
+#define TOTAL_HOURS (24)       //Total hours in a day.
+
+typedef struct IotvtICalRecur IotvtICalRecur_t;
+typedef struct IotvtICalPeriod IotvtICalPeriod_t;
+
+/*
+ *  date-time  = date "T" time
+ *
+ *  date               = date-value
+ *  date-value         = date-fullyear date-month date-mday
+ *  date-fullyear      = 4DIGIT
+ *  date-month         = 2DIGIT        ;01-12
+ *  date-mday          = 2DIGIT        ;01-28, 01-29, 01-30, 01-31
+ *                                     ;based on month/year
+ *
+ *  time               = time-hour time-minute time-second [time-utc]
+ *  time-hour          = 2DIGIT        ;00-23
+ *  time-minute        = 2DIGIT        ;00-59
+ *  time-second        = 2DIGIT        ;00-60
+ *                                     ;The "60" value is used to account for "leap" seconds.
+ *
+ *  Date-Time Forms:
+ *  1. Date with Local time
+ *      20150626T150000
+ */
+typedef struct tm IotvtICalDateTime_t; //c-lang tm date-time struct
+
+/*
+ * Bit mask for weekdays
+ */
+typedef enum
+{
+    NO_WEEKDAY  = 0X0,
+    SUNDAY      = (0x1 << 0),
+    MONDAY      = (0x1 << 1),
+    TUESDAY     = (0x1 << 2),
+    WEDNESDAY   = (0x1 << 3),
+    THURSDAY    = (0x1 << 4),
+    FRIDAY      = (0x1 << 5),
+    SATURDAY    = (0x1 << 6)
+}IotvtICalWeekdayBM_t;
+
+/*
+ * Result code for IotvtICalendar
+ */
+typedef enum
+{
+    IOTVTICAL_SUCCESS = 0,       //successfully completed operation
+    IOTVTICAL_VALID_ACCESS,      //access is within allowable time
+    IOTVTICAL_INVALID_ACCESS,    //access is not within allowable time
+    IOTVTICAL_INVALID_PARAMETER, //invalid method parameter
+    IOTVTICAL_INVALID_RRULE,     //rrule is not well form, missing FREQ
+    IOTVTICAL_INVALID_PERIOD,    //period is not well form, start-datetime is after end-datetime
+    IOTVTICAL_ERROR              //encounter error
+}IotvtICalResult_t;
+
+/*
+ *  Grammar for iCalendar data type PERIOD
+ *
+ *  period = date-time "/" date-time  ; start-time / end-time.
+ *                                    ;The start-time MUST be before the end-time.
+ *
+ */
+struct IotvtICalPeriod
+{
+    IotvtICalDateTime_t startDateTime;
+    IotvtICalDateTime_t endDateTime;
+};
+
+/*
+ * Grammar for iCalendar data type RECUR
+ *
+ * recur      = "FREQ"=freq *(
+ *            ( ";" "UNTIL" "=" enddate ) /
+ *            ( ";" "BYDAY" "=" bywdaylist ) /
+ *            )
+ *
+ * freq       = "DAILY"
+ * enddate    = date
+ * bywdaylist = weekday/ ( weekday *("," weekday) )
+ * weekday    = "SU" / "MO" / "TU" / "WE" / "TH" / "FR" / "SA"
+ *
+ * Example:
+ * 1."Allow access on every Monday, Wednesday & Friday between 3pm to 5pm"
+ *      PERIOD:20150626T150000/20150626T170000
+ *      RRULE: FREQ=DAILY; BYDAY=MO, WE, FR
+ * 2."Allow access every Monday, Wednesday & Friday from 3pm to 5pm until
+ *    July 3rd, 2015"
+ *      PERIOD:20150626T150000/20150626T170000
+ *      RRULE: FREQ=DAILY; UNTIL=20150703; BYDAY=MO, WE, FR
+ */
+struct IotvtICalRecur
+{
+    uint16_t                freq;
+    IotvtICalDateTime_t     until;
+    IotvtICalWeekdayBM_t    byDay;
+};
+
+/**
+ * This API is used by policy engine to checks if the
+ * request to access resource is within valid time.
+ *
+ * @param period string representing period.
+ * @param recur string representing recurrence rule
+ *
+ * @return  IOTVTICAL_VALID_ACCESS      -- if the request is within valid time period
+ *          IOTVTICAL_INVALID_ACCESS    -- if the request is not within valid time period
+ *          IOTVTICAL_INVALID_PARAMETER -- if parameter are invalid
+ *          IOTVTICAL_INVALID_PERIOD    -- if period string has invalid format
+ *          IOTVTICAL_INVALID_RRULE     -- if rrule string has invalid format
+ *
+ *Eg: if(IOTVTICAL_VALID_ACCESS == IsRequestWithinValidTime(period, recur))
+ *    {
+ *       //Access within allowable time
+ *    }
+ *    else
+ *    {
+ *      //Access is not within allowable time.
+ *    }
+ */
+IotvtICalResult_t IsRequestWithinValidTime(char *period, char *recur);
+
+/**
+ * Parses periodStr and populate struct IotvtICalPeriod_t
+ *
+ * @param periodStr string to be parsed.
+ * @param period    IotvtICalPeriod_t struct to be populated.
+ *
+ * @return  IOTVTICAL_INVALID_PARAMETER -- if parameter are invalid
+ *          IOTVTICAL_INVALID_PERIOD    -- if period string has invalid format
+ *          IOTVTICAL_INVALID_SUCCESS   -- if no error while parsing
+ */
+IotvtICalResult_t ParsePeriod(const char *periodStr, IotvtICalPeriod_t *period);
+
+/**
+ * Parses recurStr and populate struct IotvtICalRecur_t
+ *
+ * @param recurStr string to be parsed.
+ * @param recur    IotvtICalPeriod_t struct to be populated.
+ *
+ * @return  IOTVTICAL_INVALID_PARAMETER -- if parameter are invalid
+ *          IOTVTICAL_INVALID_PERIOD    -- if period string has invalid format
+ *          IOTVTICAL_INVALID_RRULE     -- if rrule string has invalid format
+ */
+IotvtICalResult_t ParseRecur(const char *recurStr, IotvtICalRecur_t *recur);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif //IOTVT_ICALENDAR_H
diff --git a/resource/csdk/security/include/pbkdf2.h b/resource/csdk/security/include/pbkdf2.h
new file mode 100644 (file)
index 0000000..ff2e3e5
--- /dev/null
@@ -0,0 +1,62 @@
+/* *****************************************************************
+ *
+ * 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.
+ *
+ * *****************************************************************/
+
+#ifndef _PBKDF2_H
+#define _PBKDF2_H
+
+#include <stdio.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * The number of iterations desired to derived key.
+ * (Recommened by RFC 2898)
+ */
+#define PBKDF_ITERATIONS 1000
+
+/**
+ * Function to derive cryptographic key from the password. (RFC 2898)
+ * In this implementation, HMAC with SHA2 is considered as a pseudorandom function
+ *
+ * @param[in] passwd is the master password from which a derived key is generated.
+ * @param[in] pLen is the byte size of the passwd.
+ * @param[in] salt is a cryptographic salt.
+ * @param[in] saltlen is the byte size of the salt.
+ * @param[in] iteration is the number of iterations desired.
+ * @param[in] keyLen is the desired byte size of the derived key. (should be the same as
+ *       derivedKey size)
+ * @param[out] derivedKey is the generated derived key
+ *
+ * @return  0 on success
+ */
+int DeriveCryptoKeyFromPassword(const unsigned char* passwd, size_t pLen,
+                                const uint8_t* salt, const size_t saltLen,
+                                const size_t iterations,
+                                const size_t keyLen, uint8_t* derivedKey);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // _PBKDF2_H
+
diff --git a/resource/csdk/security/include/pinoxmcommon.h b/resource/csdk/security/include/pinoxmcommon.h
new file mode 100644 (file)
index 0000000..b4658ad
--- /dev/null
@@ -0,0 +1,78 @@
+/* *****************************************************************
+ *
+ * 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.
+ *
+ * *****************************************************************/
+
+#ifndef PIN_CALLBACK_DEF_H_
+#define PIN_CALLBACK_DEF_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif // __cplusplus
+
+#define OXM_RANDOM_PIN_SIZE 8
+
+/**
+ * Function pointer to print pin code
+ */
+typedef void (*GeneratePinCallback)(char* pinData, size_t pinSize);
+
+/**
+ * Function pointer to input pin code
+ */
+typedef void (*InputPinCallback)(char* pinBuf, size_t bufSize);
+
+/**
+ * Function to setting generate PIN callback from user
+ *
+ * @param[in] pinCB implementation of generate PIN callback
+ */
+void SetGeneratePinCB(GeneratePinCallback pinCB);
+
+/**
+ * Function to setting input PIN callback from user
+ *
+ * @param[in] pinCB implementation of input PIN callback
+ */
+void SetInputPinCB(InputPinCallback pinCB);
+
+/**
+ * Function to generate random PIN.
+ * This function will send generated PIN to user via callback.
+ *
+ * @param[in,out] pinBuffer   Buffer to store the generated PIN data.
+ * @param[in] bufferSize   Size of buffer
+ * @return OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize);
+
+/**
+ * Function to input PIN callback via input callback
+ *
+ * @param[in,out] pinBuffer Buffer to store the inputed PIN data.
+ * @param[in] bufferSize Size of buffer
+ * @return OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult InputPin(char* pinBuffer, size_t bufferSize);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //PIN_CALLBACK_DEF_H_
index 6df713b..2f69026 100644 (file)
@@ -58,7 +58,9 @@ extern "C" {
 #define SUBJECT_NOT_FOUND_DEF         (1 << 3)
 #define RESOURCE_NOT_FOUND_DEF        (1 << 4)
 #define POLICY_ENGINE_ERROR_DEF       (1 << 5)
+#define INVALID_PERIOD_DEF            (1 << 6)
 #define REASON_MASK_DEF               (INSUFFICIENT_PERMISSION_DEF | \
+                                       INVALID_PERIOD_DEF | \
                                        SUBJECT_NOT_FOUND_DEF | \
                                        RESOURCE_NOT_FOUND_DEF | \
                                        POLICY_ENGINE_ERROR_DEF)
@@ -102,6 +104,8 @@ typedef enum
 {
     ACCESS_GRANTED = ACCESS_GRANTED_DEF,
     ACCESS_DENIED = ACCESS_DENIED_DEF,
+    ACCESS_DENIED_INVALID_PERIOD = ACCESS_DENIED_DEF
+        | INVALID_PERIOD_DEF,
     ACCESS_DENIED_INSUFFICIENT_PERMISSION = ACCESS_DENIED_DEF
         | INSUFFICIENT_PERMISSION_DEF,
     ACCESS_DENIED_SUBJECT_NOT_FOUND = ACCESS_DENIED_DEF
@@ -208,6 +212,13 @@ typedef enum OicSecDpom
     SINGLE_SERVICE_CLIENT_DRIVEN    = 0x3,
 } OicSecDpom_t;
 
+typedef enum OicSecSvcType
+{
+    SERVICE_UNKNOWN                 = 0x0,
+    ACCESS_MGMT_SERVICE             = 0x1,  //urn:oic.sec.ams
+} OicSecSvcType_t;
+
+
 //TODO: Need more clarification on deviceIDFormat field type.
 #if 0
 typedef enum
@@ -222,7 +233,8 @@ typedef enum
     OIC_MODE_SWITCH                         = 0x1,
     OIC_RANDOM_DEVICE_PIN                   = 0x2,
     OIC_PRE_PROVISIONED_DEVICE_PIN          = 0x3,
-    OIC_PRE_PROVISION_STRONG_CREDENTIAL     = 0x4
+    OIC_PRE_PROVISION_STRONG_CREDENTIAL     = 0x4,
+    OIC_OXM_COUNT
 }OicSecOxm_t;
 
 typedef struct OicSecJwk OicSecJwk_t;
@@ -279,9 +291,9 @@ struct OicSecAcl
     size_t              resourcesLen;   // the number of elts in Resources
     char                **resources;    // 1:R:M:Y:String
     uint16_t            permission;     // 2:R:S:Y:UINT16
-    size_t              periodsLen;     // the number of elts in Periods
-    char                **periods;      // 3:R:M*:N:String (<--M*; see Spec)
-    char                *recurrences;   // 5:R:M:N:String
+    size_t              prdRecrLen;     // the number of elts in Periods
+    char                **periods;       // 3:R:M*:N:String (<--M*; see Spec)
+    char                **recurrences;   // 5:R:M:N:String
     size_t              ownersLen;      // the number of elts in Owners
     OicUuid_t           *owners;        // 8:R:M:Y:oic.uuid
     // NOTE: we are using UUID for Owners instead of Svc type for mid-April
@@ -302,13 +314,14 @@ struct OicSecAmacl
     size_t              resourcesLen;   // the number of elts in Resources
     char                **resources;    // 0:R:M:Y:String
     size_t              amssLen;        // the number of elts in Amss
-    OicSecSvc_t         *amss;          // 1:R:M:Y:acl
+    OicUuid_t           *amss;          // 1:R:M:Y:acl
     size_t              ownersLen;      // the number of elts in Owners
     OicUuid_t           *owners;        // 2:R:M:Y:oic.uuid
     // NOTE: we are using UUID for Owners instead of Svc type for mid-April
     // SRM version only; this will change to Svc type for full implementation.
     //TODO change Owners type to oic.sec.svc
     //OicSecSvc_t         *Owners;        // 2:R:M:Y:oic.sec.svc
+    OicSecAmacl_t         *next;
 };
 
 /**
@@ -408,7 +421,11 @@ struct OicSecSacl
 struct OicSecSvc
 {
     // <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
-    //TODO fill in from OIC Security Spec
+    OicUuid_t               svcdid;                 //0:R:S:Y:oic.uuid
+    OicSecSvcType_t         svct;                   //1:R:M:Y:OIC Service Type
+    size_t                  ownersLen;              //2:the number of elts in Owners
+    OicUuid_t               *owners;                //3:R:M:Y:oic.uuid
+    OicSecSvc_t             *next;
 };
 
 #ifdef __cplusplus
index d811e25..9230ef6 100644 (file)
@@ -22,6 +22,8 @@
 #define IOTVT_SRM_UTILITY_H
 
 #include "ocstack.h"
+#include "cJSON.h"
+#include "securevirtualresourcetypes.h"
 #ifdef __cplusplus
 extern "C"
 {
@@ -62,8 +64,8 @@ struct OicParseQueryIter
  * @note Invoking function must define "exit:" label for goto functionality to work correctly.
  *
  */
-#define VERIFY_SUCCESS(tag, op, logLevel) { if (!(op)) \
-            {OC_LOG((logLevel), tag, PCF(#op " failed!!")); goto exit;} }
+#define VERIFY_SUCCESS(tag, op, logLevel) do{ if (!(op)) \
+            {OC_LOG((logLevel), tag, PCF(#op " failed!!")); goto exit; } }while(0)
 
 /**
  * @def VERIFY_NON_NULL
@@ -72,8 +74,8 @@ struct OicParseQueryIter
  * @note Invoking function must define "exit:" label for goto functionality to work correctly.
  *
  */
-#define VERIFY_NON_NULL(tag, arg, logLevel) { if (NULL == (arg)) \
-            { OC_LOG((logLevel), tag, PCF(#arg " is NULL")); goto exit; } }
+#define VERIFY_NON_NULL(tag, arg, logLevel) do{ if (NULL == (arg)) \
+            { OC_LOG((logLevel), tag, PCF(#arg " is NULL")); goto exit; } }while(0)
 
 /**
  * This method initializes the OicParseQueryIter_t struct
@@ -97,6 +99,21 @@ void ParseQueryIterInit(unsigned char * query, OicParseQueryIter_t * parseIter);
  */
 OicParseQueryIter_t * GetNextQuery(OicParseQueryIter_t * parseIter);
 
+
+
+/**
+ * This method acts as a helper funtion for JSON unmarshalling by various SVR's.
+ *
+ * @param jsonRoot  - root JSON node containing the OicUuid array
+ * @param arrayItem - name of the JSON OicUuid array item
+ * @param numUuids  - pointer to the number of OicUuid's available in JSON array
+ * @param uuids     - pointer to the array of OicUuid's
+ *
+ * @return ::OC_STACK_OK on success, some other value upon failure.
+ */
+OCStackResult AddUuidArray(cJSON* jsonRoot, const char* arrayItem,
+                           size_t *numUuids, OicUuid_t** uuids );
+
 #ifdef __cplusplus
 }
 #endif // __cplusplus
diff --git a/resource/csdk/security/provisioning/README.txt b/resource/csdk/security/provisioning/README.txt
new file mode 100644 (file)
index 0000000..ca99cfb
--- /dev/null
@@ -0,0 +1,53 @@
+Quick guide : How to make provisioning tool and servers. 
+
+1. Provisioning Tool.
+
+  1-1. Callback function registration
+       Register the callback functions of ownership transfer method(OxM) using OTMSetOwnershipTransferCallbackData API.
+       You can use default OxM callback implementation located in resource/csdk/security/provisioning/include/oxm.
+
+       [Sample code for just-works OxM]
+           OTMCallbackData_t justWorksCBData = {};
+           justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
+           justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
+           justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
+           justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
+           OTMSetOwnershipTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData);
+
+  1-2. Find un-owned devices using OCDiscoverUnownedDevices API.
+       OCDiscoverUnownedDevices will fill the unowned device list in second parameter.
+
+       [Sample code for unowned device discovery]
+          OCProvisionDev_t* pDeviceList = NULL;
+          OCStackResult res = OCDiscoverUnownedDevices(PREDEFINED_TIMEOUT, &pDeviceList);
+          if(OC_STACK_OK != res)
+          {
+              //error
+          }
+
+       NOTE : We also provide OCDiscoverOwnedDevices API to find owned devices.
+
+  1-3. Performing ownership transfer
+     We provided OCDoOwnershipTransfer API to perform ownership transfer.
+     In order to perform ownership transfer, unowned device list is required generated by OCDiscoverUnownedDevices API.
+     OCDoOwnershipTransfer will require the result callback as 3rd paramter.
+     This callback function will be invoked when ownership transfer is finished.
+     You can check result of ownership transfer for each devices as array of OCProvisionResult_t.
+
+  1-4. Find owned devices using OCDiscoverOwendDevices API.
+  1-5. Provision credential between two owned devices.
+     If you have owned devices,
+     You can send a credential to  two owned devices using OCProvisionPairwiseDevices.
+     You can also send ACL in this process.
+
+  1-6. Free memory.
+     We provide ODDeleteDiscoverdDevices API to free list of OCProvisionDev_t.
+     Please delete your device list before the exit your application.
+
+
+2. Server.
+ The samples are resource/csdk/security/provisioning/sample
+   2-1. Just-works OxM.
+       If you use just-works OxM to server.
+       You don't need any modification for your server.
+
index d5cc915..86317a1 100644 (file)
@@ -35,12 +35,14 @@ provisioning_env.AppendUnique(CPPPATH = [
                '../../ocmalloc/include',
                'include',
                'include/internal',
+               'include/oxm',
                '../../resource/csdk/security/include',
                '../../../../extlibs/cjson/',
-               '../../../../../extlibs/tinydtlsra/',
+               '../../../../../extlibs/tinydtls/',
                '../../connectivity/inc',
                '../../connectivity/external/inc',
                '../../connectivity/common/inc',
+               '../../connectivity/lib/libcoap-4.1.1',
                '../../connectivity/api',
                '../include',
                '../include/internal'
@@ -78,13 +80,17 @@ if target_os in ['darwin', 'ios']:
 # Source files and Targets
 ######################################################################
 provisioning_src = [
-       'src/provisioningmanager.c',
-    'src/credentialgenerator.c'
-       ]
-provisioningserver = provisioning_env.StaticLibrary('ocspapi', provisioning_src)
+       'src/pmutility.c',
+       'src/credentialgenerator.c',
+       'src/ownershiptransfermanager.c',
+       'src/secureresourceprovider.c',
+       'src/ocprovisioningmanager.c',
+       'src/oxmjustworks.c',
+       'src/oxmrandompin.c' ]
+provisioningserver = provisioning_env.StaticLibrary('ocpmapi', provisioning_src)
 
-provisioning_env.InstallTarget(provisioningserver, 'libocspapi')
-provisioning_env.UserInstallTargetLib(provisioningserver, 'libocspapi')
+provisioning_env.InstallTarget(provisioningserver, 'libocpmapi')
+provisioning_env.UserInstallTargetLib(provisioningserver, 'libocpmapi')
 
 if target_os in ['linux']:
        SConscript('sample/SConscript')
index 259a608..470e820 100644 (file)
  *
  * *****************************************************************/
 
-#ifndef SP_CREDENTIAL_GENERATOR_H
-#define SP_CREDENTIAL_GENERATOR_H
+#ifndef PM_CREDENTIAL_GENERATOR_H
+#define PM_CREDENTIAL_GENERATOR_H
 
 #include "ocstack.h"
 #include "securevirtualresourcetypes.h"
-#include "provisioningmanager.h"
 
 /**
  * Function to generate credentials according to the type.
  *
  * @param[in]  type           Type of credential.
+ * @param[in]  keysize        size of key.
  * @param[in]  ptDeviceId     Device ID of provisioning tool.
  * @param[in]  firstDeviceId  DeviceID of the first device.
  * @param[in]  secondDeviceId DeviceID of the second device.
  * @param[out] firstCred      Generated credential for first device.
  * @param[out] secondCred     Generated credential for second device.
- * @return  SP_SUCCESS on success
+ * @return  OC_STACK_OK on success
  */
-SPResult SPGeneratePairWiseCredentials(OicSecCredType_t type, const OicUuid_t *ptDeviceId,
+OCStackResult PMGeneratePairWiseCredentials(OicSecCredType_t type, size_t keySize,
+                                       const OicUuid_t *ptDeviceId,
                                        const OicUuid_t *firstDeviceId,
                                        const OicUuid_t *secondDeviceId,
                                        OicSecCred_t **firstCred,
@@ -45,4 +46,4 @@ SPResult SPGeneratePairWiseCredentials(OicSecCredType_t type, const OicUuid_t *p
 #ifdef __cplusplus
 }
 #endif
-#endif //SP_CREDENTIAL_GENERATOR_H
+#endif //PM_CREDENTIAL_GENERATOR_H
diff --git a/resource/csdk/security/provisioning/include/internal/ownershiptransfermanager.h b/resource/csdk/security/provisioning/include/internal/ownershiptransfermanager.h
new file mode 100644 (file)
index 0000000..64f7368
--- /dev/null
@@ -0,0 +1,98 @@
+/* *****************************************************************\r
+ *\r
+ * Copyright 2015 Samsung Electronics All Rights Reserved.\r
+ *\r
+ *\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * *****************************************************************/\r
+\r
+#ifndef OTM_OWNERSHIPTRANSFERMANAGER_H_\r
+#define OTM_OWNERSHIPTRANSFERMANAGER_H_\r
+\r
+#include "pmtypes.h"\r
+#include "ocstack.h"\r
+#include "octypes.h"\r
+#include "securevirtualresourcetypes.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif // __cplusplus\r
+\r
+#define OXM_STRING_MAX_LENGTH 32\r
+\r
+\r
+/**\r
+ * Context for ownership transfer(OT)\r
+ */\r
+typedef struct OTMContext{\r
+    void* userCtx; /**< Context for user**/\r
+    OCProvisionDev_t* selectedDeviceInfo; /**< Selected device info for OT */\r
+    OicUuid_t tempCredId;\r
+}OTMContext_t;\r
+\r
+/**\r
+ * Do ownership transfer for un-owned device.\r
+ *\r
+ * @param[in] ctx Application context would be returned in result callback\r
+ * @param[in] selectedDeviceInfo selected device information\r
+ * @param[in] resultCB 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 OTMDoOwnershipTransfer(void* ctx,\r
+                                     OCProvisionDev_t* selectedDeviceInfo, OCProvisionResultCB resultCB);\r
+\r
+/*\r
+ *Callback for load secret for temporal secure session\r
+ *\r
+ * e.g) in case of PIN based, input the pin through this callback\r
+ *       in case of X.509 based, input the certificate through this callback\r
+ */\r
+typedef OCStackResult (*OTMLoadSecret)(OTMContext_t* otmCtx);\r
+\r
+\r
+/*\r
+ * Callback for create secure channel using secret inputed from OTMLoadSecret callback\r
+ */\r
+typedef OCStackResult (*OTMCreateSecureSession)(OTMContext_t* otmCtx);\r
+\r
+/*\r
+ * Callback for creating CoAP payload.\r
+ */\r
+typedef char* (*OTMCreatePayloadCallback)(OTMContext_t* otmCtx);\r
+\r
+/**\r
+ * Required callback for performing ownership transfer\r
+ */\r
+typedef struct OTMCallbackData{\r
+    OTMLoadSecret loadSecretCB;\r
+    OTMCreateSecureSession createSecureSessionCB;\r
+    OTMCreatePayloadCallback createSelectOxmPayloadCB;\r
+    OTMCreatePayloadCallback createOwnerTransferPayloadCB;\r
+}OTMCallbackData_t;\r
+\r
+/**\r
+ * Set the callbacks for ownership transfer\r
+ *\r
+ * @param[in] oxm Ownership transfer method\r
+ * @param[in] callbackData the implementation of the ownership transfer function for each step.\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxm, OTMCallbackData_t* callbackData);\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+#endif //OTM_OWNERSHIPTRANSFERMANAGER_H_
\ No newline at end of file
diff --git a/resource/csdk/security/provisioning/include/internal/secureresourceprovider.h b/resource/csdk/security/provisioning/include/internal/secureresourceprovider.h
new file mode 100644 (file)
index 0000000..1ea7fd6
--- /dev/null
@@ -0,0 +1,62 @@
+/* *****************************************************************
+ *
+ * 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.
+ *
+ * *****************************************************************/
+
+#ifndef SRP_SECURERESOURCEPROVIDER_H
+#define SRP_SECURERESOURCEPROVIDER_H
+
+#include "ocstack.h"
+#include "securevirtualresourcetypes.h"
+#include "pmtypes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * API to send ACL information to resource.
+ *
+ * @param[in] selectedDeviceInfo Selected target device.
+ * @param[in] acl ACL to provision.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ *            provisioning request recieves a response from resource server.
+ * @return  SP_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
+                                        OicSecAcl_t *acl, OCProvisionResultCB resultCallback);
+
+/**
+ * API to provision credential to devices.
+ *
+ * @param[in] type Type of credentials to be provisioned to the device.
+ * @param[in] pDev1 Pointer to PMOwnedDeviceInfo_t instance,respresenting resource to be provsioned.
+   @param[in] pDev2 Pointer to PMOwnedDeviceInfo_t instance,respresenting resource to be provsioned.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ *            provisioning request recieves a response from first resource server.
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult SRPProvisionCredentials(void *ctx,OicSecCredType_t type, size_t keySize,
+                                      const OCProvisionDev_t *pDev1,
+                                      const OCProvisionDev_t *pDev2,
+                                      OCProvisionResultCB resultCallback);
+#ifdef __cplusplus
+}
+#endif
+#endif //SRP_SECURERESOURCEPROVIDER_H
diff --git a/resource/csdk/security/provisioning/include/ocprovisioningmanager.h b/resource/csdk/security/provisioning/include/ocprovisioningmanager.h
new file mode 100644 (file)
index 0000000..f7169c1
--- /dev/null
@@ -0,0 +1,155 @@
+/* *****************************************************************\r
+ *\r
+ * Copyright 2015 Samsung Electronics All Rights Reserved.\r
+ *\r
+ *\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ * *****************************************************************/\r
+\r
+#ifndef OCPROVISIONINGMANAGER_H_\r
+#define OCPROVISIONINGMANAGER_H_\r
+\r
+#include "octypes.h"\r
+#include "pmtypes.h"\r
+#include "ownershiptransfermanager.h"\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif // __cplusplus\r
+\r
+/**\r
+ * The function is responsible for initializaton of the provisioning manager. It will load\r
+ * provisioning database which have owned device's list and their linked status.\r
+ * In addition, if there is a device(s) which has not up-to-date credentials, this function will\r
+ * automatically try to update the deivce(s).\r
+ *\r
+ * @param[in] dbPath file path of the sqlite3 db\r
+ *\r
+ * @return OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCProvisionInit(const char* dbPath);\r
+\r
+/**\r
+ * The function is responsible for discovery of device is current subnet. It will list\r
+ * all the device in subnet which are not yet owned. Please call OCInit with OC_CLIENT_SERVER as\r
+ * OCMode.\r
+ *\r
+ * @param[in] timeout Timeout in seconds, value till which function will listen to responses from\r
+ *                    client before returning the list of devices.\r
+ * @param[out] ppList List of candidate devices to be provisioned\r
+ * @return OTM_SUCCESS in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCDiscoverUnownedDevices(unsigned short waittime, OCProvisionDev_t **ppList);\r
+\r
+/**\r
+ * Do ownership transfer for un-owned 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 OCDoOwnershipTransfer(void* ctx,\r
+                                    OCProvisionDev_t *targetDevices,\r
+                                    OCProvisionResultCB resultCallback);\r
+\r
+/**\r
+ * API to register for particular OxM.\r
+ *\r
+ * @param[in] Ownership transfer method.\r
+ * @param[in] Implementation of callback functions for owership transfer.\r
+ * @return  OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCSetOwnerTransferCallbackData(OicSecOxm_t oxm, OTMCallbackData_t* callbackData);\r
+\r
+/**\r
+ * The function is responsible for discovery of owned device is current subnet. It will list\r
+ * all the device in subnet which are owned by calling provisioning client.\r
+ *\r
+ * @param[in] timeout Timeout in seconds, value till which function will listen to responses from\r
+ *                    client before returning the list of devices.\r
+ * @param[out] ppList List of device owned by provisioning tool.\r
+ * @return OTM_SUCCESS in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCDiscoverOwnedDevices(unsigned short timeout, OCProvisionDev_t **ppList);\r
+\r
+/**\r
+ * API to provision credentials between two devices and ACLs for the devices who act as a server.\r
+ *\r
+ * @param[in] ctx Application context would be returned in result callback.\r
+ * @param[in] type Type of credentials to be provisioned to the device.\r
+ * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting device to be provisioned.\r
+ * @param[in] acl ACL for device 1. If this is not required set NULL.\r
+ * @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting device to be provisioned.\r
+ * @param[in] acl ACL for device 2. If this is not required set NULL.\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 OCProvisionPairwiseDevices(void* ctx, OicSecCredType_t type, size_t keySize,\r
+                                         const OCProvisionDev_t *pDev1, OicSecAcl_t *pDev1Acl,\r
+                                         const OCProvisionDev_t *pDev2, OicSecAcl_t *pDev2Acl,\r
+                                         OCProvisionResultCB resultCallback);\r
+\r
+/**\r
+ * API to send ACL information to device.\r
+ *\r
+ * @param[in] ctx Application context would be returned in result callback.\r
+ * @param[in] selectedDeviceInfo Selected target device.\r
+ * @param[in] acl ACL to provision.\r
+ * @param[in] resultCallback callback provided by API user, callback will be called when provisioning\r
+              request recieves a response from resource server.\r
+ * @return  OC_STACK_OK in case of success and other value otherwise.\r
+ */\r
+OCStackResult OCProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecAcl_t *acl,\r
+                             OCProvisionResultCB resultCallback);\r
+\r
+/**\r
+ * API to provision credential to devices.\r
+ *\r
+ * @param[in] ctx Application context would be returned in result callback.\r
+ * @param[in] type Type of credentials to be provisioned to the device.\r
+ * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.\r
+   @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.\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 OCProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,\r
+                                      const OCProvisionDev_t *pDev1,\r
+                                      const OCProvisionDev_t *pDev2,\r
+                                      OCProvisionResultCB resultCallback);\r
+\r
+/**\r
+ * API to delete memory allocated to linked list created by OCDiscover_XXX_Devices API.\r
+ *\r
+ * @param[in] ppList Pointer to OCProvisionDev_t which should be deleted.\r
+ */\r
+void OCDeleteDiscoveredDevices(OCProvisionDev_t **ppList);\r
+\r
+/**\r
+ * API to delete memory allocated to OCProvisionResult_t list in callback function.\r
+ *\r
+ * @note: This function must be called in the callback implementation after checking results.\r
+ *\r
+ * @param[in] pList Pointer to OCProvisionResult_t list which should be deleted.\r
+ */\r
+void OCDeleteProvisionResults(OCProvisionResult_t *pList);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif // __cplusplus\r
+\r
+#endif /* OCPROVISIONINGMANAGER_H_ */\r
diff --git a/resource/csdk/security/provisioning/include/oxm/oxmjustworks.h b/resource/csdk/security/provisioning/include/oxm/oxmjustworks.h
new file mode 100644 (file)
index 0000000..4f2b112
--- /dev/null
@@ -0,0 +1,70 @@
+/* *****************************************************************
+ *
+ * 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.
+ *
+ * *****************************************************************/
+
+#ifndef OXM_JUST_WORKS_H_
+#define OXM_JUST_WORKS_H_
+
+#include "ocstack.h"
+#include "securevirtualresourcetypes.h"
+#include "ownershiptransfermanager.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+//
+//Declaration of default callback functions for just works OxM.
+//
+
+/**
+ * In case of just works OxM, no need to implement.
+ */
+OCStackResult LoadSecretJustWorksCallback(OTMContext_t* UNUSED_PARAM);
+
+/**
+ * To establish a secure channel with anonymous cipher suite
+ *
+ * @param[in] selectedDeviceInfo Selected device infomation
+ * @return OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult CreateSecureSessionJustWorksCallback(OTMContext_t* otmCtx);
+
+/**
+ * Generate payload for select OxM request.
+ *
+ * @param[in] selectedDeviceInfo Selected device infomation
+ * @return DOXM JSON payload including the selected OxM.
+ *         NOTE : Returned memory should be deallocated by caller.
+ */
+char* CreateJustWorksSelectOxmPayload(OTMContext_t* otmCtx);
+
+/**
+ * Generate payload for owner transfer request.
+ *
+ * @param[in] selectedDeviceInfo Selected device infomation
+ * @return DOXM JSON payload including the owner information.
+ *         NOTE : Returned memory should be deallocated by caller.
+ */
+char* CreateJustWorksOwnerTransferPayload(OTMContext_t* otmCtx);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //OXM_JUST_WORKS_H_
\ No newline at end of file
diff --git a/resource/csdk/security/provisioning/include/oxm/oxmrandompin.h b/resource/csdk/security/provisioning/include/oxm/oxmrandompin.h
new file mode 100644 (file)
index 0000000..db5556f
--- /dev/null
@@ -0,0 +1,73 @@
+/* *****************************************************************
+ *
+ * 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.
+ *
+ * *****************************************************************/
+
+#ifndef OXM_RANDOM_PIN_H_
+#define OXM_RANDOM_PIN_H_
+
+#include "ocstack.h"
+#include "securevirtualresourcetypes.h"
+#include "ownershiptransfermanager.h"
+#include "pmtypes.h"
+#include "pinoxmcommon.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+#define OXM_PBKDF2_ITERATIONS 1000
+
+/**
+ * Callback implementation to input the PIN code from user.
+ *
+ * @otmCtx  Context of OTM, It includes current device infomation.
+ * @return OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult InputPinCodeCallback(OTMContext_t* otmCtx);
+
+/**
+ * Callback implemenration to establish a secure channel with PSK cipher suite
+ *
+ * @param[in] selectedDeviceInfo Selected device infomation
+ * @return OC_STACK_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult CreateSecureSessionRandomPinCallbak(OTMContext_t* otmCtx);
+
+/**
+ * Generate payload for select OxM request.
+ *
+ * @param[in] selectedDeviceInfo Selected device infomation
+ * @return DOXM JSON payload including the selected OxM.
+ *         NOTE : Returned memory should be deallocated by caller.
+ */
+char* CreatePinBasedSelectOxmPayload(OTMContext_t* otmCtx);
+
+/**
+ * Generate payload for owner transfer request.
+ *
+ * @param[in] selectedDeviceInfo Selected device infomation
+ * @return DOXM JSON payload including the owner information.
+ *         NOTE : Returned memory should be deallocated by caller.
+ */
+char* CreatePinBasedOwnerTransferPayload(OTMContext_t* otmCtx);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //OXM_RANDOM_PIN_H_
\ No newline at end of file
diff --git a/resource/csdk/security/provisioning/include/pmtypes.h b/resource/csdk/security/provisioning/include/pmtypes.h
new file mode 100644 (file)
index 0000000..377ce2b
--- /dev/null
@@ -0,0 +1,66 @@
+/* *****************************************************************
+ *
+ * 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.
+ *
+ * *****************************************************************/
+
+#ifndef OC_PROVISIONING_TYPES_H
+#define OC_PROVISIONING_TYPES_H
+
+#include <stdbool.h>
+#include "securevirtualresourcetypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Device Information of discoverd unowned/owned device(s) for provisioning.
+ */
+typedef struct OCProvisionDev
+{
+    OCDevAddr       endpoint;        /**< target address **/
+    OicSecPstat_t   *pstat;          /**< Pointer to target's pstat resource. **/
+    OicSecDoxm_t    *doxm;           /**< Pointer to target's doxm resource. **/
+    uint16_t        securePort;      /**< secure port **/
+    struct OCProvisionDev  *next;           /**< Next pointer. **/
+}OCProvisionDev_t;
+
+/**
+ * Result information for each target device.
+ */
+typedef struct OCPMResult{
+    OicUuid_t      deviceId;
+    OCStackResult  res;
+}OCProvisionResult_t;
+
+/**
+ * Callback function definition of provisioning API
+ *
+ * @param[OUT] ctx - If user set his/her context, it will be returned here.
+ * @param[OUT] nOfRes - total number of results, it depends on using which provisioning API.
+ * @param[OUT] arr - Array of OCPMResult_t, each OCPMResult_t contains result for target Device.
+ * @param[OUT} hasError - If there is no error, it's returned with 'false' but if there is a single
+ *                        or more error is/are occured during operation, it will be 'true'.
+ */
+typedef void (*OCProvisionResultCB)(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //OC_PROVISIONING_TYPES_H
\ No newline at end of file
diff --git a/resource/csdk/security/provisioning/include/pmutility.h b/resource/csdk/security/provisioning/include/pmutility.h
new file mode 100644 (file)
index 0000000..79f98b5
--- /dev/null
@@ -0,0 +1,61 @@
+/* *****************************************************************
+ *
+ * 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.
+ *
+ * *****************************************************************/
+
+#ifndef _PM_UTILITY_H_
+#define _PM_UTILITY_H_
+
+#include <stdbool.h>
+#include "ocstack.h"
+#include "pmtypes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define DEFAULT_SECURE_PORT 5684
+
+#define COAPS_PREFIX "coaps://"
+#define COAP_PREFIX "coap://"
+#define COAPS_QUERY "coaps://%s:%d%s"
+#define COAP_QUERY "coap://%s:%d%s"
+
+/**
+ * Discover owned/unowned devices in the same IP subnet. .
+ *
+ * @param[in] waittime      Timeout in seconds.
+ * @param[in] isOwned       bool flag for owned / unowned discovery
+ * @param[in] ppList        List of OCProvisionDev_t.
+ *
+ * @return OC_STACK_OK on success otherwise error.
+ */
+OCStackResult PMDeviceDiscovery(unsigned short waittime, bool isOwned, OCProvisionDev_t **ppList);
+
+/**
+ * This function deletes list of provision target devices
+ *
+ * @param[in] pList         List of OCProvisionDev_t.
+ */
+void DeleteDeviceList(OCProvisionDev_t **pList);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //_PM_UTILITY_H_
diff --git a/resource/csdk/security/provisioning/include/provisioningmanager.h b/resource/csdk/security/provisioning/include/provisioningmanager.h
deleted file mode 100644 (file)
index cf23b88..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/* *****************************************************************
- *
- * 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.
- *
- * *****************************************************************/
-
-#ifndef SP_PROVISION_API_H
-#define SP_PROVISION_API_H
-
-#include "ocstack.h"
-#include "securevirtualresourcetypes.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/**
- * Error Code.
- */
-typedef enum
-{
-    SP_RESULT_SUCCESS = 0,
-    SP_RESULT_INVALID_PARAM,
-    SP_RESULT_MEM_ALLOCATION_FAIL,
-    SP_RESULT_INTERNAL_ERROR,
-    SP_RESULT_TIMEOUT,
-    SP_RESULT_CONN_INVALID_PARAM,
-    SP_RESULT_CONN_ADAPTER_NOT_ENABLED,
-    SP_RESULT_CONN_SERVER_STARTED_ALREADY,
-    SP_RESULT_CONN_SERVER_NOT_STARTED,
-    SP_RESULT_CONN_DESTINATION_NOT_REACHABLE,
-    SP_RESULT_CONN_SOCKET_OPERATION_FAILED,
-    SP_RESULT_CONN_SEND_FAILED,
-    SP_RESULT_CONN_RECEIVE_FAILED,
-    SP_RESULT_CONN_MEMORY_ALLOC_FAILED,
-    SP_RESULT_CONN_REQUEST_TIMEOUT,
-    SP_RESULT_CONN_DESTINATION_DISCONNECTED,
-    SP_RESULT_CONN_STATUS_FAILED,
-    SP_RESULT_CONN_NOT_SUPPORTED
-
-} SPResult;
-
-typedef struct SPTargetDeviceInfo SPTargetDeviceInfo_t;
-typedef struct SPDevInfo SPDevInfo_t;
-
-/**
- * Device Info structure.
- */
-struct SPTargetDeviceInfo
-{
-    OCDevAddr endpoint;             /**< target address **/
-    OicSecPstat_t *pstat;           /**< Pointer to target's pstat resource. **/
-    OicSecDoxm_t *doxm;             /**< Pointer to target's doxm resource. **/
-    uint16_t securePort;            /**< Secure port **/
-    SPTargetDeviceInfo_t *next;     /**< Next pointer. **/
-};
-
-/**
- * Owned target device info
- */
-struct SPDevInfo
-{
-    OCDevAddr endpoint;             /**< target address **/
-    OicUuid_t deviceId;             /**< Device ID. **/
-    SPDevInfo_t *next;              /**< Next pointer. **/
-};
-
-/**
- * The function is responsible for discovery of device is current subnet. It will list
- * all the device in subnet which are not yet owned. Please call OCInit with OC_CLIENT_SERVER as
- * OCMode.
- *
- * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
- *                    client before returning the list of devices.
- * @param[out] list List of provision candidate devices.
- * @return SP_SUCCESS in case of success and other value otherwise.
- */
-SPResult SPProvisioningDiscovery(unsigned short timeout,
-                                 SPTargetDeviceInfo_t **list);
-
-/**
- * The function is reponsible for following activities:
- * - Send post to /oic/sec/doxm resource with selected ownership transfer method
- * - Get pstat resource of target device to enumerate supported operation modes.
- * - Select and let the target device know the selected methods.
- * - Initiate anon handshake and save owner PSK
- * - Update doxm resource of target device with ownership info.
- *
- * @param[in] timeout  Timeout value in secs till which call REST request will wait before
- *                     returning error in case of 0 function will wait till success.
- * @param[in] selectedDeviceInfo Device information.
- * @return SP_SUCCESS in case of success and other value otherwise.
- */
-SPResult SPInitProvisionContext(unsigned short timeout,
-                                SPTargetDeviceInfo_t *selectedDeviceInfo);
-
-/**
- * Function to send ACL information to resource.
- *
- * @param[in] timeout Timeout value in secs till which call to REST request will wait before
- *                     returning error in case of 0 function will wait till success.
- * @param[in] selectedDeviceInfo Selected target device.
- * @param[in] acl ACL to provision
- * @return  SP_SUCCESS in case of success and other value otherwise.
- */
-SPResult SPProvisionACL(unsigned short timeout, const SPTargetDeviceInfo_t *selectedDeviceInfo,
-                        OicSecAcl_t *acl);
-
-/**
- * Function to send credential information to list of resources.
- *
- * @param[in] timeout Timeout value in secs till which call to REST request will wait before
- *                    returning error in case of 0 function will wait till success.
- * @param[in] type Type of credentials to be provisioned to the device.
- * @param[in] pDevList List of devices to be provisioned with the specified credential.
- *
- * @return  SP_SUCCESS in case of success and other value otherwise.
- */
-SPResult SPProvisionCredentials(unsigned short timeout, OicSecCredType_t type,
-                                const SPDevInfo_t *pDevList);
-
-/**
- * Function to confirm the ACL post request to check  whether its updated at
- * resource server end properly or not.
- *
- * @param[in] timeout Timeout value in seconds till which call REST request will wait
- *                     before returning error in case of 0 function will wait till success.
- * @param[in] context Provisioning context
- * @return  SP_SUCCESS on success
- */
-SPResult SPFinalizeProvisioning(unsigned short timeout,
-                                SPTargetDeviceInfo_t *selectedDeviceInfo);
-
-/**
- * Function to end Provisioning session.
- *
- * @return  SP_SUCCESS on success
- */
-SPResult SPTerminateProvisioning();
-
-#ifdef __cplusplus
-}
-#endif
-#endif //SP_PROVISION_API_H
index 1947307..46e270e 100644 (file)
@@ -32,8 +32,10 @@ provisioning_env.AppendUnique(CPPPATH = [
                '../../../logger/include',
                '../../../stack/include',
                '../../../security/include',
+               '../../../security/provisioning/include/internal',
                '../../../../oc_logger/include',
                '../include',
+               '../include/oxm',
                '../../include',
                '../../../../../extlibs/tinydtls',
                '../../../../../extlibs/cjson',
@@ -49,7 +51,7 @@ provisioning_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread', '-f
 provisioning_env.AppendUnique(RPATH = [env.get('BUILD_DIR')])
 provisioning_env.AppendUnique(LIBS = ['-lpthread'])
 provisioning_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
-provisioning_env.PrependUnique(LIBS = ['ocspapi','oc', 'oc_logger', 'ocsrm','m', 'octbstack', 'connectivity_abstraction', 'coap'])
+provisioning_env.PrependUnique(LIBS = ['ocpmapi','oc', 'oc_logger', 'ocsrm','m', 'octbstack', 'connectivity_abstraction', 'coap'])
 
 if env.get('SECURED') == '1':
     provisioning_env.AppendUnique(LIBS = ['tinydtls'])
@@ -62,8 +64,10 @@ provisioning_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
 ######################################################################
 
 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')
 
-Alias("sample", [provisioningclient])
+Alias("samples", [provisioningclient, sampleserver_justworks, sampleserver_randompin])
 
 provisioning_env.AppendTarget('samples')
 
@@ -72,6 +76,8 @@ sec_provisioning_src_dir = src_dir + '/resource/csdk/security/provisioning/sampl
 sec_provisioning_build_dir = env.get('BUILD_DIR') +'/resource/csdk/security/provisioning/sample/'
 
 provisioning_env.Alias("install", provisioning_env.Install( sec_provisioning_build_dir,
-    sec_provisioning_src_dir + 'oic_svr_db_prov_tool.json'))
+    sec_provisioning_src_dir + 'oic_svr_db_client.json'))
 provisioning_env.Alias("install", provisioning_env.Install( sec_provisioning_build_dir,
-    sec_provisioning_src_dir + 'oic_svr_db_unowned_server.json'))
+    sec_provisioning_src_dir + 'oic_svr_db_server_justworks.json'))
+provisioning_env.Alias("install", provisioning_env.Install( sec_provisioning_build_dir,
+    sec_provisioning_src_dir + 'oic_svr_db_server_randompin.json'))
diff --git a/resource/csdk/security/provisioning/sample/oic_svr_db_client.json b/resource/csdk/security/provisioning/sample/oic_svr_db_client.json
new file mode 100644 (file)
index 0000000..49fb2a8
--- /dev/null
@@ -0,0 +1,43 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/d",
+                "/oic/p",
+                "/oic/res/types/d",
+                "/oic/ad"
+                       ],
+                       "perms": 2,
+                       "ownrs" : ["YWRtaW5EZXZpY2VVVUlEMA=="]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat",
+                "/oic/sec/acl",
+                "/oic/sec/cred"
+             ],
+             "perms": 7,
+             "ownrs" : ["YWRtaW5EZXZpY2VVVUlEMA=="]
+        }
+       ],
+       "pstat":        {
+               "isop": true,
+               "deviceid":     "YWRtaW5EZXZpY2VVVUlEMA==",
+               "ch": 0,
+               "cm":   0,
+               "tm":   0,
+               "om":   3,
+               "sm":   [3]
+       },
+       "doxm": {
+               "oxm":  [0],
+               "oxmsel": 0,
+               "owned": true,
+               "deviceid":     "YWRtaW5EZXZpY2VVVUlEMA==",
+               "ownr": "YWRtaW5EZXZpY2VVVUlEMA=="
+       }
+}
diff --git a/resource/csdk/security/provisioning/sample/oic_svr_db_server_justworks.json b/resource/csdk/security/provisioning/sample/oic_svr_db_server_justworks.json
new file mode 100644 (file)
index 0000000..dab0d70
--- /dev/null
@@ -0,0 +1,45 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/res/d",
+                "/oic/res/types/d",
+                "/oic/presence"
+                       ],
+                       "perms": 2,
+                       "ownrs" : [
+                               "anVzdHdvcmtzRGV2VVVJRA=="
+                       ]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat",
+                "/oic/sec/acl",
+                "/oic/sec/cred"
+             ],
+             "perms": 6,
+             "ownrs" : [
+                 "anVzdHdvcmtzRGV2VVVJRA=="
+             ]
+        }
+       ],
+       "pstat":        {
+               "isop": false,
+               "deviceid":     "anVzdHdvcmtzRGV2VVVJRA==",
+               "commithash": 0,
+               "cm":   0,
+               "tm":   0,
+               "om":   3,
+               "sm":   [3]
+       },
+       "doxm": {
+               "oxm":  [0],
+               "oxmsel": 0,
+               "owned": false,
+               "deviceid":     "anVzdHdvcmtzRGV2VVVJRA=="
+       }
+}
diff --git a/resource/csdk/security/provisioning/sample/oic_svr_db_server_randompin.json b/resource/csdk/security/provisioning/sample/oic_svr_db_server_randompin.json
new file mode 100644 (file)
index 0000000..a3a4b6f
--- /dev/null
@@ -0,0 +1,45 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/res/d",
+                "/oic/res/types/d",
+                "/oic/presence"
+                       ],
+                       "perms": 2,
+                       "ownrs" : [
+                               "cmFuZG9tUGluRGV2VVVJRA=="
+                       ]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat",
+                "/oic/sec/acl",
+                "/oic/sec/cred"
+             ],
+             "perms": 6,
+             "ownrs" : [
+                 "cmFuZG9tUGluRGV2VVVJRA=="
+             ]
+        }
+       ],
+       "pstat":        {
+               "isop": false,
+               "deviceid":     "cmFuZG9tUGluRGV2VVVJRA==",
+               "commithash": 0,
+               "cm":   0,
+               "tm":   0,
+               "om":   3,
+               "sm":   [3]
+       },
+       "doxm": {
+               "oxm":  [0,2],
+               "oxmsel": 0,
+               "owned": false,
+               "deviceid":     "cmFuZG9tUGluRGV2VVVJRA=="
+       }
+}
index b342959..ee16b58 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
-#include <getopt.h>
+
 #include "logger.h"
 #include "oic_malloc.h"
 #include "utlist.h"
-#include "securevirtualresourcetypes.h"
-#include "provisioningmanager.h"
+#include "ocprovisioningmanager.h"
+#include "secureresourceprovider.h"
+#include "oxmjustworks.h"
+#include "oxmrandompin.h"
+#include "pinoxmcommon.h"
+#include "oic_string.h"
 
 #define MAX_URI_LENGTH (64)
 #define MAX_PERMISSION_LENGTH (5)
-#define MAX_INPUT_ID_LENGTH (16)
-#define PREDEFINED_TIMEOUT (10)
 #define CREATE (1)
 #define READ (2)
 #define UPDATE (4)
 #define DELETE (8)
 #define NOTIFY (16)
 #define DASH '-'
+#define PREDEFINED_TIMEOUT (10)
+#define MAX_OWNED_DEVICE (10)
 #define TAG  "provisioningclient"
 
-static OicSecAcl_t        *gAcl = NULL;
-static char PROV_TOOL_DB_FILE[] = "oic_svr_db_prov_tool.json";
+static char CRED_FILE[] = "oic_svr_db_client.json";
+static OicSecAcl_t        *gAcl1 = NULL;
+static OicSecAcl_t        *gAcl2 = NULL;
+static int gOwnershipState = 0;
+
+typedef enum
+{
+    ownershipDone = 1 << 1,
+    finalizeDone = 1 << 2,
+    provisionCredDone = 1 << 3,
+    provisionAclDone = 1 << 4
+} StateManager;
+
 
 /**
- * Perform cleanup for ACL list
- *
- * @param[in]    ACL list
+ * Perform cleanup for ACL
+ * @param[in]    ACL
  */
-static void DeleteACLList(OicSecAcl_t *acl)
+static void deleteACL(OicSecAcl_t *acl)
 {
     if (acl)
     {
-        OicSecAcl_t *aclTmp1 = NULL;
-        OicSecAcl_t *aclTmp2 = NULL;
-        LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
+        /* Clean Resources */
+        for (size_t i = 0; i < (acl)->resourcesLen; i++)
         {
-            LL_DELETE(acl, aclTmp1);
+            OICFree((acl)->resources[i]);
+        }
+        OICFree((acl)->resources);
 
-            /* Clean Resources */
-            for (int i = 0; i < aclTmp1->resourcesLen; i++)
-            {
-                OICFree(aclTmp1->resources[i]);
-            }
-            OICFree(aclTmp1->resources);
+        /* Clean Owners */
+        OICFree((acl)->owners);
 
-            /* Clean Owners */
-            OICFree(aclTmp1->owners);
+        /* Clean ACL node itself */
+        OICFree((acl));
 
-            /* Clean ACL node itself */
-            OICFree(aclTmp1);
-        }
         acl = NULL;
     }
 }
@@ -80,17 +88,15 @@ static void DeleteACLList(OicSecAcl_t *acl)
  *
  * @param[in] temp_psm    Input data of ACL permission string
  * @param[in,out] pms    The pointer of ACL permission value
- * @return  0 on success otherwise a positive error value
- * @retval  SP_RESULT_SUCCESS    Successful
- * @retval  SP_RESULT_INVALID_PARAM    Invaild input arguments
+ * @return  0 on success otherwise -1.
  */
-static SPResult CalculateAclPermission(const char *temp_pms, uint16_t *pms)
+static int CalculateAclPermission(const char *temp_pms, uint16_t *pms)
 {
     int i = 0;
 
     if (NULL == temp_pms || NULL == pms)
     {
-        return SP_RESULT_INVALID_PARAM;
+        return -1;
     }
     *pms = 0;
     while (temp_pms[i] != '\0')
@@ -134,25 +140,23 @@ static SPResult CalculateAclPermission(const char *temp_pms, uint16_t *pms)
                 }
             default:
                 {
-                    return SP_RESULT_INVALID_PARAM;
+                    return -1;
                 }
         }
     }
-    return SP_RESULT_SUCCESS;
+    return 0;
 }
 
 /**
  * Get the ACL property from user
  *
  * @param[in]    ACL Datastructure to save user inputs
- * @return  0 on success otherwise a positive error value
- * @retval  SP_RESULT_SUCCESS    Successful
- * @retval  SP_RESULT_MEM_ALLOCATION_FAIL    Memmory allocation failure
+ * @return  0 on success otherwise -1.
  */
-static SPResult InputACL(OicSecAcl_t *acl)
+static int InputACL(OicSecAcl_t *acl)
 {
-    int unused __attribute__((unused));
-    char temp_id [MAX_INPUT_ID_LENGTH + 4] = {0,};
+    int ret;
+    char temp_id [UUID_LENGTH + 4] = {0,};
     char temp_rsc[MAX_URI_LENGTH + 1] = {0,};
     char temp_pms[MAX_PERMISSION_LENGTH + 1] = {0,};
     printf("******************************************************************************\n");
@@ -162,37 +166,65 @@ static SPResult InputACL(OicSecAcl_t *acl)
     printf("-URN identifying the subject\n");
     printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
     printf("Subject : ");
-    unused = scanf("%19s", temp_id);
+    char *ptr = NULL;
+    ret = scanf("%19ms", &ptr);
+    if(1==ret)
+    {
+        OICStrcpy(temp_id, sizeof(temp_id), ptr);
+        OICFree(ptr);
+    }
+    else
+    {
+         printf("Error while input\n");
+         return -1;
+    }
     int j = 0;
     for (int i = 0; temp_id[i] != '\0'; i++)
     {
         if (DASH != temp_id[i])
+        {
+            if(j>UUID_LENGTH)
+            {
+                printf("Invalid input\n");
+                return -1;
+            }
             acl->subject.id[j++] = temp_id[i];
+        }
     }
 
     //Set Resource.
-    printf("Num. of Resource : ");
-    unused = scanf("%zu", &acl->resourcesLen);
+    printf("Num. of Resource : \n");
+    ret = scanf("%zu", &acl->resourcesLen);
     printf("-URI of resource\n");
     printf("ex)/oic/sh/temp/0 (Max_URI_Length: 64 Byte )\n");
-    acl->resources = (char **)OICMalloc(acl->resourcesLen * sizeof(char *));
+    acl->resources = (char **)OICCalloc(acl->resourcesLen, sizeof(char *));
     if (NULL == acl->resources)
     {
         OC_LOG(ERROR, TAG, "Error while memory allocation");
-        return SP_RESULT_MEM_ALLOCATION_FAIL;
+        return -1;
     }
-    for (int i = 0; i < acl->resourcesLen; i++)
+    for (size_t i = 0; i < acl->resourcesLen; i++)
     {
-        printf("[%d]Resource : ", i + 1);
-        unused = scanf("%64s", temp_rsc);
-        acl->resources[i] = (char *)OICMalloc((strlen(temp_rsc) + 1) * sizeof(char));
+        printf("[%zu]Resource : ", i + 1);
+        char *ptr_tempRsc = NULL;
+        ret = scanf("%64ms", &ptr_tempRsc);
+        if (1==ret)
+        {
+            OICStrcpy(temp_rsc, sizeof(temp_rsc), ptr_tempRsc);
+            OICFree(ptr_tempRsc);
+        }
+        else
+        {
+            printf("Error while input\n");
+            return -1;
+        }
+        acl->resources[i] = OICStrdup(temp_rsc);
+
         if (NULL == acl->resources[i])
         {
             OC_LOG(ERROR, TAG, "Error while memory allocation");
-            return SP_RESULT_MEM_ALLOCATION_FAIL;
+            return -1;
         }
-        strncpy(acl->resources[i], temp_rsc, strlen(temp_rsc));
-        acl->resources[i][strlen(temp_rsc)] = '\0';
     }
     // Set Permission
     do
@@ -200,24 +232,47 @@ static SPResult InputACL(OicSecAcl_t *acl)
         printf("-Set the permission(C,R,U,D,N)\n");
         printf("ex) CRUDN, CRU_N,..(5 Charaters)\n");
         printf("Permission : ");
-        unused = scanf("%5s", temp_pms);
+        char *ptr_temp_pms = NULL;
+        ret = scanf("%5ms", &ptr_temp_pms);
+        if(1 == ret)
+        {
+            OICStrcpy(temp_pms, sizeof(temp_pms), ptr_temp_pms);
+            OICFree(ptr_temp_pms);
+
+        }
+        else
+        {
+            printf("Error while input\n");
+            return -1;
+        }
     }
-    while (SP_RESULT_SUCCESS != CalculateAclPermission(temp_pms, &(acl->permission)) );
+    while (0 != CalculateAclPermission(temp_pms, &(acl->permission)) );
     // Set Rowner
     printf("Num. of Rowner : ");
-    unused = scanf("%zu", &acl->ownersLen);
+    ret = scanf("%zu", &acl->ownersLen);
     printf("-URN identifying the rowner\n");
     printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
     acl->owners = (OicUuid_t *)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
     if (NULL == acl->owners)
     {
         OC_LOG(ERROR, TAG, "Error while memory allocation");
-        return SP_RESULT_MEM_ALLOCATION_FAIL;
+        return -1;
     }
-    for (int i = 0; i < acl->ownersLen; i++)
+    for (size_t i = 0; i < acl->ownersLen; i++)
     {
-        printf("[%d]Rowner : ", i + 1);
-        unused = scanf("%19s", temp_id);
+        printf("[%zu]Rowner : ", i + 1);
+        char *ptr_temp_id = NULL;
+        ret = scanf("%19ms", &ptr_temp_id);
+        if (1 == ret)
+        {
+            OICStrcpy(temp_id, sizeof(temp_id), ptr_temp_id);
+            OICFree(ptr_temp_id);
+        }
+        else
+        {
+            printf("Error while input\n");
+            return -1;
+        }
         j = 0;
         for (int k = 0; temp_id[k] != '\0'; k++)
         {
@@ -227,27 +282,116 @@ static SPResult InputACL(OicSecAcl_t *acl)
             }
         }
     }
-    return SP_RESULT_SUCCESS;
+    return 0;
+}
+
+
+//FILE *client_fopen(const char *path, const char *mode)
+FILE *client_fopen(const char* UNUSED_PARAM , const char *mode)
+{
+    (void)UNUSED_PARAM;
+    return fopen(CRED_FILE, mode);
+}
+
+void PrintfResult(const char* procName, void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+    printf("-----------------------------------------------------------\n");
+    if(!hasError)
+    {
+        printf("%s was successfully done.\n", procName);
+    }
+    else
+    {
+        for(int i = 0; i < nOfRes; i++)
+        {
+            printf("UUID : ");
+            for(int j = 0; j < UUID_LENGTH; i++)
+            {
+                printf("%c", arr[i].deviceId.id[j]);
+            }
+            printf("\t");
+            printf("Result=%d\n", arr[i].res);
+        }
+    }
+
+    if(ctx)
+    {
+        printf("Context is %s\n", (char*)ctx);
+    }
+    printf("-----------------------------------------------------------\n");
+}
+
+void ProvisionCredCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+    if(!hasError)
+    {
+        gOwnershipState = 1;
+        PrintfResult("Provision Credential", ctx, nOfRes, arr, hasError);
+    }
+}
+
+void ProvisionAclCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+    if(!hasError)
+    {
+        gOwnershipState = 1;
+        PrintfResult("Provision ACL", ctx, nOfRes, arr, hasError);
+    }
 }
 
-FILE* client_fopen(const char *path, const char *mode)
+void ProvisionPairwiseCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
 {
-    (void)path;
-    return fopen(PROV_TOOL_DB_FILE, mode);
+    if(!hasError)
+    {
+        gOwnershipState = 1;
+        PrintfResult("Provision Pairwise Credential", ctx, nOfRes, arr, hasError);
+    }
+}
+
+void OwnershipTransferCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+    if(!hasError)
+    {
+        gOwnershipState = 1;
+        PrintfResult("Ownership transfer", ctx, nOfRes, arr, hasError);
+    }
+}
+
+void InputPinCB(char* pinBuf, size_t bufSize)
+{
+    if(pinBuf)
+    {
+        printf("INPUT PIN : ");
+        char *ptr = NULL;
+        int ret = scanf("%ms", &ptr);
+        if(1 == ret)
+        {
+            OICStrcpy(pinBuf, bufSize, ptr);
+            OICFree(ptr);
+        }
+        else
+        {
+             printf("Error in input\n");
+             return;
+        }
+    }
 }
 
 /**
- * Provisioning client sample using ProvisioningAPI on provisioningmanager.c
- * To change network type use command line option -w for Wifi and -e for Ethernet
+ * Provisioning client sample using ProvisioningAPI
  */
-int main(int argc, char **argv)
+int main()
 {
-    SPResult res = SP_RESULT_SUCCESS;
-    SPTargetDeviceInfo_t *pDeviceList = NULL;
-    gAcl = (OicSecAcl_t *)OICMalloc(sizeof(OicSecAcl_t));
+    OCStackResult res = OC_STACK_OK;
+    int unused;
+    (void)unused;
 
     // Initialize Persistent Storage for SVR database
-    OCPersistentStorage ps = {};
+    OCPersistentStorage ps = { .open = NULL,
+                               .read = NULL,
+                               .write = NULL,
+                               .close = NULL,
+                               .unlink = NULL };
     ps.open = client_fopen;
     ps.read = fread;
     ps.write = fwrite;
@@ -255,72 +399,175 @@ int main(int argc, char **argv)
     ps.unlink = unlink;
     OCRegisterPersistentStorageHandler(&ps);
 
-    if (OCInit(NULL, 0, OC_CLIENT_SERVER) != OC_STACK_OK)
+    if (OC_STACK_OK != OCInit(NULL, 0, OC_CLIENT_SERVER))
     {
         OC_LOG(ERROR, TAG, "OCStack init error");
-        return 0;
+        goto error;
     }
 
-    if (NULL == gAcl)
+    OCProvisionDev_t* pDeviceList = NULL;
+    res = OCDiscoverUnownedDevices(PREDEFINED_TIMEOUT, &pDeviceList);
+    if(OC_STACK_OK != res)
     {
-        OC_LOG(ERROR, TAG, "Error while memory allocation");
-        return SP_RESULT_MEM_ALLOCATION_FAIL;
+        OC_LOG_V(ERROR, TAG, "Failed to PMDeviceDiscovery : %d", res);
+        goto error;
+    }
+
+    OCProvisionDev_t* pCurDev = pDeviceList;
+    int i;
+    while(pCurDev !=NULL)
+    {
+        for(i = 0; i < UUID_LENGTH; i++)
+            printf("%c", pCurDev->doxm->deviceID.id[i]);
+        printf("\n");
+        pCurDev = pCurDev->next;
+    }
+
+    //Register callback function to each OxM
+    OTMCallbackData_t justWorksCBData = {.loadSecretCB=NULL,
+                                         .createSecureSessionCB=NULL,
+                                         .createSelectOxmPayloadCB=NULL,
+                                         .createOwnerTransferPayloadCB=NULL};
+    justWorksCBData.loadSecretCB = LoadSecretJustWorksCallback;
+    justWorksCBData.createSecureSessionCB = CreateSecureSessionJustWorksCallback;
+    justWorksCBData.createSelectOxmPayloadCB = CreateJustWorksSelectOxmPayload;
+    justWorksCBData.createOwnerTransferPayloadCB = CreateJustWorksOwnerTransferPayload;
+    OTMSetOwnershipTransferCallbackData(OIC_JUST_WORKS, &justWorksCBData);
+
+    OTMCallbackData_t pinBasedCBData = {.loadSecretCB=NULL,
+                                         .createSecureSessionCB=NULL,
+                                         .createSelectOxmPayloadCB=NULL,
+                                         .createOwnerTransferPayloadCB=NULL};
+    pinBasedCBData.loadSecretCB = InputPinCodeCallback;
+    pinBasedCBData.createSecureSessionCB = CreateSecureSessionRandomPinCallbak;
+    pinBasedCBData.createSelectOxmPayloadCB = CreatePinBasedSelectOxmPayload;
+    pinBasedCBData.createOwnerTransferPayloadCB = CreatePinBasedOwnerTransferPayload;
+    OTMSetOwnershipTransferCallbackData(OIC_RANDOM_DEVICE_PIN, &pinBasedCBData);
+
+    SetInputPinCB(&InputPinCB);
+
+    char* myContext = "OTM Context";
+    //Perform ownership transfer
+    res = OCDoOwnershipTransfer((void*)myContext, pDeviceList, OwnershipTransferCB);
+    if(OC_STACK_OK == res)
+    {
+        OC_LOG(INFO, TAG, "Request for ownership transfer is sent successfully.");
+    }
+    else
+    {
+        OC_LOG_V(ERROR, TAG, "Failed to OCDoOwnershipTransfer : %d", res);
+    }
+
+    gOwnershipState = 0;
+    while ( gOwnershipState == 0 )
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            goto error;
+        }
+        sleep(1);
     }
 
-    res = SPProvisioningDiscovery(PREDEFINED_TIMEOUT, &pDeviceList);
-    if (SP_RESULT_SUCCESS == res)
+// Credential & ACL provisioning between two devices.
+
+    OCProvisionDev_t *pOwnedList = NULL;
+    OCProvisionDev_t *pOwnedDevices [MAX_OWNED_DEVICE] = {0,};
+    int nOwnedDevice = 0;
+
+    res = OCDiscoverOwnedDevices(PREDEFINED_TIMEOUT, &pOwnedList);
+    if (OC_STACK_OK == res)
     {
-        while (pDeviceList != NULL)
+        printf("################## Owned Device List #######################\n");
+        while (pOwnedList != NULL)
         {
-            printf("-Provisioning device ID : ");
-            for (int i = 0; i < MAX_INPUT_ID_LENGTH; i++)
+            nOwnedDevice ++;
+            printf(" %d : ", nOwnedDevice);
+            for (int i = 0; i < UUID_LENGTH; i++)
             {
-                if (pDeviceList->doxm->deviceID.id[i] == '\0')
-                {
-                     break;
-                }
-                printf("%c", pDeviceList->doxm->deviceID.id[i]);
+                printf("%c", pOwnedList->doxm->deviceID.id[i]);
             }
             printf("\n");
-            res = SPInitProvisionContext(PREDEFINED_TIMEOUT, pDeviceList);
-            if (SP_RESULT_SUCCESS != res)
-            {
-                OC_LOG(ERROR, TAG, "Error while init provisioning Context");
-                goto error;
-            }
-            res = InputACL(gAcl);
-            if (SP_RESULT_SUCCESS != res)
-            {
-                OC_LOG(ERROR, TAG, "Error while user ACL input ");
-                goto error;
-            }
-            res = SPProvisionACL(PREDEFINED_TIMEOUT, pDeviceList, gAcl);
-            if (SP_RESULT_SUCCESS != res)
-            {
-                OC_LOG(ERROR, TAG, "Error while provisioning ACL");
-                goto error;
-            }
-            res = SPFinalizeProvisioning(PREDEFINED_TIMEOUT, pDeviceList);
-            if (SP_RESULT_SUCCESS == res)
-            {
-                printf("Provisioning Success~!!\n");
-            }
-            else if (SP_RESULT_SUCCESS != res)
-            {
-                OC_LOG(ERROR, TAG, "Error while Finalize Provisioning");
-                goto error;
-            }
-            pDeviceList = pDeviceList->next;
+            pOwnedDevices[nOwnedDevice] = pOwnedList;
+            pOwnedList = pOwnedList->next;
         }
     }
     else
     {
-        OC_LOG(ERROR, TAG, "Error while Provisioning Discovery");
+        OC_LOG(ERROR, TAG, "Error while Owned Device Discovery");
+    }
+
+    int Device1 = 0;
+    int Device2 = 0;
+
+    printf("Select 2 devices for Credential & ACL provisioning\n");
+    printf("Device 1: ");
+    unused = scanf("%d", &Device1);
+    printf("Device 2: ");
+    unused = scanf("%d", &Device2);
+
+
+    gAcl1 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
+    if (NULL == gAcl1)
+    {
+        OC_LOG(ERROR, TAG, "Error while memory allocation");
+        goto error;
+    }
+
+    gAcl2 = (OicSecAcl_t *)OICCalloc(1,sizeof(OicSecAcl_t));
+    if (NULL == gAcl2)
+    {
+        OC_LOG(ERROR, TAG, "Error while memory allocation");
+        goto error;
+    }
+
+    printf("Input ACL for Device1\n");
+    if ( 0 == InputACL(gAcl1))
+    {
+        printf("Success Input ACL\n");
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, "InputACL error");
+        goto error;
+    }
+
+    printf("Input ACL for Device2\n");
+    if (0 == InputACL(gAcl2))
+    {
+        printf("Success Input ACL\n");
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, "InputACL error");
+        goto error;
+    }
+    char *ctx = "DUMMY";
+    OCProvisionPairwiseDevices(ctx,SYMMETRIC_PAIR_WISE_KEY, OWNER_PSK_LENGTH_128, pOwnedDevices[Device1],
+                           gAcl1, pOwnedDevices[Device2], gAcl2, ProvisionPairwiseCB);
+
+    gOwnershipState = 0;
+    while ( gOwnershipState == 0 )
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            goto error;
+        }
+        sleep(1);
+    }
+
+    if (OCStop() != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack process error");
         goto error;
     }
 
 error:
-    DeleteACLList(gAcl);
-    SPTerminateProvisioning();
+    deleteACL(gAcl1);
+    deleteACL(gAcl2);
+    OCDeleteDiscoveredDevices(&pDeviceList);
+    OCDeleteDiscoveredDevices(&pOwnedList);
+
     return 0;
 }
diff --git a/resource/csdk/security/provisioning/sample/sampleserver_justworks.cpp b/resource/csdk/security/provisioning/sample/sampleserver_justworks.cpp
new file mode 100644 (file)
index 0000000..1bbaf41
--- /dev/null
@@ -0,0 +1,466 @@
+/******************************************************************
+*
+* 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.
+*
+******************************************************************/
+///////////////////////////////////////////////////////////////////////
+//NOTE :  This sample server is generated based on ocserverbasicops.cpp
+///////////////////////////////////////////////////////////////////////
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include "ocstack.h"
+#include "logger.h"
+#include "ocpayload.h"
+
+#define TAG "SAMPLE_JUSTWORKS"
+
+int gQuitFlag = 0;
+
+/* Structure to represent a LED resource */
+typedef struct LEDRESOURCE{
+    OCResourceHandle handle;
+    bool state;
+    int power;
+} LEDResource;
+
+static LEDResource LED;
+// This variable determines instance number of the LED resource.
+// Used by POST method to create a new instance of LED resource.
+static int gCurrLedInstance = 0;
+#define SAMPLE_MAX_NUM_POST_INSTANCE  2
+static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
+
+char *gResourceUri= (char *)"/a/led";
+
+//Secure Virtual Resource database for Iotivity Server
+//It contains Server's Identity and the PSK credentials
+//of other devices which the server trusts
+static char CRED_FILE[] = "oic_svr_db_server_justworks.json";
+
+/* Function that creates a new LED resource by calling the
+ * OCCreateResource() method.
+ */
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower);
+
+/* This method converts the payload to JSON format */
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest);
+
+/* Following methods process the PUT, GET, POST
+ * requests
+ */
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+                                         OCRepPayload **payload);
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+                                         OCRepPayload **payload);
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+                                        OCEntityHandlerResponse *response,
+                                        OCRepPayload **payload);
+
+/* Entity Handler callback functions */
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest *entityHandlerRequest,
+        void* callbackParam);
+
+const char *getResult(OCStackResult result) {
+    switch (result) {
+    case OC_STACK_OK:
+        return "OC_STACK_OK";
+    case OC_STACK_RESOURCE_CREATED:
+        return "OC_STACK_RESOURCE_CREATED";
+    case OC_STACK_RESOURCE_DELETED:
+        return "OC_STACK_RESOURCE_DELETED";
+    case OC_STACK_INVALID_URI:
+        return "OC_STACK_INVALID_URI";
+    case OC_STACK_INVALID_QUERY:
+        return "OC_STACK_INVALID_QUERY";
+    case OC_STACK_INVALID_IP:
+        return "OC_STACK_INVALID_IP";
+    case OC_STACK_INVALID_PORT:
+        return "OC_STACK_INVALID_PORT";
+    case OC_STACK_INVALID_CALLBACK:
+        return "OC_STACK_INVALID_CALLBACK";
+    case OC_STACK_INVALID_METHOD:
+        return "OC_STACK_INVALID_METHOD";
+    case OC_STACK_NO_MEMORY:
+        return "OC_STACK_NO_MEMORY";
+    case OC_STACK_COMM_ERROR:
+        return "OC_STACK_COMM_ERROR";
+    case OC_STACK_INVALID_PARAM:
+        return "OC_STACK_INVALID_PARAM";
+    case OC_STACK_NOTIMPL:
+        return "OC_STACK_NOTIMPL";
+    case OC_STACK_NO_RESOURCE:
+        return "OC_STACK_NO_RESOURCE";
+    case OC_STACK_RESOURCE_ERROR:
+        return "OC_STACK_RESOURCE_ERROR";
+    case OC_STACK_SLOW_RESOURCE:
+        return "OC_STACK_SLOW_RESOURCE";
+    case OC_STACK_NO_OBSERVERS:
+        return "OC_STACK_NO_OBSERVERS";
+    #ifdef WITH_PRESENCE
+    case OC_STACK_PRESENCE_STOPPED:
+        return "OC_STACK_PRESENCE_STOPPED";
+    #endif
+    case OC_STACK_ERROR:
+        return "OC_STACK_ERROR";
+    default:
+        return "UNKNOWN";
+    }
+}
+
+OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
+{
+    OCRepPayload* payload = OCRepPayloadCreate();
+    if(!payload)
+    {
+        OC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
+        return NULL;
+    }
+
+    OCRepPayloadSetUri(payload, uri);
+    OCRepPayloadSetPropBool(payload, "state", state);
+    OCRepPayloadSetPropInt(payload, "power", power);
+
+    return payload;
+}
+
+//This function takes the request as an input and returns the response
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
+{
+    if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
+    {
+        OC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
+        return NULL;
+    }
+
+    OCRepPayload* input = (OCRepPayload*)(ehRequest->payload);
+
+    LEDResource *currLEDResource = &LED;
+
+    if (ehRequest->resource == gLedInstance[0].handle)
+    {
+        currLEDResource = &gLedInstance[0];
+        gResourceUri = (char *) "/a/led/0";
+    }
+    else if (ehRequest->resource == gLedInstance[1].handle)
+    {
+        currLEDResource = &gLedInstance[1];
+        gResourceUri = (char *) "/a/led/1";
+    }
+
+    if(OC_REST_PUT == ehRequest->method)
+    {
+        // Get pointer to query
+        int64_t pow;
+        if(OCRepPayloadGetPropInt(input, "power", &pow))
+        {
+            currLEDResource->power =pow;
+        }
+
+        bool state;
+        if(OCRepPayloadGetPropBool(input, "state", &state))
+        {
+            currLEDResource->state = state;
+        }
+    }
+
+    return getPayload(gResourceUri, currLEDResource->power, currLEDResource->state);
+}
+
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+        OCRepPayload **payload)
+{
+    OCEntityHandlerResult ehResult;
+
+    OCRepPayload *getResp = constructResponse(ehRequest);
+
+    if(getResp)
+    {
+        *payload = getResp;
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        ehResult = OC_EH_ERROR;
+    }
+
+    return ehResult;
+}
+
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+        OCRepPayload **payload)
+{
+    OCEntityHandlerResult ehResult;
+
+    OCRepPayload *putResp = constructResponse(ehRequest);
+
+    if(putResp)
+    {
+        *payload = putResp;
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        ehResult = OC_EH_ERROR;
+    }
+
+    return ehResult;
+}
+
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+        OCEntityHandlerResponse *response, OCRepPayload **payload)
+{
+    OCRepPayload *respPLPost_led = NULL;
+    OCEntityHandlerResult ehResult = OC_EH_OK;
+
+    /*
+     * The entity handler determines how to process a POST request.
+     * Per the REST paradigm, POST can also be used to update representation of existing
+     * resource or create a new resource.
+     * In the sample below, if the POST is for /a/led then a new instance of the LED
+     * resource is created with default representation (if representation is included in
+     * POST payload it can be used as initial values) as long as the instance is
+     * lesser than max new instance count. Once max instance count is reached, POST on
+     * /a/led updated the representation of /a/led (just like PUT)
+     */
+
+    if (ehRequest->resource == LED.handle)
+    {
+        if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
+        {
+            // Create new LED instance
+            char newLedUri[15] = "/a/led/";
+            int newLedUriLength = strlen(newLedUri);
+            snprintf (newLedUri + newLedUriLength, sizeof(newLedUri)-newLedUriLength, "%d", gCurrLedInstance);
+
+            respPLPost_led = OCRepPayloadCreate();
+            OCRepPayloadSetUri(respPLPost_led, gResourceUri);
+            OCRepPayloadSetPropString(respPLPost_led, "createduri", newLedUri);
+
+            if (0 == createLEDResource (newLedUri, &gLedInstance[gCurrLedInstance], false, 0))
+            {
+                OC_LOG (INFO, TAG, "Created new LED instance");
+                gLedInstance[gCurrLedInstance].state = 0;
+                gLedInstance[gCurrLedInstance].power = 0;
+                gCurrLedInstance++;
+                strncpy ((char *)response->resourceUri, newLedUri, MAX_URI_LENGTH);
+                ehResult = OC_EH_RESOURCE_CREATED;
+            }
+        }
+        else
+        {
+            respPLPost_led = constructResponse(ehRequest);
+        }
+    }
+    else
+    {
+        for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
+        {
+            if (ehRequest->resource == gLedInstance[i].handle)
+            {
+                if (i == 0)
+                {
+                    respPLPost_led = constructResponse(ehRequest);
+                    break;
+                }
+                else if (i == 1)
+                {
+                    respPLPost_led = constructResponse(ehRequest);
+                }
+            }
+        }
+    }
+
+    if (respPLPost_led != NULL)
+    {
+        *payload = respPLPost_led;
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        OC_LOG_V (INFO, TAG, "Payload was NULL");
+        ehResult = OC_EH_ERROR;
+    }
+
+    return ehResult;
+}
+
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest *entityHandlerRequest,
+        void* callbackParam)
+{
+    OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+    (void)callbackParam;
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
+    OCEntityHandlerResponse response;
+    memset(&response, 0, sizeof(response));
+
+    // Validate pointer
+    if (!entityHandlerRequest)
+    {
+        OC_LOG (ERROR, TAG, "Invalid request pointer");
+        return OC_EH_ERROR;
+    }
+
+    OCRepPayload* payload = NULL;
+
+    if (flag & OC_REQUEST_FLAG)
+    {
+        OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
+        if (entityHandlerRequest)
+        {
+            if (OC_REST_GET == entityHandlerRequest->method)
+            {
+                OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+                ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
+            }
+            else if (OC_REST_PUT == entityHandlerRequest->method)
+            {
+                OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
+                ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
+            }
+            else if (OC_REST_POST == entityHandlerRequest->method)
+            {
+                OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
+                ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
+            }
+            else
+            {
+                OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                        entityHandlerRequest->method);
+                ehResult = OC_EH_ERROR;
+            }
+
+            if (ehResult == OC_EH_OK && ehResult != OC_EH_FORBIDDEN)
+            {
+                // Format the response.  Note this requires some info about the request
+                response.requestHandle = entityHandlerRequest->requestHandle;
+                response.resourceHandle = entityHandlerRequest->resource;
+                response.ehResult = ehResult;
+                response.payload = (OCPayload*)(payload);
+                response.numSendVendorSpecificHeaderOptions = 0;
+                memset(response.sendVendorSpecificHeaderOptions, 0,
+                       sizeof(response.sendVendorSpecificHeaderOptions));
+                memset(response.resourceUri, 0, sizeof(response.resourceUri));
+                // Indicate that response is NOT in a persistent buffer
+                response.persistentBufferFlag = 0;
+
+                // Send the response
+                if (OCDoResponse(&response) != OC_STACK_OK)
+                {
+                    OC_LOG(ERROR, TAG, "Error sending response");
+                    ehResult = OC_EH_ERROR;
+                }
+            }
+        }
+    }
+
+    OCPayloadDestroy(response.payload);
+    return ehResult;
+}
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+    if (signum == SIGINT)
+    {
+        gQuitFlag = 1;
+    }
+}
+
+FILE* server_fopen(const char *path, const char *mode)
+{
+    (void)path;
+    return fopen(CRED_FILE, mode);
+}
+
+int main()
+{
+    struct timespec timeout;
+
+    OC_LOG(DEBUG, TAG, "OCServer is starting...");
+
+    // Initialize Persistent Storage for SVR database
+    OCPersistentStorage ps = {server_fopen, fread, fwrite, fclose, unlink};
+
+    OCRegisterPersistentStorageHandler(&ps);
+
+    if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack init error");
+        return 0;
+    }
+
+    /*
+     * 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
+    OC_LOG(INFO, TAG, "Entering ocserver main loop...");
+    signal(SIGINT, handleSigInt);
+    while (!gQuitFlag)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            return 0;
+        }
+        nanosleep(&timeout, NULL);
+    }
+
+    OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
+
+    if (OCStop() != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack process error");
+    }
+
+    return 0;
+}
+
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower)
+{
+    if (!uri)
+    {
+        OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
+        return -1;
+    }
+
+    ledResource->state = resourceState;
+    ledResource->power= resourcePower;
+    OCStackResult res = OCCreateResource(&(ledResource->handle),
+            "core.led",
+            OC_RSRVD_INTERFACE_DEFAULT,
+            uri,
+            OCEntityHandlerCb,
+            NULL,
+            OC_DISCOVERABLE|OC_OBSERVABLE | OC_SECURE);
+    OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
+
+    return 0;
+}
diff --git a/resource/csdk/security/provisioning/sample/sampleserver_randompin.cpp b/resource/csdk/security/provisioning/sample/sampleserver_randompin.cpp
new file mode 100644 (file)
index 0000000..bd9560f
--- /dev/null
@@ -0,0 +1,485 @@
+/******************************************************************
+*
+* 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.
+*
+******************************************************************/
+///////////////////////////////////////////////////////////////////////
+//NOTE :  This sample server is generated based on ocserverbasicops.cpp
+///////////////////////////////////////////////////////////////////////
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+#include "ocstack.h"
+#include "logger.h"
+#include "ocpayload.h"
+#include "pinoxmcommon.h"
+
+#define TAG "SAMPLE_RANDOMPIN"
+
+int gQuitFlag = 0;
+
+/* Structure to represent a LED resource */
+typedef struct LEDRESOURCE{
+    OCResourceHandle handle;
+    bool state;
+    int power;
+} LEDResource;
+
+static LEDResource LED;
+// This variable determines instance number of the LED resource.
+// Used by POST method to create a new instance of LED resource.
+static int gCurrLedInstance = 0;
+#define SAMPLE_MAX_NUM_POST_INSTANCE  2
+static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
+
+char *gResourceUri= (char *)"/a/led";
+
+//Secure Virtual Resource database for Iotivity Server
+//It contains Server's Identity and the PSK credentials
+//of other devices which the server trusts
+static char CRED_FILE[] = "oic_svr_db_server_randompin.json";
+
+/* Function that creates a new LED resource by calling the
+ * OCCreateResource() method.
+ */
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower);
+
+/* This method converts the payload to JSON format */
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest);
+
+/* Following methods process the PUT, GET, POST
+ * requests
+ */
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+                                         OCRepPayload **payload);
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+                                         OCRepPayload **payload);
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+                                        OCEntityHandlerResponse *response,
+                                        OCRepPayload **payload);
+
+/* Entity Handler callback functions */
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest *entityHandlerRequest,
+        void* callbackParam);
+
+const char *getResult(OCStackResult result) {
+    switch (result) {
+    case OC_STACK_OK:
+        return "OC_STACK_OK";
+    case OC_STACK_RESOURCE_CREATED:
+        return "OC_STACK_RESOURCE_CREATED";
+    case OC_STACK_RESOURCE_DELETED:
+        return "OC_STACK_RESOURCE_DELETED";
+    case OC_STACK_INVALID_URI:
+        return "OC_STACK_INVALID_URI";
+    case OC_STACK_INVALID_QUERY:
+        return "OC_STACK_INVALID_QUERY";
+    case OC_STACK_INVALID_IP:
+        return "OC_STACK_INVALID_IP";
+    case OC_STACK_INVALID_PORT:
+        return "OC_STACK_INVALID_PORT";
+    case OC_STACK_INVALID_CALLBACK:
+        return "OC_STACK_INVALID_CALLBACK";
+    case OC_STACK_INVALID_METHOD:
+        return "OC_STACK_INVALID_METHOD";
+    case OC_STACK_NO_MEMORY:
+        return "OC_STACK_NO_MEMORY";
+    case OC_STACK_COMM_ERROR:
+        return "OC_STACK_COMM_ERROR";
+    case OC_STACK_INVALID_PARAM:
+        return "OC_STACK_INVALID_PARAM";
+    case OC_STACK_NOTIMPL:
+        return "OC_STACK_NOTIMPL";
+    case OC_STACK_NO_RESOURCE:
+        return "OC_STACK_NO_RESOURCE";
+    case OC_STACK_RESOURCE_ERROR:
+        return "OC_STACK_RESOURCE_ERROR";
+    case OC_STACK_SLOW_RESOURCE:
+        return "OC_STACK_SLOW_RESOURCE";
+    case OC_STACK_NO_OBSERVERS:
+        return "OC_STACK_NO_OBSERVERS";
+    #ifdef WITH_PRESENCE
+    case OC_STACK_PRESENCE_STOPPED:
+        return "OC_STACK_PRESENCE_STOPPED";
+    #endif
+    case OC_STACK_ERROR:
+        return "OC_STACK_ERROR";
+    default:
+        return "UNKNOWN";
+    }
+}
+
+OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
+{
+    OCRepPayload* payload = OCRepPayloadCreate();
+    if(!payload)
+    {
+        OC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
+        return NULL;
+    }
+
+    OCRepPayloadSetUri(payload, uri);
+    OCRepPayloadSetPropBool(payload, "state", state);
+    OCRepPayloadSetPropInt(payload, "power", power);
+
+    return payload;
+}
+
+//This function takes the request as an input and returns the response
+OCRepPayload* constructResponse (OCEntityHandlerRequest *ehRequest)
+{
+    if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
+    {
+        OC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
+        return NULL;
+    }
+
+    OCRepPayload* input = (OCRepPayload*)(ehRequest->payload);
+
+    LEDResource *currLEDResource = &LED;
+
+    if (ehRequest->resource == gLedInstance[0].handle)
+    {
+        currLEDResource = &gLedInstance[0];
+        gResourceUri = (char *) "/a/led/0";
+    }
+    else if (ehRequest->resource == gLedInstance[1].handle)
+    {
+        currLEDResource = &gLedInstance[1];
+        gResourceUri = (char *) "/a/led/1";
+    }
+
+    if(OC_REST_PUT == ehRequest->method)
+    {
+        // Get pointer to query
+        int64_t pow;
+        if(OCRepPayloadGetPropInt(input, "power", &pow))
+        {
+            currLEDResource->power =pow;
+        }
+
+        bool state;
+        if(OCRepPayloadGetPropBool(input, "state", &state))
+        {
+            currLEDResource->state = state;
+        }
+    }
+
+    return getPayload(gResourceUri, currLEDResource->power, currLEDResource->state);
+}
+
+OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
+        OCRepPayload **payload)
+{
+    OCEntityHandlerResult ehResult;
+
+    OCRepPayload *getResp = constructResponse(ehRequest);
+
+    if(getResp)
+    {
+        *payload = getResp;
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        ehResult = OC_EH_ERROR;
+    }
+
+    return ehResult;
+}
+
+OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
+        OCRepPayload **payload)
+{
+    OCEntityHandlerResult ehResult;
+
+    OCRepPayload *putResp = constructResponse(ehRequest);
+
+    if(putResp)
+    {
+        *payload = putResp;
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        ehResult = OC_EH_ERROR;
+    }
+
+    return ehResult;
+}
+
+OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
+        OCEntityHandlerResponse *response, OCRepPayload **payload)
+{
+    OCRepPayload *respPLPost_led = NULL;
+    OCEntityHandlerResult ehResult = OC_EH_OK;
+
+    /*
+     * The entity handler determines how to process a POST request.
+     * Per the REST paradigm, POST can also be used to update representation of existing
+     * resource or create a new resource.
+     * In the sample below, if the POST is for /a/led then a new instance of the LED
+     * resource is created with default representation (if representation is included in
+     * POST payload it can be used as initial values) as long as the instance is
+     * lesser than max new instance count. Once max instance count is reached, POST on
+     * /a/led updated the representation of /a/led (just like PUT)
+     */
+
+    if (ehRequest->resource == LED.handle)
+    {
+        if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
+        {
+            // Create new LED instance
+            char newLedUri[15] = "/a/led/";
+            int newLedUriLength = strlen(newLedUri);
+            snprintf (newLedUri + newLedUriLength, sizeof(newLedUri)-newLedUriLength, "%d", gCurrLedInstance);
+
+            respPLPost_led = OCRepPayloadCreate();
+            OCRepPayloadSetUri(respPLPost_led, gResourceUri);
+            OCRepPayloadSetPropString(respPLPost_led, "createduri", newLedUri);
+
+            if (0 == createLEDResource (newLedUri, &gLedInstance[gCurrLedInstance], false, 0))
+            {
+                OC_LOG (INFO, TAG, "Created new LED instance");
+                gLedInstance[gCurrLedInstance].state = 0;
+                gLedInstance[gCurrLedInstance].power = 0;
+                gCurrLedInstance++;
+                strncpy ((char *)response->resourceUri, newLedUri, MAX_URI_LENGTH);
+                ehResult = OC_EH_RESOURCE_CREATED;
+            }
+        }
+        else
+        {
+            respPLPost_led = constructResponse(ehRequest);
+        }
+    }
+    else
+    {
+        for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
+        {
+            if (ehRequest->resource == gLedInstance[i].handle)
+            {
+                if (i == 0)
+                {
+                    respPLPost_led = constructResponse(ehRequest);
+                    break;
+                }
+                else if (i == 1)
+                {
+                    respPLPost_led = constructResponse(ehRequest);
+                }
+            }
+        }
+    }
+
+    if (respPLPost_led != NULL)
+    {
+        *payload = respPLPost_led;
+        ehResult = OC_EH_OK;
+    }
+    else
+    {
+        OC_LOG_V (INFO, TAG, "Payload was NULL");
+        ehResult = OC_EH_ERROR;
+    }
+
+    return ehResult;
+}
+
+OCEntityHandlerResult
+OCEntityHandlerCb (OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest *entityHandlerRequest,
+        void* callbackParam)
+{
+    OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
+    (void)callbackParam;
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
+    OCEntityHandlerResponse response;
+    memset(&response, 0, sizeof(response));
+
+    // Validate pointer
+    if (!entityHandlerRequest)
+    {
+        OC_LOG (ERROR, TAG, "Invalid request pointer");
+        return OC_EH_ERROR;
+    }
+
+    OCRepPayload* payload = NULL;
+
+    if (flag & OC_REQUEST_FLAG)
+    {
+        OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
+        if (entityHandlerRequest)
+        {
+            if (OC_REST_GET == entityHandlerRequest->method)
+            {
+                OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
+                ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
+            }
+            else if (OC_REST_PUT == entityHandlerRequest->method)
+            {
+                OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
+                ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
+            }
+            else if (OC_REST_POST == entityHandlerRequest->method)
+            {
+                OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
+                ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
+            }
+            else
+            {
+                OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
+                        entityHandlerRequest->method);
+                ehResult = OC_EH_ERROR;
+            }
+
+            if (ehResult == OC_EH_OK && ehResult != OC_EH_FORBIDDEN)
+            {
+                // Format the response.  Note this requires some info about the request
+                response.requestHandle = entityHandlerRequest->requestHandle;
+                response.resourceHandle = entityHandlerRequest->resource;
+                response.ehResult = ehResult;
+                response.payload = (OCPayload*)(payload);
+                response.numSendVendorSpecificHeaderOptions = 0;
+                memset(response.sendVendorSpecificHeaderOptions, 0,
+                       sizeof(response.sendVendorSpecificHeaderOptions));
+                memset(response.resourceUri, 0, sizeof(response.resourceUri));
+                // Indicate that response is NOT in a persistent buffer
+                response.persistentBufferFlag = 0;
+
+                // Send the response
+                if (OCDoResponse(&response) != OC_STACK_OK)
+                {
+                    OC_LOG(ERROR, TAG, "Error sending response");
+                    ehResult = OC_EH_ERROR;
+                }
+            }
+        }
+    }
+
+    OCPayloadDestroy(response.payload);
+    return ehResult;
+}
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum)
+{
+    if (signum == SIGINT)
+    {
+        gQuitFlag = 1;
+    }
+}
+
+FILE* server_fopen(const char *path, const char *mode)
+{
+    (void)path;
+    return fopen(CRED_FILE, mode);
+}
+
+void GeneratePinCB(char* pin, size_t pinSize)
+{
+    if(NULL == pin || pinSize <= 0)
+    {
+        OC_LOG(INFO, TAG, "Invalid PIN");
+        return;
+    }
+
+    OC_LOG(INFO, TAG, "============================");
+    OC_LOG_V(INFO, TAG, "    PIN CODE : %s", pin);
+    OC_LOG(INFO, TAG, "============================");
+}
+
+int main()
+{
+    struct timespec timeout;
+
+    OC_LOG(DEBUG, TAG, "OCServer is starting...");
+
+    // Initialize Persistent Storage for SVR database
+    OCPersistentStorage ps = {server_fopen, fread, fwrite, fclose, unlink};
+    OCRegisterPersistentStorageHandler(&ps);
+
+    if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack init error");
+        return 0;
+    }
+
+   /**
+     * If server supported random pin based ownership transfer,
+     * callback of print PIN should be registered before runing server.
+     */
+    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
+    OC_LOG(INFO, TAG, "Entering ocserver main loop...");
+    signal(SIGINT, handleSigInt);
+    while (!gQuitFlag)
+    {
+        if (OCProcess() != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "OCStack process error");
+            return 0;
+        }
+        nanosleep(&timeout, NULL);
+    }
+
+    OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
+
+    if (OCStop() != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack process error");
+    }
+
+    return 0;
+}
+
+int createLEDResource (char *uri, LEDResource *ledResource, bool resourceState, int resourcePower)
+{
+    if (!uri)
+    {
+        OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
+        return -1;
+    }
+
+    ledResource->state = resourceState;
+    ledResource->power= resourcePower;
+    OCStackResult res = OCCreateResource(&(ledResource->handle),
+            "core.led",
+            OC_RSRVD_INTERFACE_DEFAULT,
+            uri,
+            OCEntityHandlerCb,
+            NULL,
+            OC_DISCOVERABLE|OC_OBSERVABLE | OC_SECURE);
+    OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
+
+    return 0;
+}
index 8e96518..0343627 100644 (file)
  *
  * *****************************************************************/
 #include <string.h>
-
-#include "provisioningmanager.h"
 #include "credentialgenerator.h"
 #include "oic_malloc.h"
 #include "logger.h"
 #include "credresource.h"
 #include "ocrandom.h"
 #include "base64.h"
-#define TAG "SPProvisionAPI"
-#define KEY_LENGTH 16
+#include "stdbool.h"
+#include "securevirtualresourcetypes.h"
 
-SPResult SPGeneratePairWiseCredentials(OicSecCredType_t type, const OicUuid_t *ptDeviceId,
-                                       const OicUuid_t *firstDeviceId,
-                                       const OicUuid_t *secondDeviceId,
-                                       OicSecCred_t **firstCred,
-                                       OicSecCred_t **secondCred)
-{
+#define TAG "SRPAPI-CG"
 
-    if (NULL == ptDeviceId || NULL == firstDeviceId || NULL == secondDeviceId)
-    {
-        return SP_RESULT_INVALID_PARAM;
-    }
-    uint8_t privData[KEY_LENGTH] = {0,};
-    OCFillRandomMem(privData, KEY_LENGTH);
+/**
+ * @def PM_VERIFY_SUCCESS
+ * @brief Macro to verify success of operation.
+ *        eg: PM_VERIFY_SUCCESS(TAG, OC_STACK_OK == foo(), OC_STACK_ERROR, ERROR);
+ * @note Invoking function must define "bail:" label for goto functionality to work correctly and
+ *       must define "OCStackResult res" for setting error code.
+ * */
+#define PM_VERIFY_SUCCESS(tag, op, errCode, logLevel) { if (!(op)) \
+                       {OC_LOG((logLevel), tag, PCF(#op " failed!!")); res = errCode; goto bail;} }
+/**
+ * @def PM_VERIFY_NON_NULL
+ * @brief Macro to verify argument is not equal to NULL.
+ *        eg: PM_VERIFY_NON_NULL(TAG, ptrData, ERROR);
+ * @note Invoking function must define "bail:" label for goto functionality to work correctly.
+ * */
+#define PM_VERIFY_NON_NULL(tag, arg, errCode, logLevel) { if (NULL == (arg)) \
+                   { OC_LOG((logLevel), tag, PCF(#arg " is NULL")); res = errCode; goto bail;} }
 
-    uint32_t outLen = 0;
-    char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(privData)) + 1] = {};
-    B64Result b64Ret = b64Encode(privData, sizeof(privData), base64Buff,
-                                sizeof(base64Buff), &outLen);
-    if (B64_OK != b64Ret)
-    {
-        OC_LOG(ERROR, TAG, "Error while encoding key");
-        return SP_RESULT_INTERNAL_ERROR;
-    }
+OCStackResult PMGeneratePairWiseCredentials(OicSecCredType_t type, size_t keySize,
+                                    const OicUuid_t *ptDeviceId,
+                                    const OicUuid_t *firstDeviceId, const OicUuid_t *secondDeviceId,
+                                    OicSecCred_t **firstCred, OicSecCred_t **secondCred)
+{
 
-    // TODO currently owner array is 1. only provisioning tool's id.
-    OicSecCred_t *tempFirstCred =  GenerateCredential(secondDeviceId, type, NULL, base64Buff, 1,
-                                   ptDeviceId);
-    if (NULL == tempFirstCred)
+    if (NULL == ptDeviceId || NULL == firstDeviceId || NULL != *firstCred || \
+        NULL == secondDeviceId || NULL != *secondCred)
     {
-        OC_LOG(ERROR, TAG, "Error while generating credential.");
-        return SP_RESULT_INTERNAL_ERROR;
+        OC_LOG(INFO, TAG, "Invalid params");
+        return OC_STACK_INVALID_PARAM;
     }
-    // TODO currently owner array is 1. only provisioning tool's id.
-    OicSecCred_t *tempSecondCred =  GenerateCredential(firstDeviceId, type, NULL, base64Buff, 1,
-                                    ptDeviceId);
-    if (NULL == tempSecondCred)
+    if(!(keySize == OWNER_PSK_LENGTH_128 || keySize == OWNER_PSK_LENGTH_256))
     {
-        DeleteCredList(tempFirstCred);
-        OC_LOG(ERROR, TAG, "Error while generating credential.");
-        return SP_RESULT_INTERNAL_ERROR;
+        OC_LOG(INFO, TAG, "Invalid key size");
+        return OC_STACK_INVALID_PARAM;
     }
+    OCStackResult res = OC_STACK_ERROR;
+    uint8_t* privData = NULL;
+    char* base64Buff = NULL;
+    OicSecCred_t *tempFirstCred = NULL;
+    OicSecCred_t *tempSecondCred = NULL;
+
+    size_t privDataKeySize = keySize;
+
+    privData = (uint8_t*) OICCalloc(privDataKeySize,sizeof(uint8_t));
+    PM_VERIFY_NON_NULL(TAG, privData, OC_STACK_NO_MEMORY, ERROR);
+
+    OCFillRandomMem(privData,privDataKeySize);
+
+    uint32_t outLen = 0;
+
+    base64Buff = (char*) OICCalloc(B64ENCODE_OUT_SAFESIZE(privDataKeySize) + 1, sizeof(char));
+    PM_VERIFY_NON_NULL(TAG, base64Buff, OC_STACK_NO_MEMORY, ERROR);
+    int memReq = (B64ENCODE_OUT_SAFESIZE(privDataKeySize) + 1) * sizeof(char);
+    B64Result b64Ret = b64Encode(privData, privDataKeySize*sizeof(uint8_t), base64Buff,
+                                 memReq, &outLen);
+    PM_VERIFY_SUCCESS(TAG, B64_OK == b64Ret, OC_STACK_ERROR, ERROR);
+
+    // TODO: currently owner array is 1. only provisioning tool's id.
+    tempFirstCred =  GenerateCredential(secondDeviceId, type, NULL, base64Buff, 1, ptDeviceId);
+    PM_VERIFY_NON_NULL(TAG, tempFirstCred, OC_STACK_ERROR, ERROR);
+
+    // TODO: currently owner array is 1. only provisioning tool's id.
+    tempSecondCred =  GenerateCredential(firstDeviceId, type, NULL, base64Buff, 1, ptDeviceId);
+    PM_VERIFY_NON_NULL(TAG, tempSecondCred, OC_STACK_ERROR, ERROR);
+
     *firstCred = tempFirstCred;
     *secondCred = tempSecondCred;
-    return SP_RESULT_SUCCESS;
+    res = OC_STACK_OK;
+
+bail:
+    OICFree(privData);
+    OICFree(base64Buff);
+
+    if(res != OC_STACK_OK)
+    {
+        OICFree(tempFirstCred);
+        OICFree(tempSecondCred);
+        *firstCred = NULL;
+        *secondCred = NULL;
+    }
+
+    return res;
 }
diff --git a/resource/csdk/security/provisioning/src/ocprovisioningmanager.c b/resource/csdk/security/provisioning/src/ocprovisioningmanager.c
new file mode 100644 (file)
index 0000000..cdef12d
--- /dev/null
@@ -0,0 +1,402 @@
+/* *****************************************************************
+ *
+ * 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 <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include "ocprovisioningmanager.h"
+#include "pmutility.h"
+#include "ownershiptransfermanager.h"
+#include "oic_malloc.h"
+#include "logger.h"
+#include "secureresourceprovider.h"
+
+#define TAG "OCPMAPI"
+
+typedef struct Linkdata Linkdata_t;
+struct Linkdata
+{
+    void *ctx;
+    const OCProvisionDev_t *pDev1;
+    OicSecAcl_t *pDev1Acl;
+    const OCProvisionDev_t *pDev2;
+    OicSecAcl_t *pDev2Acl;
+    OCProvisionResult_t *resArr;
+    int numOfResults;
+    int currentCountResults;
+    OCProvisionResultCB resultCallback;
+
+};
+
+/**
+ * The function is responsible for discovery of device is current subnet. It will list
+ * all the device in subnet which are not yet owned. Please call OCInit with OC_CLIENT_SERVER as
+ * OCMode.
+ *
+ * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
+ *                    client before returning the list of devices.
+ * @param[out] ppList List of candidate devices to be provisioned
+ * @return OTM_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult OCDiscoverUnownedDevices(unsigned short timeout, OCProvisionDev_t **ppList)
+{
+    if( ppList == NULL || *ppList != NULL)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    return PMDeviceDiscovery(timeout, false, ppList);
+}
+
+/**
+ * The function is responsible for discovery of owned device is current subnet. It will list
+ * all the device in subnet which are owned by calling provisioning client.
+ *
+ * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
+ *                    client before returning the list of devices.
+ * @param[out] ppList List of device owned by provisioning tool.
+ * @return OTM_SUCCESS in case of success and other value otherwise.
+ */
+OCStackResult OCDiscoverOwnedDevices(unsigned short timeout, OCProvisionDev_t **ppList)
+{
+    if( ppList == NULL || *ppList != NULL)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    return PMDeviceDiscovery(timeout, true, ppList);
+}
+
+/**
+ * API to register for particular OxM.
+ *
+ * @param[in] Ownership transfer method.
+ * @param[in] Implementation of callback functions for owership transfer.
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCSetOwnerTransferCallbackData(OicSecOxm_t oxm, OTMCallbackData_t* callbackData)
+{
+    if(NULL == callbackData)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    return OTMSetOwnershipTransferCallbackData(oxm, callbackData);
+}
+
+OCStackResult OCDoOwnershipTransfer(void* ctx,
+                                      OCProvisionDev_t *targetDevices,
+                                      OCProvisionResultCB resultCallback)
+{
+    if( NULL == targetDevices )
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    return OTMDoOwnershipTransfer(ctx, targetDevices, resultCallback);
+}
+
+/**
+ * This function deletes memory allocated to linked list created by OCDiscover_XXX_Devices API.
+ *
+ * @param[in] pList Pointer to OCProvisionDev_t which should be deleted.
+ */
+void OCDeleteDiscoveredDevices(OCProvisionDev_t **ppList)
+{
+    DeleteDeviceList(ppList);
+}
+
+/**
+ * this function sends ACL information to resource.
+ *
+ * @param[in] ctx Application context would be returned in result callback.
+ * @param[in] selectedDeviceInfo Selected target device.
+ * @param[in] acl ACL to provision.
+ * @param[in] resultCallback callback provided by API user, callback will be called when provisioning
+              request recieves a response from resource server.
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCProvisionACL(void* ctx, const OCProvisionDev_t *selectedDeviceInfo, OicSecAcl_t *acl,
+                             OCProvisionResultCB resultCallback)
+{
+    return SRPProvisionACL(ctx, selectedDeviceInfo, acl, resultCallback);
+}
+
+/**
+ * function to provision credential to devices.
+ *
+ * @param[in] ctx Application context would be returned in result callback.
+ * @param[in] type Type of credentials to be provisioned to the device.
+ * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
+   @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ *            provisioning request recieves a response from first resource server.
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
+                                      const OCProvisionDev_t *pDev1,
+                                      const OCProvisionDev_t *pDev2,
+                                      OCProvisionResultCB resultCallback)
+{
+    return SRPProvisionCredentials(ctx, type, keySize,
+                                      pDev1, pDev2, resultCallback);
+
+}
+
+/**
+ * Internal Function to update result in link result array.
+ */
+static void UpdateLinkResults(Linkdata_t *link, int device, OCStackResult stackresult)
+{
+
+    OC_LOG_V(INFO,TAG,"value of link->currentCountResults is %d",link->currentCountResults);
+    if(1 == device)
+    {
+        memcpy(link->resArr[(link->currentCountResults)].deviceId.id, link->pDev1->doxm->deviceID.id,UUID_LENGTH);
+    }
+    else
+    {
+        memcpy(link->resArr[(link->currentCountResults)].deviceId.id, link->pDev2->doxm->deviceID.id,UUID_LENGTH);
+    }
+    link->resArr[(link->currentCountResults)].res = stackresult;
+    ++(link->currentCountResults);
+
+}
+
+/**
+ * Callback to handle ACL provisioning for device 2.
+ */
+static void AclProv2CB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+
+    if (NULL == ctx)
+    {
+        OC_LOG(ERROR,TAG,"Context is Null in ACLProv 2");
+        return;
+    }
+    (void)nOfRes;
+    Linkdata_t *link = (Linkdata_t*)ctx;
+    OCProvisionResultCB resultCallback = link->resultCallback;
+
+
+    if(hasError)
+    {
+        UpdateLinkResults(link, 2,arr[0].res);
+        OC_LOG(ERROR,TAG,"Error occured while ACL provisioning device 1");
+        ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
+                                                link->resArr,
+                                                true);
+        OICFree(link->resArr);
+        OICFree(link) ;
+        return;
+    }
+    UpdateLinkResults(link, 2, arr[0].res);
+   ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
+                                           link->resArr,
+                                           false);
+    OICFree(link->resArr);
+    OICFree(link);
+    return;
+}
+
+/**
+ * Callback to handle ACL provisioning for device 1
+ */
+static void AclProv1CB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+
+    if (NULL == ctx)
+    {
+        OC_LOG(ERROR,TAG,"Context is Null in ACLProv1");
+        return;
+    }
+    (void)nOfRes;
+    Linkdata_t *link = (Linkdata_t*)ctx;
+    OCProvisionResultCB resultCallback = link->resultCallback;
+
+    if(hasError)
+    {
+        OC_LOG(ERROR,TAG,"Error occured while ACL provisioning device 1");
+        UpdateLinkResults(link, 1, arr[0].res);
+        ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
+                                                link->resArr,
+                                                true);
+        OICFree(link->resArr);
+        OICFree(link);
+        return;
+    }
+    UpdateLinkResults(link, 1, arr[0].res);
+    if (NULL != link->pDev2Acl)
+    {
+        OCStackResult res =  SRPProvisionACL(ctx, link->pDev2, link->pDev2Acl, &AclProv2CB);
+        if (OC_STACK_OK!=res)
+        {
+             UpdateLinkResults(link, 2, res);
+             ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
+                                                     link->resArr,
+                                                     true);
+
+        }
+    }
+    else
+    {
+        ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
+                                                link->resArr,
+                                                false);
+        OICFree(link->resArr);
+        OICFree(link);
+    }
+
+    return;
+}
+
+/**
+ * Callback to handle credential provisioning.
+ */
+static void ProvisionCredsCB(void* ctx, int nOfRes, OCProvisionResult_t *arr, bool hasError)
+{
+    if (NULL == ctx)
+    {
+        OC_LOG(ERROR,TAG,"Error occured while credential provisioning");
+        return;
+    }
+    Linkdata_t *link = (Linkdata_t*)ctx;
+    OCProvisionResultCB resultCallback = link->resultCallback;
+    OC_LOG_V(INFO, TAG, "has error returned %d",hasError);
+    UpdateLinkResults(link, 1, arr[0].res);
+    UpdateLinkResults(link, 2, arr[1].res);
+    if (hasError)
+    {
+        OC_LOG(ERROR,TAG,"Error occured while credential provisioning");
+        ((OCProvisionResultCB)(resultCallback))(link->ctx, nOfRes,
+                                                link->resArr,
+                                                true);
+         OICFree(link->resArr);
+         OICFree(link);
+         return;
+    }
+    if (NULL != link->pDev1Acl)
+    {
+
+        OCStackResult res =  SRPProvisionACL(ctx, link->pDev1, link->pDev1Acl, &AclProv1CB);
+        if (OC_STACK_OK!=res)
+        {
+             OC_LOG(ERROR, TAG, "Error while provisioning ACL for device 1");
+             UpdateLinkResults(link, 1, res);
+             ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
+                                                     link->resArr,
+                                                     true);
+              OICFree(link->resArr);
+              OICFree(link);
+        }
+    }
+    else if (NULL!=link->pDev2Acl)
+    {
+        OC_LOG(ERROR, TAG, "ACL for device 1 is NULL");
+        OCStackResult res =  SRPProvisionACL(ctx, link->pDev2, link->pDev2Acl, &AclProv2CB);
+        if (OC_STACK_OK!=res)
+        {
+             OC_LOG(ERROR, TAG, "Error while provisioning ACL for device 2");
+              UpdateLinkResults(link, 2, res);
+             ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
+                                                     link->resArr,
+                                                     true);
+              OICFree(link->resArr);
+              OICFree(link);
+        }
+
+    }
+    else
+    {
+        OC_LOG(INFO, TAG, "ACLs of both devices are NULL");
+        ((OCProvisionResultCB)(resultCallback))(link->ctx, link->currentCountResults,
+                                                link->resArr,
+                                                false);
+        OICFree(link->resArr);
+        OICFree(link);
+    }
+    return;
+}
+/**
+ * function to provision credentials between two devices and ACLs for the devices who act as a server.
+ *
+ * @param[in] ctx Application context would be returned in result callback.
+ * @param[in] type Type of credentials to be provisioned to the device.
+ * @param[in] pDev1 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
+ * @param[in] acl ACL for device 1. If this is not required set NULL.
+ * @param[in] pDev2 Pointer to OCProvisionDev_t instance,respresenting resource to be provsioned.
+ * @param[in] acl ACL for device 2. If this is not required set NULL.
+ * @param[in] resultCallback callback provided by API user, callback will be called when
+ *            provisioning request recieves a response from first resource server.
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+OCStackResult OCProvisionPairwiseDevices(void* ctx, OicSecCredType_t type, size_t keySize,
+                                         const OCProvisionDev_t *pDev1, OicSecAcl_t *pDev1Acl,
+                                         const OCProvisionDev_t *pDev2, OicSecAcl_t *pDev2Acl,
+                                         OCProvisionResultCB resultCallback)
+{
+
+    if(!pDev1 || !pDev2 || !resultCallback)
+    {
+        OC_LOG(ERROR, TAG, "OCProvisionPairwiseDevices : Invalid parameters");
+        return OC_STACK_INVALID_PARAM;
+    }
+    if (!(keySize == OWNER_PSK_LENGTH_128 || keySize == OWNER_PSK_LENGTH_256))
+    {
+        OC_LOG(INFO, TAG, "OCProvisionPairwiseDevices : Invalid key size");
+        return OC_STACK_INVALID_PARAM;
+    }
+    int noOfResults = 2; // Initial Value
+    if (NULL!=pDev1Acl)
+    {
+        ++noOfResults;
+    }
+    if(NULL!=pDev2Acl)
+    {
+       ++noOfResults;
+    }
+    Linkdata_t *link = (Linkdata_t*) OICMalloc(sizeof(Linkdata_t));
+    if(!link)
+    {
+        OC_LOG(ERROR, TAG, "Failed to memory allocation");
+        return OC_STACK_NO_MEMORY;
+    }
+    OC_LOG_V(INFO,TAG, "Maximum no od results %d",noOfResults);
+
+    link->pDev1 = pDev1;
+    link->pDev1Acl = pDev1Acl;
+    link->pDev2 = pDev2;
+    link->pDev2Acl = pDev2Acl;
+    link->ctx = ctx;
+    // 1 call for each device for credential provisioning. implict call by SRPProvisioning credential
+    // 1 call for ACL provisioning for device 1 and 1 call for ACL provisioning for device 2.
+    link->numOfResults = noOfResults;
+    link->resultCallback = resultCallback;
+    link->currentCountResults = 0;
+    link->resArr = (OCProvisionResult_t*) OICMalloc(sizeof(OCProvisionResult_t)*noOfResults);
+    OCStackResult res = SRPProvisionCredentials(link, type, keySize,
+                                     pDev1, pDev2, &ProvisionCredsCB);
+    if (res != OC_STACK_OK)
+    {
+        OICFree(link->resArr);
+        OICFree(link);
+    }
+    return res;
+
+}
diff --git a/resource/csdk/security/provisioning/src/ownershiptransfermanager.c b/resource/csdk/security/provisioning/src/ownershiptransfermanager.c
new file mode 100644 (file)
index 0000000..e1f69f0
--- /dev/null
@@ -0,0 +1,1148 @@
+/* *****************************************************************
+ *
+ * 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.
+ *
+ * *****************************************************************/
+
+// Defining _POSIX_C_SOURCE macro with 199309L (or greater) as value
+// causes header files to expose definitions
+// corresponding to the POSIX.1b, Real-time extensions
+// (IEEE Std 1003.1b-1993) specification
+//
+// For this specific file, see use of clock_gettime,
+// Refer to http://pubs.opengroup.org/stage7tc1/functions/clock_gettime.html
+// and to http://man7.org/linux/man-pages/man2/clock_gettime.2.html
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
+
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <stdbool.h>
+#include <string.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 "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"
+
+// TODO: Not yet supported.
+//#include "oxmrandompin.h"
+
+#define DEFAULT_CONTEXT_VALUE 0x99
+#define DEFAULT_SECURE_PORT 5684
+
+#define TAG "OTM"
+
+OCProvisionResultCB g_resultCallback;
+OCProvisionResult_t* g_resultArray = NULL;
+size_t g_resultArraySize = 0;
+bool g_hasError = false;
+
+/**
+ * Possible states of ownership transfer manager module.
+ */
+typedef enum
+{
+    SP_NO_MASK                = (0       ),
+    SP_DISCOVERY_STARTED      = (0x1 << 1),
+    SP_DISCOVERY_ERROR        = (0x1 << 2),
+    SP_DISCOVERY_DONE         = (0x1 << 3),
+    SP_UP_OWN_TR_METH_STARTED = (0x1 << 4),
+    SP_UP_OWN_TR_METH_ERROR   = (0x1 << 5),
+    SP_UP_OWN_TR_METH_DONE    = (0x1 << 6),
+    SP_LIST_METHODS_STARTED   = (0x1 << 7),
+    SP_LIST_METHODS_ERROR     = (0x1 << 8),
+    SP_LIST_METHODS_DONE      = (0x1 << 9),
+    SP_UPDATE_OP_MODE_STARTED = (0x1 << 10),
+    SP_UPDATE_OP_MODE_ERROR   = (0x1 << 11),
+    SP_UPDATE_OP_MODE_DONE    = (0x1 << 12),
+    SP_UPDATE_OWNER_STARTED   = (0x1 << 13),
+    SP_UPDATE_OWNER_ERROR     = (0x1 << 14),
+    SP_UPDATE_OWNER_DONE      = (0x1 << 15)
+} OTMStates;
+
+
+
+/**
+ * Array to store the callbacks for each owner transfer method.
+ */
+OTMCallbackData_t g_OTMDatas[OIC_OXM_COUNT];
+
+/**
+ * Variable for storing provisioning tool's provisioning capabilities
+ * Must be in decreasing order of preference. More prefered method should
+ * have lower array index.
+ */
+static OicSecDpom_t gProvisioningToolCapability[] = { SINGLE_SERVICE_CLIENT_DRIVEN };
+
+/**
+ * Number of supported provisioning methods
+ * current version supports only one.
+ */
+static size_t gNumOfProvisioningMethodsPT = 1;
+
+/**
+ * Function to getting string of ownership transfer method
+ */
+static const char* GetOxmString(OicSecOxm_t oxmType)
+{
+    switch(oxmType)
+    {
+        case OIC_JUST_WORKS:
+            return OXM_JUST_WORKS;
+        case OIC_MODE_SWITCH:
+            return OXM_MODE_SWITCH;
+        case OIC_RANDOM_DEVICE_PIN:
+            return OXM_RANDOM_DEVICE_PIN;
+        case OIC_PRE_PROVISIONED_DEVICE_PIN:
+            return OXM_PRE_PROVISIONED_DEVICE_PIN;
+        case OIC_PRE_PROVISION_STRONG_CREDENTIAL:
+            return OXM_PRE_PROVISIONED_STRONG_CREDENTIAL;
+        default:
+            return NULL;
+    }
+}
+
+/**
+ * Function to select appropriate  provisioning method.
+ *
+ * @param[in] supportedMethods   Array of supported methods
+ * @param[in] numberOfMethods   number of supported methods
+ * @param[out]  selectedMethod         Selected methods
+ * @return  SP_SUCCESS on success
+ */
+static OCStackResult SelectProvisioningMethod(const OicSecOxm_t *supportedMethods,
+                                                            size_t numberOfMethods,
+                                                            OicSecOxm_t *selectedMethod)
+{
+    OC_LOG(DEBUG, TAG, "IN SelectProvisioningMethod");
+
+    if(numberOfMethods == 0 || !supportedMethods)
+    {
+        OC_LOG(WARNING, TAG, "Could not find a supported OxM.");
+        return OC_STACK_ERROR;
+    }
+
+    *selectedMethod  = supportedMethods[0];
+    for(size_t i = 0; i < numberOfMethods; i++)
+    {
+        if(*selectedMethod < supportedMethods[i])
+        {
+            *selectedMethod =  supportedMethods[i];
+        }
+    }
+
+    return OC_STACK_OK;
+}
+
+/**
+ * Function to select operation mode.This function will return most secure common operation mode.
+ *
+ * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
+ * @param[out]   selectedMode   selected operation mode
+ * @return  SP_SUCCESS on success
+ */
+static void SelectOperationMode(const OCProvisionDev_t *selectedDeviceInfo,
+                                OicSecDpom_t *selectedMode)
+{
+    OC_LOG(DEBUG, TAG, "IN SelectOperationMode");
+
+    size_t i = 0;
+    size_t j = 0;
+
+    while (i < gNumOfProvisioningMethodsPT && j < selectedDeviceInfo->pstat->smLen)
+    {
+        if (gProvisioningToolCapability[i] < selectedDeviceInfo->pstat->sm[j])
+        {
+            i++;
+        }
+        else if (selectedDeviceInfo->pstat->sm[j] < gProvisioningToolCapability[i])
+        {
+            j++;
+        }
+        else /* if gProvisioningToolCapability[i] == deviceSupportedMethods[j] */
+        {
+            *selectedMode = gProvisioningToolCapability[j];
+            break;
+        }
+    }
+    OC_LOG(DEBUG, TAG, "OUT SelectOperationMode");
+}
+
+/**
+ * Function to update owner transfer mode
+ *
+ * @param[in]  otmCtx  Context value of ownership transfer.
+ * @return  OC_STACK_OK on success
+ */
+static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx);
+
+/**
+ * Function to send request to resource to get its pstat resource information.
+ *
+ * @param[in]  otmCtx  Context value of ownership transfer.
+ * @return  OC_STACK_OK on success
+ */
+static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx);
+
+
+/**
+ * Function to send ownerShip info. This function would update Owned as true and
+ * owner as UUID for provisioning tool
+ *
+ * @param[in]  otmCtx  Context value of ownership transfer.
+ * @return  OC_STACK_OK on success
+ */
+static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx);
+
+/**
+ * Function to update the operation mode. As per the spec. Operation mode in client driven
+ * single service provisioning it will be updated to 0x3
+ *
+ * @param[in]  otmCtx  Context value of ownership transfer.
+ * @param[in] selectedOperationMode selected operation mode
+ * @return  OC_STACK_OK on success
+ */
+static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
+                                    OicSecDpom_t selectedOperationMode);
+
+/**
+ * Function to start ownership transfer.
+ * This function will send the first request for provisioning,
+ * The next request message is sent from the response handler for this request.
+ *
+ * @param[in] ctx   context value passed to callback from calling function.
+ * @param[in] selectedDevice   selected device information to performing provisioning.
+ * @return  OC_STACK_OK on success
+ */
+static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice);
+
+/*
+ * Function to finalize provisioning.
+ * This function will send default ACL and commit hash.
+ *
+ * @param[in] otmCtx   Context value of ownership transfer.
+ * @return  OC_STACK_OK on success
+ */
+static OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx);
+
+
+static bool IsComplete()
+{
+    for(size_t i = 0; i < g_resultArraySize; i++)
+    {
+        if(OC_STACK_CONTINUE == g_resultArray[i].res)
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+/**
+ * Function to save the result of provisioning.
+ *
+ * @param[in,out] otmCtx   Context value of ownership transfer.
+ * @param[in] res   result of provisioning
+ */
+static void SetResult(OTMContext_t* otmCtx, const OCStackResult res)
+{
+    OC_LOG(DEBUG, TAG, "IN SetResult");
+
+    if(!otmCtx)
+    {
+        OC_LOG(WARNING, TAG, "OTMContext is NULL");
+        return;
+    }
+
+    if(otmCtx->selectedDeviceInfo)
+    {
+        for(size_t i = 0; i < g_resultArraySize; i++)
+        {
+            if(memcmp(otmCtx->selectedDeviceInfo->doxm->deviceID.id,
+                      g_resultArray[i].deviceId.id, UUID_LENGTH) == 0)
+            {
+                g_resultArray[i].res = res;
+                if(OC_STACK_OK != res)
+                {
+                    g_hasError = true;
+                }
+            }
+        }
+
+        //If all request is completed, invoke the user callback.
+        if(IsComplete())
+        {
+            g_resultCallback(otmCtx->userCtx, g_resultArraySize, g_resultArray, g_hasError);
+        }
+        else
+        {
+            if(OC_STACK_OK != StartOwnershipTransfer(otmCtx->userCtx,
+                                                     otmCtx->selectedDeviceInfo->next))
+            {
+                OC_LOG(ERROR, TAG, "Failed to StartOwnershipTransfer");
+            }
+        }
+    }
+
+    OC_LOG(DEBUG, TAG, "OUT SetResult");
+
+    OICFree(otmCtx);
+}
+
+
+/**
+ * Function to save ownerPSK at provisioning tool end.
+ *
+ * @param[in] selectedDeviceInfo   selected device information to performing provisioning.
+ * @return  OC_STACK_OK on success
+ */
+static OCStackResult SaveOwnerPSK(OCProvisionDev_t *selectedDeviceInfo)
+{
+    OC_LOG(DEBUG, TAG, "IN SaveOwnerPSK");
+
+    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;
+
+    OicUuid_t ptDeviceID = {.id={0}};
+    if (OC_STACK_OK != GetDoxmDeviceID(&ptDeviceID))
+    {
+        OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+        return res;
+    }
+
+    uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {0};
+
+    //Generating OwnerPSK
+    CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
+            (uint8_t *)GetOxmString(selectedDeviceInfo->doxm->oxmSel),
+            strlen(GetOxmString(selectedDeviceInfo->doxm->oxmSel)), ptDeviceID.id,
+            sizeof(ptDeviceID.id), selectedDeviceInfo->doxm->deviceID.id,
+            sizeof(selectedDeviceInfo->doxm->deviceID.id), ownerPSK,
+            OWNER_PSK_LENGTH_128);
+
+    if (CA_STATUS_OK == pskRet)
+    {
+        OC_LOG(INFO, TAG,"ownerPSK dump:\n");
+        OC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
+        //Generating new credential for provisioning tool
+        size_t ownLen = 1;
+        uint32_t outLen = 0;
+
+        char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
+        B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
+                &outLen);
+        VERIFY_SUCCESS(TAG, B64_OK == b64Ret, ERROR);
+
+        OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
+                SYMMETRIC_PAIR_WISE_KEY, NULL,
+                base64Buff, ownLen, &ptDeviceID);
+        VERIFY_NON_NULL(TAG, cred, ERROR);
+
+        res = AddCredential(cred);
+        if(res != OC_STACK_OK)
+        {
+            DeleteCredList(cred);
+            return res;
+        }
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
+    }
+
+    OC_LOG(DEBUG, TAG, "OUT SaveOwnerPSK");
+exit:
+    return res;
+}
+
+/**
+ * Callback handler for OwnerShipTransferModeHandler API.
+ *
+ * @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 OwnerTransferModeHandler(void *ctx, OCDoHandle UNUSED,
+                                                         OCClientResponse *clientResponse)
+{
+    OC_LOG(DEBUG, TAG, "IN OwnerTransferModeHandler");
+
+    VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+    VERIFY_NON_NULL(TAG, ctx, WARNING);
+
+    OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+    (void)UNUSED;
+    if(clientResponse->result == OC_STACK_OK)
+    {
+        OC_LOG(INFO, TAG, "OwnerTransferModeHandler : response result = OC_STACK_OK");
+        //Send request : GET /oic/sec/pstat
+        OCStackResult res = GetProvisioningStatusResource(otmCtx);
+        if(OC_STACK_OK != res)
+        {
+            OC_LOG(WARNING, TAG, "Failed to get pstat information");
+            SetResult(otmCtx, res);
+        }
+    }
+    else
+    {
+        OC_LOG_V(WARNING, TAG, "OwnerTransferModeHandler : Client response is incorrect : %d",
+        clientResponse->result);
+        SetResult(otmCtx, clientResponse->result);
+    }
+
+    OC_LOG(DEBUG, TAG, "OUT OwnerTransferModeHandler");
+
+exit:
+    return  OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler for ProvisioningStatusResouceHandler API.
+ *
+ * @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 ListMethodsHandler(void *ctx, OCDoHandle UNUSED,
+                                                    OCClientResponse *clientResponse)
+{
+    OC_LOG(DEBUG, TAG, "IN ListMethodsHandler");
+
+    VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+    VERIFY_NON_NULL(TAG, ctx, WARNING);
+
+    OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+    (void)UNUSED;
+    if  (OC_STACK_OK == clientResponse->result)
+    {
+        if  (NULL == clientResponse->payload)
+        {
+            OC_LOG(INFO, TAG, "Skiping Null payload");
+            SetResult(otmCtx, OC_STACK_ERROR);
+            return OC_STACK_DELETE_TRANSACTION;
+        }
+
+        if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
+        {
+            OC_LOG(INFO, TAG, "Unknown payload type");
+            SetResult(otmCtx, OC_STACK_ERROR);
+            return OC_STACK_DELETE_TRANSACTION;
+        }
+
+        OicSecPstat_t* pstat = JSONToPstatBin(
+                ((OCSecurityPayload*)clientResponse->payload)->securityData);
+        if(NULL == pstat)
+        {
+            OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
+            SetResult(otmCtx, OC_STACK_ERROR);
+            return OC_STACK_DELETE_TRANSACTION;
+        }
+        otmCtx->selectedDeviceInfo->pstat = pstat;
+
+        //Select operation mode (Currently supported SINGLE_SERVICE_CLIENT_DRIVEN only)
+        OicSecDpom_t selectedOperationMode;
+        SelectOperationMode(otmCtx->selectedDeviceInfo, &selectedOperationMode);
+
+        //Send request : PUT /oic/sec/pstat [{"OM":"0x11", .. }]
+        OCStackResult res = PutUpdateOperationMode(otmCtx, selectedOperationMode);
+        if (OC_STACK_OK != res)
+        {
+            OC_LOG(ERROR, TAG, "Error while updating operation mode.");
+            SetResult(otmCtx, res);
+        }
+    }
+    else
+    {
+        OC_LOG_V(WARNING, TAG, "ListMethodsHandler : Client response is incorrect : %d",
+            clientResponse->result);
+        SetResult(otmCtx, clientResponse->result);
+    }
+
+    OC_LOG(DEBUG, TAG, "OUT ListMethodsHandler");
+exit:
+    return  OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler for OwnershipInformationHandler API.
+ *
+ * @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 OwnershipInformationHandler(void *ctx, OCDoHandle UNUSED,
+                                OCClientResponse *clientResponse)
+{
+    VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+    VERIFY_NON_NULL(TAG, ctx, WARNING);
+
+    OC_LOG(DEBUG, TAG, "IN OwnershipInformationHandler");
+    (void)UNUSED;
+    OCStackResult res = OC_STACK_OK;
+    OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+    if  (OC_STACK_OK == clientResponse->result)
+    {
+        if(OIC_RANDOM_DEVICE_PIN == otmCtx->selectedDeviceInfo->doxm->oxmSel)
+        {
+            res = RemoveCredential(&otmCtx->tempCredId);
+            if(OC_STACK_RESOURCE_DELETED != res)
+            {
+                OC_LOG_V(ERROR, TAG, "Failed to remove temporal PSK : %d", res);
+                return OC_STACK_DELETE_TRANSACTION;
+            }
+        }
+
+        res = SaveOwnerPSK(otmCtx->selectedDeviceInfo);
+        if(OC_STACK_OK != res)
+        {
+            OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to owner PSK generation");
+            SetResult(otmCtx, res);
+            return OC_STACK_DELETE_TRANSACTION;
+        }
+
+        CAEndpoint_t* endpoint = (CAEndpoint_t *)&otmCtx->selectedDeviceInfo->endpoint;
+        endpoint->port = otmCtx->selectedDeviceInfo->securePort;
+        CAResult_t closeRes = CACloseDtlsSession(endpoint);
+        if(CA_STATUS_OK != closeRes)
+        {
+            OC_LOG(ERROR, TAG, "Failed to close DTLS session");
+            SetResult(otmCtx, closeRes);
+            return OC_STACK_DELETE_TRANSACTION;
+        }
+
+        OC_LOG(INFO, TAG, "Ownership transfer was successfully completed.");
+        OC_LOG(INFO, TAG, "Start defualt ACL & commit-hash provisioning.");
+
+        res = FinalizeProvisioning(otmCtx);
+        if(OC_STACK_OK != res)
+        {
+            SetResult(otmCtx, res);
+        }
+    }
+    else
+    {
+        res = clientResponse->result;
+    }
+
+    OC_LOG(DEBUG, TAG, "OUT OwnershipInformationHandler");
+
+exit:
+    return  OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Response handler for update operation mode.
+ *
+ * @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 OperationModeUpdateHandler(void *ctx, OCDoHandle UNUSED,
+                                OCClientResponse *clientResponse)
+{
+    OC_LOG(DEBUG, TAG, "IN OperationModeUpdateHandler");
+
+    VERIFY_NON_NULL(TAG, clientResponse, WARNING);
+    VERIFY_NON_NULL(TAG, ctx, WARNING);
+
+    OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+    (void) UNUSED;
+    if  (OC_STACK_OK == clientResponse->result)
+    {
+        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)
+        {
+            res = g_OTMDatas[selOxm].loadSecretCB(otmCtx);
+            if(OC_STACK_OK != res)
+            {
+                OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to load secret");
+                SetResult(otmCtx, res);
+                return  OC_STACK_DELETE_TRANSACTION;
+            }
+        }
+
+        //Try DTLS handshake to generate secure session
+        if(g_OTMDatas[selOxm].createSecureSessionCB)
+        {
+            res = g_OTMDatas[selOxm].createSecureSessionCB(otmCtx);
+            if(OC_STACK_OK != res)
+            {
+                OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to create DTLS session");
+                SetResult(otmCtx, res);
+                return OC_STACK_DELETE_TRANSACTION;
+            }
+        }
+
+        //Send request : PUT /oic/sec/doxm [{"Owned":"True", .. , "Owner":"PT's UUID"}]
+        res = PutOwnershipInformation(otmCtx);
+        if(OC_STACK_OK != res)
+        {
+            OC_LOG(ERROR, TAG, "OperationModeUpdate : Failed to send owner information");
+            SetResult(otmCtx, res);
+        }
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, "Error while update operation mode");
+        SetResult(otmCtx, clientResponse->result);
+    }
+
+    OC_LOG(DEBUG, TAG, "OUT OperationModeUpdateHandler");
+
+exit:
+    return  OC_STACK_DELETE_TRANSACTION;
+}
+
+
+static OCStackResult PutOwnerTransferModeToResource(OTMContext_t* otmCtx)
+{
+    OC_LOG(DEBUG, TAG, "IN PutOwnerTransferModeToResource");
+
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        OC_LOG(ERROR, TAG, "Invailed parameters");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
+    OicSecOxm_t selectedOxm = deviceInfo->doxm->oxmSel;
+    char query[MAX_QUERY_LENGTH] = {};
+    sprintf(query, "%s%s:%d%s", COAP_PREFIX,
+                                deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
+                                OIC_RSRC_DOXM_URI);
+    OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+    if(!secPayload)
+    {
+        OC_LOG(ERROR, TAG, "Failed to memory allocation");
+        return OC_STACK_NO_MEMORY;
+    }
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+    secPayload->securityData = g_OTMDatas[selectedOxm].createSelectOxmPayloadCB(otmCtx);
+    if (NULL == secPayload->securityData)
+    {
+        OICFree(secPayload);
+        OC_LOG(ERROR, TAG, "Error while converting bin to json");
+        return OC_STACK_ERROR;
+    }
+    OC_LOG_V(DEBUG, TAG, "Payload : %s", secPayload->securityData);
+
+    OCCallbackData cbData;
+    cbData.cb = &OwnerTransferModeHandler;
+    cbData.context = (void *)otmCtx;
+    cbData.cd = NULL;
+
+    // TODO: 6th argument need to be changed, if we have to use CT_FLAG_SECURE
+    OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query,
+                                     &deviceInfo->endpoint, (OCPayload*)secPayload,
+                                     CT_ADAPTER_IP, OC_LOW_QOS, &cbData, NULL, 0);
+    if (res != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack resource error");
+    }
+
+    OC_LOG(DEBUG, TAG, "OUT PutOwnerTransferModeToResource");
+
+    return res;
+}
+
+static OCStackResult GetProvisioningStatusResource(OTMContext_t* otmCtx)
+{
+    OC_LOG(DEBUG, TAG, "IN GetProvisioningStatusResource");
+
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        OC_LOG(ERROR, TAG, "Invailed parameters");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
+    char query[MAX_QUERY_LENGTH] = {};
+    sprintf(query, "%s%s:%d%s", COAP_PREFIX,
+                                deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
+                                OIC_RSRC_PSTAT_URI);
+    OCCallbackData cbData;
+    cbData.cb = &ListMethodsHandler;
+    cbData.context = (void *)otmCtx;
+    cbData.cd = NULL;
+
+    // TODO: 6th argument need to be changed, if we have to use CT_FLAG_SECURE
+    OCStackResult res = OCDoResource(NULL, OC_REST_GET, query, NULL, NULL,
+                                     CT_ADAPTER_IP, OC_LOW_QOS, &cbData, NULL, 0);
+    if (res != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack resource error");
+    }
+
+    OC_LOG(DEBUG, TAG, "OUT GetProvisioningStatusResource");
+
+    return res;
+}
+
+
+static OCStackResult PutOwnershipInformation(OTMContext_t* otmCtx)
+{
+    OC_LOG(DEBUG, TAG, "IN PutOwnershipInformation");
+
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        OC_LOG(ERROR, TAG, "Invailed parameters");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
+    char query[MAX_QUERY_LENGTH] = {};
+    sprintf(query, "%s%s:%d%s", COAPS_PREFIX,
+                                deviceInfo->endpoint.addr, deviceInfo->securePort,
+                                OIC_RSRC_DOXM_URI);
+    //OwnershipInformationHandler
+    OicSecOxm_t selOxm = deviceInfo->doxm->oxmSel;
+    OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+    if(!secPayload)
+    {
+        OC_LOG(ERROR, TAG, "Failed to memory allocation");
+        return OC_STACK_NO_MEMORY;
+    }
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+    secPayload->securityData = g_OTMDatas[selOxm].createOwnerTransferPayloadCB(otmCtx);
+    if (NULL == secPayload->securityData)
+    {
+        OICFree(secPayload);
+        OC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCCallbackData cbData;
+    cbData.cb = &OwnershipInformationHandler;
+    cbData.context = (void *)otmCtx;
+    cbData.cd = NULL;
+    // TODO: 6th argument need to be changed, if we have to use CT_FLAG_SECURE
+    OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
+                                     CT_ADAPTER_IP, OC_LOW_QOS, &cbData, NULL, 0);
+    if (res != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack resource error");
+    }
+
+    OC_LOG(DEBUG, TAG, "OUT PutOwnershipInformation");
+
+    return res;
+}
+
+static OCStackResult PutUpdateOperationMode(OTMContext_t* otmCtx,
+                                    OicSecDpom_t selectedOperationMode)
+{
+    OC_LOG(DEBUG, TAG, "IN PutUpdateOperationMode");
+
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCProvisionDev_t* deviceInfo = otmCtx->selectedDeviceInfo;
+    char query[MAX_QUERY_LENGTH] = {};
+    sprintf(query, "%s%s:%d%s", COAP_PREFIX,
+                                deviceInfo->endpoint.addr, deviceInfo->endpoint.port,
+                                OIC_RSRC_PSTAT_URI);
+    deviceInfo->pstat->om = selectedOperationMode;
+
+    OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+    if(!secPayload)
+    {
+        OC_LOG(ERROR, TAG, "Failed to memory allocation");
+        return OC_STACK_NO_MEMORY;
+    }
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+    secPayload->securityData = BinToPstatJSON(deviceInfo->pstat);
+    if (NULL == secPayload->securityData)
+    {
+        OICFree(secPayload);
+        OC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCCallbackData cbData;
+    cbData.cb = &OperationModeUpdateHandler;
+    cbData.context = (void *)otmCtx;
+    cbData.cd = NULL;
+
+    OCStackResult res = OCDoResource(NULL, OC_REST_PUT, query, 0, (OCPayload*)secPayload,
+                                     CT_ADAPTER_IP, OC_LOW_QOS, &cbData, NULL, 0);
+    if (res != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack resource error");
+    }
+
+    OC_LOG(DEBUG, TAG, "OUT PutUpdateOperationMode");
+
+    return res;
+}
+
+static OCStackResult StartOwnershipTransfer(void* ctx, OCProvisionDev_t* selectedDevice)
+{
+    OC_LOG(INFO, TAG, "IN StartOwnershipTransfer");
+    OTMContext_t* otmCtx = (OTMContext_t*)OICMalloc(sizeof(OTMContext_t));
+    if(!otmCtx)
+    {
+        OC_LOG(ERROR, TAG, "Failed to create OTM Context");
+        return OC_STACK_NO_MEMORY;
+    }
+    otmCtx->userCtx = 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);
+    if(OC_STACK_OK != res)
+    {
+        OC_LOG(ERROR, TAG, "Failed to select the provisioning method");
+        SetResult(otmCtx, res);
+        return res;
+    }
+    OC_LOG_V(DEBUG, TAG, "Selected provisoning method = %d", selectedDevice->doxm->oxmSel);
+
+    //Send Req: PUT /oic/sec/doxm [{..."OxmSel" :g_OTMDatas[Index of Selected OxM].OXMString,...}]
+    res = PutOwnerTransferModeToResource(otmCtx);
+    if(OC_STACK_OK != res)
+    {
+        OC_LOG(WARNING, TAG, "Failed to select the provisioning method");
+        SetResult(otmCtx, res);
+        return res;
+    }
+
+    OC_LOG(INFO, TAG, "OUT StartOwnershipTransfer");
+
+    return res;
+
+}
+
+OCStackResult OTMSetOwnershipTransferCallbackData(OicSecOxm_t oxmType, OTMCallbackData_t* data)
+{
+    OC_LOG(DEBUG, TAG, "IN OTMSetOwnerTransferCallbackData");
+
+    if(!data)
+    {
+        OC_LOG(ERROR, TAG, "OTMSetOwnershipTransferCallbackData : Invalid parameters");
+        return OC_STACK_INVALID_PARAM;
+    }
+    if(oxmType >= OIC_OXM_COUNT)
+    {
+        OC_LOG(INFO, TAG, "Unknow ownership transfer method");
+        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;
+
+    OC_LOG(DEBUG, TAG, "OUT OTMSetOwnerTransferCallbackData");
+
+    return OC_STACK_OK;
+}
+
+/**
+ * NOTE : Unowned discovery should be done before performing OTMDoOwnershipTransfer
+ */
+OCStackResult OTMDoOwnershipTransfer(void* ctx,
+                                     OCProvisionDev_t *selectedDevicelist,
+                                     OCProvisionResultCB resultCallback)
+{
+    OC_LOG(DEBUG, TAG, "IN OTMDoOwnershipTransfer");
+
+    if (NULL == selectedDevicelist || NULL == resultCallback )
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    g_resultCallback = resultCallback;
+    g_hasError = false;
+
+    OCProvisionDev_t* pCurDev = selectedDevicelist;
+
+    //Counting number of selected devices.
+    g_resultArraySize = 0;
+    while(NULL != pCurDev)
+    {
+        g_resultArraySize++;
+        pCurDev = pCurDev->next;
+    }
+
+    if(g_resultArray)
+    {
+        OICFree(g_resultArray);
+    }
+    g_resultArray =
+        (OCProvisionResult_t*)OICMalloc(sizeof(OCProvisionResult_t) * g_resultArraySize);
+    if(NULL == g_resultArray)
+    {
+        OC_LOG(ERROR, TAG, "OTMDoOwnershipTransfer : Failed to memory allocation");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    pCurDev = selectedDevicelist;
+    //Fill the device UUID for result array.
+    for(size_t devIdx = 0; devIdx < g_resultArraySize; devIdx++)
+    {
+        memcpy(g_resultArray[devIdx].deviceId.id,
+               pCurDev->doxm->deviceID.id,
+               UUID_LENGTH);
+        g_resultArray[devIdx].res = OC_STACK_CONTINUE;
+        pCurDev = pCurDev->next;
+    }
+
+    StartOwnershipTransfer(ctx, selectedDevicelist);
+
+    OC_LOG(DEBUG, TAG, "OUT OTMDoOwnershipTransfer");
+
+    return (g_hasError ? OC_STACK_ERROR : OC_STACK_OK);
+}
+
+/**
+ * Callback handler of SRPFinalizeProvisioning.
+ *
+ * @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 FinalizeProvisioningCB(void *ctx, OCDoHandle UNUSED,
+                                                       OCClientResponse *clientResponse)
+{
+    OC_LOG_V(INFO, TAG, "IN FinalizeProvisioningCB.");
+
+    VERIFY_NON_NULL(TAG, clientResponse, ERROR);
+    VERIFY_NON_NULL(TAG, ctx, ERROR);
+
+    OTMContext_t* otmCtx = (OTMContext_t*)ctx;
+    (void)UNUSED;
+    if(OC_STACK_OK == clientResponse->result)
+    {
+        SetResult(otmCtx, OC_STACK_OK);
+    }
+exit:
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler of default ACL provisioning.
+ *
+ * @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 ProvisionDefaultACLCB(void *ctx, OCDoHandle UNUSED,
+                                                       OCClientResponse *clientResponse)
+{
+    OC_LOG_V(INFO, TAG, "IN ProvisionDefaultACLCB.");
+
+    VERIFY_NON_NULL(TAG, clientResponse, ERROR);
+    VERIFY_NON_NULL(TAG, ctx, ERROR);
+
+    OTMContext_t* otmCtx = (OTMContext_t*) ctx;
+    (void)UNUSED;
+
+    if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
+    {
+        OC_LOG_V(INFO, TAG, "Staring commit hash task.");
+        // TODO hash currently have fixed value 0.
+        uint16_t aclHash = 0;
+        otmCtx->selectedDeviceInfo->pstat->commitHash = aclHash;
+        otmCtx->selectedDeviceInfo->pstat->tm = NORMAL;
+        OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+        if(!secPayload)
+        {
+            OC_LOG(ERROR, TAG, "Failed to memory allocation");
+            return OC_STACK_NO_MEMORY;
+        }
+        secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+        secPayload->securityData = BinToPstatJSON(otmCtx->selectedDeviceInfo->pstat);
+        if (NULL == secPayload->securityData)
+        {
+            OICFree(secPayload);
+            SetResult(otmCtx, OC_STACK_INVALID_JSON);
+            return OC_STACK_DELETE_TRANSACTION;
+        }
+        OC_LOG_V(INFO, TAG, "Created payload for commit hash: %s",secPayload->securityData);
+
+        char uri[MAX_QUERY_LENGTH] = { 0 };
+        size_t uriLen = sizeof(uri);
+
+        snprintf(uri, uriLen - 1, COAPS_QUERY, otmCtx->selectedDeviceInfo->endpoint.addr,
+                otmCtx->selectedDeviceInfo->securePort, OIC_RSRC_PSTAT_URI);
+        uri[uriLen - 1] = '\0';
+        OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
+        cbData.cb = &FinalizeProvisioningCB;
+        cbData.context = (void*)otmCtx; // forward context to SRPFinalizeProvisioningCB
+        cbData.cd = NULL;
+
+        // TODO change value of CT_ADAPTER_IP with val from discovery
+        OCStackResult ret = OCDoResource(NULL, OC_REST_PUT, uri, 0, (OCPayload*)secPayload,
+                CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
+        OC_LOG_V(INFO, TAG, "OCDoResource returned: %d",ret);
+        if (ret != OC_STACK_OK)
+        {
+            OC_LOG(ERROR, TAG, "OCStack resource error");
+            SetResult(otmCtx, ret);
+        }
+    }
+    else
+    {
+        OC_LOG_V(INFO, TAG, "Error occured in provisionDefaultACLCB :: %d\n",
+                            clientResponse->result);
+        SetResult(otmCtx, clientResponse->result);
+    }
+exit:
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+OCStackResult FinalizeProvisioning(OTMContext_t* otmCtx)
+{
+    OC_LOG(INFO, TAG, "IN FinalizeProvisioning");
+
+    if(!otmCtx)
+    {
+        OC_LOG(ERROR, TAG, "OTMContext is NULL");
+        return OC_STACK_INVALID_PARAM;
+    }
+    if(!otmCtx->selectedDeviceInfo)
+    {
+        OC_LOG(ERROR, TAG, "Can't find device information in OTMContext");
+        OICFree(otmCtx);
+        return OC_STACK_INVALID_PARAM;
+    }
+    // Provision Default ACL to device
+    OicSecAcl_t defaultAcl =
+    { {.id={0}},
+        1,
+        NULL,
+        0x001F,
+        0,
+        NULL,
+        NULL,
+        1,
+        NULL,
+        NULL,
+    };
+
+    OicUuid_t provTooldeviceID = {.id={0}};
+    if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
+    {
+        OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+        SetResult(otmCtx, OC_STACK_ERROR);
+        return OC_STACK_ERROR;
+    }
+    OC_LOG(INFO, TAG, "Retieved deviceID");
+    memcpy(defaultAcl.subject.id, provTooldeviceID.id, sizeof(defaultAcl.subject.id));
+    char *wildCardResource = "*";
+    defaultAcl.resources = &wildCardResource;
+
+    defaultAcl.owners = (OicUuid_t *) OICCalloc(1, UUID_LENGTH);
+    if(!defaultAcl.owners)
+    {
+        OC_LOG(ERROR, TAG, "Failed to memory allocation for default ACL");
+        SetResult(otmCtx, OC_STACK_NO_MEMORY);
+        return OC_STACK_NO_MEMORY;
+    }
+    memcpy(defaultAcl.owners->id, provTooldeviceID.id, UUID_LENGTH);
+    OC_LOG(INFO, TAG, "Provisioning default ACL");
+
+    OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+    if(!secPayload)
+    {
+        OC_LOG(ERROR, TAG, "Failed to memory allocation");
+        return OC_STACK_NO_MEMORY;
+    }
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+    secPayload->securityData = BinToAclJSON(&defaultAcl);
+    OICFree(defaultAcl.owners);
+    if(!secPayload->securityData)
+    {
+        OICFree(secPayload);
+        OC_LOG(INFO, TAG, "FinalizeProvisioning : Failed to BinToAclJSON");
+        SetResult(otmCtx, OC_STACK_ERROR);
+        return OC_STACK_ERROR;
+    }
+    OC_LOG_V(INFO, TAG, "Provisioning default ACL : %s",secPayload->securityData);
+
+    char uri[MAX_QUERY_LENGTH] = { 0 };
+
+    size_t uriLen = sizeof(uri);
+    snprintf(uri, uriLen - 1, COAPS_QUERY, otmCtx->selectedDeviceInfo->endpoint.addr,
+            otmCtx->selectedDeviceInfo->securePort, OIC_RSRC_ACL_URI);
+    uri[uriLen - 1] = '\0';
+    OC_LOG_V(INFO, TAG, "Request URI for Provisioning default ACL : %s",uri);
+
+    OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
+    cbData.cb = &ProvisionDefaultACLCB;
+    cbData.context = (void *)otmCtx;
+    cbData.cd = NULL;
+
+    OCStackResult ret = OCDoResource(NULL, OC_REST_POST, uri,
+            &otmCtx->selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
+            CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
+    if (OC_STACK_OK != ret)
+    {
+        SetResult(otmCtx, ret);
+        return ret;
+    }
+
+    OC_LOG(INFO, TAG, "OUT FinalizeProvisioning");
+
+    return ret;
+
+}
+
diff --git a/resource/csdk/security/provisioning/src/oxmjustworks.c b/resource/csdk/security/provisioning/src/oxmjustworks.c
new file mode 100644 (file)
index 0000000..2d1988c
--- /dev/null
@@ -0,0 +1,108 @@
+/* *****************************************************************
+ *
+ * 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 <memory.h>
+#include "ocstack.h"
+#include "securevirtualresourcetypes.h"
+#include "doxmresource.h"
+#include "cacommon.h"
+#include "cainterface.h"
+#include "oic_malloc.h"
+#include "logger.h"
+#include "global.h"
+#include "pmtypes.h"
+#include "ownershiptransfermanager.h"
+
+#define TAG "OXM_JustWorks"
+
+char* CreateJustWorksSelectOxmPayload(OTMContext_t* otmCtx)
+{
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        return NULL;
+    }
+
+    otmCtx->selectedDeviceInfo->doxm->oxmSel = OIC_JUST_WORKS;
+    return BinToDoxmJSON(otmCtx->selectedDeviceInfo->doxm);
+}
+
+char* CreateJustWorksOwnerTransferPayload(OTMContext_t* otmCtx)
+{
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        return NULL;
+    }
+
+    OicUuid_t uuidPT = {.id={0}};
+
+    if (OC_STACK_OK != GetDoxmDeviceID(&uuidPT))
+    {
+        OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+        return NULL;
+    }
+    memcpy(otmCtx->selectedDeviceInfo->doxm->owner.id, uuidPT.id , UUID_LENGTH);
+    otmCtx->selectedDeviceInfo->doxm->owned = true;
+
+    return BinToDoxmJSON(otmCtx->selectedDeviceInfo->doxm);
+}
+
+OCStackResult LoadSecretJustWorksCallback(OTMContext_t* UNUSED_PARAM)
+{
+    //In case of 'just works', secret data not required
+    (void)UNUSED_PARAM;
+    return OC_STACK_OK;
+}
+
+OCStackResult CreateSecureSessionJustWorksCallback(OTMContext_t* otmCtx)
+{
+    OC_LOG(INFO, TAG, "IN CreateSecureSessionJustWorksCallback");
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    CAResult_t caresult = CAEnableAnonECDHCipherSuite(true);
+    if (CA_STATUS_OK != caresult)
+    {
+        OC_LOG_V(ERROR, TAG, "Unable to enable anon cipher suite");
+        return OC_STACK_ERROR;
+    }
+    OC_LOG(INFO, TAG, "Anonymous cipher suite Enabled.");
+
+    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)
+    {
+        OC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
+        return OC_STACK_ERROR;
+    }
+
+    OC_LOG(INFO, TAG, "OUT CreateSecureSessionJustWorksCallback");
+    return OC_STACK_OK;
+}
diff --git a/resource/csdk/security/provisioning/src/oxmrandompin.c b/resource/csdk/security/provisioning/src/oxmrandompin.c
new file mode 100644 (file)
index 0000000..ea09fb4
--- /dev/null
@@ -0,0 +1,145 @@
+/* *****************************************************************
+ *
+ * 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 <memory.h>
+
+#include "ocstack.h"
+#include "ocsecurityconfig.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 "oxmrandompin.h"
+#include "ownershiptransfermanager.h"
+#include "pinoxmcommon.h"
+
+#define TAG "OXM_RandomPIN"
+
+char* CreatePinBasedSelectOxmPayload(OTMContext_t* otmCtx)
+{
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        return NULL;
+    }
+
+    otmCtx->selectedDeviceInfo->doxm->oxmSel = OIC_RANDOM_DEVICE_PIN;
+
+    OicUuid_t uuidPT = {.id={0}};
+    if (OC_STACK_OK != GetDoxmDeviceID(&uuidPT))
+    {
+        OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+        return NULL;
+    }
+    memcpy(otmCtx->selectedDeviceInfo->doxm->owner.id, uuidPT.id, UUID_LENGTH);
+
+    return BinToDoxmJSON(otmCtx->selectedDeviceInfo->doxm);
+}
+
+char* CreatePinBasedOwnerTransferPayload(OTMContext_t* otmCtx)
+{
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        return NULL;
+    }
+
+    OicUuid_t uuidPT = {.id={0}};
+
+    if (OC_STACK_OK != GetDoxmDeviceID(&uuidPT))
+    {
+        OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+        return NULL;
+    }
+    memcpy(otmCtx->selectedDeviceInfo->doxm->owner.id, uuidPT.id , UUID_LENGTH);
+    otmCtx->selectedDeviceInfo->doxm->owned = true;
+
+    return BinToDoxmJSON(otmCtx->selectedDeviceInfo->doxm);
+}
+
+OCStackResult InputPinCodeCallback(OTMContext_t* otmCtx)
+{
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    uint8_t pinData[OXM_RANDOM_PIN_SIZE + 1];
+
+    OCStackResult res = InputPin((char*)pinData, OXM_RANDOM_PIN_SIZE + 1);
+    if(OC_STACK_OK != res)
+    {
+        OC_LOG(ERROR, TAG, "Failed to input PIN");
+        return res;
+    }
+
+    OicUuid_t deviceUUID = {.id={0}};
+    if (OC_STACK_OK != GetDoxmDeviceID(&deviceUUID))
+    {
+        OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+        return OC_STACK_ERROR;
+    }
+
+    res = AddTmpPskWithPIN(&otmCtx->selectedDeviceInfo->doxm->deviceID,
+                           SYMMETRIC_PAIR_WISE_KEY,
+                           (char*)pinData, OXM_RANDOM_PIN_SIZE,
+                           1, &deviceUUID, &otmCtx->tempCredId);
+    if(res != OC_STACK_OK)
+    {
+        OC_LOG_V(ERROR, TAG, "Failed to save the temporal PSK : %d", res);
+    }
+
+    return res;
+}
+
+OCStackResult CreateSecureSessionRandomPinCallbak(OTMContext_t* otmCtx)
+{
+    OC_LOG(INFO, TAG, "IN CreateSecureSessionRandomPinCallbak");
+
+    if(!otmCtx || !otmCtx->selectedDeviceInfo)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    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_t caresult = CAInitiateHandshake(endpoint);
+    OICFree(endpoint);
+    if (CA_STATUS_OK != caresult)
+    {
+        OC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
+        return OC_STACK_ERROR;
+    }
+
+    OC_LOG(INFO, TAG, "OUT CreateSecureSessionRandomPinCallbak");
+
+    return OC_STACK_OK;
+}
diff --git a/resource/csdk/security/provisioning/src/pmutility.c b/resource/csdk/security/provisioning/src/pmutility.c
new file mode 100644 (file)
index 0000000..0f46c36
--- /dev/null
@@ -0,0 +1,475 @@
+/* *****************************************************************
+ *
+ * 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.
+ *
+ * *****************************************************************/
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200112L
+#endif
+
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <sys/time.h>
+
+#include "ocstack.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "logger.h"
+#include "cJSON.h"
+#include "utlist.h"
+#include "ocpayload.h"
+
+#include "securevirtualresourcetypes.h"
+#include "srmresourcestrings.h" //@note: SRM's internal header
+#include "doxmresource.h"       //@note: SRM's internal header
+#include "pstatresource.h"      //@note: SRM's internal header
+
+#include "pmtypes.h"
+#include "pmutility.h"
+
+#define TAG ("PM-UTILITY")
+
+/**
+ * Function to search node in linked list that matches given IP and port.
+ *
+ * @param[in] pList         List of OCProvisionDev_t.
+ * @param[in] addr          address of target device.
+ * @param[in] port          port of remote server.
+ *
+ * @return pointer of OCProvisionDev_t if exist, otherwise NULL
+ */
+OCProvisionDev_t* GetDevice(OCProvisionDev_t **ppDevicesList, const char* addr, const uint16_t port)
+{
+    if(NULL == addr || NULL == *ppDevicesList)
+    {
+        OC_LOG_V(ERROR, TAG, "Invalid Input parameters in [%s]\n", __FUNCTION__);
+        return NULL;
+    }
+
+    OCProvisionDev_t *ptr = NULL;
+    LL_FOREACH(*ppDevicesList, ptr)
+    {
+        if( strcmp(ptr->endpoint.addr, addr) == 0 && port == ptr->endpoint.port)
+        {
+            return ptr;
+        }
+    }
+
+    return NULL;
+}
+
+
+/**
+ * Add device information to list.
+ *
+ * @param[in] pList         List of OCProvisionDev_t.
+ * @param[in] addr          address of target device.
+ * @param[in] port          port of remote server.
+ * @param[in] adapter       adapter type of endpoint.
+ * @param[in] doxm          pointer to doxm instance.
+ *
+ * @return OC_STACK_OK for success and errorcode otherwise.
+ */
+OCStackResult AddDevice(OCProvisionDev_t **ppDevicesList, const char* addr, const uint16_t port,
+                               OCTransportAdapter adapter, OicSecDoxm_t *doxm)
+{
+    if (NULL == addr)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OCProvisionDev_t *ptr = GetDevice(ppDevicesList, addr, port);
+    if(!ptr)
+    {
+        ptr = (OCProvisionDev_t *)OICCalloc(1, sizeof (OCProvisionDev_t));
+        if (NULL == ptr)
+        {
+            OC_LOG(ERROR, TAG, "Error while allocating memory for linkedlist node !!");
+            return OC_STACK_NO_MEMORY;
+        }
+
+        OICStrcpy(ptr->endpoint.addr, MAX_ADDR_STR_SIZE, addr);
+        ptr->endpoint.port = port;
+        ptr->doxm = doxm;
+        ptr->securePort = DEFAULT_SECURE_PORT;
+        ptr->endpoint.adapter = adapter;
+        ptr->next = NULL;
+
+        LL_PREPEND(*ppDevicesList, ptr);
+    }
+
+    return OC_STACK_OK;
+}
+
+/**
+ * Function to set secure port information from the given list of devices.
+ *
+ * @param[in] pList         List of OCProvisionDev_t.
+ * @param[in] addr          address of target device.
+ * @param[in] port          port of remote server.
+ * @param[in] secureport    secure port information.
+ *
+ * @return OC_STACK_OK for success and errorcode otherwise.
+ */
+OCStackResult UpdateSecurePortOfDevice(OCProvisionDev_t **ppDevicesList, const char *addr, uint16_t port,
+                                        uint16_t securePort)
+{
+    OCProvisionDev_t *ptr = GetDevice(ppDevicesList, addr, port);
+
+    if(!ptr)
+    {
+        OC_LOG(ERROR, TAG, "Can not find device information in the discovery device list");
+        return OC_STACK_ERROR;
+    }
+
+    ptr->securePort = securePort;
+
+    return OC_STACK_OK;
+}
+
+/**
+ * This function deletes list of provision target devices
+ *
+ * @param[in] pList         List of OCProvisionDev_t.
+ */
+void DeleteDeviceList(OCProvisionDev_t **ppDevicesList)
+{
+    if(*ppDevicesList)
+    {
+        OCProvisionDev_t *del = NULL, *tmp = NULL;
+        LL_FOREACH_SAFE(*ppDevicesList, del, tmp)
+        {
+            LL_DELETE(*ppDevicesList, del);
+
+            DeleteDoxmBinData(del->doxm);
+            DeletePstatBinData(del->pstat);
+            OICFree(del);
+        }
+    }
+}
+
+/**
+ * Timeout implementation for secure discovery. When performing secure discovery,
+ * we should wait a certain period of time for getting response of each devices.
+ *
+ * @param[in]  waittime  Timeout in seconds.
+ * @return OC_STACK_OK on success otherwise error.
+ */
+OCStackResult PMTimeout(unsigned short waittime)
+{
+    struct timespec startTime = {.tv_sec=0, .tv_nsec=0};
+    struct timespec currTime  = {.tv_sec=0, .tv_nsec=0};
+
+    OCStackResult res = OC_STACK_OK;
+#ifdef _POSIX_MONOTONIC_CLOCK
+    int clock_res = clock_gettime(CLOCK_MONOTONIC, &startTime);
+#else
+    int clock_res = clock_gettime(CLOCK_REALTIME, &startTime);
+#endif
+    if (0 != clock_res)
+    {
+        return OC_STACK_ERROR;
+    }
+    while (OC_STACK_OK == res)
+    {
+#ifdef _POSIX_MONOTONIC_CLOCK
+        clock_res = clock_gettime(CLOCK_MONOTONIC, &currTime);
+#else
+        clock_res = clock_gettime(CLOCK_REALTIME, &currTime);
+#endif
+        if (0 != clock_res)
+        {
+            return OC_STACK_TIMEOUT;
+        }
+        long elapsed = (currTime.tv_sec - startTime.tv_sec);
+        if (elapsed > waittime)
+        {
+            return OC_STACK_OK;
+        }
+        res = OCProcess();
+    }
+
+    return res;
+}
+
+/**
+ * Extract secure port information from payload of discovery response.
+ *
+ * @param[in] jsonStr response payload of /oic/res discovery.
+ *
+ * @return Secure port
+ */
+uint16_t GetSecurePortFromJSON(char* jsonStr)
+{
+    // TODO: Modify error handling
+    if (NULL == jsonStr)
+    {
+        return 0;
+    }
+    cJSON *jsonProp = NULL;
+    cJSON *jsonP = NULL;
+    cJSON *jsonPort = NULL;
+
+    cJSON *jsonRoot = cJSON_Parse(jsonStr);
+    if(!jsonRoot)
+    {
+        // TODO: Add error log & return default secure port
+        return 0;
+    }
+
+    jsonProp = cJSON_GetObjectItem(jsonRoot, "prop");
+    if(!jsonProp)
+    {
+        // TODO: Add error log & return default secure port
+        return 0;
+    }
+
+    jsonP = cJSON_GetObjectItem(jsonProp, "p");
+    if(!jsonP)
+    {
+        // TODO: Add error log & return default secure port
+        return 0;
+    }
+
+    jsonPort = cJSON_GetObjectItem(jsonP, "port");
+    if(!jsonPort)
+    {
+        // TODO: Add error log & return default secure port
+        return 0;
+    }
+
+    return (uint16_t)jsonPort->valueint;
+}
+
+
+/**
+ * Callback handler for getting secure port information using /oic/res discovery.
+ *
+ * @param[in] ctx             user context
+ * @param[in] handle          Handle for response
+ * @param[in] clientResponse  Response information(It will contain payload)
+ *
+ * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
+ *         OC_STACK_DELETE_TRANSACTION to delete it.
+ */
+static OCStackApplicationResult SecurePortDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
+                                 OCClientResponse *clientResponse)
+{
+    if (ctx == NULL)
+    {
+        OC_LOG(ERROR, TAG, "Lost List of device information");
+        return OC_STACK_KEEP_TRANSACTION;
+    }
+    (void)UNUSED;
+    if (clientResponse)
+    {
+        if  (NULL == clientResponse->payload)
+        {
+            OC_LOG(INFO, TAG, "Skiping Null payload");
+        }
+        else
+        {
+            if (PAYLOAD_TYPE_DISCOVERY != clientResponse->payload->type)
+            {
+                OC_LOG(INFO, TAG, "Wrong payload type");
+                return OC_STACK_KEEP_TRANSACTION;
+            }
+
+            OCDiscoveryPayload* discover = (OCDiscoveryPayload*) clientResponse->payload;
+            uint16_t securePort = 0;
+
+            if (discover && discover->resources && discover->resources->secure)
+            {
+                securePort = discover->resources->port;
+            }
+            else
+            {
+                OC_LOG(INFO, TAG, "Secure Port info is missing");
+                return OC_STACK_KEEP_TRANSACTION;
+            }
+
+            OCProvisionDev_t** ppDevicesList = (OCProvisionDev_t**) ctx;
+
+            OCStackResult res = UpdateSecurePortOfDevice(ppDevicesList, clientResponse->devAddr.addr,
+                                                         clientResponse->devAddr.port, securePort);
+            if (OC_STACK_OK != res)
+            {
+                OC_LOG(ERROR, TAG, "Error while getting secure port.");
+                return OC_STACK_KEEP_TRANSACTION;
+            }
+            OC_LOG(INFO, TAG, "Exiting SecurePortDiscoveryHandler.");
+        }
+
+        return  OC_STACK_KEEP_TRANSACTION;
+    }
+    else
+    {
+        OC_LOG(INFO, TAG, "Skiping Null response");
+    }
+    return  OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler for PMDeviceDiscovery API.
+ *
+ * @param[in] ctx             User context
+ * @param[in] handle          Handler for response
+ * @param[in] clientResponse  Response information (It will contain payload)
+ * @return OC_STACK_KEEP_TRANSACTION to keep transaction and
+ *         OC_STACK_DELETE_TRANSACTION to delete it.
+ */
+static OCStackApplicationResult DeviceDiscoveryHandler(void *ctx, OCDoHandle UNUSED,
+                                OCClientResponse *clientResponse)
+{
+    if (ctx == NULL)
+    {
+        OC_LOG(ERROR, TAG, "Lost List of device information");
+        return OC_STACK_KEEP_TRANSACTION;
+    }
+    (void)UNUSED;
+    if (clientResponse)
+    {
+        if  (NULL == clientResponse->payload)
+        {
+            OC_LOG(INFO, TAG, "Skiping Null payload");
+            return OC_STACK_KEEP_TRANSACTION;
+        }
+        if (OC_STACK_OK != clientResponse->result)
+        {
+            OC_LOG(INFO, TAG, "Error in response");
+            return OC_STACK_KEEP_TRANSACTION;
+        }
+        else
+        {
+            if (PAYLOAD_TYPE_SECURITY != clientResponse->payload->type)
+            {
+                OC_LOG(INFO, TAG, "Unknown payload type");
+                return OC_STACK_KEEP_TRANSACTION;
+            }
+            OicSecDoxm_t *ptrDoxm = JSONToDoxmBin(
+                            ((OCSecurityPayload*)clientResponse->payload)->securityData);
+            if (NULL == ptrDoxm)
+            {
+                OC_LOG(INFO, TAG, "Ignoring malformed JSON");
+                return OC_STACK_KEEP_TRANSACTION;
+            }
+            else
+            {
+                OC_LOG(DEBUG, TAG, "Successfully converted doxm json to bin.");
+
+                OCProvisionDev_t **ppDevicesList = (OCProvisionDev_t**) ctx;
+
+                OCStackResult res = AddDevice(ppDevicesList, clientResponse->devAddr.addr,
+                        clientResponse->devAddr.port,
+                        clientResponse->devAddr.adapter, ptrDoxm);
+                if (OC_STACK_OK != res)
+                {
+                    OC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
+                    DeleteDoxmBinData(ptrDoxm);
+                    return OC_STACK_KEEP_TRANSACTION;
+                }
+
+                //Try to the unicast discovery to getting secure port
+                char query[MAX_QUERY_LENGTH] = { 0, };
+                sprintf(query, "%s%s:%d%s",
+                        COAP_PREFIX,
+                        clientResponse->devAddr.addr, clientResponse->devAddr.port,
+                        OC_RSRVD_WELL_KNOWN_URI);
+
+                OCCallbackData cbData;
+                cbData.cb = &SecurePortDiscoveryHandler;
+                cbData.context = ctx;
+                cbData.cd = NULL;
+                OCStackResult ret = OCDoResource(NULL, OC_REST_GET, query, 0, 0,
+                        CT_ADAPTER_IP, OC_LOW_QOS, &cbData, NULL, 0);
+                // TODO: Should we use the default secure port in case of error?
+                if(OC_STACK_OK != ret)
+                {
+                    UpdateSecurePortOfDevice(ppDevicesList, clientResponse->devAddr.addr,
+                            clientResponse->devAddr.port, DEFAULT_SECURE_PORT);
+                }
+                else
+                {
+                    OC_LOG_V(ERROR, TAG, "OCDoResource with [%s] Success", query);
+                }
+                OC_LOG(INFO, TAG, "Exiting ProvisionDiscoveryHandler.");
+            }
+
+            return  OC_STACK_KEEP_TRANSACTION;
+        }
+    }
+    else
+    {
+        OC_LOG(INFO, TAG, "Skiping Null response");
+        return OC_STACK_KEEP_TRANSACTION;
+    }
+
+    return  OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Discover owned/unowned devices in the same IP subnet. .
+ *
+ * @param[in] waittime      Timeout in seconds.
+ * @param[in] isOwned       bool flag for owned / unowned discovery
+ * @param[in] ppDevicesList        List of OCProvisionDev_t.
+ *
+ * @return OC_STACK_OK on success otherwise error.
+ */
+OCStackResult PMDeviceDiscovery(unsigned short waittime, bool isOwned, OCProvisionDev_t **ppDevicesList)
+{
+    OC_LOG(DEBUG, TAG, "IN PMDeviceDiscovery");
+
+    if (NULL != *ppDevicesList)
+    {
+        OC_LOG(ERROR, TAG, "List is not null can cause memory leak");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    const char DOXM_OWNED_FALSE_MULTICAST_QUERY[] = "/oic/sec/doxm?Owned=FALSE";
+    const char DOXM_OWNED_TRUE_MULTICAST_QUERY[] = "/oic/sec/doxm?Owned=TRUE";
+
+    OCCallbackData cbData;
+    cbData.cb = &DeviceDiscoveryHandler;
+    cbData.context = (void *)ppDevicesList;
+    cbData.cd = NULL;
+    OCStackResult res = OC_STACK_ERROR;
+
+    const char* query = isOwned ? DOXM_OWNED_TRUE_MULTICAST_QUERY :
+                                  DOXM_OWNED_FALSE_MULTICAST_QUERY;
+
+    res = OCDoResource(NULL, OC_REST_DISCOVER, query, 0, 0,
+                                     CT_DEFAULT, OC_LOW_QOS, &cbData, NULL, 0);
+    if (res != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack resource error");
+        goto exit;
+    }
+
+    //Waiting for each response.
+    res = PMTimeout(waittime);
+    if(OC_STACK_OK != res)
+    {
+        OC_LOG(ERROR, TAG, "Failed to wait response for secure discovery.");
+        goto exit;
+    }
+
+    OC_LOG(DEBUG, TAG, "OUT PMDeviceDiscovery");
+exit:
+    return res;
+}
diff --git a/resource/csdk/security/provisioning/src/provisioningmanager.c b/resource/csdk/security/provisioning/src/provisioningmanager.c
deleted file mode 100644 (file)
index bcd5e4d..0000000
+++ /dev/null
@@ -1,1669 +0,0 @@
-/* *****************************************************************
- *
- * 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.
- *
- * *****************************************************************/
-
-// Defining _POSIX_C_SOURCE macro with 199309L (or greater) as value
-// causes header files to expose definitions
-// corresponding to the POSIX.1b, Real-time extensions
-// (IEEE Std 1003.1b-1993) specification
-//
-// For this specific file, see use of clock_gettime,
-// Refer to http://pubs.opengroup.org/stage7tc1/functions/clock_gettime.html
-// and to http://man7.org/linux/man-pages/man2/clock_gettime.2.html
-
-#ifndef _POSIX_C_SOURCE
-#define _POSIX_C_SOURCE 200809L
-#endif
-
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <stdbool.h>
-
-#include "cJSON.h"
-#include "ocpayload.h"
-#include "ocpayloadcbor.h"
-#include "oic_malloc.h"
-#include "logger.h"
-#include "cacommon.h"
-#include "cainterface.h"
-#include "provisioningmanager.h"
-#include "credentialgenerator.h"
-#include "global.h"
-#include "base64.h"
-#include "aclresource.h"
-#include "doxmresource.h"
-#include "pstatresource.h"
-#include "srmresourcestrings.h"
-#include "credresource.h"
-#include "oic_string.h"
-#include "secureresourcemanager.h"
-
-typedef enum
-{
-    SP_NO_MASK                = (0       ),
-    SP_DISCOVERY_STARTED      = (0x1 << 1),
-    SP_DISCOVERY_ERROR        = (0x1 << 2),
-    SP_DISCOVERY_DONE         = (0x1 << 3),
-    SP_SEC_RES_INFO_STARTED   = (0x1 << 4),
-    SP_SEC_RES_INFO_ERROR     = (0x1 << 5),
-    SP_SEC_RES_INFO_DONE      = (0x1 << 6),
-    SP_UP_OWN_TR_METH_STARTED = (0x1 << 7),
-    SP_UP_OWN_TR_METH_ERROR   = (0x1 << 8),
-    SP_UP_OWN_TR_METH_DONE    = (0x1 << 9),
-    SP_LIST_METHODS_STARTED   = (0x1 << 10),
-    SP_LIST_METHODS_ERROR     = (0x1 << 11),
-    SP_LIST_METHODS_DONE      = (0x1 << 12),
-    SP_UPDATE_OP_MODE_STARTED = (0x1 << 13),
-    SP_UPDATE_OP_MODE_ERROR   = (0x1 << 14),
-    SP_UPDATE_OP_MODE_DONE    = (0x1 << 15),
-    SP_UPDATE_OWNER_STARTED   = (0x1 << 16),
-    SP_UPDATE_OWNER_ERROR     = (0x1 << 17),
-    SP_UPDATE_OWNER_DONE      = (0x1 << 18),
-    SP_PROV_ACL_STARTED       = (0x1 << 19),
-    SP_PROV_ACL_ERROR         = (0x1 << 20),
-    SP_PROV_ACL_DONE          = (0x1 << 21),
-    SP_UP_HASH_STARTED        = (0x1 << 22),
-    SP_UP_HASH_ERROR          = (0x1 << 23),
-    SP_UP_HASH_DONE           = (0x1 << 24),
-    SP_PROV_CRED_STARTED      = (0x1 << 25),
-    SP_PROV_CRED_ERROR        = (0x1 << 26),
-    SP_PROV_CRED_DONE         = (0x1 << 27)
-} SPProvisioningStates;
-
-#define SP_MAX_BUF_LEN 1024
-#define TAG "SPProvisionAPI"
-#define COAP_QUERY "coap://%s:%d%s"
-#define COAPS_QUERY "coaps://%s:%d%s"
-
-bool (*handler)(const CAEndpoint_t *, const CAResponseInfo_t *);
-
-/**
- * CA token to keep track of response.
- */
-static CAToken_t gToken = NULL;
-
-/**
- * start pointer for discovered device linked list.
- */
-static SPTargetDeviceInfo_t *gStartOfDiscoveredDevices = NULL;
-
-/**
- * current pointer of device linked list.
- */
-static SPTargetDeviceInfo_t *gCurrent = NULL;
-
-/**
- * Variable to keep track of various request.
- */
-static uint32_t gStateManager = 0;
-
-/**
- * Variable for storing provisioning tool's provisioning capabilities
- * Must be in decreasing order of preference. More prefered method should
- * have lower array index.
- */
-static OicSecDpom_t gProvisioningToolCapability[] = { SINGLE_SERVICE_CLIENT_DRIVEN };
-
-/**
- * Number of supported provisioning methods
- * current version supports only one.
- */
-static int gNumOfProvisioningMethodsPT = 1;
-
-/**
- * Global variable to save pstat.
- */
-static OicSecPstat_t *gPstat = NULL;
-
-/**
- * Secure String copy function
- * @param[in] destination  Pointer to destination string.
- * @param[in] source       Pointer to source string.
- * @return pointer to destination string, NULL in case of error.
- */
-static inline char *SPStringCopy(char *destination, const char *source, size_t num)
-{
-    if (strncpy(destination, source, num))
-    {
-        destination[num - 1] = '\0';
-        return destination;
-    }
-    return NULL;
-}
-
-/**
- * Function to convert CA result code to SP result code.
- *
- * @return result code of SP corresponding to that of CA.
- */
-static SPResult convertCAResultToSPResult(CAResult_t caResult)
-{
-    switch (caResult)
-    {
-        case CA_STATUS_OK:
-            {
-                return SP_RESULT_SUCCESS;
-            }
-        case CA_STATUS_INVALID_PARAM:
-            {
-                return SP_RESULT_CONN_INVALID_PARAM;
-            }
-        case CA_ADAPTER_NOT_ENABLED:
-            {
-                return SP_RESULT_CONN_SERVER_STARTED_ALREADY;
-            }
-        case CA_SERVER_STARTED_ALREADY:
-            {
-                return SP_RESULT_CONN_SERVER_STARTED_ALREADY;
-            }
-        case CA_SERVER_NOT_STARTED:
-            {
-                return SP_RESULT_CONN_SERVER_NOT_STARTED;
-            }
-        case CA_DESTINATION_NOT_REACHABLE:
-            {
-                return SP_RESULT_CONN_DESTINATION_NOT_REACHABLE;
-            }
-        case CA_SOCKET_OPERATION_FAILED:
-            {
-                return SP_RESULT_CONN_SOCKET_OPERATION_FAILED;
-            }
-        case CA_SEND_FAILED:
-            {
-                return SP_RESULT_CONN_SEND_FAILED;
-            }
-        case CA_RECEIVE_FAILED:
-            {
-                return SP_RESULT_CONN_RECEIVE_FAILED;
-            }
-        case CA_MEMORY_ALLOC_FAILED:
-            {
-                return SP_RESULT_CONN_MEMORY_ALLOC_FAILED;
-            }
-        case CA_REQUEST_TIMEOUT:
-            {
-                return SP_RESULT_CONN_REQUEST_TIMEOUT;
-            }
-        case CA_DESTINATION_DISCONNECTED:
-            {
-                return SP_RESULT_CONN_DESTINATION_DISCONNECTED;
-            }
-        case CA_STATUS_FAILED:
-            {
-                return SP_RESULT_CONN_STATUS_FAILED;
-            }
-        case CA_NOT_SUPPORTED:
-            {
-                return SP_RESULT_CONN_NOT_SUPPORTED;
-            }
-        default:
-            {
-                return SP_RESULT_INTERNAL_ERROR;
-            }
-    }
-}
-
-/**
- * Function to delete memory allocated to linked list.
- *
- */
-static void deleteList()
-{
-    SPTargetDeviceInfo_t *current = gStartOfDiscoveredDevices;
-
-    while (current)
-    {
-        SPTargetDeviceInfo_t *next = current->next;
-        DeleteDoxmBinData(current->doxm);
-        DeletePstatBinData(current->pstat);
-        OICFree(current);
-        current = next;
-    }
-    gStartOfDiscoveredDevices = NULL;
-}
-
-/**
- * Timeout implementation.
- * @param[in]  timeout  Timeout in seconds. with 0 it will wait forever for success.
- * @param[in]  mask     Mask of operation and 0 for no mask.
- * @return SP_RESULT_SUCCESS on success otherwise error.
- */
-static SPResult SPTimeout(unsigned short timeout, uint32_t mask)
-{
-    struct timespec startTime = {};
-    struct timespec currTime  = {};
-
-    CAResult_t res = SP_RESULT_SUCCESS;
-#ifdef _POSIX_MONOTONIC_CLOCK
-    int clock_res = clock_gettime(CLOCK_MONOTONIC, &startTime);
-#else
-    int clock_res = clock_gettime(CLOCK_REALTIME, &startTime);
-#endif
-    if (0 != clock_res)
-    {
-        return SP_RESULT_INTERNAL_ERROR;
-    }
-    while (CA_STATUS_OK == res)
-    {
-        res = CAHandleRequestResponse();
-#ifdef _POSIX_MONOTONIC_CLOCK
-        clock_res = clock_gettime(CLOCK_MONOTONIC, &currTime);
-#else
-        clock_res = clock_gettime(CLOCK_REALTIME, &currTime);
-#endif
-        if (0 != clock_res)
-        {
-            return SP_RESULT_INTERNAL_ERROR;
-        }
-        long elapsed = (currTime.tv_sec - startTime.tv_sec);
-        if (SP_NO_MASK == mask)
-        {
-            if (elapsed > timeout)
-            {
-                return SP_RESULT_SUCCESS;
-            }
-        }
-        else
-        {
-            if (gStateManager & mask)
-            {
-                return SP_RESULT_SUCCESS;
-            }
-            if ((elapsed > timeout) && timeout)
-            {
-                return SP_RESULT_INTERNAL_ERROR;
-            }
-        }
-    }
-    return convertCAResultToSPResult(res);
-}
-
-/**
- * Function to send request to resource server.
- * @param[in] method          method to be used for sending rquest.
- * @param[in] endpoint        endpoint address
- * @param[in] secure          use secure connection
- * @param[in] resourceUri     resourceUri token.
- * @param[in] payload         Payload to be sent with data. NULL is case message
- *                            doesn't have payload.
- * @param[in] payloadLen      Size of data to be sent.
- * @return  CA_STATUS_OK on success, otherwise error code.
- */
-static CAResult_t sendCARequest(CAMethod_t method,
-                                const OCDevAddr *devAddr,
-                                OCTransportFlags secure,
-                                const char *resourceUri,
-                                char *payload, int payloadLen)
-{
-    if (payload && '\0' != (*(payload + payloadLen)))
-    {
-        OC_LOG(ERROR, TAG, "Payload not properly terminated.");
-        return CA_STATUS_INVALID_PARAM;
-    }
-
-    if (CA_STATUS_OK != CAGenerateToken(&gToken, CA_MAX_TOKEN_LEN))
-    {
-        OC_LOG(ERROR, TAG, "Error while generating token");
-        return CA_MEMORY_ALLOC_FAILED;
-    }
-
-    CAEndpoint_t *endpoint = NULL;
-    if (CA_STATUS_OK != CACreateEndpoint(devAddr->flags | (CATransportFlags_t)secure,
-                                         devAddr->adapter, devAddr->addr,
-                                         devAddr->port, &endpoint))
-    {
-        OC_LOG(ERROR, TAG, "Failed to create remote endpoint");
-        CADestroyEndpoint(endpoint);
-        return CA_STATUS_FAILED;
-    }
-
-    OCSecurityPayload secPayload = {};
-    secPayload.securityData = payload;
-    secPayload.base.type = PAYLOAD_TYPE_SECURITY;
-
-    CARequestInfo_t requestInfo = {};
-    requestInfo.method = method;
-    requestInfo.isMulticast = false;
-    OCConvertPayload((OCPayload*)(&secPayload), &requestInfo.info.payload,
-            &requestInfo.info.payloadSize);
-
-    requestInfo.info.type = CA_MSG_CONFIRM;
-    requestInfo.info.token = gToken;
-    requestInfo.info.tokenLength  = CA_MAX_TOKEN_LEN;
-    requestInfo.info.resourceUri  = (CAURI_t)resourceUri;
-
-    CAResult_t caResult = CA_STATUS_OK;
-    caResult = CASendRequest(endpoint, &requestInfo);
-    if (CA_STATUS_OK != caResult)
-    {
-        OC_LOG(ERROR, TAG, "Send Request Error !!");
-    }
-    CADestroyEndpoint(endpoint);
-    return caResult;
-}
-
-/**
- * addDevice to list.
- *
- * @param[in] endpoint   Endpoint information
- * @param[in] doxm   pointer to doxm instance.
- * @return SP_RESULT_SUCCESS for success and errorcode otherwise.
- */
-static SPResult addDevice(const CAEndpoint_t *endpoint, OicSecDoxm_t* doxm)
-{
-    if (NULL == endpoint)
-    {
-        return SP_RESULT_INVALID_PARAM;
-    }
-    SPTargetDeviceInfo_t *ptr = (SPTargetDeviceInfo_t *)OICCalloc(1, sizeof (SPTargetDeviceInfo_t));
-    if (NULL == ptr)
-    {
-        OC_LOG(ERROR, TAG, "Error while allocating memory for linkedlist node !!");
-        return SP_RESULT_MEM_ALLOCATION_FAIL;
-    }
-
-    memcpy(&(ptr->endpoint), endpoint, sizeof(CAEndpoint_t));
-    ptr->doxm = doxm;
-
-    ptr->next = NULL;
-
-    if (NULL == gStartOfDiscoveredDevices)
-    {
-        gStartOfDiscoveredDevices = ptr;
-        gCurrent = ptr;
-    }
-    else
-    {
-        gCurrent->next = ptr;
-        gCurrent = ptr;
-    }
-    return SP_RESULT_SUCCESS;
-}
-
-/**
- * updateDevice to update resource info for the endpoint.
- *
- * @param[in] endpoint   Endpoint information
- * @param[in] port   secure port.
- * @return SP_RESULT_SUCCESS for success and errorcode otherwise.
- */
-
-static SPResult updateDevice(const CAEndpoint_t *endpoint, uint16_t port)
-{
-    if (NULL == endpoint)
-    {
-        return SP_RESULT_INVALID_PARAM;
-    }
-    SPTargetDeviceInfo_t *ptr = gStartOfDiscoveredDevices;
-    while(ptr)
-    {
-        if(0 == strcmp(ptr->endpoint.addr, endpoint->addr) &&
-                ptr->endpoint.port == endpoint->port)
-        {
-            ptr->securePort = port;
-            return SP_RESULT_SUCCESS;
-        }
-        ptr = ptr->next;
-    }
-    return SP_RESULT_INTERNAL_ERROR;
-}
-
-/**
- * Function to provide timeframe in which response can be received.
- *
- * @param[in]  timeout   Timeout in seconds.
- * @return  SP_RESULT_SUCCESS on success , otherwise error code.
- */
-static SPResult SPWaitForResponse(unsigned short timeout)
-{
-    return SPTimeout(timeout, SP_NO_MASK);
-}
-
-/**
- * Function to select appropriate  provisioning method.
- *
- * @param[in]   supportedMethodsList   List of supported methods
- * @param[out]  selectedMethod         Selected methods
- * @return  SP_SUCCESS on success
- */
-static SPResult selectProvisioningMethod(OicSecOxm_t *supportedMethods, size_t numberOfMethods,
-        OicSecOxm_t *selectedMethod)
-{
-    /*
-     TODO Logic to find appropiate method and assign it to out param
-     for beachhead release method at index 0 will be returned.
-     */
-    *selectedMethod = supportedMethods[0];
-    return SP_RESULT_SUCCESS;
-}
-
-/**
- * Response handler for discovery.
- *
- * @param[in] object       Remote endpoint object
- * @param[in] requestInfo  Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-static bool ProvisionDiscoveryHandler(const CAEndpoint_t *object,
-                                      const CAResponseInfo_t *responseInfo)
-{
-    if ((gStateManager & SP_DISCOVERY_STARTED) && gToken)
-    {
-        // Response handler for discovery.
-        if (0 == memcmp(gToken, responseInfo->info.token, responseInfo->info.tokenLength))
-        {
-            OC_LOG(INFO, TAG, "Inside ProvisionDiscoveryHandler.");
-            if (NULL == responseInfo->info.payload)
-            {
-                OC_LOG(INFO, TAG, "Skiping Null payload");
-            }
-            else
-            {
-                OCPayload* payload = NULL;
-                OCStackResult result = OCParsePayload(&payload, responseInfo->info.payload,
-                        responseInfo->info.payloadSize);
-
-                OicSecDoxm_t *ptrDoxm = NULL;
-
-                if(result == OC_STACK_OK && payload->type == PAYLOAD_TYPE_SECURITY)
-                {
-                    ptrDoxm = JSONToDoxmBin(((OCSecurityPayload*)payload)->securityData);
-                }
-
-                OCPayloadDestroy(payload);
-
-                if (NULL == ptrDoxm)
-                {
-                    OC_LOG(INFO, TAG, "Ignoring malformed JSON");
-                }
-                else
-                {
-                    OC_LOG(DEBUG, TAG, "Successfully converted doxm json to bin.");
-
-                    SPResult res = addDevice(object, ptrDoxm);
-                    if (SP_RESULT_SUCCESS != res)
-                    {
-                        OC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
-                        gStateManager = gStateManager | SP_DISCOVERY_ERROR;
-                        DeleteDoxmBinData(ptrDoxm);
-                        return true;
-                    }
-                    OC_LOG(INFO, TAG, "Exiting ProvisionDiscoveryHandler.");
-                    gStateManager |= SP_DISCOVERY_DONE;
-                }
-            }
-            return true;
-        }
-    }
-    return false;
-}
-
-/**
- * Response handler for discovery.
- *
- * @param[in] object       Remote endpoint object
- * @param[in] requestInfo  Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-
-static bool ProvisionSecureResourceInfoHandler(const CAEndpoint_t *object,
-                                      const CAResponseInfo_t *responseInfo)
-{
-    if (!object || !responseInfo)
-    {
-        return false;
-    }
-
-    if ((gStateManager & SP_SEC_RES_INFO_STARTED) && gToken)
-    {
-        // Response handler for discovery.
-        if (0 == memcmp(gToken, responseInfo->info.token, CA_MAX_TOKEN_LEN))
-        {
-            OC_LOG(INFO, TAG, "Inside ProvisionSecureResourceInfoHandler.");
-            if (NULL == responseInfo->info.payload)
-            {
-                OC_LOG(ERROR, TAG, "Exiting ProvisionSecureResourceInfoHandler.");
-                gStateManager |= SP_SEC_RES_INFO_ERROR;
-            }
-            else
-            {
-                OCPayload* payload = NULL;
-                OCStackResult result = OCParsePayload(&payload, responseInfo->info.payload,
-                        responseInfo->info.payloadSize);
-
-                OCDiscoveryPayload* discover = (OCDiscoveryPayload*) payload;
-                // Discovered secure resource payload contains secure port; update the device
-                // with the secure port using endpoint.
-                if (result == OC_STACK_OK && discover)
-                {
-                    if (updateDevice(object, discover->resources->port) == SP_RESULT_SUCCESS)
-                    {
-                        gStateManager |= SP_SEC_RES_INFO_DONE;
-                    }
-                    else
-                    {
-                        gStateManager |= SP_SEC_RES_INFO_ERROR;
-                    }
-                    OC_LOG(INFO, TAG, "Exiting ProvisionSecureResourceInfoHandler.");
-                }
-
-                OCPayloadDestroy(payload);
-            }
-            return true;
-        }
-        else
-        {
-            OC_LOG(ERROR, TAG, "Error in ProvisionSecureResourceInfoHandler.");
-            gStateManager |= SP_SEC_RES_INFO_ERROR;
-            return false;
-        }
-    }
-    return false;
-}
-
-/**
- * Response handler ownership transfer.
- *
- * @param[in] object       Remote endpoint object
- * @param[in] requestInfo  Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-static bool OwnerShipTransferModeHandler(const CAEndpoint_t *object,
-        const CAResponseInfo_t *responseInfo)
-{
-    if ((gStateManager & SP_UP_OWN_TR_METH_STARTED) && gToken)
-    {
-        // response handler for ownership tranfer
-        OC_LOG(INFO, TAG, "Inside OwnerShipTransferModeHandler.");
-        if (memcmp(gToken, responseInfo->info.token, responseInfo->info.tokenLength) == 0)
-        {
-            OC_LOG_V(DEBUG, TAG, "Response result for OwnerShipTransferMode: %d", responseInfo->result);
-            if (CA_SUCCESS == responseInfo->result)
-            {
-                gStateManager |= SP_UP_OWN_TR_METH_DONE;
-                OC_LOG(INFO, TAG, "Exiting OwnerShipTransferModeHandler.");
-            }
-            else
-            {
-                gStateManager |= SP_UP_OWN_TR_METH_ERROR;
-                OC_LOG(ERROR, TAG, "Error in OwnerShipTransferModeHandler.");
-            }
-            return true;
-        }
-    }
-    return false;
-}
-
-/**
- * Response handler list methods.
- *
- * @param[in] object       Remote endpoint object
- * @param[in] requestInfo  Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-static bool ListMethodsHandler(const CAEndpoint_t *object,
-                               const CAResponseInfo_t *responseInfo)
-{
-    if ((gStateManager & SP_LIST_METHODS_STARTED) && gToken)
-    {
-        OC_LOG(INFO, TAG, "Inside ListMethodsHandler.");
-        if (memcmp(gToken, responseInfo->info.token, responseInfo->info.tokenLength) == 0)
-        {
-            OC_LOG_V(DEBUG, TAG, "Response result for ListMethodsHandler: %d", responseInfo->result);
-            if (CA_SUCCESS == responseInfo->result)
-            {
-                OC_LOG_V (DEBUG, TAG, "Response Payload: %s", responseInfo->info.payload);
-                // Temp logic to trim oc attribute from json
-                // JSONToPstatBin should handle OC in JSON.
-                if (NULL == responseInfo->info.payload)
-                {
-                    OC_LOG(ERROR, TAG, "response payload is null.");
-                    gStateManager |= SP_LIST_METHODS_ERROR;
-                    return true;
-                }
-
-                OCPayload* payload = NULL;
-                OCStackResult result = OCParsePayload(&payload, responseInfo->info.payload,
-                        responseInfo->info.payloadSize);
-
-                OicSecPstat_t *pstat = NULL;
-
-                if(result == OC_STACK_OK && payload->type == PAYLOAD_TYPE_SECURITY)
-                {
-                    pstat =  JSONToPstatBin(((OCSecurityPayload*)payload)->securityData);
-                }
-
-                OCPayloadDestroy(payload);
-
-                if (NULL == pstat)
-                {
-                    OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
-                    gStateManager |= SP_LIST_METHODS_ERROR;
-                    return true;
-                }
-                DeletePstatBinData(gPstat);
-
-                gPstat = pstat;
-                gStateManager |= SP_LIST_METHODS_DONE;
-
-                OC_LOG(INFO, TAG, "Exiting ListMethodsHandler.");
-            }
-            return true;
-        }
-    }
-    return false;
-}
-
-/**
- * Response handler for update operation mode.
- *
- * @param[in] object       Remote endpoint object
- * @param[in] requestInfo  Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-static bool OperationModeUpdateHandler(const CAEndpoint_t *object,
-                                       const CAResponseInfo_t *responseInfo)
-{
-    if ((gStateManager & SP_UPDATE_OP_MODE_STARTED) && gToken)
-    {
-        if (0 == memcmp(gToken, responseInfo->info.token, responseInfo->info.tokenLength))
-        {
-            OC_LOG(INFO, TAG, "Inside OperationModeUpdateHandler.");
-            OC_LOG_V(DEBUG, TAG, "Response result for OperationModeUpdateHandler: %d", responseInfo->result);
-            if (CA_SUCCESS == responseInfo->result)
-            {
-                gStateManager |= SP_UPDATE_OP_MODE_DONE;
-                OC_LOG(INFO, TAG, "Exiting OperationModeUpdateHandler.");
-            }
-            else
-            {
-                gStateManager |= SP_UPDATE_OP_MODE_ERROR;
-                OC_LOG(ERROR, TAG, "Error in OperationModeUpdateHandler.");
-            }
-            return true;
-        }
-    }
-    return false;
-}
-
-/**
- * Response handler for ownership transfer.
- *
- * @param[in] object       Remote endpoint object
- * @param[in] requestInfo  Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-static bool OwnerShipUpdateHandler(const CAEndpoint_t *object,
-                                   const CAResponseInfo_t *responseInfo)
-{
-    if ((gStateManager & SP_UPDATE_OWNER_STARTED) && gToken)
-    {
-        // response handler for ownership tranfer
-        if (0 == memcmp(gToken, responseInfo->info.token, responseInfo->info.tokenLength))
-        {
-            OC_LOG(INFO, TAG, "Inside OwnerShipUpdateHandler.");
-            OC_LOG_V(DEBUG, TAG, "Response result for OwnerShipUpdateHandler: %d", responseInfo->result);
-            if (CA_SUCCESS == responseInfo->result)
-            {
-                gStateManager |= SP_UPDATE_OWNER_DONE;
-                OC_LOG(INFO, TAG, "Exiting OwnerShipUpdateHandler.");
-            }
-            else
-            {
-                gStateManager |= SP_UPDATE_OWNER_ERROR;
-                OC_LOG(ERROR, TAG, "Error in OwnerShipUpdateHandler.");
-            }
-            return true;
-        }
-    }
-    return false;
-}
-
-/**
- * Response handler for ACL provisioning.
- *
- * @param[in] object       Remote endpoint object
- * @param[in] requestInfo  Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-static bool ACLProvisioningHandler(const CAEndpoint_t *object,
-                                   const CAResponseInfo_t *responseInfo)
-{
-    if ((gStateManager & SP_PROV_ACL_STARTED) && gToken)
-    {
-
-        // response handler for ACL provisioning.
-        if (0 == memcmp(gToken, responseInfo->info.token, responseInfo->info.tokenLength))
-        {
-            OC_LOG(INFO, TAG, "Inside ACLProvisioningHandler.");
-            OC_LOG_V(DEBUG, TAG, "Response result for ACLProvisioningHandler: %d", responseInfo->result);
-            if (CA_CREATED == responseInfo->result)
-            {
-                OC_LOG(INFO, TAG, "Exiting ACLProvisioningHandler.");
-                gStateManager |= SP_PROV_ACL_DONE;
-            }
-            else
-            {
-                OC_LOG(ERROR, TAG, "Error in ACLProvisioningHandler.");
-                gStateManager |= SP_PROV_ACL_ERROR;
-            }
-            return true;
-        }
-    }
-    return false;
-}
-
-/**
- * Response handler for provisioning finalization.
- *
- * @param[in] object       Remote endpoint object
- * @param[in] requestInfo  Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-static bool FinalizeProvisioningHandler(const CAEndpoint_t *object,
-                                        const CAResponseInfo_t *responseInfo)
-{
-    if ((gStateManager & SP_UP_HASH_STARTED) && gToken)
-    {
-        // response handler for finalize provisioning.
-        if (0 == memcmp(gToken, responseInfo->info.token, responseInfo->info.tokenLength))
-        {
-            OC_LOG(INFO, TAG, "Inside FinalizeProvisioningHandler.");
-            OC_LOG_V(DEBUG, TAG, "Response result for FinalizeProvisioningHandler: %d", responseInfo->result);
-            if (CA_SUCCESS == responseInfo->result)
-            {
-                gStateManager |= SP_UP_HASH_DONE;
-                OC_LOG(INFO, TAG, "Exiting FinalizeProvisioningHandler.");
-            }
-            else
-            {
-                gStateManager |= SP_UP_HASH_ERROR;
-                OC_LOG(ERROR, TAG, "Error in FinalizeProvisioningHandler.");
-            }
-            return true;
-        }
-    }
-    return false;
-}
-
-/**
- * Response handler for Credential provisioning.
- *
- * @param[in] object        Remote endpoint object
- * @param[in] requestInfo   Datastructure containing request information.
- * @return true is CA token matches request token, false otherwise.
- */
-static bool CredProvisioningHandler(const CAEndpoint_t *object,
-                                    const CAResponseInfo_t *responseInfo)
-{
-    if ((gStateManager & SP_PROV_CRED_STARTED) && gToken)
-    {
-        // response handler for CRED provisioning.
-        OC_LOG(INFO, TAG, "Inside CredProvisioningHandler.");
-        OC_LOG_V(DEBUG, TAG, "Response result for CredProvisioningHandler: %d", responseInfo->result);
-        if (0 == memcmp(gToken, responseInfo->info.token, responseInfo->info.tokenLength))
-        {
-            if (CA_CREATED == responseInfo->result)
-            {
-                gStateManager |= SP_PROV_CRED_DONE;
-                OC_LOG(INFO, TAG, "Exiting CredProvisioningHandler.");
-            }
-            else
-            {
-                gStateManager |= SP_PROV_CRED_ERROR;
-                OC_LOG(ERROR, TAG, "Error in CredProvisioningHandler.");
-            }
-            return true;
-        }
-    }
-    return false;
-}
-
-/**
- * Response Handler
- *
- * @param[in] object        Remote endpoint object
- * @param[in] responseInfo  Datastructure containing response information.
- * @return true if received response is for provisioning API false otherwise.
- */
-static bool SPResponseHandler(const CAEndpoint_t *object,
-                              const CAResponseInfo_t *responseInfo)
-{
-    bool isProvResponse = false;
-    if ((NULL != responseInfo) && (NULL != responseInfo->info.token))
-    {
-        isProvResponse = handler(object, responseInfo);
-    }
-    return isProvResponse;
-}
-
-/**
- * Function to find the resources using multicast discovery.
- *
- * @param[in]   timeout     timeout in secs
- * @return  SP_RESULT_SUCCESS normally otherwise error code.
- */
-static SPResult findResource(unsigned short timeout)
-{
-    static char DOXM_OWNED_FALSE_MULTICAST_QUERY[] = "/oic/sec/doxm?Owned=FALSE";
-    CAResult_t res = CAGenerateToken(&gToken, CA_MAX_TOKEN_LEN);
-    if (CA_STATUS_OK != res)
-    {
-        OC_LOG(ERROR, TAG, "Error while generating token.");
-        return SP_RESULT_INTERNAL_ERROR;
-    }
-
-    CAEndpoint_t endpoint = {};
-
-    // Only IP is supported currently for provisioning and ownership transfer
-    endpoint.adapter = CA_ADAPTER_IP;
-    endpoint.flags   = CA_IPV4 | CA_IPV6 | CA_SCOPE_LINK;
-
-    CAMessageType_t msgType = CA_MSG_NONCONFIRM;
-    CAInfo_t requestData = { 0 };
-    requestData.token = gToken;
-    requestData.tokenLength  = CA_MAX_TOKEN_LEN;
-    requestData.payload = NULL;
-    requestData.payloadSize = 0;
-    requestData.type = msgType;
-    requestData.resourceUri = DOXM_OWNED_FALSE_MULTICAST_QUERY;
-    CARequestInfo_t requestInfo = { 0 };
-    requestInfo.method = CA_GET;
-    requestInfo.info = requestData;
-    requestInfo.isMulticast = true;
-    res = CASendRequest(&endpoint, &requestInfo);
-
-    handler = &ProvisionDiscoveryHandler;
-    gStateManager |= SP_DISCOVERY_STARTED;
-    if (CA_STATUS_OK != res)
-    {
-        OC_LOG(ERROR, TAG, "Error while finding resource.");
-        return convertCAResultToSPResult(res);
-    }
-    else
-    {
-        OC_LOG(INFO, TAG, "Discovery Request sent successfully");
-    }
-    return SPWaitForResponse(timeout);
-}
-
-/**
- * Function to get the secure resource info.
- *
- * @param[in]   devAddr     Device address for the destination
- * @param[in]   timeout     timeout in secs
- * @return  SP_RESULT_SUCCESS normally otherwise error code.
- */
-static SPResult getSecureResourceInfo(OCDevAddr *devAddr, unsigned short timeout)
-{
-    char OIC_UNICAST_SEC_QUERY[] = "/oic/res?rt=oic.sec.doxm";
-    CAResult_t res = CAGenerateToken(&gToken, CA_MAX_TOKEN_LEN);
-    if (CA_STATUS_OK != res)
-    {
-        OC_LOG(ERROR, TAG, "Error while generating token.");
-        return SP_RESULT_INTERNAL_ERROR;
-    }
-
-    CAInfo_t requestData = {};
-    requestData.token = gToken;
-    requestData.tokenLength  = CA_MAX_TOKEN_LEN;
-    requestData.payload = NULL;
-    requestData.payloadSize = 0;
-    requestData.type = CA_MSG_NONCONFIRM;
-    requestData.resourceUri = OIC_UNICAST_SEC_QUERY;
-    CARequestInfo_t requestInfo = { 0 };
-    requestInfo.method = CA_GET;
-    requestInfo.info = requestData;
-    requestInfo.isMulticast = false;
-    handler = &ProvisionSecureResourceInfoHandler;
-    res = CASendRequest((CAEndpoint_t*)devAddr, &requestInfo);
-
-    gStateManager |= SP_SEC_RES_INFO_STARTED;
-    if (CA_STATUS_OK != res)
-    {
-        OC_LOG(ERROR, TAG, "Error while finding secure resource.");
-        return convertCAResultToSPResult(res);
-    }
-    else
-    {
-        OC_LOG(INFO, TAG, "Secure resource info request sent successfully");
-    }
-    return SPWaitForResponse(timeout);
-}
-
-/**
- * Function to update the operation mode. As per the spec. Operation mode in client driven
- * single service provisioning it will be updated to 0x3
- *
- * @param[in]  timeout     timeout for operation.
- * @param[in]  deviceInfo  Device Info.
- * @return  SP_SUCCESS on success
- */
-static SPResult updateOwnerTransferModeToResource(unsigned short timeout,
-        SPTargetDeviceInfo_t *deviceInfo, OicSecOxm_t selectedMethod)
-{
-    SPResult res = SP_RESULT_INTERNAL_ERROR;
-
-    deviceInfo->doxm->oxmSel = selectedMethod;
-    char *payload = BinToDoxmJSON(deviceInfo->doxm);
-    if (NULL == payload)
-    {
-        OC_LOG(ERROR, TAG, "Error while converting bin to json");
-        return SP_RESULT_INTERNAL_ERROR;
-    }
-    OC_LOG_V(DEBUG, TAG, "Payload: %s", payload);
-    int payloadLen = strlen(payload);
-
-    handler = &OwnerShipTransferModeHandler;
-    gStateManager |= SP_UP_OWN_TR_METH_STARTED;
-
-    CAResult_t result = sendCARequest(CA_PUT,
-                                      &deviceInfo->endpoint,
-                                      OC_DEFAULT_FLAGS,
-                                      OIC_RSRC_DOXM_URI,
-                                      payload, payloadLen);
-    OICFree(payload);
-    if (CA_STATUS_OK != result)
-    {
-        OC_LOG(ERROR, TAG, "Error while sending request.");
-        CADestroyToken(gToken);
-        return convertCAResultToSPResult(result);
-    }
-    res = SPTimeout(timeout, SP_UP_OWN_TR_METH_DONE);
-    if (SP_RESULT_SUCCESS != res)
-    {
-        OC_LOG(ERROR, TAG, "Internal Error occured");
-        CADestroyToken(gToken);
-        return SP_RESULT_TIMEOUT;
-    }
-    CADestroyToken(gToken);
-    return SP_RESULT_SUCCESS;
-}
-
-/**
- * Function to send request to resource to get its pstat resource information.
- *
- * @param[in]  timeout     timeout for operation.
- * @param[in]  deviceInfo  Device Info.
- * @return  SP_SUCCESS on success
- */
-static SPResult getProvisioningStatusResource(unsigned short timeout,
-                                              SPTargetDeviceInfo_t *deviceInfo)
-{
-    handler = &ListMethodsHandler;
-    gStateManager |= SP_LIST_METHODS_STARTED;
-
-    CAResult_t result = sendCARequest(CA_GET,
-                                      &deviceInfo->endpoint,
-                                      OC_DEFAULT_FLAGS,
-                                      OIC_RSRC_PSTAT_URI,
-                                      NULL, 0);
-    if (CA_STATUS_OK != result)
-    {
-        OC_LOG(ERROR, TAG, "Failure while sending request.");
-        CADestroyToken(gToken);
-        return convertCAResultToSPResult(result);
-    }
-    SPResult res = SPTimeout(timeout, SP_LIST_METHODS_DONE);
-    if (SP_RESULT_SUCCESS != res)
-    {
-        OC_LOG(ERROR, TAG, "Timeout while getting method list.");
-        CADestroyToken(gToken);
-        return SP_RESULT_TIMEOUT;
-    }
-    if (gStateManager && SP_LIST_METHODS_DONE)
-    {
-        deviceInfo->pstat = gPstat;
-        CADestroyToken(gToken);
-        OC_LOG(DEBUG, TAG, "getProvisioningStatusResource completed.");
-        return SP_RESULT_SUCCESS;
-    }
-    CADestroyToken(gToken);
-    return SP_RESULT_INTERNAL_ERROR;
-}
-
-/**
- * Function to update the operation mode. As per the spec. Operation mode in client driven
- * single service provisioning it will be updated to 0x3
- *
- * @param[in]  timeout     timeout for operation.
- * @param[in]  deviceInfo  Device Info.
- * @return  SP_SUCCESS on success
- */
-static SPResult updateOperationMode(unsigned short timeout,
-                                    SPTargetDeviceInfo_t *deviceInfo,
-                                    OicSecDpom_t selectedOperationMode)
-{
-
-    SPResult res = SP_RESULT_INTERNAL_ERROR;
-
-    deviceInfo->pstat->om = selectedOperationMode;
-
-    char *payloadBuffer = BinToPstatJSON(deviceInfo->pstat);
-    if (NULL == payloadBuffer)
-    {
-        OC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
-        return SP_RESULT_INTERNAL_ERROR;
-    }
-
-    size_t payloadLen = strlen(payloadBuffer);
-    handler = &OperationModeUpdateHandler;
-    gStateManager |= SP_UPDATE_OP_MODE_STARTED;
-
-    CAResult_t result = sendCARequest(CA_PUT,
-                                      &deviceInfo->endpoint,
-                                      OC_DEFAULT_FLAGS,
-                                      OIC_RSRC_PSTAT_URI,
-                                      payloadBuffer, payloadLen);
-    if (CA_STATUS_OK != result)
-    {
-        OC_LOG(ERROR, TAG, "Error while sending request.");
-        CADestroyToken(gToken);
-        OICFree(payloadBuffer);
-        return convertCAResultToSPResult(result);
-    }
-    res = SPTimeout(timeout, SP_UPDATE_OP_MODE_DONE);
-    if (SP_RESULT_SUCCESS != res)
-    {
-        OC_LOG(ERROR, TAG, "Internal Error occured");
-        CADestroyToken(gToken);
-        OICFree(payloadBuffer);
-        return SP_RESULT_TIMEOUT;
-    }
-    CADestroyToken(gToken);
-    OICFree(payloadBuffer);
-
-    if (gStateManager & SP_UPDATE_OP_MODE_DONE)
-    {
-        return SP_RESULT_SUCCESS;
-    }
-    return SP_RESULT_INTERNAL_ERROR;
-}
-
-/**
- * Function to initiate DTLS handshake.
- *
- * @param[in]  deviceInfo  Provisioning context
- * @return SP_SUCCESS on success
- */
-static SPResult initiateDtlsHandshake(const CAEndpoint_t *endpoint)
-{
-    CAResult_t caresult = CAEnableAnonECDHCipherSuite(true);
-    if (CA_STATUS_OK != caresult)
-    {
-        OC_LOG_V(ERROR, TAG, "Unable to enable anon cipher suite");
-        return SP_RESULT_INTERNAL_ERROR;
-    }
-    OC_LOG(INFO, TAG, "Anonymous cipher suite Enabled.");
-
-    caresult = CAInitiateHandshake(endpoint);
-    if (CA_STATUS_OK != caresult)
-    {
-        OC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
-    }
-
-    return SP_RESULT_SUCCESS;
-}
-
-/**
- * Function to send ownerShip info. This function would update Owned as true and
- * owner as UUID for provisioning tool
- *
- * @param[in]  timeout     timeout value for the operation.
- * @param[in]  deviceInfo  provisioning context.
- * @return  SP_SUCCESS on success
- */
-static SPResult sendOwnershipInfo(unsigned short timeout,
-                                  SPTargetDeviceInfo_t *selectedDeviceInfo)
-{
-    OicUuid_t provTooldeviceID = {};
-
-    if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
-    {
-        OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
-        return SP_RESULT_INTERNAL_ERROR;
-    }
-    memcpy(selectedDeviceInfo->doxm->owner.id, provTooldeviceID.id , UUID_LENGTH);
-
-    selectedDeviceInfo->doxm->owned = true;
-
-    char *payloadBuffer =  BinToDoxmJSON(selectedDeviceInfo->doxm);
-    if (NULL == payloadBuffer)
-    {
-        OC_LOG(ERROR, TAG, "Error while converting doxm bin to json");
-        return SP_RESULT_INTERNAL_ERROR;
-    }
-    int payloadLen = strlen(payloadBuffer);
-
-    handler = &OwnerShipUpdateHandler;
-    gStateManager |= SP_UPDATE_OWNER_STARTED;
-
-    CAResult_t result = sendCARequest(CA_PUT,
-                                      &selectedDeviceInfo->endpoint,
-                                      OC_FLAG_SECURE,
-                                      OIC_RSRC_DOXM_URI,
-                                      payloadBuffer, payloadLen);
-    if (CA_STATUS_OK != result)
-    {
-        OC_LOG(ERROR, TAG, "Error while sending request.");
-        CADestroyToken(gToken);
-        OICFree(payloadBuffer);
-        return convertCAResultToSPResult(result);
-    }
-    SPResult res = SPTimeout(timeout, SP_UPDATE_OWNER_DONE);
-    if (SP_RESULT_SUCCESS != res)
-    {
-        OC_LOG(ERROR, TAG, "Internal Error occured");
-        CADestroyToken(gToken);
-        OICFree(payloadBuffer);
-        return SP_RESULT_TIMEOUT;
-    }
-    CADestroyToken(gToken);
-    OICFree(payloadBuffer);
-    return SP_RESULT_SUCCESS;
-}
-
-/**
- * Function to save ownerPSK at provisioning tool end.
- *
- * @return  SP_SUCCESS on success
- */
-static SPResult saveOwnerPSK(SPTargetDeviceInfo_t *selectedDeviceInfo)
-{
-    SPResult result = SP_RESULT_INTERNAL_ERROR;
-
-    CAEndpoint_t endpoint = {};
-    OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
-    endpoint.port = selectedDeviceInfo->securePort;
-
-    OicUuid_t provTooldeviceID = {};
-    if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
-    {
-        OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
-        return result;
-    }
-
-    uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {};
-
-    //Generating OwnerPSK
-    CAResult_t pskRet = CAGenerateOwnerPSK(&endpoint,
-            (uint8_t *)OXM_JUST_WORKS, strlen(OXM_JUST_WORKS), provTooldeviceID.id,
-            sizeof(provTooldeviceID.id), selectedDeviceInfo->doxm->deviceID.id,
-            sizeof(selectedDeviceInfo->doxm->deviceID.id), ownerPSK,
-            OWNER_PSK_LENGTH_128);
-
-    if (CA_STATUS_OK == pskRet)
-    {
-        OC_LOG(INFO, TAG,"ownerPSK dump:\n");
-        OC_LOG_BUFFER(INFO, TAG,ownerPSK, OWNER_PSK_LENGTH_128);
-        //Generating new credential for provisioning tool
-        size_t ownLen = 1;
-        uint32_t outLen = 0;
-
-        char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
-        B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff, sizeof(base64Buff),
-                &outLen);
-        if (B64_OK == b64Ret)
-        {
-            OicSecCred_t *cred = GenerateCredential(&selectedDeviceInfo->doxm->deviceID,
-                    SYMMETRIC_PAIR_WISE_KEY, NULL,
-                    base64Buff, ownLen, &provTooldeviceID);
-            if (cred)
-            {
-                //Update the SVR database.
-                if (OC_STACK_OK == AddCredential(cred))
-                {
-                    result = SP_RESULT_SUCCESS;
-                }
-                else
-                {
-                    OC_LOG(ERROR, TAG, "AddCredential failed");
-                }
-            }
-            else
-            {
-                OC_LOG(ERROR, TAG, "GenerateCredential failed");
-            }
-        }
-        else
-        {
-            OC_LOG(ERROR, TAG, "b64Encode failed");
-        }
-    }
-    else
-    {
-        OC_LOG(ERROR, TAG, "CAGenerateOwnerPSK failed");
-    }
-    return result;
-}
-
-/**
- * Function to select operation mode.This function will return most secure common operation mode.
- *
- * @param[out]   selectedMode   selected operation mode
- * @return  SP_SUCCESS on success
- */
-static void selectOperationMode(const SPTargetDeviceInfo_t *selectedDeviceInfo,
-                                OicSecDpom_t **selectedMode)
-{
-    int i = 0;
-    int j = 0;
-    while (i < gNumOfProvisioningMethodsPT && j < selectedDeviceInfo->pstat->smLen)
-    {
-        if (gProvisioningToolCapability[i] < selectedDeviceInfo->pstat->sm[j])
-        {
-            i++;
-        }
-        else if (selectedDeviceInfo->pstat->sm[j] < gProvisioningToolCapability[i])
-        {
-            j++;
-        }
-        else /* if gProvisioningToolCapability[i] == deviceSupportedMethods[j] */
-        {
-            *selectedMode = &(gProvisioningToolCapability[j]);
-            break;
-        }
-    }
-}
-
-/**
- * Function to perform onwership tranfer based to ownership transfer mode.
- *
- * @param[in]  timeout            timeout in secs to perform operation. 0 timeout means
-                                  function will wait forever.
- * @param[in]  selectedDeviceInfo instance of SPTargetDeviceInfo_t structure.
- * @return  SP_SUCCESS on success
- */
-static SPResult doOwnerShipTransfer(unsigned short timeout,
-                                    SPTargetDeviceInfo_t *selectedDeviceInfo)
-{
-    OicSecDpom_t *selectedOperationMode = NULL;
-    selectOperationMode(selectedDeviceInfo, &selectedOperationMode);
-
-    SPResult res = updateOperationMode(timeout, selectedDeviceInfo, *selectedOperationMode);
-    if (SP_RESULT_SUCCESS != res)
-    {
-        OC_LOG(ERROR, TAG, "Error while updating operation mode.");
-        return SP_RESULT_INTERNAL_ERROR;
-    }
-    if (*selectedOperationMode == SINGLE_SERVICE_CLIENT_DRIVEN)
-    {
-        CAEndpoint_t endpoint = {0};
-        OICStrcpy(endpoint.addr, MAX_ADDR_STR_SIZE_CA, selectedDeviceInfo->endpoint.addr);
-        endpoint.port = selectedDeviceInfo->securePort;
-
-        res = initiateDtlsHandshake(&endpoint);
-        if (SP_RESULT_SUCCESS == res)
-        {
-            selectedDeviceInfo->endpoint.port = selectedDeviceInfo->securePort;
-            res = sendOwnershipInfo(timeout, selectedDeviceInfo);
-            if (SP_RESULT_SUCCESS != res)
-            {
-                OC_LOG(ERROR, TAG, "Error while updating ownership information.");
-            }
-            res = saveOwnerPSK(selectedDeviceInfo);
-
-            //Close temporal DTLS session
-            if(CA_STATUS_OK != CACloseDtlsSession(&endpoint))
-            {
-                OC_LOG(WARNING, TAG, "doOwnerShipTransfer() : failed to close the dtls session");
-            }
-        }
-        else
-        {
-            OC_LOG(ERROR, TAG, "Error during initiating DTLS handshake.");
-        }
-
-        //Disable Anonymous ECDH cipher suite before leaving this method
-        if(CA_STATUS_OK != CAEnableAnonECDHCipherSuite(false))
-        {
-            OC_LOG(WARNING, TAG, "doOwnerShipTransfer() : failed to disable Anon ECDH cipher suite");
-        }
-    }
-    return (res != SP_RESULT_SUCCESS) ? SP_RESULT_INTERNAL_ERROR : SP_RESULT_SUCCESS;
-
-}
-/**
- * The function is responsible for discovering secure resources(such as, /oic/sec/doxm etc) with
- * OC_EXPLICIT_DISCOVERABLE on a OIC device which needs to be provisioned.
- *
- * @param[in] timeout Timeout in seconds, value till which function will listen to responses from
- *                    client before returning the list of devices.
- * @param[in] selectedDeviceInfo Device information.
- * @return SP_SUCCESS in case of success and other value otherwise.
- */
-static SPResult discoverSecureResource(unsigned short timeout,
-        SPTargetDeviceInfo_t *selectedDeviceInfo)
-{
-    if (NULL == selectedDeviceInfo)
-    {
-        OC_LOG(ERROR, TAG, "List is not null can cause memory leak");
-        return SP_RESULT_INVALID_PARAM;
-    }
-    SPResult smResponse = SP_RESULT_SUCCESS;
-    smResponse = getSecureResourceInfo(&selectedDeviceInfo->endpoint, timeout);
-    if (SP_RESULT_SUCCESS != smResponse)
-    {
-        return SP_RESULT_INTERNAL_ERROR;
-    }
-    if (gStateManager & SP_SEC_RES_INFO_DONE)
-    {
-        if (gStateManager & SP_SEC_RES_INFO_ERROR)
-        {
-            return SP_RESULT_INTERNAL_ERROR;
-        }
-        return SP_RESULT_SUCCESS;
-    }
-    return SP_RESULT_INTERNAL_ERROR;
-}
-
-/**
- * Function to provision credentials to specific device.
- *
- * @param[in] timeout     timeout in secs to perform operation. 0 timeout means function will
-                          wait till success.
- * @param[in] cred        credential to be provisioned.
- * @param[in] deviceInfo  Instance of SPDevInfo_t structure. Representing a selected device for
-                          provisioning.
- * @return  SP_SUCCESS on success
- */
-SPResult provisionCredentials(unsigned short timeout, const OicSecCred_t *cred,
-                              const SPDevInfo_t *deviceInfo)
-{
-    char *credJson = NULL;
-    credJson = BinToCredJSON(cred);
-    if (NULL == credJson)
-    {
-        OC_LOG(ERROR, TAG, "Memory allocation problem");
-        return SP_RESULT_MEM_ALLOCATION_FAIL;
-    }
-
-    int payloadLen = strlen(credJson);
-    handler = &CredProvisioningHandler;
-    gStateManager |= SP_PROV_CRED_STARTED;
-
-    CAResult_t result = sendCARequest(CA_POST,
-                                      &deviceInfo->endpoint,
-                                      OC_FLAG_SECURE,
-                                      OIC_RSRC_CRED_URI,
-                                      credJson, payloadLen);
-    OICFree(credJson);
-    if (CA_STATUS_OK != result)
-    {
-        OC_LOG(ERROR, TAG, "Internal Error while sending Credentials.");
-        CADestroyToken(gToken);
-        return convertCAResultToSPResult(result);
-    }
-
-    SPResult res = SPTimeout(timeout, SP_PROV_CRED_DONE);
-    if (SP_RESULT_SUCCESS != res)
-    {
-        OC_LOG(ERROR, TAG, "Internal Error occured");
-        CADestroyToken(gToken);
-        return SP_RESULT_TIMEOUT;
-    }
-    CADestroyToken(gToken);
-    gStateManager = 0;
-    return res;
-}
-
-SPResult SPProvisioningDiscovery(unsigned short timeout,
-                                 SPTargetDeviceInfo_t **list)
-{
-    if (NULL != *list)
-    {
-        OC_LOG(ERROR, TAG, "List is not null can cause memory leak");
-        return SP_RESULT_INVALID_PARAM;
-    }
-    SRMRegisterProvisioningResponseHandler(SPResponseHandler);
-    SPResult smResponse = SP_RESULT_SUCCESS;
-    smResponse = findResource(timeout);
-    if (SP_RESULT_SUCCESS != smResponse)
-    {
-        return SP_RESULT_INTERNAL_ERROR;
-    }
-    if (gStateManager & SP_DISCOVERY_DONE)
-    {
-        if (gStateManager & SP_DISCOVERY_ERROR)
-        {
-            return SP_RESULT_INTERNAL_ERROR;
-        }
-        *list = gStartOfDiscoveredDevices;
-        return SP_RESULT_SUCCESS;
-    }
-    return SP_RESULT_INTERNAL_ERROR;
-}
-
-SPResult SPInitProvisionContext(unsigned short timeout,
-                                SPTargetDeviceInfo_t *selectedDeviceInfo)
-{
-    if (NULL == selectedDeviceInfo )
-    {
-        return SP_RESULT_INVALID_PARAM;
-    }
-    SPResult res = SP_RESULT_SUCCESS;
-
-    //Discover secure resource and update the device info.
-    res = discoverSecureResource(timeout, selectedDeviceInfo);
-    if (SP_RESULT_SUCCESS != res)
-    {
-        OC_LOG(ERROR, TAG, "Error in discoverSecureResource");
-        return SP_RESULT_INTERNAL_ERROR;
-    }
-
-    OicSecOxm_t selectedMethod = OIC_JUST_WORKS;
-
-    selectProvisioningMethod(selectedDeviceInfo->doxm->oxm, selectedDeviceInfo->doxm->oxmLen,
-                             &selectedMethod);
-    OC_LOG_V(DEBUG, TAG, "Selected method %d:", selectedMethod);
-    res = updateOwnerTransferModeToResource(timeout, selectedDeviceInfo, selectedMethod);
-
-    if (SP_RESULT_SUCCESS != res)
-    {
-        OC_LOG(ERROR, TAG, "Error while updating owner transfer mode.");
-        return SP_RESULT_INTERNAL_ERROR;
-    }
-
-    res = getProvisioningStatusResource(timeout, selectedDeviceInfo);
-    if (SP_RESULT_SUCCESS != res)
-    {
-        OC_LOG(ERROR, TAG, "Error while getting provisioning status.");
-        return SP_RESULT_INTERNAL_ERROR;
-    }
-    OC_LOG(INFO, TAG, "Starting ownership transfer");
-    return doOwnerShipTransfer(timeout, selectedDeviceInfo);
-
-}
-
-SPResult SPProvisionACL(unsigned short timeout, const SPTargetDeviceInfo_t *selectedDeviceInfo,
-                        OicSecAcl_t *acl)
-{
-    if (NULL == selectedDeviceInfo || NULL == acl)
-    {
-        return SP_RESULT_INVALID_PARAM;
-    }
-    char *aclString = NULL;
-    aclString = BinToAclJSON(acl);
-
-    if (NULL == aclString)
-    {
-        OC_LOG(ERROR, TAG, "Memory allocation problem");
-        return SP_RESULT_MEM_ALLOCATION_FAIL;
-    }
-
-    int payloadLen = strlen(aclString);
-    handler = &ACLProvisioningHandler;
-    gStateManager |= SP_PROV_ACL_STARTED;
-
-    CAResult_t result = sendCARequest(CA_POST,
-                                      &selectedDeviceInfo->endpoint,
-                                      OC_FLAG_SECURE,
-                                      OIC_RSRC_ACL_URI,
-                                      aclString, payloadLen);
-    OICFree(aclString);
-    if (CA_STATUS_OK != result)
-    {
-        OC_LOG(ERROR, TAG, "Internal Error while sending ACL.");
-        CADestroyToken(gToken);
-        return convertCAResultToSPResult(result);
-    }
-
-    SPResult res = SPTimeout(timeout, SP_PROV_ACL_DONE);
-    if (SP_RESULT_SUCCESS != res)
-    {
-        OC_LOG(ERROR, TAG, "Internal Error occured");
-        CADestroyToken(gToken);
-        return SP_RESULT_TIMEOUT;
-    }
-    CADestroyToken(gToken);
-    return res;
-}
-
-SPResult SPProvisionCredentials(unsigned short timeout, OicSecCredType_t type,
-                                const SPDevInfo_t *pDevList)
-{
-    if (NULL == pDevList)
-    {
-        return SP_RESULT_INVALID_PARAM;
-    }
-    const SPDevInfo_t *curr = pDevList;
-    OicUuid_t provTooldeviceID = {};
-    if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
-    {
-        OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
-        return SP_RESULT_INTERNAL_ERROR;
-    }
-    //TODO Need to support other key types in future.
-    switch (type)
-    {
-        case SYMMETRIC_PAIR_WISE_KEY:
-            {
-                if (NULL == curr->next)
-                {
-                    return SP_RESULT_INVALID_PARAM;
-                }
-                // Devices if present after second node will not be considered.
-                // in scenario-2. 2 devices are provisioned with credentials.
-                const SPDevInfo_t *firstDevice = curr;
-                const SPDevInfo_t *secondDevice = curr->next;
-
-                OicSecCred_t *firstCred = NULL;
-                OicSecCred_t *secondCred = NULL;
-
-                SPResult res = SPGeneratePairWiseCredentials(type, &provTooldeviceID,
-                               &firstDevice->deviceId, &secondDevice->deviceId,
-                               &firstCred, &secondCred);
-                if (res != SP_RESULT_SUCCESS)
-                {
-                    OC_LOG(ERROR, TAG, "error while generating credentials");
-                    return SP_RESULT_INTERNAL_ERROR;
-                }
-                res = provisionCredentials(timeout, firstCred, firstDevice);
-                if (SP_RESULT_SUCCESS != res)
-                {
-                    OC_LOG_V(ERROR, TAG, "Credentials provisioning Error");
-                    DeleteCredList(firstCred);
-                    DeleteCredList(secondCred);
-                    return SP_RESULT_INTERNAL_ERROR;
-                }
-                res = provisionCredentials(timeout, secondCred, secondDevice);
-                if (SP_RESULT_SUCCESS != res)
-                {
-                    OC_LOG_V(ERROR, TAG, "Credentials provisioning Error");
-                    DeleteCredList(firstCred);
-                    DeleteCredList(secondCred);
-                    return SP_RESULT_INTERNAL_ERROR;
-                }
-                DeleteCredList(firstCred);
-                DeleteCredList(secondCred);
-                return SP_RESULT_SUCCESS;
-            }
-        default:
-            {
-                OC_LOG(ERROR, TAG, "Invalid option.");
-                return SP_RESULT_INVALID_PARAM;
-            }
-            return SP_RESULT_INTERNAL_ERROR;
-    }
-}
-
-SPResult SPFinalizeProvisioning(unsigned short timeout,
-                                SPTargetDeviceInfo_t *selectedDeviceInfo)
-{
-    // TODO
-    if (NULL == selectedDeviceInfo)
-    {
-        OC_LOG(ERROR, TAG, "Target device Info is NULL.");
-        return SP_RESULT_INVALID_PARAM;
-    }
-
-    uint16_t aclHash = 0; // value for beachhead version.
-    selectedDeviceInfo->pstat->commitHash = aclHash;
-    selectedDeviceInfo->pstat->tm = NORMAL;
-    char *payloadBuffer = BinToPstatJSON(selectedDeviceInfo->pstat);
-    if (NULL == payloadBuffer)
-    {
-        OC_LOG(ERROR, TAG, "Error while converting pstat bin to json");
-        return SP_RESULT_INTERNAL_ERROR;
-    }
-    int payloadLen = strlen(payloadBuffer);
-
-    handler = &FinalizeProvisioningHandler;
-    gStateManager |= SP_UP_HASH_STARTED;
-
-    CAResult_t result = sendCARequest(CA_PUT,
-                                      &selectedDeviceInfo->endpoint,
-                                      OC_FLAG_SECURE,
-                                      OIC_RSRC_PSTAT_URI,
-                                      payloadBuffer, payloadLen);
-    OICFree(payloadBuffer);
-    if (CA_STATUS_OK != result)
-    {
-        OC_LOG(ERROR, TAG, "Internal Error occured");
-        CADestroyToken(gToken);
-        return convertCAResultToSPResult(result);
-    }
-
-    SPResult res = SPTimeout(timeout, SP_UP_HASH_DONE);
-    if (SP_RESULT_SUCCESS != res)
-    {
-        OC_LOG(ERROR, TAG, "Internal Error occured");
-        CADestroyToken(gToken);
-        return SP_RESULT_TIMEOUT;
-    }
-
-    result = CACloseDtlsSession((CAEndpoint_t*)&selectedDeviceInfo->endpoint);
-    if (CA_STATUS_OK != result)
-    {
-        OC_LOG(WARNING, TAG, "Failed to close the DTLS session.");
-    }
-
-    CADestroyToken(gToken);
-    gStateManager = 0;
-    gPstat = NULL;
-    return res;
-}
-
-SPResult SPTerminateProvisioning()
-{
-    deleteList();
-    return SP_RESULT_SUCCESS;;
-}
diff --git a/resource/csdk/security/provisioning/src/secureresourceprovider.c b/resource/csdk/security/provisioning/src/secureresourceprovider.c
new file mode 100644 (file)
index 0000000..4ac8e32
--- /dev/null
@@ -0,0 +1,491 @@
+/* *****************************************************************
+ *
+ * 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 <stdint.h>
+#include <unistd.h>
+
+#include "ocprovisioningmanager.h"
+#include "secureresourceprovider.h"
+#include "logger.h"
+#include "oic_malloc.h"
+#include "aclresource.h"
+#include "pstatresource.h"
+#include "srmresourcestrings.h"
+#include "credresource.h"
+#include "doxmresource.h"
+#include "credentialgenerator.h"
+#include "cainterface.h"
+#include "cJSON.h"
+#include "pmtypes.h"
+#include "pmutility.h"
+
+#define SRP_MAX_URI_LENGTH 512
+#define TAG "SRPAPI"
+
+/**
+ * Macro to verify argument is not equal to NULL.
+ * eg: VERIFY_NON_NULL(TAG, ptrData, ERROR,OC_STACK_ERROR);
+ */
+#define VERIFY_NON_NULL(tag, arg, logLevel, retValue) { if (NULL == (arg)) \
+            { OC_LOG((logLevel), tag, (#arg " is NULL")); return retValue; } }
+
+/**
+ * Macro to verify success of operation.
+ * eg: VERIFY_SUCCESS(TAG, OC_STACK_OK == foo(), ERROR, OC_STACK_ERROR);
+ */
+#define VERIFY_SUCCESS(tag, op, logLevel, retValue) { if (!(op)) \
+            {OC_LOG((logLevel), tag, (#op " failed!!")); return retValue;} }
+
+/**
+ * Structure to carry credential data to callback.
+ */
+typedef struct CredentialData CredentialData_t;
+struct CredentialData
+{
+    void *ctx;                                  /**< Pointer to user context.**/
+    const OCProvisionDev_t *deviceInfo1;        /**< Pointer to OCProvisionDev_t.**/
+    const OCProvisionDev_t *deviceInfo2;        /**< Pointer to OCProvisionDev_t.**/
+    OicSecCred_t *credInfo;                     /**< Pointer to OicSecCred_t.**/
+    OicSecCred_t *credInfoFirst;                /**< Pointer to OicSecCred_t.**/
+    OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
+    OCProvisionResult_t *resArr;                /**< Result array.**/
+    int numOfResults;                           /**< Number of results in result array.**/
+};
+
+/**
+ * Structure to carry ACL provision API data to callback.
+ */
+typedef struct ACLData ACLData_t;
+struct ACLData
+{
+    void *ctx;                                  /**< Pointer to user context.**/
+    const OCProvisionDev_t *deviceInfo;         /**< Pointer to PMDevInfo_t.**/
+    OCProvisionResultCB resultCallback;         /**< Pointer to result callback.**/
+    OCProvisionResult_t *resArr;                /**< Result array.**/
+    int numOfResults;                           /**< Number of results in result array.**/
+};
+
+/**
+ * Function prototype
+ */
+static OCStackResult provisionCredentials(const OicSecCred_t *cred,
+        const OCProvisionDev_t *deviceInfo, CredentialData_t *credData,
+        OCClientResponseHandler responseHandler);
+
+
+/**
+ * Internal function to update result in result array.
+ */
+static void registerResultForCredProvisioning(CredentialData_t *credData,
+                                              OCStackResult stackresult, int cause)
+{
+
+   OC_LOG_V(INFO,TAG,"value of credData->numOfResults is %d",credData->numOfResults);
+   if(1 == cause)
+   {
+       memcpy(credData->resArr[(credData->numOfResults)].deviceId.id,
+              credData->deviceInfo1->doxm->deviceID.id,UUID_LENGTH);
+   }
+   else
+   {
+       memcpy(credData->resArr[(credData->numOfResults)].deviceId.id,
+              credData->deviceInfo2->doxm->deviceID.id,UUID_LENGTH);
+   }
+   credData->resArr[(credData->numOfResults)].res = stackresult;
+   ++(credData->numOfResults);
+}
+
+/**
+ * Callback handler for handling callback of provisioning device 2.
+ *
+ * @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 provisionCredentialCB2(void *ctx, OCDoHandle UNUSED,
+                                                       OCClientResponse *clientResponse)
+{
+    VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    CredentialData_t *credData = (CredentialData_t *) ctx;
+    (void)UNUSED;
+
+    OCProvisionResultCB resultCallback = credData->resultCallback;
+    OC_LOG(INFO, TAG, "provisionCredentialCB2 called");
+    if (clientResponse)
+    {
+        if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
+        {
+            registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CREATED, 2);
+            ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
+                                                    credData->resArr,
+                                                    false);
+             OICFree(credData->resArr);
+             OICFree(credData);
+             return OC_STACK_DELETE_TRANSACTION;
+        }
+
+    }
+    OC_LOG(INFO, TAG, "provisionCredentialCB2 received Null clientResponse");
+    registerResultForCredProvisioning(credData, OC_STACK_ERROR, 2);
+    ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
+                                            credData->resArr,
+                                            true);
+    OICFree(credData->resArr);
+    OICFree(credData);
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+/**
+ * Callback handler for handling callback of provisioning device 1.
+ *
+ * @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 provisionCredentialCB1(void *ctx, OCDoHandle UNUSED,
+                                                       OCClientResponse *clientResponse)
+{
+    VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    (void)UNUSED;
+    CredentialData_t* credData = (CredentialData_t*) ctx;
+    OICFree(credData->credInfoFirst);
+    const OCProvisionDev_t *deviceInfo = credData->deviceInfo2;
+    OicSecCred_t *credInfo = credData->credInfo;
+    const OCProvisionResultCB resultCallback = credData->resultCallback;
+    if (clientResponse)
+    {
+        if (OC_STACK_RESOURCE_CREATED == clientResponse->result)
+        {
+            // send credentials to second device
+            registerResultForCredProvisioning(credData, OC_STACK_RESOURCE_CREATED,1);
+            OCStackResult res = provisionCredentials(credInfo, deviceInfo, credData,
+                    provisionCredentialCB2);
+            DeleteCredList(credInfo);
+            if (OC_STACK_OK != res)
+            {
+                registerResultForCredProvisioning(credData, res,2);
+                ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
+                                                        credData->resArr,
+                                                        true);
+                OICFree(credData->resArr);
+                OICFree(credData);
+                credData = NULL;
+            }
+        }
+        else
+        {
+            registerResultForCredProvisioning(credData, OC_STACK_ERROR,1);
+            ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
+                                                    credData->resArr,
+                                                    true);
+            OICFree(credData->resArr);
+            OICFree(credData);
+            credData = NULL;
+        }
+    }
+    else
+    {
+        OC_LOG(INFO, TAG, "provisionCredentialCB received Null clientResponse for first device");
+        registerResultForCredProvisioning(credData, OC_STACK_ERROR,1);
+       ((OCProvisionResultCB)(resultCallback))(credData->ctx, credData->numOfResults,
+                                                     credData->resArr,
+                                                     true);
+        DeleteCredList(credInfo);
+        OICFree(credData->resArr);
+        OICFree(credData);
+        credData = NULL;
+    }
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+
+
+/**
+ * Internal function for handling credential generation and sending credential to resource server.
+ *
+ * @param[in] cred Instance of cred resource.
+ * @param[in] deviceInfo information about device to which credential is to be provisioned.
+ * @param[in] responseHandler callbak called by OC stack when request API receives response.
+ * @return  OC_STACK_OK in case of success and other value otherwise.
+ */
+static OCStackResult provisionCredentials(const OicSecCred_t *cred,
+        const OCProvisionDev_t *deviceInfo, CredentialData_t *credData,
+        OCClientResponseHandler responseHandler)
+{
+    OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+    if(!secPayload)
+    {
+        OC_LOG(ERROR, TAG, "Failed to memory allocation");
+        return OC_STACK_NO_MEMORY;
+    }
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+    secPayload->securityData = BinToCredJSON(cred);
+    if(NULL == secPayload->securityData)
+    {
+        OICFree(secPayload);
+        OC_LOG(ERROR, TAG, "Failed to BinToCredJSON");
+        return OC_STACK_NO_MEMORY;
+    }
+
+    OC_LOG_V(INFO, TAG, "Credential for provisioning : %s",secPayload->securityData);
+    char uri[SRP_MAX_URI_LENGTH] = { 0 };
+
+    size_t uriLen = sizeof(uri);
+    snprintf(uri, uriLen - 1, COAPS_QUERY, deviceInfo->endpoint.addr, deviceInfo->securePort,
+            OIC_RSRC_CRED_URI);
+
+    uri[uriLen - 1] = '\0';
+    OC_LOG_V(INFO, TAG, "URI for Credential provisioning : %s",uri);
+    OCCallbackData cbData = {.context=NULL, .cb=NULL, .cd=NULL};
+    cbData.cb = responseHandler;
+    cbData.context = (void *) credData;
+    cbData.cd = NULL;
+
+    OCDoHandle handle = NULL;
+    OCMethod method = OC_REST_POST;
+    // TODO replace CT_ADAPTER_IP with value from discovery
+    OCStackResult ret = OCDoResource(&handle, method, uri, 0, (OCPayload*)secPayload,
+            CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
+    OC_LOG_V(INFO, TAG, "OCDoResource::Credential provisioning returned : %d",ret);
+    if (ret != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack resource error");
+        return ret;
+    }
+    return OC_STACK_OK;
+}
+
+OCStackResult SRPProvisionCredentials(void *ctx, OicSecCredType_t type, size_t keySize,
+                                      const OCProvisionDev_t *pDev1,
+                                      const OCProvisionDev_t *pDev2,
+                                      OCProvisionResultCB resultCallback)
+{
+    VERIFY_NON_NULL(TAG, pDev1, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(TAG, pDev2, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
+
+    if (!(keySize == OWNER_PSK_LENGTH_128 || keySize == OWNER_PSK_LENGTH_256))
+    {
+        OC_LOG(INFO, TAG, "Invalid key size");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OC_LOG(INFO, TAG, "In SRPProvisionCredentials");
+
+    OicUuid_t provTooldeviceID =   {{0,}};
+    if (OC_STACK_OK != GetDoxmDeviceID(&provTooldeviceID))
+    {
+        OC_LOG(ERROR, TAG, "Error while retrieving provisioning tool's device ID");
+        return OC_STACK_ERROR;
+    }
+    OC_LOG(INFO, TAG, "retrieved deviceid");
+    switch (type)
+    {
+        case SYMMETRIC_PAIR_WISE_KEY:
+        {
+            const OCProvisionDev_t *firstDevice = pDev1;
+            const OCProvisionDev_t *secondDevice = pDev2;
+
+            OicSecCred_t *firstCred = NULL;
+            OicSecCred_t *secondCred = NULL;
+            OCStackResult res = PMGeneratePairWiseCredentials(type, keySize, &provTooldeviceID,
+                    &firstDevice->doxm->deviceID, &secondDevice->doxm->deviceID,
+                    &firstCred, &secondCred);
+            VERIFY_SUCCESS(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
+            OC_LOG(INFO, TAG, "Credentials generated successfully");
+            CredentialData_t *credData = (CredentialData_t *) OICMalloc(sizeof(CredentialData_t));
+            if (NULL == credData)
+            {
+                OC_LOG(ERROR, TAG, "Memory allocation problem");
+                return OC_STACK_NO_MEMORY;
+            }
+            memset(credData, 0x00, sizeof(CredentialData_t));
+            credData->deviceInfo1 = firstDevice;
+            credData->deviceInfo2 = secondDevice;
+            credData->credInfo = secondCred;
+            credData->ctx = ctx;
+            credData->credInfoFirst = firstCred;
+            credData->numOfResults = 0;
+            credData->resultCallback = resultCallback;
+            // first call to provision creds to device1.
+            // second call to provision creds to device2.
+            int noOfRiCalls = 2;
+            credData->resArr =
+                (OCProvisionResult_t*)OICMalloc(sizeof(OCProvisionResult_t) * noOfRiCalls);
+            if (NULL == credData->resArr)
+            {
+                OC_LOG(ERROR, TAG, "Memory allocation problem");
+                return OC_STACK_NO_MEMORY;
+            }
+            memset(credData->resArr, 0x00, sizeof(sizeof(OCProvisionResult_t)*noOfRiCalls));
+            res = provisionCredentials(firstCred, firstDevice, credData, &provisionCredentialCB1);
+            if (OC_STACK_OK != res)
+            {
+                DeleteCredList(firstCred);
+                DeleteCredList(secondCred);
+                OICFree(credData->resArr);
+                OICFree(credData);
+            }
+            OC_LOG_V(INFO, TAG, "provisionCredentials returned: %d",res);
+            VERIFY_SUCCESS(TAG, (res==OC_STACK_OK), ERROR, OC_STACK_ERROR);
+            return res;
+        }
+        default:
+        {
+            OC_LOG(ERROR, TAG, "Invalid option.");
+            return OC_STACK_INVALID_PARAM;
+        }
+    }
+    return OC_STACK_ERROR;
+}
+
+/**
+ * Internal Function to store results in result array during ACL provisioning.
+ */
+static void registerResultForACLProvisioning(ACLData_t *aclData,
+                                             OCStackResult stackresult)
+{
+   OC_LOG_V(INFO, TAG, "Inside registerResultForACLProvisioning aclData->numOfResults is %d\n",
+                       aclData->numOfResults);
+   memcpy(aclData->resArr[(aclData->numOfResults)].deviceId.id,
+          aclData->deviceInfo->doxm->deviceID.id, UUID_LENGTH);
+   aclData->resArr[(aclData->numOfResults)].res = stackresult;
+   ++(aclData->numOfResults);
+}
+
+/**
+ * Callback handler of SRPProvisionACL.
+ *
+ * @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 SRPProvisionACLCB(void *ctx, OCDoHandle UNUSED,
+                                                  OCClientResponse *clientResponse)
+{
+    OC_LOG_V(INFO, TAG, "Inside SRPProvisionACLCB.");
+    (void)UNUSED;
+    VERIFY_NON_NULL(TAG, ctx, ERROR, OC_STACK_DELETE_TRANSACTION);
+    ACLData_t *aclData = (ACLData_t*)ctx;
+    OCProvisionResultCB resultCallback = aclData->resultCallback;
+
+    if (clientResponse)
+    {
+        if(OC_STACK_RESOURCE_CREATED == clientResponse->result)
+        {
+            registerResultForACLProvisioning(aclData, OC_STACK_RESOURCE_CREATED);
+            ((OCProvisionResultCB)(resultCallback))(aclData->ctx, aclData->numOfResults,
+                                                    aclData->resArr,
+                                                    false);
+             OICFree(aclData->resArr);
+             OICFree(aclData);
+             return OC_STACK_DELETE_TRANSACTION;
+        }
+    }
+    registerResultForACLProvisioning(aclData, OC_STACK_ERROR);
+    ((OCProvisionResultCB)(resultCallback))(aclData->ctx, aclData->numOfResults,
+                                            aclData->resArr,
+                                            true);
+    OC_LOG_V(ERROR, TAG, "SRPProvisionACLCB received Null clientResponse");
+    OICFree(aclData->resArr);
+    OICFree(aclData);
+    return OC_STACK_DELETE_TRANSACTION;
+}
+
+OCStackResult SRPProvisionACL(void *ctx, const OCProvisionDev_t *selectedDeviceInfo,
+        OicSecAcl_t *acl, OCProvisionResultCB resultCallback)
+{
+    VERIFY_NON_NULL(TAG, selectedDeviceInfo, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(TAG, acl, ERROR,  OC_STACK_INVALID_PARAM);
+    VERIFY_NON_NULL(TAG, resultCallback, ERROR,  OC_STACK_INVALID_CALLBACK);
+
+    OCSecurityPayload* secPayload = (OCSecurityPayload*)OICCalloc(1, sizeof(OCSecurityPayload));
+    if(!secPayload)
+    {
+        OC_LOG(ERROR, TAG, "Failed to memory allocation");
+        return OC_STACK_NO_MEMORY;
+    }
+    secPayload->base.type = PAYLOAD_TYPE_SECURITY;
+    secPayload->securityData = BinToAclJSON(acl);
+    if(NULL == secPayload->securityData)
+    {
+        OICFree(secPayload);
+        OC_LOG(ERROR, TAG, "Failed to BinToAclJSON");
+        return OC_STACK_NO_MEMORY;
+    }
+    OC_LOG_V(INFO, TAG, "ACL : %s", secPayload->securityData);
+
+    char uri[SRP_MAX_URI_LENGTH] = {0};
+    size_t uriLen = sizeof(uri);
+
+    snprintf(uri, uriLen - 1, COAPS_QUERY, selectedDeviceInfo->endpoint.addr,
+            selectedDeviceInfo->securePort, OIC_RSRC_ACL_URI);
+    uri[uriLen - 1] = '\0';
+
+    OC_LOG_V(INFO, TAG, "URI : %s", uri);
+    OCCallbackData cbData =  {.context=NULL, .cb=NULL, .cd=NULL};
+    cbData.cb = &SRPProvisionACLCB;
+    ACLData_t *aclData = (ACLData_t *) OICMalloc(sizeof(ACLData_t));
+    if (aclData == NULL)
+    {
+        OICFree(secPayload);
+        OC_LOG(ERROR, TAG, "Unable to allocate memory");
+        return OC_STACK_NO_MEMORY;
+    }
+    memset(aclData, 0x00, sizeof(ACLData_t));
+    aclData->deviceInfo = selectedDeviceInfo;
+    aclData->resultCallback = resultCallback;
+    aclData->numOfResults=0;
+    aclData->ctx = ctx;
+    // call to provision ACL to device1.
+    int noOfRiCalls = 1;
+    aclData->resArr = (OCProvisionResult_t*)OICMalloc(sizeof(OCProvisionResult_t)*noOfRiCalls);
+    if (aclData->resArr == NULL)
+    {
+        OICFree(secPayload);
+        OC_LOG(ERROR, TAG, "Unable to allocate memory");
+        return OC_STACK_NO_MEMORY;
+    }
+    memset(aclData->resArr, 0x00, sizeof(sizeof(OCProvisionResult_t)*noOfRiCalls));
+    cbData.context = (void *)aclData;
+    cbData.cd = NULL;
+    OCMethod method = OC_REST_POST;
+    OCDoHandle handle = NULL;
+    OC_LOG(DEBUG, TAG, "Sending ACL info to resource server");
+    // TODO replace CT_ADAPTER_IP with value from discovery
+
+    OCStackResult ret = OCDoResource(&handle, method, uri,
+            &selectedDeviceInfo->endpoint, (OCPayload*)secPayload,
+            CT_ADAPTER_IP, OC_HIGH_QOS, &cbData, NULL, 0);
+    if (ret != OC_STACK_OK)
+    {
+        OICFree(aclData->resArr);
+        OICFree(aclData);
+    }
+    VERIFY_SUCCESS(TAG, (OC_STACK_OK == ret), ERROR, OC_STACK_ERROR);
+    return OC_STACK_OK;
+}
index e6b59ed..8a95db0 100644 (file)
@@ -35,17 +35,19 @@ sptest_env.PrependUnique(CPPPATH = [
                '../../include',
                '../../../../../extlibs/tinydtls',
                '../include/internal',
+               '../include/oxm',
                '../../../logger/include',
                '../../../stack/include',
                '../../../../oc_logger/include',
                '../../../../../extlibs/gtest/gtest-1.7.0/include',
-               '../include'
+               '../include',
+               '../include/internal'
                ])
 sptest_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
 sptest_env.AppendUnique(LIBS = ['-lpthread'])
 sptest_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
 sptest_env.AppendUnique(LIBPATH = [src_dir + '/extlibs/gtest/gtest-1.7.0/lib/.libs'])
-sptest_env.PrependUnique(LIBS = [   'ocspapi',
+sptest_env.PrependUnique(LIBS = [   'ocpmapi',
                                     'ocsrm',
                                     'octbstack',
                                     'oc_logger',
@@ -63,7 +65,7 @@ if not env.get('RELEASE'):
 ######################################################################
 # Source files and Targets
 ######################################################################
-unittest = sptest_env.Program('unittest', ['provisioningmanager.cpp'])
+unittest = sptest_env.Program('unittest', ['pmutilitytest.cpp', 'otmunittest.cpp', 'secureresourceprovider.cpp'])
 
 Alias("test", [unittest])
 
diff --git a/resource/csdk/security/provisioning/unittest/otmunittest.cpp b/resource/csdk/security/provisioning/unittest/otmunittest.cpp
new file mode 100644 (file)
index 0000000..9f69a11
--- /dev/null
@@ -0,0 +1,100 @@
+/* *****************************************************************
+ *
+ * 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 "gtest/gtest.h"
+#include "oxmjustworks.h"
+#include "oxmrandompin.h"
+#include "ownershiptransfermanager.h"
+#include "ocstack.h"
+#include "utlist.h"
+
+using namespace std;
+
+TEST(JustWorksOxMTest, NullParam)
+{
+
+    OTMContext_t* otmCtx = NULL;
+    OCStackResult res = OC_STACK_ERROR;
+    char* payloadRes;
+
+    //LoadSecretJustWorksCallback always returns OC_STACK_OK.
+    res = LoadSecretJustWorksCallback(otmCtx);
+    EXPECT_TRUE(OC_STACK_OK == res);
+
+    res = CreateSecureSessionJustWorksCallback(otmCtx);
+    EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+    payloadRes = CreateJustWorksSelectOxmPayload(otmCtx);
+    EXPECT_TRUE(NULL == payloadRes);
+
+    payloadRes = CreateJustWorksOwnerTransferPayload(otmCtx);
+    EXPECT_TRUE(NULL == payloadRes);
+
+    OTMContext_t otmCtx2;
+    otmCtx2.selectedDeviceInfo = NULL;
+
+    //LoadSecretJustWorksCallback always returns OC_STACK_OK.
+    res = LoadSecretJustWorksCallback(&otmCtx2);
+    EXPECT_TRUE(OC_STACK_OK == res);
+
+    res = CreateSecureSessionJustWorksCallback(&otmCtx2);
+    EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+    payloadRes = CreateJustWorksSelectOxmPayload(&otmCtx2);
+    EXPECT_TRUE(NULL == payloadRes);
+
+    payloadRes = CreateJustWorksOwnerTransferPayload(&otmCtx2);
+    EXPECT_TRUE(NULL == payloadRes);
+}
+
+TEST(RandomPinOxMTest, NullParam)
+{
+    OTMContext_t* otmCtx = NULL;
+    OCStackResult res = OC_STACK_ERROR;
+    char* payloadRes;
+
+    //LoadSecretJustWorksCallback always returns OC_STACK_OK.
+    res = InputPinCodeCallback(otmCtx);
+    EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+    res = CreateSecureSessionRandomPinCallbak(otmCtx);
+    EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+    payloadRes = CreatePinBasedSelectOxmPayload(otmCtx);
+    EXPECT_TRUE(NULL == payloadRes);
+
+    payloadRes = CreatePinBasedOwnerTransferPayload(otmCtx);
+    EXPECT_TRUE(NULL == payloadRes);
+
+    OTMContext_t otmCtx2;
+    otmCtx2.selectedDeviceInfo = NULL;
+
+    //LoadSecretJustWorksCallback always returns OC_STACK_OK.
+    res = InputPinCodeCallback(&otmCtx2);
+    EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+    res = CreateSecureSessionRandomPinCallbak(&otmCtx2);
+    EXPECT_TRUE(OC_STACK_INVALID_PARAM == res);
+
+    payloadRes = CreatePinBasedSelectOxmPayload(&otmCtx2);
+    EXPECT_TRUE(NULL == payloadRes);
+
+    payloadRes = CreatePinBasedOwnerTransferPayload(&otmCtx2);
+    EXPECT_TRUE(NULL == payloadRes);
+}
diff --git a/resource/csdk/security/provisioning/unittest/pmutilitytest.cpp b/resource/csdk/security/provisioning/unittest/pmutilitytest.cpp
new file mode 100644 (file)
index 0000000..378c606
--- /dev/null
@@ -0,0 +1,90 @@
+/* *****************************************************************
+ *
+ * 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 "gtest/gtest.h"
+#include "pmutility.h"
+#include "ocstack.h"
+#include "utlist.h"
+
+using namespace std;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern OCStackResult AddDevice(OCProvisionDev_t **ppList, const char* addr, const uint16_t port,
+                               OCTransportAdapter adapter, OicSecDoxm_t *doxm);
+#ifdef __cplusplus
+}
+#endif
+
+OCProvisionDev_t* gList = NULL;
+
+// List add Tests
+TEST(ProvisionListTest, Addition)
+{
+    OCProvisionDev_t* el = NULL;
+    OCStackResult res = OC_STACK_ERROR;
+    OicSecDoxm_t* pDoxm = NULL;
+    int cnt =0;
+
+    // The first addition
+    res = AddDevice(&gList, "10.20.30.40", 5684, OC_DEFAULT_ADAPTER, pDoxm);
+    EXPECT_TRUE(OC_STACK_OK == res);
+    EXPECT_TRUE(NULL != gList);
+
+    LL_FOREACH(gList,el){ ++cnt; };
+    //LL_COUNT(gList, el, cnt);
+    EXPECT_TRUE(1 == cnt);
+
+    // Same node must not be inserted
+    res = AddDevice(&gList, "10.20.30.40", 5684, OC_ADAPTER_IP, pDoxm);
+    EXPECT_TRUE(OC_STACK_OK == res);
+    EXPECT_TRUE(NULL != gList);
+
+    cnt = 0;
+    LL_FOREACH(gList,el){ ++cnt; };
+    //LL_COUNT(gList, el, cnt);
+    EXPECT_TRUE(1 == cnt);
+
+    // Differnet node must be inserted
+    res = AddDevice(&gList, "110.120.130.140", 6789, OC_DEFAULT_ADAPTER, pDoxm);
+    EXPECT_TRUE(OC_STACK_OK == res);
+    EXPECT_TRUE(NULL != gList);
+
+    cnt = 0;
+    LL_FOREACH(gList,el){ ++cnt; };
+    //LL_COUNT(gList, el, cnt);
+    EXPECT_TRUE(2 == cnt);
+}
+
+// List Delete Tests
+TEST(ProvisionListTest, Deletion)
+{
+    OCProvisionDev_t* el = NULL;
+    int cnt =0;
+
+    // Delete whole
+    DeleteDeviceList(&gList);
+    gList = NULL;
+
+    LL_FOREACH(gList,el){ ++cnt; };
+    //LL_COUNT(gList, el, cnt);
+    EXPECT_TRUE(0 == cnt);
+}
\ No newline at end of file
diff --git a/resource/csdk/security/provisioning/unittest/provisioningmanager.cpp b/resource/csdk/security/provisioning/unittest/provisioningmanager.cpp
deleted file mode 100644 (file)
index 11f7dc2..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/* *****************************************************************
- *
- * 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 "gtest/gtest.h"
-
-#include "provisioningmanager.h"
-
-
-static OicSecAcl_t acl;
-SPTargetDeviceInfo_t list;
-SPTargetDeviceInfo_t *ptr = &list;
-
-TEST(SPProvisioningDiscoveryTest, NotNullList)
-{
-    EXPECT_EQ(SP_RESULT_INVALID_PARAM, SPProvisioningDiscovery(0, &ptr));
-}
-
-TEST(SPInitProvisionContextTest, NullDeviceInfo)
-{
-    EXPECT_EQ(SP_RESULT_INVALID_PARAM, SPInitProvisionContext(0, NULL));
-}
-
-TEST(SPProvisionACLTest, NullDeviceInfo)
-{
-    EXPECT_EQ(SP_RESULT_INVALID_PARAM, SPProvisionACL(0, NULL, &acl));
-}
-
-TEST(SPFinalizeProvisioningTest, NullDeviceInfo)
-{
-    EXPECT_EQ(SP_RESULT_INVALID_PARAM, SPFinalizeProvisioning(0, NULL));
-}
-
-TEST(SPTerminateProvisioningTest, ValidCase)
-{
-    EXPECT_EQ(SP_RESULT_SUCCESS, SPTerminateProvisioning());
-}
-
-TEST(SPProvisionCredentialsTest, NullList)
-{
-    EXPECT_EQ(SP_RESULT_INVALID_PARAM, SPProvisionCredentials(0, 0, NULL));
-}
diff --git a/resource/csdk/security/provisioning/unittest/secureresourceprovider.cpp b/resource/csdk/security/provisioning/unittest/secureresourceprovider.cpp
new file mode 100644 (file)
index 0000000..6c8e3d6
--- /dev/null
@@ -0,0 +1,72 @@
+/* *****************************************************************
+ *
+ * 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 "gtest/gtest.h"
+#include "secureresourceprovider.h"
+
+
+static OicSecAcl_t acl;
+static OCProvisionDev_t pDev1;
+static OCProvisionDev_t pDev2;
+static OicSecCredType_t credType;
+
+static void provisioningCB (void* UNUSED1, int UNUSED2, OCProvisionResult_t *UNUSED3, bool UNUSED4)
+{
+    //dummy callback
+    (void) UNUSED1;
+    (void) UNUSED2;
+    (void) UNUSED3;
+    (void) UNUSED4;
+}
+
+TEST(SRPProvisionACLTest, NullDeviceInfo)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPProvisionACL(NULL, NULL, &acl, &provisioningCB));
+}
+
+TEST(SRPProvisionACLTest, NullCallback)
+{
+    EXPECT_EQ(OC_STACK_INVALID_CALLBACK, SRPProvisionACL(NULL, &pDev1, &acl, NULL));
+}
+
+TEST(SRPProvisionACLTest, NullACL)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPProvisionACL(NULL, &pDev1, NULL, &provisioningCB));
+}
+
+TEST(SRPProvisionCredentialsTest, NullDevice1)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPProvisionCredentials(NULL, credType,
+                                                              OWNER_PSK_LENGTH_128, NULL,
+                                                              &pDev2, &provisioningCB));
+}
+
+TEST(SRPProvisionCredentialsTest, NullCallback)
+{
+    EXPECT_EQ(OC_STACK_INVALID_CALLBACK, SRPProvisionCredentials(NULL, credType,
+                                                                 OWNER_PSK_LENGTH_128,
+                                                                 &pDev1, &pDev2, NULL));
+}
+
+TEST(SRPProvisionCredentialsTest, InvalidKeySize)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, SRPProvisionCredentials(NULL, credType,
+                                                                0, &pDev1, &pDev2,
+                                                                &provisioningCB));
+}
\ No newline at end of file
index bc18c20..1b858f8 100644 (file)
@@ -23,6 +23,7 @@
 #include "ocstack.h"
 #include "logger.h"
 #include "oic_malloc.h"
+#include "oic_string.h"
 #include "cJSON.h"
 #include "base64.h"
 #include "resourcemanager.h"
 #include "srmresourcestrings.h"
 #include "doxmresource.h"
 #include "srmutility.h"
+#include "ocserverrequest.h"
 #include <stdlib.h>
+#ifdef WITH_ARDUINO
 #include <string.h>
+#else
+#include <strings.h>
+#endif
 
 #define TAG  PCF("SRM-ACL")
 
-OicSecAcl_t        *gAcl = NULL;
+OicSecAcl_t               *gAcl = NULL;
 static OCResourceHandle    gAclHandle = NULL;
 
+/**
+ * This function frees OicSecAcl_t object's fields and object itself.
+ */
+static void FreeACE(OicSecAcl_t *ace)
+{
+    size_t i;
+    if(NULL == ace)
+    {
+        OC_LOG (INFO, TAG, PCF("Invalid Parameter"));
+        return;
+    }
+
+    // Clean Resources
+    for (i = 0; i < ace->resourcesLen; i++)
+    {
+        OICFree(ace->resources[i]);
+    }
+    OICFree(ace->resources);
+
+    //Clean Period & Recurrence
+    for(i = 0; i < ace->prdRecrLen; i++)
+    {
+        OICFree(ace->periods[i]);
+        OICFree(ace->recurrences[i]);
+    }
+    OICFree(ace->periods);
+    OICFree(ace->recurrences);
+
+    // Clean Owners
+    OICFree(ace->owners);
+
+    // Clean ACL node itself
+    OICFree(ace);
+}
+
 void DeleteACLList(OicSecAcl_t* acl)
 {
     if (acl)
@@ -49,19 +90,7 @@ void DeleteACLList(OicSecAcl_t* acl)
         LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
         {
             LL_DELETE(acl, aclTmp1);
-
-            // Clean Resources
-            for (size_t i = 0; i < aclTmp1->resourcesLen; i++)
-            {
-                OICFree(aclTmp1->resources[i]);
-            }
-            OICFree(aclTmp1->resources);
-
-            // Clean Owners
-            OICFree(aclTmp1->owners);
-
-            // Clean ACL node itself
-            OICFree(aclTmp1);
+            FreeACE(aclTmp1);
         }
     }
 }
@@ -122,6 +151,34 @@ char * BinToAclJSON(const OicSecAcl_t * acl)
             // Permissions -- Mandatory
             cJSON_AddNumberToObject (jsonAcl, OIC_JSON_PERMISSION_NAME, acl->permission);
 
+            //Period & Recurrence -- Not Mandatory
+            if(0 != acl->prdRecrLen)
+            {
+                cJSON *jsonPeriodArray = NULL;
+                cJSON_AddItemToObject (jsonAcl, OIC_JSON_PERIODS_NAME,
+                        jsonPeriodArray = cJSON_CreateArray());
+                VERIFY_NON_NULL(TAG, jsonPeriodArray, ERROR);
+                for (size_t i = 0; i < acl->prdRecrLen; i++)
+                {
+                    cJSON_AddItemToArray (jsonPeriodArray,
+                            cJSON_CreateString(acl->periods[i]));
+                }
+            }
+
+            //Recurrence -- Not Mandatory
+            if(0 != acl->prdRecrLen && acl->recurrences)
+            {
+                cJSON *jsonRecurArray  = NULL;
+                cJSON_AddItemToObject (jsonAcl, OIC_JSON_RECURRENCES_NAME,
+                        jsonRecurArray = cJSON_CreateArray());
+                VERIFY_NON_NULL(TAG, jsonRecurArray, ERROR);
+                for (size_t i = 0; i < acl->prdRecrLen; i++)
+                {
+                    cJSON_AddItemToArray (jsonRecurArray,
+                            cJSON_CreateString(acl->recurrences[i]));
+                }
+            }
+
             // Owners -- Mandatory
             cJSON *jsonOwnrArray = NULL;
             cJSON_AddItemToObject (jsonAcl, OIC_JSON_OWNERS_NAME, jsonOwnrArray = cJSON_CreateArray());
@@ -228,15 +285,71 @@ OicSecAcl_t * JSONToAclBin(const char * jsonStr)
                 jsonObjLen = strlen(jsonRsrc->valuestring) + 1;
                 acl->resources[idxx] = (char*)OICMalloc(jsonObjLen);
                 VERIFY_NON_NULL(TAG, (acl->resources[idxx]), ERROR);
-                strncpy(acl->resources[idxx], jsonRsrc->valuestring, jsonObjLen);
+                OICStrcpy(acl->resources[idxx], jsonObjLen, jsonRsrc->valuestring);
             } while ( ++idxx < acl->resourcesLen);
 
             // Permissions -- Mandatory
-            jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_PERMISSION_NAME);
+            jsonObj = cJSON_GetObjectItem(jsonAcl,
+                                OIC_JSON_PERMISSION_NAME);
             VERIFY_NON_NULL(TAG, jsonObj, ERROR);
             VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
             acl->permission = jsonObj->valueint;
 
+            //Period -- Not Mandatory
+            cJSON *jsonPeriodObj = cJSON_GetObjectItem(jsonAcl,
+                    OIC_JSON_PERIODS_NAME);
+            if(jsonPeriodObj)
+            {
+                VERIFY_SUCCESS(TAG, cJSON_Array == jsonPeriodObj->type,
+                               ERROR);
+                acl->prdRecrLen = cJSON_GetArraySize(jsonPeriodObj);
+                if(acl->prdRecrLen > 0)
+                {
+                    acl->periods = (char**)OICCalloc(acl->prdRecrLen,
+                                    sizeof(char*));
+                    VERIFY_NON_NULL(TAG, acl->periods, ERROR);
+
+                    cJSON *jsonPeriod = NULL;
+                    for(size_t i = 0; i < acl->prdRecrLen; i++)
+                    {
+                        jsonPeriod = cJSON_GetArrayItem(jsonPeriodObj, i);
+                        VERIFY_NON_NULL(TAG, jsonPeriod, ERROR);
+
+                        jsonObjLen = strlen(jsonPeriod->valuestring) + 1;
+                        acl->periods[i] = (char*)OICMalloc(jsonObjLen);
+                        VERIFY_NON_NULL(TAG, acl->periods[i], ERROR);
+                        OICStrcpy(acl->periods[i], jsonObjLen,
+                                  jsonPeriod->valuestring);
+                    }
+                }
+            }
+
+            //Recurrence -- Not mandatory
+            cJSON *jsonRecurObj = cJSON_GetObjectItem(jsonAcl,
+                                        OIC_JSON_RECURRENCES_NAME);
+            if(jsonRecurObj)
+            {
+                VERIFY_SUCCESS(TAG, cJSON_Array == jsonRecurObj->type,
+                               ERROR);
+                if(acl->prdRecrLen > 0)
+                {
+                    acl->recurrences = (char**)OICCalloc(acl->prdRecrLen,
+                                             sizeof(char*));
+                    VERIFY_NON_NULL(TAG, acl->recurrences, ERROR);
+
+                    cJSON *jsonRecur = NULL;
+                    for(size_t i = 0; i < acl->prdRecrLen; i++)
+                    {
+                        jsonRecur = cJSON_GetArrayItem(jsonRecurObj, i);
+                        jsonObjLen = strlen(jsonRecur->valuestring) + 1;
+                        acl->recurrences[i] = (char*)OICMalloc(jsonObjLen);
+                        VERIFY_NON_NULL(TAG, acl->recurrences[i], ERROR);
+                        OICStrcpy(acl->recurrences[i], jsonObjLen,
+                                  jsonRecur->valuestring);
+                    }
+                }
+            }
+
             // Owners -- Mandatory
             jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_OWNERS_NAME);
             VERIFY_NON_NULL(TAG, jsonObj, ERROR);
@@ -279,6 +392,119 @@ exit:
     return headAcl;
 }
 
+static bool UpdatePersistentStorage(const OicSecAcl_t *acl)
+{
+    // Convert ACL data into JSON for update to persistent storage
+    char *jsonStr = BinToAclJSON(acl);
+    if (jsonStr)
+    {
+        cJSON *jsonAcl = cJSON_Parse(jsonStr);
+        OICFree(jsonStr);
+
+        if ((jsonAcl) && (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl)))
+        {
+            return true;
+        }
+        cJSON_Delete(jsonAcl);
+    }
+    return false;
+}
+/*
+ * This method removes ACE for the subject and resource from the ACL
+ *
+ * @param subject  - subject of the ACE
+ * @param resource - resource of the ACE
+ *
+ * @return
+ *     OC_STACK_RESOURCE_DELETED on success
+ *     OC_STACK_NO_RESOURC on failure to find the appropriate ACE
+ *     OC_STACK_INVALID_PARAM on invalid parameter
+ */
+static OCStackResult RemoveACE(const OicUuid_t * subject,
+                               const char * resource)
+{
+    OC_LOG(INFO, TAG, PCF("IN RemoveACE"));
+
+    OicSecAcl_t *acl = NULL;
+    OicSecAcl_t *tempAcl = NULL;
+    bool deleteFlag = false;
+    OCStackResult ret = OC_STACK_NO_RESOURCE;
+
+    if(memcmp(subject->id, &WILDCARD_SUBJECT_ID, sizeof(subject->id)) == 0)
+    {
+        OC_LOG_V (INFO, TAG, PCF("%s received invalid parameter"), __func__ );
+        return  OC_STACK_INVALID_PARAM;
+    }
+
+    //If resource is NULL then delete all the ACE for the subject.
+    if(NULL == resource)
+    {
+        LL_FOREACH_SAFE(gAcl, acl, tempAcl)
+        {
+            if(memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
+            {
+                LL_DELETE(gAcl, acl);
+                FreeACE(acl);
+                deleteFlag = true;
+            }
+        }
+    }
+    else
+    {
+        //Looping through ACL to find the right ACE to delete. If the required resource is the only
+        //resource in the ACE for the subject then delete the whole ACE. If there are more resources
+        //than the required resource in the ACE, for the subject then just delete the resource from
+        //the resource array
+        LL_FOREACH_SAFE(gAcl, acl, tempAcl)
+        {
+            if(memcmp(acl->subject.id, subject->id, sizeof(subject->id)) == 0)
+            {
+                if(1 == acl->resourcesLen && strcmp(acl->resources[0],  resource) == 0)
+                {
+                    LL_DELETE(gAcl, acl);
+                    FreeACE(acl);
+                    deleteFlag = true;
+                    break;
+                }
+                else
+                {
+                    int resPos = -1;
+                    size_t i;
+                    for(i = 0; i < acl->resourcesLen; i++)
+                    {
+                        if(strcmp(acl->resources[i],  resource) == 0)
+                        {
+                            resPos = i;
+                            break;
+                        }
+                    }
+                    if((0 <= resPos))
+                    {
+                        OICFree(acl->resources[resPos]);
+                        acl->resources[resPos] = NULL;
+                        acl->resourcesLen -= 1;
+                        for(i = resPos; i < acl->resourcesLen; i++)
+                        {
+                            acl->resources[i] = acl->resources[i+1];
+                        }
+                        deleteFlag = true;
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    if(deleteFlag)
+    {
+        if(UpdatePersistentStorage(gAcl))
+        {
+            ret = OC_STACK_RESOURCE_DELETED;
+        }
+    }
+    return ret;
+}
+
 static OCEntityHandlerResult HandleACLGetRequest (const OCEntityHandlerRequest * ehRequest)
 {
     // Convert ACL data into JSON for transmission
@@ -311,19 +537,9 @@ static OCEntityHandlerResult HandleACLPostRequest (const OCEntityHandlerRequest
         // Append the new ACL to existing ACL
         LL_APPEND(gAcl, newAcl);
 
-        // Convert ACL data into JSON for update to persistent storage
-        char *jsonStr = BinToAclJSON(gAcl);
-        if (jsonStr)
+        if(UpdatePersistentStorage(gAcl))
         {
-            cJSON *jsonAcl = cJSON_Parse(jsonStr);
-            OICFree(jsonStr);
-
-            if ((jsonAcl) &&
-                (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_ACL_NAME, jsonAcl)))
-            {
-                ehRet = OC_EH_RESOURCE_CREATED;
-            }
-            cJSON_Delete(jsonAcl);
+            ehRet = OC_EH_RESOURCE_CREATED;
         }
     }
 
@@ -334,6 +550,57 @@ static OCEntityHandlerResult HandleACLPostRequest (const OCEntityHandlerRequest
     return ehRet;
 }
 
+static OCEntityHandlerResult HandleACLDeleteRequest(const OCEntityHandlerRequest *ehRequest)
+{
+    OC_LOG (INFO, TAG, PCF("Processing ACLDeleteRequest"));
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+    if(NULL == ehRequest->query)
+    {
+        return ehRet;
+    }
+    OicParseQueryIter_t parseIter = {.attrPos=NULL};
+    OicUuid_t subject = {.id={0}};
+    char * resource = NULL;
+
+    //Parsing REST query to get subject & resource
+    ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
+
+    while(GetNextQuery(&parseIter))
+    {
+        if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME, parseIter.attrLen) == 0)
+        {
+            unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
+            uint32_t outLen = 0;
+            B64Result b64Ret = B64_OK;
+
+           b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen, base64Buff,
+                               sizeof(base64Buff), &outLen);
+
+           VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(subject.id)), ERROR);
+           memcpy(subject.id, base64Buff, outLen);
+        }
+        if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_RESOURCES_NAME, parseIter.attrLen) == 0)
+        {
+            resource = (char *)OICMalloc(parseIter.valLen);
+            VERIFY_NON_NULL(TAG, resource, ERROR);
+            OICStrcpy(resource, sizeof(resource), (char *)parseIter.valPos);
+        }
+    }
+
+    if(OC_STACK_RESOURCE_DELETED == RemoveACE(&subject, resource))
+    {
+        ehRet = OC_EH_RESOURCE_DELETED;
+    }
+    OICFree(resource);
+
+    // Send payload to request originator
+    SendSRMResponse(ehRequest, ehRet, NULL);
+
+exit:
+    return ehRet;
+}
+
 /*
  * This internal method is the entity handler for ACL resources and
  * will handle REST request (GET/PUT/POST/DEL) for them.
@@ -342,6 +609,7 @@ OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag,
                                         OCEntityHandlerRequest * ehRequest,
                                         void* callbackParameter)
 {
+    OC_LOG(INFO, TAG, PCF("Received request ACLEntityHandler"));
     (void)callbackParameter;
     OCEntityHandlerResult ehRet = OC_EH_ERROR;
 
@@ -364,6 +632,10 @@ OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag,
                 ehRet = HandleACLPostRequest(ehRequest);
                 break;
 
+            case OC_REST_DELETE:
+                ehRet = HandleACLDeleteRequest(ehRequest);
+                break;
+
             default:
                 ehRet = OC_EH_ERROR;
                 SendSRMResponse(ehRequest, ehRet, NULL);
@@ -450,11 +722,11 @@ OCStackResult  GetDefaultACL(OicSecAcl_t** defaultAcl)
         size_t len = strlen(rsrcs[i]) + 1;
         acl->resources[i] = (char*)OICMalloc(len * sizeof(char));
         VERIFY_NON_NULL(TAG, (acl->resources[i]), ERROR);
-        strncpy(acl->resources[i], rsrcs[i], len);
+        OICStrcpy(acl->resources[i], len, rsrcs[i]);
     }
 
     acl->permission = PERMISSION_READ;
-    acl->periodsLen = 0;
+    acl->prdRecrLen = 0;
     acl->periods = NULL;
     acl->recurrences = NULL;
 
diff --git a/resource/csdk/security/src/amaclresource.c b/resource/csdk/security/src/amaclresource.c
new file mode 100644 (file)
index 0000000..5b80fbe
--- /dev/null
@@ -0,0 +1,403 @@
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include <stdlib.h>
+#include <string.h>
+#include "ocstack.h"
+#include "logger.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "cJSON.h"
+#include "base64.h"
+#include "resourcemanager.h"
+#include "psinterface.h"
+#include "utlist.h"
+#include "srmresourcestrings.h"
+#include "amaclresource.h"
+#include "srmutility.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define TAG  PCF("SRM-AMACL")
+
+OicSecAmacl_t *gAmacl = NULL;
+static OCResourceHandle gAmaclHandle = NULL;
+
+void DeleteAmaclList(OicSecAmacl_t* amacl)
+{
+    if (amacl)
+    {
+        OicSecAmacl_t *amaclTmp1 = NULL, *amaclTmp2 = NULL;
+        LL_FOREACH_SAFE(amacl, amaclTmp1, amaclTmp2)
+        {
+            unsigned int i = 0;
+
+            LL_DELETE(amacl, amaclTmp1);
+
+            // Clean Resources
+            for (i = 0; i < amaclTmp1->resourcesLen; i++)
+            {
+                OICFree(amaclTmp1->resources[i]);
+            }
+            OICFree(amaclTmp1->resources);
+
+            // Clean Amss
+            OICFree(amaclTmp1->amss);
+
+            // Clean Owners
+            OICFree(amaclTmp1->owners);
+
+            // Clean Amacl node itself
+            OICFree(amaclTmp1);
+        }
+    }
+}
+
+/*
+ * This internal method converts AMACL data into JSON format.
+ *
+ * Note: Caller needs to invoke 'free' when finished using the return string.
+ */
+char * BinToAmaclJSON(const OicSecAmacl_t * amacl)
+{
+    cJSON *jsonRoot = NULL;
+    char *jsonStr = NULL;
+
+    if (amacl)
+    {
+        jsonRoot = cJSON_CreateObject();
+        VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+        cJSON *jsonAmaclArray = NULL;
+        cJSON_AddItemToObject (jsonRoot, OIC_JSON_AMACL_NAME, jsonAmaclArray = cJSON_CreateArray());
+        VERIFY_NON_NULL(TAG, jsonAmaclArray, ERROR);
+
+        while(amacl)
+        {
+            char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
+            uint32_t outLen = 0;
+            B64Result b64Ret = B64_OK;
+
+            cJSON *jsonAmacl = cJSON_CreateObject();
+
+            // Resources -- Mandatory
+            cJSON *jsonRsrcArray = NULL;
+            cJSON_AddItemToObject(jsonAmacl, OIC_JSON_RESOURCES_NAME, jsonRsrcArray =
+                    cJSON_CreateArray());
+            VERIFY_NON_NULL(TAG, jsonRsrcArray, ERROR);
+            for (unsigned int i = 0; i < amacl->resourcesLen; i++)
+            {
+                cJSON_AddItemToArray(jsonRsrcArray, cJSON_CreateString(amacl->resources[i]));
+            }
+
+            // Amss -- Mandatory
+            cJSON *jsonAmsArray = NULL;
+            cJSON_AddItemToObject(jsonAmacl, OIC_JSON_AMSS_NAME, jsonAmsArray =
+                    cJSON_CreateArray());
+            VERIFY_NON_NULL(TAG, jsonAmsArray, ERROR);
+            for (unsigned int i = 0; i < amacl->amssLen; i++)
+            {
+                outLen = 0;
+
+                b64Ret = b64Encode(amacl->amss[i].id, sizeof(((OicUuid_t*) 0)->id), base64Buff,
+                        sizeof(base64Buff), &outLen);
+                VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+
+                cJSON_AddItemToArray(jsonAmsArray, cJSON_CreateString(base64Buff));
+            }
+
+            // Owners -- Mandatory
+            cJSON *jsonOwnrArray = NULL;
+            cJSON_AddItemToObject(jsonAmacl, OIC_JSON_OWNERS_NAME, jsonOwnrArray =
+                    cJSON_CreateArray());
+            VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
+            for (unsigned int i = 0; i < amacl->ownersLen; i++)
+            {
+                outLen = 0;
+
+                b64Ret = b64Encode(amacl->owners[i].id, sizeof(((OicUuid_t*) 0)->id), base64Buff,
+                        sizeof(base64Buff), &outLen);
+                VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+
+                cJSON_AddItemToArray(jsonOwnrArray, cJSON_CreateString(base64Buff));
+            }
+
+            // Attach current amacl node to Amacl Array
+            cJSON_AddItemToArray(jsonAmaclArray, jsonAmacl);
+            amacl = amacl->next;
+        }
+
+        jsonStr = cJSON_PrintUnformatted(jsonRoot);
+    }
+
+exit:
+    if (jsonRoot)
+    {
+        cJSON_Delete(jsonRoot);
+    }
+    return jsonStr;
+}
+
+
+
+
+/*
+ * This internal method converts JSON AMACL into binary AMACL.
+ */
+OicSecAmacl_t * JSONToAmaclBin(const char * jsonStr)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    OicSecAmacl_t * headAmacl = NULL;
+    OicSecAmacl_t * prevAmacl = NULL;
+    cJSON *jsonRoot = NULL;
+    cJSON *jsonAmaclArray = NULL;
+
+    VERIFY_NON_NULL(TAG, jsonStr, ERROR);
+
+    jsonRoot = cJSON_Parse(jsonStr);
+    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+    jsonAmaclArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_AMACL_NAME);
+    VERIFY_NON_NULL(TAG, jsonAmaclArray, INFO);
+
+    if (cJSON_Array == jsonAmaclArray->type)
+    {
+        int numAmacl = cJSON_GetArraySize(jsonAmaclArray);
+        int idx = 0;
+
+        VERIFY_SUCCESS(TAG, numAmacl > 0, INFO);
+        do
+        {
+            cJSON *jsonAmacl = cJSON_GetArrayItem(jsonAmaclArray, idx);
+            VERIFY_NON_NULL(TAG, jsonAmacl, ERROR);
+
+            OicSecAmacl_t *amacl = (OicSecAmacl_t*)OICCalloc(1, sizeof(OicSecAmacl_t));
+            VERIFY_NON_NULL(TAG, amacl, ERROR);
+
+            headAmacl = (headAmacl) ? headAmacl : amacl;
+            if (prevAmacl)
+            {
+                prevAmacl->next = amacl;
+            }
+
+            size_t jsonObjLen = 0;
+            cJSON *jsonObj = NULL;
+
+            // Resources -- Mandatory
+            jsonObj = cJSON_GetObjectItem(jsonAmacl, OIC_JSON_RESOURCES_NAME);
+            VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+            VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
+
+            amacl->resourcesLen = cJSON_GetArraySize(jsonObj);
+            VERIFY_SUCCESS(TAG, amacl->resourcesLen > 0, ERROR);
+            amacl->resources = (char**)OICCalloc(amacl->resourcesLen, sizeof(char*));
+            VERIFY_NON_NULL(TAG, (amacl->resources), ERROR);
+
+            size_t idxx = 0;
+            do
+            {
+                cJSON *jsonRsrc = cJSON_GetArrayItem(jsonObj, idxx);
+                VERIFY_NON_NULL(TAG, jsonRsrc, ERROR);
+
+                jsonObjLen = strlen(jsonRsrc->valuestring) + 1;
+                amacl->resources[idxx] = (char*)OICMalloc(jsonObjLen);
+                VERIFY_NON_NULL(TAG, (amacl->resources[idxx]), ERROR);
+                OICStrcpy(amacl->resources[idxx], jsonObjLen, jsonRsrc->valuestring);
+            } while ( ++idxx < amacl->resourcesLen);
+
+            // Amss -- Mandatory
+            VERIFY_SUCCESS( TAG, OC_STACK_OK == AddUuidArray(jsonAmacl, OIC_JSON_AMSS_NAME,
+                               &(amacl->amssLen), &(amacl->amss)), ERROR);
+
+            // Owners -- Mandatory
+            VERIFY_SUCCESS( TAG, OC_STACK_OK == AddUuidArray(jsonAmacl, OIC_JSON_OWNERS_NAME,
+                               &(amacl->ownersLen), &(amacl->owners)), ERROR);
+
+            prevAmacl = amacl;
+        } while( ++idx < numAmacl);
+    }
+
+    ret = OC_STACK_OK;
+
+exit:
+    cJSON_Delete(jsonRoot);
+    if (OC_STACK_OK != ret)
+    {
+        DeleteAmaclList(headAmacl);
+        headAmacl = NULL;
+    }
+    return headAmacl;
+}
+
+static OCEntityHandlerResult HandleAmaclGetRequest (const OCEntityHandlerRequest * ehRequest)
+{
+    // Convert Amacl data into JSON for transmission
+    char* jsonStr = BinToAmaclJSON(gAmacl);
+
+    OCEntityHandlerResult ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
+
+    // Send response payload to request originator
+    SendSRMResponse(ehRequest, ehRet, jsonStr);
+
+    OICFree(jsonStr);
+
+    OC_LOG_V (INFO, TAG, PCF("%s RetVal %d"), __func__ , ehRet);
+    return ehRet;
+}
+
+static OCEntityHandlerResult HandleAmaclPostRequest (const OCEntityHandlerRequest * ehRequest)
+{
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+    // Convert JSON Amacl data into binary. This will also validate the Amacl data received.
+    OicSecAmacl_t* newAmacl = JSONToAmaclBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
+
+    if (newAmacl)
+    {
+        // Append the new Amacl to existing Amacl
+        LL_APPEND(gAmacl, newAmacl);
+
+        // Convert Amacl data into JSON for update to persistent storage
+        char *jsonStr = BinToAmaclJSON(gAmacl);
+        if (jsonStr)
+        {
+            cJSON *jsonAmacl = cJSON_Parse(jsonStr);
+            OICFree(jsonStr);
+
+            if ((jsonAmacl) &&
+                (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_AMACL_NAME, jsonAmacl)))
+            {
+                ehRet = OC_EH_RESOURCE_CREATED;
+            }
+            cJSON_Delete(jsonAmacl);
+        }
+    }
+
+    // Send payload to request originator
+    SendSRMResponse(ehRequest, ehRet, NULL);
+
+    OC_LOG_V (INFO, TAG, PCF("%s RetVal %d"), __func__ , ehRet);
+    return ehRet;
+}
+
+/*
+ * This internal method is the entity handler for Amacl resources and
+ * will handle REST request (GET/PUT/POST/DEL) for them.
+ */
+OCEntityHandlerResult AmaclEntityHandler (OCEntityHandlerFlag flag,
+                                          OCEntityHandlerRequest * ehRequest,
+                                          void* callbackParameter)
+{
+    (void) callbackParameter;
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+    if (!ehRequest)
+    {
+        return ehRet;
+    }
+
+    if (flag & OC_REQUEST_FLAG)
+    {
+        OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+        switch (ehRequest->method)
+        {
+            case OC_REST_GET:
+                ehRet = HandleAmaclGetRequest(ehRequest);
+                break;
+
+            case OC_REST_POST:
+                ehRet = HandleAmaclPostRequest(ehRequest);
+                break;
+
+            default:
+                ehRet = OC_EH_ERROR;
+                SendSRMResponse(ehRequest, ehRet, NULL);
+        }
+    }
+
+    return ehRet;
+}
+
+/*
+ * This internal method is used to create '/oic/sec/amacl' resource.
+ */
+OCStackResult CreateAmaclResource()
+{
+    OCStackResult ret;
+
+    ret = OCCreateResource(&gAmaclHandle,
+                           OIC_RSRC_TYPE_SEC_AMACL,
+                           OIC_MI_DEF,
+                           OIC_RSRC_AMACL_URI,
+                           AmaclEntityHandler,
+                           NULL,
+                           OC_OBSERVABLE);
+
+    if (OC_STACK_OK != ret)
+    {
+        OC_LOG (FATAL, TAG, PCF("Unable to instantiate Amacl resource"));
+        DeInitAmaclResource();
+    }
+    return ret;
+}
+
+/**
+ * Initialize Amacl resource by loading data from persistent storage.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitAmaclResource()
+{
+    OCStackResult ret = OC_STACK_ERROR;
+
+    // Read Amacl resource from PS
+    char* jsonSVRDatabase = GetSVRDatabase();
+
+    if (jsonSVRDatabase)
+    {
+        // Convert JSON Amacl into binary format
+        gAmacl = JSONToAmaclBin(jsonSVRDatabase);
+        OICFree(jsonSVRDatabase);
+    }
+
+    // Instantiate 'oic/sec/amacl' resource
+    ret = CreateAmaclResource();
+
+    if (OC_STACK_OK != ret)
+    {
+        DeInitAmaclResource();
+    }
+    return ret;
+}
+
+/**
+ * Perform cleanup for Amacl resources.
+ *
+ * @retval  none
+ */
+void DeInitAmaclResource()
+{
+    OCDeleteResource(gAmaclHandle);
+    gAmaclHandle = NULL;
+
+    DeleteAmaclList(gAmacl);
+    gAmacl = NULL;
+}
index 30f1b08..901e5d5 100644 (file)
 #include "base64.h"
 #include "srmutility.h"
 #include "cainterface.h"
+#include "pbkdf2.h"
 #include <stdlib.h>
+#ifdef WITH_ARDUINO
 #include <string.h>
+#else
+#include <strings.h>
+#endif
 #include <stdint.h>
 
-
 #define TAG  PCF("SRM-CREDL")
 
+
 static OicSecCred_t        *gCred = NULL;
 static OCResourceHandle    gCredHandle = NULL;
 
-void DeleteCredList(OicSecCred_t* cred)
+/**
+ * This function frees OicSecCred_t object's fields and object itself.
+ */
+static void FreeCred(OicSecCred_t *cred)
 {
-    if (cred)
+    if(NULL == cred)
     {
-        OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
-        LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
-        {
-            LL_DELETE(cred, credTmp1);
-
-            //Note: Need further clarification on roleID data type
+        OC_LOG (INFO, TAG, PCF("Invalid Parameter"));
+        return;
+    }
+    //Note: Need further clarification on roleID data type
 #if 0
-            //Clean roleIds
-            OICFree(credTmp1->roleIds);
+    //Clean roleIds
+    OICFree(cred->roleIds);
 #endif
 
-            //Clean PublicData
-            OICFree(credTmp1->publicData.data);
+    //Clean PublicData
+    OICFree(cred->publicData.data);
 
-            //Clean PrivateData
-            OICFree(credTmp1->privateData.data);
+    //Clean PrivateData
+    OICFree(cred->privateData.data);
 
-            //Clean Period
-            OICFree(credTmp1->period);
+    //Clean Period
+    OICFree(cred->period);
 
-            //Clean Owners
-            OICFree(credTmp1->owners);
+    //Clean Owners
+    OICFree(cred->owners);
 
-            //Clean Cred node itself
-            OICFree(credTmp1);
+    //Clean Cred node itself
+    OICFree(cred);
+}
+
+void DeleteCredList(OicSecCred_t* cred)
+{
+    if (cred)
+    {
+        OicSecCred_t *credTmp1 = NULL, *credTmp2 = NULL;
+        LL_FOREACH_SAFE(cred, credTmp1, credTmp2)
+        {
+            LL_DELETE(cred, credTmp1);
+            FreeCred(credTmp1);
         }
     }
 }
@@ -290,7 +307,7 @@ OicSecCred_t * JSONToCredBin(const char * jsonStr)
             //Owners -- Mandatory
             jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_OWNERS_NAME);
             VERIFY_NON_NULL(TAG, jsonObj, ERROR);
-            VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR)
+            VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
             cred->ownersLen = cJSON_GetArraySize(jsonObj);
             VERIFY_SUCCESS(TAG, cred->ownersLen > 0, ERROR);
             cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
@@ -396,7 +413,35 @@ exit:
     return cred;
 }
 
-/*
+static bool UpdatePersistentStorage(const OicSecCred_t *cred)
+{
+    bool ret = false;
+
+    // Convert Cred data into JSON for update to persistent storage
+    char *jsonStr = BinToCredJSON(cred);
+    if (jsonStr)
+    {
+        cJSON *jsonCred = cJSON_Parse(jsonStr);
+        OICFree(jsonStr);
+
+        if ((jsonCred) &&
+          (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, jsonCred)))
+        {
+            ret = true;
+        }
+        cJSON_Delete(jsonCred );
+    }
+    else //Empty cred list
+    {
+        if (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, NULL))
+        {
+            ret = true;
+        }
+    }
+    return ret;
+}
+
+/**
  * Compare function used LL_SORT for sorting credentials
  *
  * @param first   pointer to OicSecCred_t struct
@@ -459,6 +504,8 @@ static uint16_t GetCredId()
 exit:
     return 0;
 }
+
+
 /**
  * This function adds the new cred to the credential list.
  *
@@ -471,7 +518,6 @@ exit:
 OCStackResult AddCredential(OicSecCred_t * newCred)
 {
     OCStackResult ret = OC_STACK_ERROR;
-    char * jsonStr = NULL;
 
     VERIFY_SUCCESS(TAG, NULL != newCred, ERROR);
 
@@ -483,23 +529,41 @@ OCStackResult AddCredential(OicSecCred_t * newCred)
     //Append the new Cred to existing list
     LL_APPEND(gCred, newCred);
 
-    //Convert CredList to JSON and update the persistent Storage
-    jsonStr = BinToCredJSON(gCred);
-
-    if(jsonStr)
+    if(UpdatePersistentStorage(gCred))
     {
-        cJSON *jsonCred = cJSON_Parse(jsonStr);
-        OICFree(jsonStr);
+        ret = OC_STACK_OK;
+    }
+
+exit:
+    return ret;
+}
 
-        if((jsonCred) && (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, jsonCred)))
+OCStackResult RemoveCredential(const OicUuid_t *subject)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    OicSecCred_t *cred = NULL;
+    OicSecCred_t *tempCred = NULL;
+    bool deleteFlag = false;
+
+    LL_FOREACH_SAFE(gCred, cred, tempCred)
+    {
+        if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
         {
-            ret = OC_STACK_OK;
+            LL_DELETE(gCred, cred);
+            FreeCred(cred);
+            deleteFlag = 1;
         }
-        cJSON_Delete(jsonCred);
     }
 
-exit:
+    if(deleteFlag)
+    {
+        if(UpdatePersistentStorage(gCred))
+        {
+            ret = OC_STACK_RESOURCE_DELETED;
+        }
+    }
     return ret;
+
 }
 
 static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
@@ -521,6 +585,49 @@ static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * eh
     return ret;
 }
 
+static OCEntityHandlerResult HandleDeleteRequest(const OCEntityHandlerRequest *ehRequest)
+{
+    OC_LOG_V (INFO, TAG, PCF("Processing CredDeleteRequest"));
+
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+    if(NULL == ehRequest->query)
+   {
+       return ehRet;
+   }
+
+   OicParseQueryIter_t parseIter = {.attrPos=NULL};
+   OicUuid_t subject = {.id={0}};
+
+   //Parsing REST query to get the subject
+   ParseQueryIterInit((unsigned char *)ehRequest->query, &parseIter);
+   while(GetNextQuery(&parseIter))
+   {
+       if(strncasecmp((char *)parseIter.attrPos, OIC_JSON_SUBJECT_NAME,
+               parseIter.attrLen) == 0)
+       {
+           unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
+           uint32_t outLen = 0;
+           B64Result b64Ret = B64_OK;
+
+           b64Ret = b64Decode((char *)parseIter.valPos, parseIter.valLen,
+                   base64Buff, sizeof(base64Buff), &outLen);
+
+           VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(subject.id)), ERROR);
+           memcpy(subject.id, base64Buff, outLen);
+       }
+   }
+
+   if(OC_STACK_RESOURCE_DELETED == RemoveCredential(&subject))
+   {
+       ehRet = OC_EH_RESOURCE_DELETED;
+   }
+
+exit:
+    return ehRet;
+}
+
+
 /*
  * This internal method is the entity handler for Cred resources
  * to handle REST request (PUT/POST/DEL)
@@ -548,6 +655,9 @@ OCEntityHandlerResult CredEntityHandler (OCEntityHandlerFlag flag,
             case OC_REST_POST:
                 ret = HandlePostRequest(ehRequest);
                 break;
+            case OC_REST_DELETE:
+                ret = HandleDeleteRequest(ehRequest);
+                break;
             default:
                 ret = OC_EH_ERROR;
                 break;
@@ -657,16 +767,16 @@ const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
 {
     OicSecCred_t *cred = NULL;
 
-    if ( NULL == subject)
+   if ( NULL == subject)
     {
-        return NULL;
+       return NULL;
     }
 
     LL_FOREACH(gCred, cred)
     {
         if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
         {
-             return cred;
+            return cred;
         }
     }
     return NULL;
@@ -694,7 +804,7 @@ void GetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo)
         caBlob = (CADtlsPskCredsBlob_t *)OICCalloc(sizeof(CADtlsPskCredsBlob_t), 1);
         if (caBlob)
         {
-            OicUuid_t deviceID = {};
+            OicUuid_t deviceID = {.id={}};
 
             // Retrieve Device ID from doxm resource and copy in PSK creds blob
             VERIFY_SUCCESS(TAG, GetDoxmDeviceID(&deviceID) == OC_STACK_OK, ERROR);
@@ -752,4 +862,61 @@ exit:
     }
     OICFree(caBlob);
 }
+
+/**
+ * Add temporal PSK to PIN based OxM
+ *
+ * @param[in] tmpSubject UUID of target device
+ * @param[in] credType Type of credential to be added
+ * @param[in] pin numeric characters
+ * @param[in] pinSize length of 'pin'
+ * @param[in] ownersLen Number of owners
+ * @param[in] owners Array of owners
+ * @param[out] tmpCredSubject Generated credential's subject.
+ *
+ * @return OC_STACK_OK for success and errorcode otherwise.
+ */
+OCStackResult AddTmpPskWithPIN(const OicUuid_t* tmpSubject, OicSecCredType_t credType,
+                            const char * pin, size_t pinSize,
+                            size_t ownersLen, const OicUuid_t * owners, OicUuid_t* tmpCredSubject)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+
+    if(tmpSubject == NULL || pin == NULL || pinSize == 0 || tmpCredSubject == NULL)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    uint8_t privData[OWNER_PSK_LENGTH_128] = {0,};
+    int dtlsRes = DeriveCryptoKeyFromPassword((const unsigned char *)pin, pinSize, owners->id,
+                                              UUID_LENGTH, PBKDF_ITERATIONS,
+                                              OWNER_PSK_LENGTH_128, privData);
+    VERIFY_SUCCESS(TAG, (dtlsRes == 0) , ERROR);
+
+    uint32_t outLen = 0;
+    char base64Buff[B64ENCODE_OUT_SAFESIZE(OWNER_PSK_LENGTH_128) + 1] = {};
+    B64Result b64Ret = b64Encode(privData, OWNER_PSK_LENGTH_128, base64Buff,
+                                sizeof(base64Buff), &outLen);
+    VERIFY_SUCCESS(TAG, (B64_OK == b64Ret), ERROR);
+
+    OicSecCred_t* cred = GenerateCredential(tmpSubject, credType, NULL,
+                                            base64Buff, ownersLen, owners);
+    if(NULL == cred)
+    {
+        OC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to generate credential");
+        return OC_STACK_ERROR;
+    }
+
+    memcpy(tmpCredSubject->id, cred->subject.id, UUID_LENGTH);
+
+    ret = AddCredential(cred);
+    if( OC_STACK_OK != ret)
+    {
+        OC_LOG(ERROR, TAG, "GeneratePskWithPIN() : Failed to add credential");
+    }
+
+exit:
+    return ret;
+}
+
 #endif /* __WITH_DTLS__ */
index 8251214..0423a21 100644 (file)
 #include "credresource.h"
 #include "ocserverrequest.h"
 #include "srmutility.h"
+#include "pinoxmcommon.h"
+
+#ifdef __WITH_DTLS__
+#include "global.h"
+#endif
+
 #include <stdlib.h>
 #include <string.h>
 
@@ -229,7 +235,7 @@ OicSecDoxm_t * JSONToDoxmBin(const char * jsonStr)
     jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_SEL_NAME);
     if(jsonObj)
     {
-        VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR)
+        VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
         doxm->oxmSel = (OicSecOxm_t)jsonObj->valueint;
     }
     else // PUT/POST JSON may not have oxmsel so set it to the gDoxm->oxmSel
@@ -242,7 +248,7 @@ OicSecDoxm_t * JSONToDoxmBin(const char * jsonStr)
     jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNED_NAME);
     if(jsonObj)
     {
-        VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type), ERROR)
+        VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type), ERROR);
         doxm->owned = jsonObj->valueint;
     }
     else // PUT/POST JSON may not have owned so set it to the gDomx->owned
@@ -277,16 +283,19 @@ OicSecDoxm_t * JSONToDoxmBin(const char * jsonStr)
         strncpy((char *)doxm->deviceID.id, (char *)gDoxm->deviceID.id, sizeof(doxm->deviceID.id));
     }
 
-    // Owner -- will be empty when device state is unowned.
-    if (true == doxm->owned)
+    //Owner -- will be empty when device status is unowned.
+    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNER_NAME);
+    if(true == doxm->owned)
     {
-        jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNER_NAME);
         VERIFY_NON_NULL(TAG, jsonObj, ERROR);
-        VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR)
-            outLen = 0;
+    }
+    if(jsonObj)
+    {
+        VERIFY_SUCCESS(TAG, (cJSON_String == jsonObj->type), ERROR);
+        outLen = 0;
         b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
                 sizeof(base64Buff), &outLen);
-        VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(doxm->owner.id)), ERROR);
+        VERIFY_SUCCESS(TAG, ((b64Ret == B64_OK) && (outLen <= sizeof(doxm->owner.id))), ERROR);
         memcpy(doxm->owner.id, base64Buff, outLen);
     }
 
@@ -348,7 +357,7 @@ static bool ValidateQuery(unsigned char * query)
         return false;
     }
 
-    OicParseQueryIter_t parseIter = {0};
+    OicParseQueryIter_t parseIter = {.attrPos = NULL};
 
     ParseQueryIterInit(query, &parseIter);
 
@@ -408,6 +417,51 @@ static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest
     return ehRet;
 }
 
+#ifdef __WITH_DTLS__
+/*
+ * Generating new credential for provisioning tool
+ *
+ * PSK generated by
+ */
+static OCEntityHandlerResult AddOwnerPSK(const CAEndpoint_t* endpoint,
+                    OicSecDoxm_t* ptDoxm,
+                    const uint8_t* label, const size_t labelLen)
+{
+    size_t ownLen = 1;
+    uint32_t outLen = 0;
+    OicSecCred_t *cred = NULL;
+    uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {};
+
+    CAResult_t pskRet = CAGenerateOwnerPSK(endpoint,
+        label, labelLen,
+        ptDoxm->owner.id, sizeof(ptDoxm->owner.id),
+        gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
+        ownerPSK, OWNER_PSK_LENGTH_128);
+
+    VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
+
+    char base64Buff[B64ENCODE_OUT_SAFESIZE(OWNER_PSK_LENGTH_128) + 1] = {};
+    B64Result b64Ret = b64Encode(ownerPSK, OWNER_PSK_LENGTH_128, base64Buff,
+                    sizeof(base64Buff), &outLen);
+    VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+
+    OC_LOG (INFO, TAG, PCF("Doxm EntityHandle  generating Credential"));
+    cred = GenerateCredential(&ptDoxm->owner, SYMMETRIC_PAIR_WISE_KEY,
+                              NULL, base64Buff, ownLen, &ptDoxm->owner);
+    VERIFY_NON_NULL(TAG, cred, ERROR);
+
+    //Adding provisioning tool credential to cred Resource.
+    VERIFY_SUCCESS(TAG, OC_STACK_OK == AddCredential(cred), ERROR);
+
+    gDoxm->owned = true;
+    memcpy(&(gDoxm->owner), &(ptDoxm->owner), sizeof(OicUuid_t));
+
+    return OC_EH_OK;
+
+exit:
+    return OC_EH_ERROR;
+}
+#endif //__WITH_DTLS__
 
 static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest * ehRequest)
 {
@@ -455,40 +509,16 @@ static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest
                  *
                  */
 #ifdef __WITH_DTLS__
-                CAResult_t pskRet;
-
                 OCServerRequest *request = (OCServerRequest *)ehRequest->requestHandle;
-                uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {};
 
                 //Generating OwnerPSK
                 OC_LOG (INFO, TAG, PCF("Doxm EntityHandle  generating OwnerPSK"));
-                pskRet = CAGenerateOwnerPSK((CAEndpoint_t *)&request->devAddr,
-                        (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS),
-                        newDoxm->owner.id, sizeof(newDoxm->owner.id),
-                        gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id),
-                        ownerPSK, OWNER_PSK_LENGTH_128);
-
-                VERIFY_SUCCESS(TAG, pskRet == CA_STATUS_OK, ERROR);
-
-                //Generating new credential for provisioning tool
-                size_t ownLen = 1;
-                uint32_t outLen = 0;
 
-                char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(ownerPSK)) + 1] = {};
-                B64Result b64Ret = b64Encode(ownerPSK, sizeof(ownerPSK), base64Buff,
-                                sizeof(base64Buff), &outLen);
-                VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+                //Generate new credential for provisioning tool
+                ehRet = AddOwnerPSK((CAEndpoint_t *)&request->devAddr, newDoxm,
+                        (uint8_t*) OXM_JUST_WORKS, strlen(OXM_JUST_WORKS));
 
-                OC_LOG (INFO, TAG, PCF("Doxm EntityHandle  generating Credential"));
-                OicSecCred_t *cred = GenerateCredential(&newDoxm->owner, SYMMETRIC_PAIR_WISE_KEY,
-                                        NULL, base64Buff, ownLen, &newDoxm->owner);
-                VERIFY_NON_NULL(TAG, cred, ERROR);
-
-                //Adding provisioning tool credential to cred Resource.
-                VERIFY_SUCCESS(TAG, OC_STACK_OK == AddCredential(cred), ERROR);
-
-                gDoxm->owned = true;
-                memcpy(&(gDoxm->owner), &(newDoxm->owner), sizeof(OicUuid_t));
+                VERIFY_SUCCESS(TAG, ehRet = OC_EH_OK, ERROR);
 
                 // Update new state in persistent storage
                 if (true == UpdatePersistentStorage(gDoxm))
@@ -515,6 +545,75 @@ static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest
 #endif //__WITH_DTLS__
             }
         }
+        else if(OIC_RANDOM_DEVICE_PIN == newDoxm->oxmSel)
+        {
+            //this temp Credential ID is used to track temporal Cred Id
+            static OicUuid_t tmpCredId = {.id={0}};
+            static bool tmpCredGenFlag = false;
+
+            if ((false == gDoxm->owned) && (false == newDoxm->owned))
+            {
+#ifdef __WITH_DTLS__
+                CAEnableAnonECDHCipherSuite(false);
+                OC_LOG(DEBUG, TAG, "ECDH_ANON CipherSuite is DISABLED");
+                CASelectCipherSuite(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA_256);
+
+                char ranPin[OXM_RANDOM_PIN_SIZE + 1] = {0,};
+                if(OC_STACK_OK == GeneratePin(ranPin, OXM_RANDOM_PIN_SIZE + 1))
+                {
+                    if(tmpCredGenFlag)
+                    {
+                       OC_LOG(DEBUG, TAG, "Corrupted PSK is detected!!!");
+                       VERIFY_SUCCESS(TAG,
+                                      OC_STACK_RESOURCE_DELETED == RemoveCredential(&tmpCredId),
+                                      ERROR);
+                    }
+
+                    OCStackResult res = AddTmpPskWithPIN( &(newDoxm->owner), SYMMETRIC_PAIR_WISE_KEY,
+                                     ranPin, OXM_RANDOM_PIN_SIZE, 1, &(newDoxm->owner), &tmpCredId);
+                    VERIFY_SUCCESS(TAG, res == OC_STACK_OK, ERROR);
+                    tmpCredGenFlag = true;
+                    ehRet = OC_EH_OK;
+                }
+                else
+                {
+                    OC_LOG(ERROR, TAG, "Failed to generate random PIN");
+                    ehRet = OC_EH_ERROR;
+                }
+
+#endif //__WITH_DTLS__
+            }
+
+            /*
+             * When current state of the device is un-owned and Provisioning
+             * Tool is attempting to change the state to 'Owned' with a
+             * qualified value for the field 'Owner'
+             */
+            if ((false == gDoxm->owned) && (true == newDoxm->owned) &&
+                (memcmp(&(newDoxm->owner), &emptyOwner, sizeof(OicUuid_t)) != 0))
+            {
+#ifdef __WITH_DTLS__
+                OCServerRequest * request = (OCServerRequest *)ehRequest->requestHandle;
+
+                //Remove Temporal Credential resource
+                if(tmpCredGenFlag)
+                {
+                    VERIFY_SUCCESS(TAG,
+                                   OC_STACK_RESOURCE_DELETED == RemoveCredential(&tmpCredId),
+                                   ERROR);
+                    tmpCredGenFlag = false;
+                }
+
+                //Generate new credential for provisioning tool
+                ehRet = AddOwnerPSK((CAEndpoint_t*)(&request->devAddr), newDoxm,
+                                    (uint8_t*)OXM_RANDOM_DEVICE_PIN, strlen(OXM_RANDOM_DEVICE_PIN));
+                VERIFY_SUCCESS(TAG, OC_EH_OK == ehRet, ERROR);
+
+                //Update new state in persistent storage
+                ehRet = (UpdatePersistentStorage(gDoxm) == true) ? OC_EH_OK : OC_EH_ERROR;
+#endif
+             }
+        }
     }
 
 exit:
diff --git a/resource/csdk/security/src/iotvticalendar.c b/resource/csdk/security/src/iotvticalendar.c
new file mode 100644 (file)
index 0000000..8276365
--- /dev/null
@@ -0,0 +1,418 @@
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+//Not supported on Arduino due lack of absolute time need to implement iCalendar
+#ifndef WITH_ARDUINO
+
+#define _XOPEN_SOURCE  //Needed by strptime
+#include <string.h>
+#include "iotvticalendar.h"
+#include "oic_string.h"
+
+static char dtFormat[] =  "%Y%m%dT%H%M%S"; //date-time format
+static char dFormat[] =  "%Y%m%d";         // date format
+
+static const char FREQ[]  = "FREQ";
+static const char UNTIL[] = "UNTIL";
+static const char BYDAY[] = "BYDAY";
+static const char DAILY[] = "DAILY";
+
+
+/**
+ * Parses periodStr and populate struct IotvtICalPeriod_t
+ *
+ * @param periodStr string to be parsed.
+ * @param period    IotvtICalPeriod_t struct to be populated.
+ *
+ * @return  IOTVTICAL_INVALID_PARAMETER -- if parameter are invalid
+ *          IOTVTICAL_INVALID_PERIOD    -- if period string has invalid format
+ *          IOTVTICAL_INVALID_SUCCESS   -- if no error while parsing
+ */
+IotvtICalResult_t ParsePeriod(const char *periodStr, IotvtICalPeriod_t *period)
+{
+    if((NULL == periodStr) || (NULL == period))
+    {
+        return IOTVTICAL_INVALID_PARAMETER;
+    }
+
+    char *endDTPos;
+    char *fmt = "";
+    int   startDTLen;
+    int   endDTLen;
+
+    //Finding length of startDateTime and endDateTime in period
+    //startDateTime and endDateTime can have form YYYYmmdd or YYYYmmddTHHMMSS
+    //startDateTime and endDateTime must be same form
+    //Eg: periodStr = "20150629T153050/20150630T203055"
+    //    periodStr = "20150629/20150630"
+    if(NULL == (endDTPos = strchr(periodStr, '/')))
+    {
+        return IOTVTICAL_INVALID_PERIOD;
+    }
+    endDTPos += 1;
+    startDTLen = endDTPos - periodStr - 1;
+    endDTLen   = strlen(endDTPos);
+
+    //Checking if both startDateTime and endDateTime are of same form
+    if(startDTLen == endDTLen)
+    {
+        if(8 == startDTLen) //YYYYmmdd
+        {
+            fmt = dFormat;
+        }
+        else if(15 == startDTLen) //YYYYmmddTHHMMSS
+        {
+            fmt = dtFormat;
+        }
+        else
+        {
+            return IOTVTICAL_INVALID_PERIOD;
+        }
+    }
+    else
+    {
+        return IOTVTICAL_INVALID_PERIOD;
+    }
+
+    //Checking if startDateTime has right format
+    if(NULL != strptime(periodStr, fmt, &period->startDateTime))
+    {
+        //Checking if endDateTime has right format
+        if(NULL != strptime(endDTPos, fmt, &period->endDateTime))
+        {
+            //Checking if endDateTime is after startDateTime
+            if(difftime(mktime(&period->endDateTime),
+                        mktime(&period->startDateTime)) > 0)
+            {
+                //mktime increases value of tm_hour by 1 if tm_isdst is set.
+                //The tm_hour value in period's startDateTime and endDatetime
+                //should remain same irrespective of daylight saving time.
+                if(period->startDateTime.tm_isdst)
+                {
+                    period->startDateTime.tm_hour =
+                   (period->startDateTime.tm_hour + TOTAL_HOURS - TM_DST_OFFSET) % TOTAL_HOURS;
+                }
+                if(period->endDateTime.tm_isdst)
+                {
+                    period->endDateTime.tm_hour =
+                   (period->endDateTime.tm_hour + TOTAL_HOURS - TM_DST_OFFSET) % TOTAL_HOURS;
+                }
+                return IOTVTICAL_SUCCESS;
+            }
+        }
+    }
+    return IOTVTICAL_INVALID_PERIOD;
+}
+
+
+/**
+ * Parses untilRule and populate "until" field of struct IotvtICalRecur_t
+ *
+ * @param untilRule  string to be parsed.
+ * @param recur      IotvtICalRecur_t struct to be populated.
+ *
+ * @return  IOTVTICAL_ERRRO             -- if untilRule has invalid format
+ *          IOTVTICAL_INVALID_SUCCESS   -- if no error while parsing
+ */
+static IotvtICalResult_t ParseDate(char *untilRule, IotvtICalRecur_t *recur)
+{
+    char *date = strchr(untilRule, '=');
+
+    if(NULL == date)
+    {
+        return IOTVTICAL_ERROR;
+    }
+    date += 1;
+
+    if(strlen(date) == 8) //YYYYmmdd
+    {
+        if(NULL != strptime(date, dFormat, &recur->until))
+        {
+            return IOTVTICAL_SUCCESS;
+        }
+    }
+    return IOTVTICAL_ERROR;
+}
+
+
+/**
+ * Parses bydayRule and populate "byDay" field of struct IotvtICalRecur_t
+ *
+ * @param bydayRule  string to be parsed.
+ * @param recur      IotvtICalRecur_t struct to be populated.
+ *
+ * @return  IOTVTICAL_ERRRO             -- if bydayRule has empty weekday list or invalid weekdays
+ *          IOTVTICAL_INVALID_SUCCESS   -- if no error while parsing
+ */
+static IotvtICalResult_t  ParseByday(char *bydayRule, IotvtICalRecur_t *recur)
+{
+    if(strstr(bydayRule, "SU"))
+    {
+        recur->byDay = recur->byDay | SUNDAY;
+    }
+    if(strstr(bydayRule, "MO"))
+    {
+        recur->byDay = recur->byDay | MONDAY;
+    }
+    if(strstr(bydayRule, "TU"))
+    {
+        recur->byDay = recur->byDay | TUESDAY;
+    }
+    if(strstr(bydayRule, "WE"))
+    {
+        recur->byDay = recur->byDay | WEDNESDAY;
+    }
+    if(strstr(bydayRule, "TH"))
+    {
+        recur->byDay = recur->byDay | THURSDAY;
+    }
+    if(strstr(bydayRule, "FR"))
+    {
+        recur->byDay = recur->byDay | FRIDAY;
+    }
+    if(strstr(bydayRule, "SA"))
+    {
+        recur->byDay = recur->byDay | SATURDAY;
+    }
+
+    //Checking if byDay list is empty or has inValid weekdays
+    if(recur->byDay == NO_WEEKDAY)
+    {
+        return IOTVTICAL_ERROR;
+    }
+
+    return IOTVTICAL_SUCCESS;
+}
+
+
+/**
+ * Parses recurStr and populate struct IotvtICalRecur_t
+ *
+ * @param recurStr string to be parsed.
+ * @param recur    IotvtICalPeriod_t struct to be populated.
+ *
+ * @return  IOTVTICAL_INVALID_PARAMETER -- if parameter are invalid
+ *          IOTVTICAL_INVALID_PERIOD    -- if period string has invalid format
+ *          IOTVTICAL_INVALID_RRULE     -- if rrule string has invalid format
+ */
+IotvtICalResult_t ParseRecur(const char *recurStr, IotvtICalRecur_t *recur)
+{
+
+    if((NULL == recurStr) || (NULL == recur))
+    {
+        return IOTVTICAL_INVALID_PARAMETER;
+    }
+
+    const char *startPos="";
+    const char *endPos="";
+    char        buf[50];
+    int         freqFlag = 0; //valid RRULE must have "FREQ" parameter.
+                              //flag to track if RRULE has "FREQ" or not
+
+    startPos = recurStr;
+    //Iterates though recurrence rule
+    //Eg, RRULE: FREQ=DAILY; UNTIL=20150703; BYDAY=MO, WE, FR
+    while('\0' != startPos)
+    {
+        endPos = strchr(startPos, ';');
+        if(endPos)
+        {
+            endPos += 1;
+        }
+        OICStrcpy(buf, (endPos - startPos), startPos);
+        if(NULL != strstr(buf, FREQ))
+        {
+            if(NULL != strstr(buf, DAILY))
+            {
+                recur->freq = FREQ_DAILY;
+                freqFlag = 1;
+            }
+            else
+            {
+                return IOTVTICAL_INVALID_RRULE;
+            }
+        }
+        else if(NULL != strstr(buf, UNTIL))
+        {
+            if(IOTVTICAL_SUCCESS != ParseDate(buf, recur))
+            {
+                return IOTVTICAL_INVALID_RRULE;
+            }
+        }
+        else if(NULL != strstr(buf, BYDAY))
+        {
+            if(IOTVTICAL_SUCCESS != ParseByday(buf, recur))
+            {
+                return IOTVTICAL_INVALID_RRULE;
+            };
+        }
+        startPos = endPos;
+    }
+
+    if(1 != freqFlag)
+    {
+        return IOTVTICAL_INVALID_RRULE;
+    }
+
+    return IOTVTICAL_SUCCESS;
+}
+
+/**
+ * Computes number of days between two dates.
+ *
+ * @param date1 earlier date.
+ * @param date2 later date.
+ *
+ * @return  number of days between date1 & date2.
+ */
+static int DiffDays(IotvtICalDateTime_t *date1, IotvtICalDateTime_t *date2)
+{
+    int days;
+    int leapDays=0;
+
+    if(date2->tm_year > date1->tm_year)
+    {
+        for(int y = date1->tm_year; y < date2->tm_year; y++)
+        {
+            y += TM_YEAR_OFFSET;
+            if(y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
+            {
+               leapDays += 1;
+            }
+        }
+    }
+
+    days = (365 * date2->tm_year + date2->tm_yday + leapDays) -
+           (365 * date1->tm_year + date1->tm_yday);
+
+    return days;
+}
+
+
+/**
+ * Computes number of seconds between two time.
+ *
+ * @param time1 earlier time.
+ * @param date2 later time.
+ *
+ * @return  number of seconds between time1 and time2.
+ */
+static int DiffSecs(IotvtICalDateTime_t *time1, IotvtICalDateTime_t *time2)
+{
+    return (3600 * time2->tm_hour + 60 * time2->tm_min + time2->tm_sec) -
+           (3600 * time1->tm_hour + 60 * time1->tm_min + time1->tm_sec);
+}
+
+
+/**
+ * This API is used by policy engine to checks if the
+ * request to access resource is within valid time.
+ *
+ * @param period string representing period.
+ * @param recur string representing recurrence rule
+ *
+ * @return  IOTVTICAL_VALID_ACCESS      -- if the request is within valid time period
+ *          IOTVTICAL_INVALID_ACCESS    -- if the request is not within valid time period
+ *          IOTVTICAL_INVALID_PARAMETER -- if parameter are invalid
+ *          IOTVTICAL_INVALID_PERIOD    -- if period string has invalid format
+ *          IOTVTICAL_INVALID_RRULE     -- if rrule string has invalid format
+ */
+
+IotvtICalResult_t IsRequestWithinValidTime(char *periodStr, char *recurStr)
+{
+    //NULL recur rule means no recurring patter exist.
+    //Period can't be null. Period is used with or without
+    //recur rule to compute allowable access time.
+    if(NULL == periodStr)
+    {
+        return IOTVTICAL_INVALID_PARAMETER;
+    }
+
+    IotvtICalPeriod_t period = {.startDateTime={.tm_sec=0}};
+    IotvtICalRecur_t recur = {.freq=0};
+    IotvtICalResult_t ret = IOTVTICAL_INVALID_ACCESS;
+
+    time_t rawTime = time(0);
+    IotvtICalDateTime_t *currentTime = localtime(&rawTime);
+
+    ret  = ParsePeriod(periodStr, &period);
+    if(ret != IOTVTICAL_SUCCESS)
+    {
+        return ret;
+    }
+
+    //If recur is NULL then the access time is between period's startDate and endDate
+    if(NULL == recurStr)
+    {
+        if((0 <= DiffDays(&period.startDateTime, currentTime)) &&
+           (0 <= DiffDays(currentTime, &period.endDateTime)))
+        {
+            ret = IOTVTICAL_VALID_ACCESS;
+        }
+    }
+
+    //If recur is not NULL then the access time is between period's startTime and
+    //endTime on days specified in "BYDAY" list. The first instance of recurrence
+    //is computed from period's startDate and the last instance is computed from
+    //"UNTIL". If "UNTIL" is not specified then the recurrence goes for forever.
+    //Eg, RRULE: FREQ=DAILY; UNTIL=20150703; BYDAY=MO, WE, FR
+    if(NULL != recurStr)
+    {
+        ret = ParseRecur(recurStr, &recur);
+        if(ret != IOTVTICAL_SUCCESS)
+        {
+            return ret;
+        }
+
+        if((0 <= DiffSecs(&period.startDateTime, currentTime))&&
+           (0 <= DiffSecs(currentTime, &period.endDateTime)) &&
+           (0 <= DiffDays(&period.startDateTime, currentTime)))
+        {
+            IotvtICalDateTime_t emptyDT = {.tm_sec=0};
+            ret = IOTVTICAL_VALID_ACCESS;
+
+            //"UNTIL" is an optional parameter of RRULE, checking if until present in recur
+            if(0 != memcmp(&recur.until, &emptyDT, sizeof(IotvtICalDateTime_t)))
+            {
+                if(0 > DiffDays(currentTime, &recur.until))
+                {
+                    ret = IOTVTICAL_INVALID_ACCESS;
+                }
+            }
+
+            //"BYDAY" is an optional parameter of RRULE, checking if byday present in recur
+            if(NO_WEEKDAY != recur.byDay)
+            {
+
+                int isValidWD = (0x1 << currentTime->tm_wday) & recur.byDay; //Valid weekdays
+                if(!isValidWD)
+                {
+                    ret = IOTVTICAL_INVALID_ACCESS;
+                }
+             }
+        }
+        else
+        {
+            ret = IOTVTICAL_INVALID_ACCESS;
+        }
+    }
+    return ret;
+}
+#endif
diff --git a/resource/csdk/security/src/oxmpincommon.c b/resource/csdk/security/src/oxmpincommon.c
new file mode 100644 (file)
index 0000000..fc7c0f3
--- /dev/null
@@ -0,0 +1,110 @@
+/* *****************************************************************
+ *
+ * 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 "ocstack.h"
+#include "ocrandom.h"
+#include "logger.h"
+#include "pinoxmcommon.h"
+
+#define TAG PCF("PIN_OXM_COMMON")
+
+static GeneratePinCallback gGenPinCallback = NULL;
+static InputPinCallback gInputPinCallback = NULL;
+
+void SetInputPinCB(InputPinCallback pinCB)
+{
+    if(NULL == pinCB)
+    {
+        OC_LOG(ERROR, TAG, "Failed to set callback for input pin.");
+        return;
+    }
+
+    gInputPinCallback = pinCB;
+}
+
+void SetGeneratePinCB(GeneratePinCallback pinCB)
+{
+    if(NULL == pinCB)
+    {
+        OC_LOG(ERROR, TAG, "Failed to set callback for generate pin.");
+        return;
+    }
+
+    gGenPinCallback = pinCB;
+}
+
+OCStackResult GeneratePin(char* pinBuffer, size_t bufferSize)
+{
+    if(!pinBuffer)
+    {
+        OC_LOG(ERROR, TAG, "PIN buffer is NULL");
+        return OC_STACK_INVALID_PARAM;
+    }
+    if(OXM_RANDOM_PIN_SIZE + 1 > bufferSize)
+    {
+        OC_LOG(ERROR, TAG, "PIN buffer size is too small");
+        return OC_STACK_INVALID_PARAM;
+    }
+    for(size_t i = 0; i < OXM_RANDOM_PIN_SIZE; i++)
+    {
+        pinBuffer[i] = OCGetRandomRange((uint32_t)'0', (uint32_t)'9');
+    }
+    pinBuffer[OXM_RANDOM_PIN_SIZE] = '\0';
+
+    if(gGenPinCallback)
+    {
+        gGenPinCallback(pinBuffer, OXM_RANDOM_PIN_SIZE);
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
+        OC_LOG(ERROR, TAG, "Callback for genrate PIN should be registered to use PIN based OxM.");
+        return OC_STACK_ERROR;
+    }
+
+    return OC_STACK_OK;
+}
+
+
+OCStackResult InputPin(char* pinBuffer, size_t bufferSize)
+{
+    if(!pinBuffer)
+    {
+        OC_LOG(ERROR, TAG, "PIN buffer is NULL");
+        return OC_STACK_INVALID_PARAM;
+    }
+    if(OXM_RANDOM_PIN_SIZE + 1 > bufferSize)
+    {
+        OC_LOG(ERROR, TAG, "PIN buffer size is too small");
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    if(gInputPinCallback)
+    {
+        gInputPinCallback(pinBuffer, OXM_RANDOM_PIN_SIZE + 1);
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, "Invoke PIN callback failed!");
+        OC_LOG(ERROR, TAG, "Callback for input PIN should be registered to use PIN based OxM.");
+        return OC_STACK_ERROR;
+    }
+
+    return OC_STACK_OK;
+}
diff --git a/resource/csdk/security/src/pbkdf2.c b/resource/csdk/security/src/pbkdf2.c
new file mode 100644 (file)
index 0000000..1ddabed
--- /dev/null
@@ -0,0 +1,149 @@
+/* *****************************************************************
+ *
+ * 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 <string.h>
+#include <math.h>
+#include "pbkdf2.h"
+#include "hmac.h"
+#include "debug.h"
+#include "logger.h"
+
+#define TAG "PBDKF2"
+#define XOR_BUF(in, out, bufSize)\
+do{\
+    size_t i=0;\
+    for(i=0; i< (bufSize); i++)\
+    {\
+        (out)[i] = (in)[i] ^ (out)[i];\
+    }\
+}while(0)\
+
+
+static int isLittle()
+{
+    static int a = 1;
+    static int flag = -1;
+    if (flag == -1)
+    {
+        if (  ((uint8_t *)&a)[0]  == 0x1) // little
+            flag = 1;
+        else
+            flag = 0;
+    }
+    return flag;
+}
+
+static void GetBigEndianBuf(uint8_t *buf, int num)
+{
+    uint8_t *nBuf = (uint8_t *)&num;
+    if ( isLittle() == 1 )
+    {
+        size_t i = 0;
+        for (i = 0; i < sizeof(int); i++)
+        {
+            buf[i] = nBuf[ sizeof(int) - i - 1];
+        }
+    }
+    else
+    {
+        memcpy(buf, nBuf, sizeof(int));
+    }
+}
+
+// TODO: Add comments to explain implementation.
+int DeriveCryptoKeyFromPassword(const unsigned char *passwd, size_t pLen,
+                                const uint8_t *salt, const size_t saltLen,
+                                const size_t iterations,
+                                const size_t keyLen, uint8_t *derivedKey)
+{
+    int res = 0;
+    uint8_t buf[DTLS_HMAC_DIGEST_SIZE];
+    uint8_t uBuf[DTLS_HMAC_DIGEST_SIZE];
+
+    size_t nBlocks = 0;
+    size_t nOctetInLastBlock = 0;
+
+    nBlocks = (size_t)ceil ((double)keyLen / (double)DTLS_HMAC_DIGEST_SIZE);
+    nOctetInLastBlock = keyLen - (nBlocks - 1) * DTLS_HMAC_DIGEST_SIZE;
+
+    dtls_hmac_context_t *ctx = NULL;
+    ctx = dtls_hmac_new( (const unsigned char *)passwd, pLen);
+    if (NULL == ctx)
+    {
+        OC_LOG(ERROR, TAG, "DTLS HMAC Context is NULL");
+        goto bail;
+    }
+
+    size_t i = 1;
+    size_t idx = 0; //index for buffer
+    size_t counter = 0;
+    while (i != nBlocks + 1)
+    {
+        counter = 0 ;
+        dtls_hmac_init(ctx, (const unsigned char *)passwd, pLen);
+        while (counter != iterations)
+        {
+            if (counter == 0)
+            {
+                uint8_t intBuf[4] = {0x00, 0x00, 0x00, 0x00};
+                dtls_hmac_update(ctx, salt, saltLen);
+                GetBigEndianBuf(intBuf, i);
+                dtls_hmac_update(ctx, intBuf, 4);
+
+                int len = dtls_hmac_finalize(ctx, buf);
+                if (DTLS_HMAC_DIGEST_SIZE != len)
+                {
+                    OC_LOG(ERROR, TAG, "DTLS HMAC is failed");
+                    res = -1;
+                }
+                memcpy(uBuf, buf, DTLS_HMAC_DIGEST_SIZE);
+            }
+            else
+            {
+                dtls_hmac_init(ctx, (const unsigned char *)passwd, pLen);
+                dtls_hmac_update(ctx, buf, DTLS_HMAC_DIGEST_SIZE);
+                int len = dtls_hmac_finalize(ctx, buf);
+                if (DTLS_HMAC_DIGEST_SIZE != len)
+                {
+                    OC_LOG(ERROR, TAG, "DTLS HMAC is failed");
+                    res = -1;
+                }
+                XOR_BUF(buf, uBuf, DTLS_HMAC_DIGEST_SIZE);
+            }
+            counter++;
+        }
+
+
+        if (i == nBlocks)
+        {
+            memcpy(derivedKey + idx, uBuf, nOctetInLastBlock);
+        }
+        else
+        {
+            memcpy(derivedKey + idx, uBuf, DTLS_HMAC_DIGEST_SIZE);
+            idx += DTLS_HMAC_DIGEST_SIZE;
+        }
+        i++;
+    }
+
+bail:
+    dtls_hmac_free(ctx);
+    return res;
+}
+
index c39814d..9a61f00 100644 (file)
@@ -27,6 +27,7 @@
 #include "aclresource.h"
 #include "srmutility.h"
 #include "doxmresource.h"
+#include "iotvticalendar.h"
 #include <string.h>
 
 #define TAG PCF("SRM-PE")
@@ -187,23 +188,56 @@ exit:
 }
 
 /**
- * Check whether 'resource' is in the passed ACL.
- * @param   resource    The resource to search for.
+ * Check whether 'resource' is getting accessed within the valid time period.
  * @param   acl         The ACL to check.
- * @return true if 'resource' found, otherwise false.
+ * @return
+ *      true if access is within valid time period or if the period or recurrence is not present.
+ *      false if period and recurrence present and the access is not within valid time period.
  */
- bool IsResourceInAcl(const char *resource, const OicSecAcl_t *acl)
- {
-    for(size_t n = 0; n < acl->resourcesLen; n++)
+static bool IsAccessWithinValidTime(const OicSecAcl_t *acl)
+{
+#ifndef WITH_ARDUINO //Period & Recurrence not supported on Arduino due
+                     //lack of absolute time
+    if(NULL== acl || NULL == acl->periods || 0 == acl->prdRecrLen)
+    {
+        return true;
+    }
+
+    for(size_t i = 0; i < acl->prdRecrLen; i++)
     {
-        if(0 == strcmp(resource, acl->resources[n]) || // TODO null terms?
-         0 == strcmp(WILDCARD_RESOURCE_URI, acl->resources[n]))
+        if(IOTVTICAL_VALID_ACCESS ==  IsRequestWithinValidTime(acl->periods[i],
+            acl->recurrences[i]))
         {
+            OC_LOG(INFO, TAG, PCF("Access request is in allowed time period"));
             return true;
         }
     }
+    OC_LOG(INFO, TAG, PCF("Access request is in invalid time period"));
     return false;
- }
+
+#else
+    return true;
+#endif
+}
+
+/**
+ * Check whether 'resource' is in the passed ACL.
+ * @param   resource    The resource to search for.
+ * @param   acl         The ACL to check.
+ * @return true if 'resource' found, otherwise false.
+ */
+ bool IsResourceInAcl(const char *resource, const OicSecAcl_t *acl)
+{
+     for(size_t n = 0; n < acl->resourcesLen; n++)
+     {
+         if(0 == strcmp(resource, acl->resources[n]) || // TODO null terms?
+                 0 == strcmp(WILDCARD_RESOURCE_URI, acl->resources[n]))
+         {
+             return true;
+         }
+    }
+    return false;
+}
 
 /**
  * Find ACLs containing context->subject.
@@ -241,12 +275,17 @@ void ProcessAccessRequest(PEContext_t *context)
                     OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
                         found matching resource in ACL."));
                     context->matchingAclFound = true;
-                    // Found the resource, so it's down to permission.
-                    context->retVal = ACCESS_DENIED_INSUFFICIENT_PERMISSION;
-                    if(IsPermissionAllowingRequest(currentAcl->permission, \
-                        context->permission))
+
+                    // Found the resource, so it's down to valid period & permission.
+                    context->retVal = ACCESS_DENIED_INVALID_PERIOD;
+                    if(IsAccessWithinValidTime(currentAcl))
                     {
-                        context->retVal = ACCESS_GRANTED;
+                        context->retVal = ACCESS_DENIED_INSUFFICIENT_PERMISSION;
+                        if(IsPermissionAllowingRequest(currentAcl->permission, \
+                        context->permission))
+                        {
+                            context->retVal = ACCESS_GRANTED;
+                        }
                     }
                 }
             }
index f295fce..746a164 100644 (file)
@@ -128,6 +128,7 @@ OCStackResult UpdateSVRDatabase(const char* rsrcName, cJSON* jsonObj)
 {
     OCStackResult ret = OC_STACK_ERROR;
     cJSON *jsonSVRDb = NULL;
+    OCPersistentStorage* ps = NULL;
 
     // Read SVR database from PS
     char* jsonSVRDbStr = GetSVRDatabase();
@@ -140,7 +141,13 @@ OCStackResult UpdateSVRDatabase(const char* rsrcName, cJSON* jsonObj)
     OICFree(jsonSVRDbStr);
     jsonSVRDbStr = NULL;
 
-    if (jsonObj->child )
+    //If Cred resource gets updated with empty list then delete the Cred
+    //object from database.
+    if(NULL == jsonObj && (0 == strcmp(rsrcName, OIC_JSON_CRED_NAME)))
+    {
+        cJSON_DeleteItemFromObject(jsonSVRDb, rsrcName);
+    }
+    else if (jsonObj->child )
     {
         // Create a duplicate of the JSON object which was passed.
         cJSON* jsonDuplicateObj = cJSON_Duplicate(jsonObj, 1);
@@ -164,31 +171,31 @@ OCStackResult UpdateSVRDatabase(const char* rsrcName, cJSON* jsonObj)
             // Replace the modified json object in existing SVR database json
             cJSON_ReplaceItemInObject(jsonSVRDb, rsrcName, jsonDuplicateObj->child);
         }
+    }
 
-        // Generate string representation of updated SVR database json object
-        jsonSVRDbStr = cJSON_PrintUnformatted(jsonSVRDb);
-        VERIFY_NON_NULL(TAG,jsonSVRDbStr, ERROR);
+    // Generate string representation of updated SVR database json object
+    jsonSVRDbStr = cJSON_PrintUnformatted(jsonSVRDb);
+    VERIFY_NON_NULL(TAG,jsonSVRDbStr, ERROR);
 
-        // Update the persistent storage with new SVR database
-        OCPersistentStorage* ps = SRMGetPersistentStorageHandler();
-        if (ps && ps->open)
+    // Update the persistent storage with new SVR database
+    ps = SRMGetPersistentStorageHandler();
+    if (ps && ps->open)
+    {
+        FILE* fp = ps->open(SVR_DB_FILE_NAME, "w");
+        if (fp)
         {
-            FILE* fp = ps->open(SVR_DB_FILE_NAME, "w");
-            if (fp)
+            size_t bytesWritten = ps->write(jsonSVRDbStr, 1, strlen(jsonSVRDbStr), fp);
+            if (bytesWritten == strlen(jsonSVRDbStr))
             {
-                size_t bytesWritten = ps->write(jsonSVRDbStr, 1, strlen(jsonSVRDbStr), fp);
-                if (bytesWritten == strlen(jsonSVRDbStr))
-                {
-                    ret = OC_STACK_OK;
-                }
-                OC_LOG_V(INFO, TAG, PCF("Written %d bytes into SVR database file"), bytesWritten);
-                ps->close(fp);
-                fp = NULL;
-            }
-            else
-            {
-                OC_LOG (ERROR, TAG, PCF("Unable to open SVR database file!! "));
+                ret = OC_STACK_OK;
             }
+            OC_LOG_V(INFO, TAG, PCF("Written %d bytes into SVR database file"), bytesWritten);
+            ps->close(fp);
+            fp = NULL;
+        }
+        else
+        {
+            OC_LOG (ERROR, TAG, PCF("Unable to open SVR database file!! "));
         }
     }
 
index 63df79c..7ca79b1 100644 (file)
@@ -254,7 +254,7 @@ static OCEntityHandlerResult HandlePstatPutRequest(const OCEntityHandlerRequest
              */
             for(size_t i=0; i< gPstat->smLen; i++)
             {
-                if(gPstat->sm[i] == omJson->valueint)
+                if(gPstat->sm[i] == (unsigned int)omJson->valueint)
                 {
                     gPstat->om = (OicSecDpom_t)omJson->valueint;
                     break;
index 7e61926..5eefbd4 100644 (file)
@@ -24,6 +24,8 @@
 #include "pstatresource.h"
 #include "doxmresource.h"
 #include "credresource.h"
+#include "svcresource.h"
+#include "amaclresource.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
 #include "logger.h"
@@ -45,7 +47,7 @@ OCStackResult SendSRMResponse(const OCEntityHandlerRequest *ehRequest,
         OCEntityHandlerResult ehRet, const char *rspPayload)
 {
     OC_LOG (INFO, TAG, PCF("SRM sending SRM response"));
-    OCEntityHandlerResponse response = {0};
+    OCEntityHandlerResponse response = {.requestHandle = NULL};
     if (ehRequest)
     {
         OCSecurityPayload ocPayload = {.base = {.type = PAYLOAD_TYPE_INVALID}};
@@ -91,6 +93,14 @@ OCStackResult InitSecureResources( )
     {
         ret = InitCredResource();
     }
+    if(OC_STACK_OK == ret)
+    {
+        ret = InitSVCResource();
+       }
+       if(OC_STACK_OK == ret)
+    {
+        ret = InitAmaclResource();
+    }
     if(OC_STACK_OK != ret)
     {
         //TODO: Update the default behavior if one of the SVR fails
index 48e7bfc..ab56071 100644 (file)
@@ -236,7 +236,6 @@ OCStackResult SRMRegisterPersistentStorageHandler(OCPersistentStorage* persisten
 
 OCPersistentStorage* SRMGetPersistentStorageHandler()
 {
-    OC_LOG(INFO, TAG, PCF("SRMGetPersistentStorageHandler !!"));
     return gPersistentStorageHandler;
 }
 
index 02a5f0e..4cca17b 100644 (file)
 const char * SVR_DB_FILE_NAME = "oic_svr_db.json";
 const char * OIC_MI_DEF = "oic.mi.def";
 
+//AMACL
+const char * OIC_RSRC_TYPE_SEC_AMACL = "oic.sec.amacl";
+const char * OIC_RSRC_AMACL_URI =  "/oic/sec/amacl";
+const char * OIC_JSON_AMACL_NAME = "amacl";
+
 //ACL
 const char * OIC_RSRC_TYPE_SEC_ACL = "oic.sec.acl";
 const char * OIC_RSRC_ACL_URI =  "/oic/sec/acl";
@@ -44,8 +49,15 @@ const char * OIC_RSRC_TYPE_SEC_CRED = "oic.sec.cred";
 const char * OIC_RSRC_CRED_URI =  "/oic/sec/cred";
 const char * OIC_JSON_CRED_NAME = "cred";
 
+//svc
+const char * OIC_RSRC_TYPE_SEC_SVC = "oic.sec.svc";
+const char * OIC_RSRC_SVC_URI =  "/oic/sec/svc";
+const char * OIC_JSON_SVC_NAME = "svc";
+
+
 const char * OIC_JSON_SUBJECT_NAME = "sub";
 const char * OIC_JSON_RESOURCES_NAME = "rsrc";
+const char * OIC_JSON_AMSS_NAME = "amss";
 const char * OIC_JSON_PERMISSION_NAME = "perms";
 const char * OIC_JSON_OWNERS_NAME = "ownrs";
 const char * OIC_JSON_OWNER_NAME = "ownr";
@@ -67,7 +79,11 @@ const char * OIC_JSON_ROLEIDS_NAME = "roleid";
 const char * OIC_JSON_CREDTYPE_NAME = "credtyp";
 const char * OIC_JSON_PUBLICDATA_NAME = "pbdata";
 const char * OIC_JSON_PRIVATEDATA_NAME = "pvdata";
-const char * OIC_JSON_PERIOD_NAME = "period";
+const char * OIC_JSON_SERVICE_DEVICE_ID = "svcdid";
+const char * OIC_JSON_SERVICE_TYPE = "svct";
+const char * OIC_JSON_PERIOD_NAME = "prd";
+const char * OIC_JSON_PERIODS_NAME = "prds";
+const char * OIC_JSON_RECURRENCES_NAME = "recurs";
 
 OicUuid_t WILDCARD_SUBJECT_ID = {"*"};
 size_t WILDCARD_SUBJECT_ID_LEN = 1;
@@ -83,5 +99,6 @@ const char * OXM_PRE_PROVISIONED_STRONG_CREDENTIAL = "oic.sec.doxm.ppsc";
 const char * OIC_SEC_TRUE = "true";
 const char * OIC_SEC_FALSE = "false";
 
-const char * OIC_SEC_REST_QUERY_SEPARATOR = "&";
+const char * OIC_SEC_REST_QUERY_SEPARATOR = ";";
 char OIC_SEC_REST_QUERY_DELIMETER = '=';
+
index 3f97b57..510a5c5 100644 (file)
@@ -23,6 +23,8 @@
 #include "srmutility.h"
 #include "srmresourcestrings.h"
 #include "logger.h"
+#include "oic_malloc.h"
+#include "base64.h"
 
 #define TAG  PCF("SRM-UTILITY")
 
@@ -47,7 +49,6 @@ void ParseQueryIterInit(unsigned char * query, OicParseQueryIter_t * parseIter)
           (unsigned char *)OIC_SEC_REST_QUERY_SEPARATOR, (unsigned char *) "", 0, &parseIter->pi);
 }
 
-
 /**
  * This method fills the OicParseQueryIter_t struct with next REST query's
  * attribute's and value's information
@@ -84,3 +85,46 @@ OicParseQueryIter_t * GetNextQuery(OicParseQueryIter_t * parseIter)
     }
     return NULL;
 }
+
+
+// TODO This functionality is replicated in all SVR's and therefore we need
+// to encapsulate it in a common method. However, this may not be the right
+// file for this method.
+OCStackResult AddUuidArray(cJSON* jsonRoot, const char* arrayItem,
+                           size_t *numUuids, OicUuid_t** uuids )
+{
+    size_t idxx = 0;
+    cJSON* jsonObj = cJSON_GetObjectItem(jsonRoot, arrayItem);
+    VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+    VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
+
+    *numUuids = cJSON_GetArraySize(jsonObj);
+    VERIFY_SUCCESS(TAG, *numUuids > 0, ERROR);
+    *uuids = (OicUuid_t*)OICCalloc(*numUuids, sizeof(OicUuid_t));
+    VERIFY_NON_NULL(TAG, *uuids, ERROR);
+
+    do
+    {
+        unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
+        uint32_t outLen = 0;
+        B64Result b64Ret = B64_OK;
+
+        cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, idxx);
+        VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
+        VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
+
+        outLen = 0;
+        b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring), base64Buff,
+                sizeof(base64Buff), &outLen);
+
+        VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof((*uuids)[idxx].id)),
+                ERROR);
+        memcpy((*uuids)[idxx].id, base64Buff, outLen);
+    } while ( ++idxx < *numUuids);
+
+    return OC_STACK_OK;
+
+exit:
+    return OC_STACK_ERROR;
+
+}
diff --git a/resource/csdk/security/src/svcresource.c b/resource/csdk/security/src/svcresource.c
new file mode 100644 (file)
index 0000000..abd6bc4
--- /dev/null
@@ -0,0 +1,383 @@
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "ocstack.h"
+#include "logger.h"
+#include "oic_malloc.h"
+#include "cJSON.h"
+#include "base64.h"
+#include "resourcemanager.h"
+#include "psinterface.h"
+#include "svcresource.h"
+#include "utlist.h"
+#include "srmresourcestrings.h"
+#include "srmutility.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define TAG  PCF("SRM-SVC")
+
+OicSecSvc_t        *gSvc = NULL;
+static OCResourceHandle    gSvcHandle = NULL;
+
+void DeleteSVCList(OicSecSvc_t* svc)
+{
+    if (svc)
+    {
+        OicSecSvc_t *svcTmp1 = NULL, *svcTmp2 = NULL;
+        LL_FOREACH_SAFE(svc, svcTmp1, svcTmp2)
+        {
+            LL_DELETE(svc, svcTmp1);
+
+            // Clean Owners
+            OICFree(svcTmp1->owners);
+
+            // Clean SVC node itself
+            OICFree(svcTmp1);
+        }
+    }
+}
+
+/*
+ * This internal method converts SVC data into JSON format.
+ *
+ * Note: Caller needs to invoke 'free' when finished done using
+ * return string.
+ */
+char * BinToSvcJSON(const OicSecSvc_t * svc)
+{
+    cJSON *jsonRoot = NULL;
+    char *jsonStr = NULL;
+
+    if (svc)
+    {
+        jsonRoot = cJSON_CreateObject();
+        VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+        cJSON *jsonSvcArray = NULL;
+        cJSON_AddItemToObject (jsonRoot, OIC_JSON_SVC_NAME, jsonSvcArray = cJSON_CreateArray());
+        VERIFY_NON_NULL(TAG, jsonSvcArray, ERROR);
+
+        while(svc)
+        {
+            char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
+            uint32_t outLen = 0;
+            B64Result b64Ret = B64_OK;
+
+            cJSON *jsonSvc = cJSON_CreateObject();
+
+            // Service Device Identity
+            outLen = 0;
+            b64Ret = b64Encode(svc->svcdid.id, sizeof(OicUuid_t), base64Buff,
+                    sizeof(base64Buff), &outLen);
+            VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+            cJSON_AddStringToObject(jsonSvc, OIC_JSON_SERVICE_DEVICE_ID, base64Buff );
+
+            // Service Type
+            cJSON_AddNumberToObject (jsonSvc, OIC_JSON_SERVICE_TYPE, svc->svct);
+
+            // Owners
+            cJSON *jsonOwnrArray = NULL;
+            cJSON_AddItemToObject (jsonSvc, OIC_JSON_OWNERS_NAME, jsonOwnrArray = cJSON_CreateArray());
+            VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
+            for (unsigned int i = 0; i < svc->ownersLen; i++)
+            {
+                outLen = 0;
+
+                b64Ret = b64Encode(svc->owners[i].id, sizeof(((OicUuid_t*)0)->id), base64Buff,
+                        sizeof(base64Buff), &outLen);
+                VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+
+                cJSON_AddItemToArray (jsonOwnrArray, cJSON_CreateString(base64Buff));
+            }
+
+            // Attach current svc node to Svc Array
+            cJSON_AddItemToArray(jsonSvcArray, jsonSvc);
+            svc = svc->next;
+        }
+
+        jsonStr = cJSON_PrintUnformatted(jsonRoot);
+    }
+
+exit:
+    if (jsonRoot)
+    {
+        cJSON_Delete(jsonRoot);
+    }
+    return jsonStr;
+}
+
+/*
+ * This internal method converts JSON SVC into binary SVC.
+ */
+OicSecSvc_t * JSONToSvcBin(const char * jsonStr)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    OicSecSvc_t * headSvc = NULL;
+    OicSecSvc_t * prevSvc = NULL;
+    cJSON *jsonRoot = NULL;
+    cJSON *jsonSvcArray = NULL;
+
+    VERIFY_NON_NULL(TAG, jsonStr, ERROR);
+
+    jsonRoot = cJSON_Parse(jsonStr);
+    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+    jsonSvcArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_SVC_NAME);
+    VERIFY_NON_NULL(TAG, jsonSvcArray, INFO);
+
+    if (cJSON_Array == jsonSvcArray->type)
+    {
+        int numSvc = cJSON_GetArraySize(jsonSvcArray);
+        int idx = 0;
+
+        VERIFY_SUCCESS(TAG, numSvc > 0, INFO);
+        do
+        {
+            cJSON *jsonSvc = cJSON_GetArrayItem(jsonSvcArray, idx);
+            VERIFY_NON_NULL(TAG, jsonSvc, ERROR);
+
+            OicSecSvc_t *svc = (OicSecSvc_t*)OICCalloc(1, sizeof(OicSecSvc_t));
+            VERIFY_NON_NULL(TAG, svc, ERROR);
+
+            headSvc = (headSvc) ? headSvc : svc;
+            if (prevSvc)
+            {
+                prevSvc->next = svc;
+            }
+
+            cJSON *jsonObj = NULL;
+
+            unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
+            uint32_t outLen = 0;
+            B64Result b64Ret = B64_OK;
+
+            // Service Device Identity
+            jsonObj = cJSON_GetObjectItem(jsonSvc, OIC_JSON_SERVICE_DEVICE_ID);
+            VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+            VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
+            outLen = 0;
+            b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
+                        sizeof(base64Buff), &outLen);
+            VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(svc->svcdid.id)), ERROR);
+            memcpy(svc->svcdid.id, base64Buff, outLen);
+
+            // Service Type
+            jsonObj = cJSON_GetObjectItem(jsonSvc, OIC_JSON_SERVICE_TYPE);
+            VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+            VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
+            svc->svct = (OicSecSvcType_t)jsonObj->valueint;
+
+            // Resource Owners
+            jsonObj = cJSON_GetObjectItem(jsonSvc, OIC_JSON_OWNERS_NAME);
+            VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+            VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
+
+            svc->ownersLen = cJSON_GetArraySize(jsonObj);
+            VERIFY_SUCCESS(TAG, svc->ownersLen > 0, ERROR);
+            svc->owners = (OicUuid_t*)OICCalloc(svc->ownersLen, sizeof(OicUuid_t));
+            VERIFY_NON_NULL(TAG, (svc->owners), ERROR);
+
+            size_t idxx = 0;
+            do
+            {
+                cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, idxx);
+                VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
+                VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
+
+                outLen = 0;
+                b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring), base64Buff,
+                            sizeof(base64Buff), &outLen);
+
+                VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(svc->owners[idxx].id)),
+                                    ERROR);
+                memcpy(svc->owners[idxx].id, base64Buff, outLen);
+            } while ( ++idxx < svc->ownersLen);
+
+            prevSvc = svc;
+        } while( ++idx < numSvc);
+    }
+
+    ret = OC_STACK_OK;
+
+exit:
+    cJSON_Delete(jsonRoot);
+    if (OC_STACK_OK != ret)
+    {
+        DeleteSVCList(headSvc);
+        headSvc = NULL;
+    }
+    return headSvc;
+}
+
+static OCEntityHandlerResult HandleSVCGetRequest (const OCEntityHandlerRequest * ehRequest)
+{
+    // Convert SVC data into JSON for transmission
+    char* jsonStr = BinToSvcJSON(gSvc);
+
+    OCEntityHandlerResult ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
+
+    // Send response payload to request originator
+    SendSRMResponse(ehRequest, ehRet, jsonStr);
+
+    OICFree(jsonStr);
+
+    OC_LOG_V (INFO, TAG, PCF("%s RetVal %d"), __func__ , ehRet);
+    return ehRet;
+}
+
+static OCEntityHandlerResult HandleSVCPostRequest (const OCEntityHandlerRequest * ehRequest)
+{
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+    // Convert JSON SVC data into binary. This will also validate the SVC data received.
+    OicSecSvc_t* newSvc = JSONToSvcBin(((OCSecurityPayload*)ehRequest->payload)->securityData);
+
+    if (newSvc)
+    {
+        // Append the new SVC to existing SVC
+        LL_APPEND(gSvc, newSvc);
+
+        // Convert SVC data into JSON for update to persistent storage
+        char *jsonStr = BinToSvcJSON(gSvc);
+        if (jsonStr)
+        {
+            cJSON *jsonSvc = cJSON_Parse(jsonStr);
+            OICFree(jsonStr);
+
+            if ((jsonSvc) &&
+                (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_SVC_NAME, jsonSvc)))
+            {
+                ehRet = OC_EH_RESOURCE_CREATED;
+            }
+            cJSON_Delete(jsonSvc);
+        }
+    }
+
+    // Send payload to request originator
+    SendSRMResponse(ehRequest, ehRet, NULL);
+
+    OC_LOG_V (INFO, TAG, PCF("%s RetVal %d"), __func__ , ehRet);
+    return ehRet;
+}
+
+/*
+ * This internal method is the entity handler for SVC resources and
+ * will handle REST request (GET/PUT/POST/DEL) for them.
+ */
+OCEntityHandlerResult SVCEntityHandler (OCEntityHandlerFlag flag,
+                                        OCEntityHandlerRequest * ehRequest,
+                                        void* callbackParameter)
+{
+    (void) callbackParameter;
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+    if (!ehRequest)
+    {
+        return ehRet;
+    }
+
+    if (flag & OC_REQUEST_FLAG)
+    {
+        switch (ehRequest->method)
+        {
+            case OC_REST_GET:
+                ehRet = HandleSVCGetRequest(ehRequest);
+                break;
+
+            case OC_REST_POST:
+                ehRet = HandleSVCPostRequest(ehRequest);
+                break;
+
+            default:
+                ehRet = OC_EH_ERROR;
+                SendSRMResponse(ehRequest, ehRet, NULL);
+        }
+    }
+
+    return ehRet;
+}
+
+/*
+ * This internal method is used to create '/oic/sec/svc' resource.
+ */
+OCStackResult CreateSVCResource()
+{
+    OCStackResult ret;
+
+    ret = OCCreateResource(&gSvcHandle,
+                           OIC_RSRC_TYPE_SEC_SVC,
+                           OIC_MI_DEF,
+                           OIC_RSRC_SVC_URI,
+                           SVCEntityHandler,
+                           NULL,
+                           OC_OBSERVABLE);
+
+    if (OC_STACK_OK != ret)
+    {
+        OC_LOG (FATAL, TAG, PCF("Unable to instantiate SVC resource"));
+        DeInitSVCResource();
+    }
+    return ret;
+}
+
+
+OCStackResult InitSVCResource()
+{
+    OCStackResult ret = OC_STACK_ERROR;
+
+    OC_LOG_V (INFO, TAG, PCF("Begin %s "), __func__ );
+
+    // Read SVC resource from PS
+    char* jsonSVRDatabase = GetSVRDatabase();
+
+    if (jsonSVRDatabase)
+    {
+        // Convert JSON SVC into binary format
+        gSvc = JSONToSvcBin(jsonSVRDatabase);
+        OICFree(jsonSVRDatabase);
+    }
+
+    // Instantiate 'oic.sec.svc'
+    ret = CreateSVCResource();
+
+    if (OC_STACK_OK != ret)
+    {
+        DeInitSVCResource();
+    }
+
+    OC_LOG_V (INFO, TAG, PCF("%s RetVal %d"), __func__ , ret);
+    return ret;
+}
+
+/**
+ * Perform cleanup for SVC resources.
+ *
+ * @retval  none
+ */
+void DeInitSVCResource()
+{
+    OCDeleteResource(gSvcHandle);
+    gSvcHandle = NULL;
+
+    DeleteSVCList(gSvc);
+    gSvc = NULL;
+}
+
index d1193ac..be35bb3 100644 (file)
@@ -75,7 +75,10 @@ unittest = srmtest_env.Program('unittest', ['aclresourcetest.cpp',
                                             'securityresourcemanager.cpp',
                                             'credentialresource.cpp',
                                             'srmutility.cpp',
-                                            'base64tests.cpp'])
+                                            'iotvticalendartest.cpp',
+                                            'base64tests.cpp',
+                                            'svcresourcetest.cpp',
+                                            'srmtestcommon.cpp'])
 
 Alias("test", [unittest])
 
index 5dd5a6a..9bbca6c 100644 (file)
 #include "ocstack.h"
 #include "ocpayload.h"
 #include "oic_malloc.h"
+#include "oic_string.h"
 #include "cJSON.h"
 #include "cainterface.h"
 #include "secureresourcemanager.h"
 #include "securevirtualresourcetypes.h"
 #include "srmresourcestrings.h"
 #include "aclresource.h"
+#include "srmtestcommon.h"
+#include "srmutility.h"
+#include "logger.h"
 
 using namespace std;
 
+#define TAG  PCF("SRM-ACL-UT")
+
 #ifdef __cplusplus
 extern "C" {
 #endif
+
 extern char * BinToAclJSON(const OicSecAcl_t * acl);
 extern OicSecAcl_t * JSONToAclBin(const char * jsonStr);
-char* ReadFile(const char* filename);
 extern void DeleteACLList(OicSecAcl_t* acl);
 OCStackResult  GetDefaultACL(OicSecAcl_t** defaultAcl);
 OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag,
@@ -55,56 +61,6 @@ const char* ACL1_JSON_FILE_NAME = "oic_unittest_acl1.json";
 
 #define NUM_ACE_FOR_WILDCARD_IN_ACL1_JSON (2)
 
-char* ReadFile(const char* filename)
-{
-
-    FILE *fp = NULL;
-    char *data = NULL;
-    struct stat st;
-    // TODO: Find the location of the executable and concatenate the SVR file name
-    // before opening it.
-    fp = fopen(filename, "r");
-    if (fp)
-    {
-        if (stat(filename, &st) == 0)
-        {
-            data = (char*)OICMalloc(st.st_size);
-            if (data)
-            {
-                if (fread(data, 1, st.st_size, fp) != (size_t)st.st_size)
-                {
-                    printf("Error in reading file %s", filename);
-                }
-            }
-        }
-        fclose(fp);
-    }
-    else
-    {
-        printf("Unable to open %s file", filename);
-    }
-
-    return data;
-}
-
-void SetPersistentHandler(OCPersistentStorage *ps, bool set)
-{
-    if (set)
-    {
-        ps->open = fopen;
-        ps->read = fread;
-        ps->write = fwrite;
-        ps->close = fclose;
-        ps->unlink = unlink;
-    }
-    else
-    {
-        memset(ps, 0, sizeof(OCPersistentStorage));
-    }
-    EXPECT_EQ(OC_STACK_OK,
-            OCRegisterPersistentStorageHandler(ps));
-}
-
 // JSON Marshalling Tests
 TEST(ACLResourceTest, JSONMarshallingTests)
 {
@@ -181,14 +137,14 @@ TEST(ACLResourceTest, GetDefaultACLTests)
 // 'POST' ACL tests
 TEST(ACLResourceTest, ACLPostTest)
 {
-    OCEntityHandlerRequest ehReq = {};
+    OCEntityHandlerRequest ehReq =  OCEntityHandlerRequest();
 
     // Read an ACL from the file
     char *jsonStr = ReadFile(ACL1_JSON_FILE_NAME);
     if (jsonStr)
     {
-        static OCPersistentStorage ps =
-        { };
+        static OCPersistentStorage ps = OCPersistentStorage();
+
         SetPersistentHandler(&ps, true);
 
         // Create Entity Handler POST request payload
@@ -249,4 +205,143 @@ TEST(ACLResourceTest, GetACLResourceTests)
         OICFree(jsonStr);
     }
 }
+//'DELETE' ACL test
+TEST(ACLResourceTest, ACLDeleteWithSingleResourceTest)
+{
+    OCEntityHandlerRequest ehReq = OCEntityHandlerRequest();
+    static OCPersistentStorage ps = OCPersistentStorage();
+    char *jsonStr = NULL;
+    OicSecAcl_t acl = OicSecAcl_t();
+    OicSecAcl_t* savePtr = NULL;
+    const OicSecAcl_t* subjectAcl1 = NULL;
+    const OicSecAcl_t* subjectAcl2 = NULL;
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+    char query[] = "sub=MjIyMjIyMjIyMjIyMjIyMg==;rsrc=/a/led";
+
+    SetPersistentHandler(&ps, true);
+
+    //ACE to POST
+    memcpy(acl.subject.id, "2222222222222222", sizeof(acl.subject.id));
+    acl.resourcesLen = 1;
+    acl.resources = (char**)OICCalloc(acl.resourcesLen, sizeof(char*));
+    VERIFY_NON_NULL(TAG, acl.resources, ERROR);
+    acl.resources[0] = (char*)OICMalloc(strlen("/a/led")+1);
+    VERIFY_NON_NULL(TAG, acl.resources[0], ERROR);
+    OICStrcpy(acl.resources[0], sizeof(acl.resources[0]), "/a/led");
+    acl.permission = 6;
+    acl.ownersLen = 1;
+    acl.owners = (OicUuid_t*)OICCalloc(acl.ownersLen, sizeof(OicUuid_t));
+    VERIFY_NON_NULL(TAG, acl.owners, ERROR);
+    memcpy(acl.owners->id, "1111111111111111", sizeof(acl.owners->id));
+
+    //GET json POST payload
+    jsonStr = BinToAclJSON(&acl);
+    VERIFY_NON_NULL(TAG, jsonStr, ERROR);
+
+    // Create Entity Handler POST request payload
+    ehReq.method = OC_REST_POST;
+    ehReq.payload = (OCPayload*)OCSecurityPayloadCreate(jsonStr);
+    ehRet = ACLEntityHandler(OC_REQUEST_FLAG, &ehReq);
+    EXPECT_TRUE(OC_EH_ERROR == ehRet);
+
+    // Verify if SRM contains ACE for the subject
+    savePtr = NULL;
+    subjectAcl1 = GetACLResourceData(&acl.subject, &savePtr);
+    EXPECT_TRUE(NULL != subjectAcl1);
+
+    // Create Entity Handler DELETE request
+    ehReq.method = OC_REST_DELETE;
+    ehReq.query = (char*)OICMalloc(strlen(query)+1);
+    VERIFY_NON_NULL(TAG, ehReq.query, ERROR);
+    OICStrcpy(ehReq.query, strlen(query)+1, query);
+    ehRet = ACLEntityHandler(OC_REQUEST_FLAG, &ehReq);
+    EXPECT_TRUE(OC_EH_ERROR == ehRet);
+
+    // Verify if SRM has deleted ACE for the subject
+    savePtr = NULL;
+    subjectAcl2 = GetACLResourceData(&acl.subject, &savePtr);
+    EXPECT_TRUE(NULL == subjectAcl2);
+
+exit:
+    // Perform cleanup
+    if(NULL != subjectAcl1)
+    {
+        DeInitACLResource();
+    }
+    OCPayloadDestroy(ehReq.payload);
+    OICFree(ehReq.query);
+    OICFree(jsonStr);
+
+}
+
+TEST(ACLResourceTest, ACLDeleteWithMultiResourceTest)
+{
+    OCEntityHandlerRequest ehReq = OCEntityHandlerRequest();
+    static OCPersistentStorage ps = OCPersistentStorage();
+    OicSecAcl_t acl = OicSecAcl_t();
+    char *jsonStr = NULL;
+    OicSecAcl_t* savePtr = NULL;
+    const OicSecAcl_t* subjectAcl1 = NULL;
+    const OicSecAcl_t* subjectAcl2 = NULL;
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+    char query[] = "sub=MjIyMjIyMjIyMjIyMjIyMg==;rsrc=/a/led";
+
+    SetPersistentHandler(&ps, true);
+
+    memcpy(acl.subject.id, "2222222222222222", sizeof(acl.subject.id));
+    acl.resourcesLen = 2;
+    acl.resources = (char**)OICCalloc(acl.resourcesLen, sizeof(char*));
+    VERIFY_NON_NULL(TAG, acl.resources, ERROR);
+    acl.resources[0] = (char*)OICMalloc(strlen("/a/led")+1);
+    VERIFY_NON_NULL(TAG, acl.resources[0], ERROR);
+    OICStrcpy(acl.resources[0], sizeof(acl.resources[0]), "/a/led");
+    acl.resources[1] = (char*)OICMalloc(strlen("/a/fan")+1);
+    VERIFY_NON_NULL(TAG, acl.resources[1], ERROR);
+    OICStrcpy(acl.resources[1], sizeof(acl.resources[1]), "/a/fan");
+    acl.permission = 6;
+    acl.ownersLen = 1;
+    acl.owners = (OicUuid_t*)OICCalloc(acl.ownersLen, sizeof(OicUuid_t));
+    VERIFY_NON_NULL(TAG, acl.owners, ERROR);
+    memcpy(acl.owners->id, "1111111111111111", sizeof(acl.owners->id));
+
+    jsonStr = BinToAclJSON(&acl);
+    VERIFY_NON_NULL(TAG, jsonStr, ERROR);
+
+    // Create Entity Handler POST request payload
+    ehReq.method = OC_REST_POST;
+    ehReq.payload = (OCPayload*)OCSecurityPayloadCreate(jsonStr);
+    ehRet = ACLEntityHandler(OC_REQUEST_FLAG, &ehReq);
+    EXPECT_TRUE(OC_EH_ERROR == ehRet);
+
+    // Verify if SRM contains ACE for the subject with two resources
+    savePtr = NULL;
+    subjectAcl1 = GetACLResourceData(&acl.subject, &savePtr);
+    EXPECT_TRUE(NULL != subjectAcl1);
+    EXPECT_TRUE(subjectAcl1->resourcesLen == 2);
+
+    // Create Entity Handler DELETE request
+    ehReq.method = OC_REST_DELETE;
+    ehReq.query = (char*)OICMalloc(strlen(query)+1);
+    VERIFY_NON_NULL(TAG, ehReq.query, ERROR);
+    OICStrcpy(ehReq.query, strlen(query)+1, query);
+
+    ehRet = ACLEntityHandler(OC_REQUEST_FLAG, &ehReq);
+    EXPECT_TRUE(OC_EH_ERROR == ehRet);
+
+    // Verify if SRM contains ACL for the subject but only with one resource
+    savePtr = NULL;
+    subjectAcl2 = GetACLResourceData(&acl.subject, &savePtr);
+    EXPECT_TRUE(NULL != subjectAcl2);
+    EXPECT_TRUE(subjectAcl2->resourcesLen == 1);
+
+exit:
+    // Perform cleanup
+    if(NULL != subjectAcl1)
+    {
+        DeInitACLResource();
+    }
+    OCPayloadDestroy(ehReq.payload);
+    OICFree(ehReq.query);
+    OICFree(jsonStr);
+}
 
index 962b9cc..1ee9238 100644 (file)
 
 #include "gtest/gtest.h"
 #include "ocstack.h"
+#include "ocpayload.h"
 #include "resourcemanager.h"
 #include "securevirtualresourcetypes.h"
 #include "credresource.h"
 #include "oic_malloc.h"
 #include "oic_string.h"
+#include "srmtestcommon.h"
+#include "srmutility.h"
 #include "logger.h"
 
 #define TAG PCF("SRM-CRED-UT")
@@ -40,76 +43,73 @@ OicSecCred_t * JSONToCredBin(const char * jsonStr);
 void InitSecCredInstance(OicSecCred_t * cred);
 void DeleteCredList(OicSecCred_t* cred);
 const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject);
+
 #ifdef __cplusplus
 }
 #endif
 
+
 OicSecCred_t * getCredList()
 {
-    OicSecCred_t * cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
-    if(!cred)
-    {
-        return NULL;
-    }
+
+    OicSecCred_t * cred = NULL;
+    size_t sz = 0;
+
+    cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
+    VERIFY_NON_NULL(TAG, cred, ERROR);
     cred->credId = 1234;
     OICStrcpy((char *)cred->subject.id, sizeof(cred->subject.id), "subject1");
 
 #if 0
     cred->roleIdsLen = 2;
     cred->roleIds = (OicSecRole_t *)OICCalloc(cred->roleIdsLen, sizeof(OicSecRole_t));
+    VERIFY_NON_NULL(TAG, cred->roleIds, ERROR);
     OICStrcpy((char *)cred->roleIds[0].id, sizeof(cred->roleIds[0].id), "role11");
     OICStrcpy((char *)cred->roleIds[1].id, sizeof(cred->roleIds[1].id), "role12");
+
 #endif
 
     cred->credType = 1;
+    cred->privateData.data = (char *)OICCalloc(1, strlen("My private Key11") + 1);
+    VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
+    strcpy(cred->privateData.data, "My private Key11");
     cred->ownersLen = 1;
     cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
-    if(!cred->owners)
-    {
-        OICFree(cred);
-        return NULL;
-    }
+    VERIFY_NON_NULL(TAG, cred->owners, ERROR);
     OICStrcpy((char *)cred->owners[0].id, sizeof(cred->owners[0].id), "ownersId11");
 
     cred->next = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
-    if(!cred->next)
-    {
-        OICFree(cred->owners);
-        OICFree(cred);
-        return NULL;
-    }
+    VERIFY_NON_NULL(TAG, cred->next, ERROR);
     cred->next->credId = 5678;
     OICStrcpy((char *)cred->next->subject.id, sizeof(cred->next->subject.id), "subject2");
 #if 0
     cred->next->roleIdsLen = 0;
 #endif
     cred->next->credType = 1;
-    size_t data_size = strlen("My private Key21") + 1;
-    cred->next->privateData.data = (char *)OICCalloc(1, data_size);
-    if(!cred->next->privateData.data)
-    {
-        OICFree(cred->next);
-        OICFree(cred->owners);
-        OICFree(cred);
-        return NULL;
-    }
-    OICStrcpy(cred->next->privateData.data, data_size,"My private Key21");
+    sz = strlen("My private Key21") + 1;
+    cred->next->privateData.data = (char *)OICCalloc(1, sz);
+    VERIFY_NON_NULL(TAG, cred->next->privateData.data, ERROR);
+    OICStrcpy(cred->next->privateData.data, sz,"My private Key21");
 #if 0
-    cred->next->publicData.data = (char *)OICCalloc(1, strlen("My Public Key123") + 1);
-    OICStrcpy(cred->next->publicData.data, sizeof(cred->next->publicData.data),"My Public Key123");
+    sz = strlen("My Public Key123") + 1
+    cred->next->publicData.data = (char *)OICCalloc(1, sz);
+    VERIFY_NON_NULL(TAG, cred->next->publicData.data, ERROR);
+    OICStrcpy(cred->next->publicData.data, sz,"My Public Key123");
 #endif
     cred->next->ownersLen = 2;
     cred->next->owners = (OicUuid_t*)OICCalloc(cred->next->ownersLen, sizeof(OicUuid_t));
-    if(!cred->next->owners)
-    {
-        OICFree(cred->next->privateData.data);
-        OICFree(cred->next);
-        OICFree(cred->owners);
-        OICFree(cred);
-        return NULL;
-    }
+    VERIFY_NON_NULL(TAG, cred->next->owners, ERROR);
     OICStrcpy((char *)cred->next->owners[0].id, sizeof(cred->next->owners[0].id), "ownersId21");
     OICStrcpy((char *)cred->next->owners[1].id, sizeof(cred->next->owners[1].id), "ownersId22");
+
+    return cred;
+
+exit:
+    if(cred)
+    {
+        DeleteCredList(cred);
+        cred = NULL;
+    }
     return cred;
 }
 
@@ -161,18 +161,75 @@ TEST(CreateCredResourceTest, CreateCredResource)
 TEST(CredEntityHandlerTest, CredEntityHandlerWithDummyRequest)
 {
     OCEntityHandlerRequest req;
-    EXPECT_EQ(OC_EH_ERROR, CredEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, &req));
+    EXPECT_EQ(OC_EH_ERROR,
+            CredEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, &req));
 }
 
 TEST(CredEntityHandlerTest, CredEntityHandlerWithNULLRequest)
 {
-    EXPECT_EQ(OC_EH_ERROR, CredEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, NULL));
+    EXPECT_EQ(OC_EH_ERROR,
+            CredEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, NULL));
 }
 
 TEST(CredEntityHandlerTest, CredEntityHandlerInvalidFlag)
 {
     OCEntityHandlerRequest req;
-    EXPECT_EQ(OC_EH_ERROR, CredEntityHandler(OCEntityHandlerFlag::OC_OBSERVE_FLAG, &req));
+    EXPECT_EQ(OC_EH_ERROR,
+            CredEntityHandler(OCEntityHandlerFlag::OC_OBSERVE_FLAG, &req));
+}
+
+//Cred DELETE request
+TEST(CredEntityHandlerTest, CredEntityHandlerDeleteTest)
+{
+    OCEntityHandlerRequest ehReq =  OCEntityHandlerRequest();
+    static OCPersistentStorage ps =  OCPersistentStorage();
+    const OicSecCred_t* subjectCred1 = NULL;
+    const OicSecCred_t* subjectCred2 = NULL;
+    char *jsonStr = NULL;
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+    char query[] = "sub=c3ViamVjdDE=";
+
+    SetPersistentHandler(&ps, true);
+
+    OicSecCred_t *cred = getCredList();
+    VERIFY_NON_NULL(TAG, cred, ERROR);
+
+    jsonStr = BinToCredJSON(cred);
+    VERIFY_NON_NULL(TAG, jsonStr, ERROR);
+
+    // Create Entity Handler POST request payload
+    ehReq.method = OC_REST_POST;
+    ehReq.payload = (OCPayload*)OCSecurityPayloadCreate(jsonStr);
+    ehRet = CredEntityHandler(OC_REQUEST_FLAG, &ehReq);
+    EXPECT_TRUE(OC_EH_ERROR == ehRet);
+
+    // Verify if SRM contains Credential for the subject
+    subjectCred1 = GetCredResourceData(&cred->subject);
+    EXPECT_TRUE(NULL != subjectCred1);
+
+   // Create Entity Handler DELETE request
+   ehReq.method = OC_REST_DELETE;
+   ehReq.query = (char*)OICMalloc(strlen(query)+1);
+   VERIFY_NON_NULL(TAG, ehReq.query, ERROR);
+   OICStrcpy(ehReq.query, strlen(query)+1, query);
+
+   ehRet = CredEntityHandler(OC_REQUEST_FLAG, &ehReq);
+   EXPECT_TRUE(OC_EH_ERROR == ehRet);
+
+   // Verify if SRM has deleted ACE for the subject
+   subjectCred2 = GetCredResourceData(&cred->subject);
+   EXPECT_TRUE(NULL == subjectCred2);
+
+exit:
+   // Perform cleanup
+   OICFree(ehReq.query);
+   OICFree(jsonStr);
+   OCPayloadDestroy(ehReq.payload);
+   if(NULL != cred)
+   {
+       DeInitCredResource();
+       DeleteCredList(cred);
+   }
 }
 
 //BinToCredJSON Tests
@@ -189,6 +246,7 @@ TEST(BinToCredJSONTest, BinToCredJSONValidCred)
 
     json = BinToCredJSON(cred);
 
+    OC_LOG_V(INFO, TAG, PCF("BinToCredJSON:%s\n"), json);
     EXPECT_TRUE(json != NULL);
     DeleteCredList(cred);
     OICFree(json);
@@ -202,7 +260,7 @@ TEST(JSONToCredBinTest, JSONToCredBinValidJSON)
 
     EXPECT_TRUE(json != NULL);
     OicSecCred_t *cred2 = JSONToCredBin(json);
-    EXPECT_TRUE(cred2 == NULL);
+    EXPECT_TRUE(cred2 != NULL);
     DeleteCredList(cred1);
     DeleteCredList(cred2);
     OICFree(json);
@@ -225,7 +283,7 @@ TEST(CredGenerateCredentialTest, GenerateCredentialValidInput)
     OicUuid_t owners[1];
     OICStrcpy((char *)owners[0].id, sizeof(owners[0].id), "ownersId21");
 
-    OicUuid_t subject = {0};
+    OicUuid_t subject = {{0}};
     OICStrcpy((char *)subject.id, sizeof(subject.id), "subject11");
 
     char privateKey[] = "My private Key11";
@@ -236,6 +294,7 @@ TEST(CredGenerateCredentialTest, GenerateCredentialValidInput)
                              privateKey, 1, owners);
     printCred(cred);
 
+    EXPECT_TRUE(NULL != cred);
     DeleteCredList(cred);
 }
 
@@ -244,7 +303,7 @@ TEST(GenerateAndAddCredentialTest, GenerateAndAddCredentialValidInput)
     OicUuid_t owners[1];
     OICStrcpy((char *)owners[0].id, sizeof(owners[0].id), "ownersId11");
 
-    OicUuid_t subject = {0};
+    OicUuid_t subject = {{0}};
     OICStrcpy((char *)subject.id, sizeof(subject.id), "subject11");
 
     char privateKey[] = "My private Key11";
index 5d68e03..cfee71a 100644 (file)
 #include "ocserverrequest.h"
 #include "oic_string.h"
 #include "oic_malloc.h"
+#include "logger.h"
+
+#define TAG  PCF("SRM-DOXM")
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+
 //Declare Doxm resource methods for testing
 OCStackResult CreateDoxmResource();
 OCEntityHandlerResult DoxmEntityHandler (OCEntityHandlerFlag flag,
@@ -44,6 +48,7 @@ OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehReq
 }
 #endif
 
+
 OicSecDoxm_t * getBinDoxm()
 {
     OicSecDoxm_t * doxm = (OicSecDoxm_t*)OICCalloc(1, sizeof(OicSecDoxm_t));
@@ -126,8 +131,8 @@ TEST(DoxmEntityHandlerTest, DoxmEntityHandlerInvalidFlag)
 TEST(DoxmEntityHandlerTest, DoxmEntityHandlerValidRequest)
 {
     EXPECT_EQ(OC_STACK_INVALID_PARAM, InitDoxmResource());
-    char query[] = "oxm=0&owned=false&owner=owner1";
-    OCEntityHandlerRequest req = {0};
+    char query[] = "oxm=0;owned=false;owner=owner1";
+    OCEntityHandlerRequest req = OCEntityHandlerRequest();
     req.method = OC_REST_GET;
     req.query = OICStrdup(query);
     EXPECT_EQ(OC_EH_ERROR, DoxmEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, &req));
@@ -147,6 +152,7 @@ TEST(BinToDoxmJSONTest, BinToDoxmJSONValidDoxm)
     OicSecDoxm_t * doxm =  getBinDoxm();
 
     char * json = BinToDoxmJSON(doxm);
+    OC_LOG_V(INFO, TAG, PCF("BinToDoxmJSON:%s"), json);
     EXPECT_TRUE(json != NULL);
 
     DeleteDoxmBinData(doxm);
diff --git a/resource/csdk/security/unittest/iotvticalendartest.cpp b/resource/csdk/security/unittest/iotvticalendartest.cpp
new file mode 100644 (file)
index 0000000..2d207cd
--- /dev/null
@@ -0,0 +1,302 @@
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+//Not supported on Arduino due lack of absolute time need to implement iCalendar
+#ifndef WITH_ARDUINO
+
+#include "gtest/gtest.h"
+#include "iotvticalendar.h"
+#include "logger.h"
+
+#define TAG  PCF("CALENDAR-UT")
+
+static void printPeriod(IotvtICalPeriod_t *period)
+{
+    if(NULL == period)
+    {
+        return;
+    }
+
+    OC_LOG_V(INFO, TAG, PCF("period->startDateTime.tm_year = %d"),period->startDateTime.tm_year);
+    OC_LOG_V(INFO, TAG, PCF("period->startDateTime.tm_mon = %d"),period->startDateTime.tm_mon);
+    OC_LOG_V(INFO, TAG, PCF("period->startDateTime.tm_mday = %d"),period->startDateTime.tm_mday);
+    OC_LOG_V(INFO, TAG, PCF("period->startDateTime.tm_hour = %d"),period->startDateTime.tm_hour);
+    OC_LOG_V(INFO, TAG, PCF("period->startDateTime.tm_min = %d"),period->startDateTime.tm_min);
+    OC_LOG_V(INFO, TAG, PCF("period->startDateTime.tm_sec = %d"),period->startDateTime.tm_sec);
+
+    OC_LOG_V(INFO, TAG, PCF("period->endDateTime.tm_year = %d"),period->endDateTime.tm_year);
+    OC_LOG_V(INFO, TAG, PCF("period->endDateTime.tm_mon = %d"),period->endDateTime.tm_mon);
+    OC_LOG_V(INFO, TAG, PCF("period->endDateTime.tm_mday = %d"),period->endDateTime.tm_mday);
+    OC_LOG_V(INFO, TAG, PCF("period->endDateTime.tm_hour = %d"),period->endDateTime.tm_hour);
+    OC_LOG_V(INFO, TAG, PCF("period->endDateTime.tm_min = %d"),period->endDateTime.tm_min);
+    OC_LOG_V(INFO, TAG, PCF("period->startDateTime.tm_sec = %d"),period->endDateTime.tm_sec);
+}
+
+
+static void printRecur(IotvtICalRecur_t *recur)
+{
+    OC_LOG_V(INFO, TAG, PCF("recur->freq = %d"), recur->freq);
+    OC_LOG_V(INFO, TAG, PCF("recur->until.tm_year = %d"), recur->until.tm_year);
+    OC_LOG_V(INFO, TAG, PCF("recur->until.tm_mon = %d"), recur->until.tm_mon);
+    OC_LOG_V(INFO, TAG, PCF("recur->until.tm_mday = %d"), recur->until.tm_mday);
+
+    if(recur->byDay & SUNDAY)
+    {
+        OC_LOG_V(INFO, TAG, PCF("recur->byDay = %s"), "Sunday");
+    }
+    if(recur->byDay & MONDAY)
+    {
+        OC_LOG_V(INFO, TAG, PCF("recur->byDay = %s"), "Monday");
+    }
+    if(recur->byDay & TUESDAY)
+    {
+        OC_LOG_V(INFO, TAG, PCF("recur->byDay = %s"), "Tuesday");
+    }
+    if(recur->byDay & WEDNESDAY)
+    {
+        OC_LOG_V(INFO, TAG, PCF("recur->byDay = %s"), "Wednesday");
+    }
+    if(recur->byDay & THURSDAY)
+    {
+        OC_LOG_V(INFO, TAG, PCF("recur->byDay = %s"), "Thursday");
+    }
+    if(recur->byDay & FRIDAY)
+    {
+        OC_LOG_V(INFO, TAG, PCF("recur->byDay = %s"), "Friday");
+    }
+    if(recur->byDay & SATURDAY)
+    {
+        OC_LOG_V(INFO, TAG, PCF("recur->byDay = %s"), "Saturday");
+    }
+}
+
+//ParsePeriod Tests
+TEST(ParsePeriodTest, ParsePeriodValidDateTime)
+{
+    char periodStr[] = "20150629T153050/20150630T233055";
+    IotvtICalPeriod_t period = IotvtICalPeriod_t();
+    EXPECT_EQ(IOTVTICAL_SUCCESS, ParsePeriod(periodStr,&period));
+    printPeriod(&period);
+}
+
+TEST(ParsePeriodTest, ParsePeriodValidDate)
+{
+    char periodStr[] = "20150629/20150630";
+    IotvtICalPeriod_t period = IotvtICalPeriod_t();
+    EXPECT_EQ(IOTVTICAL_SUCCESS, ParsePeriod(periodStr,&period));
+    printPeriod(&period);
+}
+
+TEST(ParsePeriodTest, ParsePeriodMismatchStartDTEndDT1)
+{
+    char periodStr[] = "20150629T153050/20150630";
+    IotvtICalPeriod_t period = IotvtICalPeriod_t();
+    EXPECT_EQ(IOTVTICAL_INVALID_PERIOD, ParsePeriod(periodStr,&period));
+}
+
+TEST(ParsePeriodTest, ParsePeriodMismatchStartDTEndDT2)
+{
+    char periodStr[] = "20150629/20150630T203055";
+    IotvtICalPeriod_t period = IotvtICalPeriod_t();
+    EXPECT_EQ(IOTVTICAL_INVALID_PERIOD, ParsePeriod(periodStr,&period));
+}
+
+TEST(ParsePeriodTest, ParsePeriodInvalidStartDT1)
+{
+    char periodStr[] = "20150629T1530/20150630T203055";
+    IotvtICalPeriod_t period = IotvtICalPeriod_t();
+    EXPECT_EQ(IOTVTICAL_INVALID_PERIOD, ParsePeriod(periodStr,&period));
+}
+
+TEST(ParsePeriodTest, ParsePeriodInvalidEndtDT2)
+{
+    char periodStr[] = "20150629T153050/20150630203055";
+    IotvtICalPeriod_t period = IotvtICalPeriod_t();
+    EXPECT_EQ(IOTVTICAL_INVALID_PERIOD, ParsePeriod(periodStr,&period));
+}
+
+TEST(ParsePeriodTest, ParsePeriodInvalidStartD3)
+{
+    char periodStr[] = "201506/20150630";
+    IotvtICalPeriod_t period = IotvtICalPeriod_t();
+    EXPECT_EQ(IOTVTICAL_INVALID_PERIOD, ParsePeriod(periodStr,&period));
+}
+
+TEST(ParsePeriodTest, ParsePeriodInvalidEndD4)
+{
+    char periodStr[] = "20150629/201530";
+    IotvtICalPeriod_t period = IotvtICalPeriod_t();
+    EXPECT_EQ(IOTVTICAL_INVALID_PERIOD, ParsePeriod(periodStr,&period));
+}
+
+TEST(ParsePeriodTest, ParsePeriodEndDTBeforeStartDT)
+{
+    char periodStr[] = "20150630T203055/20150629T153050";
+    IotvtICalPeriod_t period = IotvtICalPeriod_t();
+    EXPECT_EQ(IOTVTICAL_INVALID_PERIOD, ParsePeriod(periodStr,&period));
+}
+TEST(ParsePeriodTest, ParsePeriodEndDBeforeStartD)
+{
+    char periodStr[] = "20150630/20150629";
+    IotvtICalPeriod_t period = IotvtICalPeriod_t();
+    EXPECT_EQ(IOTVTICAL_INVALID_PERIOD, ParsePeriod(periodStr,&period));
+}
+
+TEST(ParseRecurTest, ParseRecurValid1)
+{
+    char recurStr[] = "FREQ=DAILY; UNTIL=20150703; BYDAY=MO, WE, FR";
+    IotvtICalRecur_t recur = IotvtICalRecur_t();
+    EXPECT_EQ(IOTVTICAL_SUCCESS, ParseRecur(recurStr, &recur));
+    printRecur(&recur);
+}
+
+TEST(ParseRecurTest, ParseRecurValid2)
+{
+    char recurStr[] = "FREQ=DAILY";
+    IotvtICalRecur_t recur =  IotvtICalRecur_t();
+    EXPECT_EQ(IOTVTICAL_SUCCESS, ParseRecur(recurStr, &recur));
+    printRecur(&recur);
+}
+
+TEST(ParseRecurTest, ParseRecurInValidFreq1)
+{
+    char recurStr[] = "FREQ=WEEKLY; UNTIL=20150703; BYDAY=TU";
+    IotvtICalRecur_t recur = IotvtICalRecur_t();
+    EXPECT_EQ(IOTVTICAL_INVALID_RRULE, ParseRecur(recurStr, &recur));
+}
+
+TEST(ParseRecurTest, ParseRecurInValidFreq2)
+{
+    char recurStr[] = "UNTIL=20150703; BYDAY=TU";
+    IotvtICalRecur_t recur =  IotvtICalRecur_t();
+    EXPECT_EQ(IOTVTICAL_INVALID_RRULE, ParseRecur(recurStr, &recur));
+}
+
+TEST(ParseRecurTest, ParseRecurInValidUntil)
+{
+    char recurStr[] = "FREQ=DAILY; UNTIL=20150703T095055; BYDAY=MO, WE, FR";
+    IotvtICalRecur_t recur = IotvtICalRecur_t();
+    EXPECT_EQ(IOTVTICAL_INVALID_RRULE, ParseRecur(recurStr, &recur));
+}
+
+TEST(ParseRecurTest, ParseRecurInValidByday)
+{
+    char recurStr[] = "FREQ=DAILY; UNTIL=20150703; BYDAY=";
+    IotvtICalRecur_t recur = IotvtICalRecur_t();
+    EXPECT_EQ(IOTVTICAL_INVALID_RRULE, ParseRecur(recurStr, &recur));
+}
+
+//FIXME: ALL IsRequestWithinValidTime tests will fail after 20151230
+TEST(IsRequestWithinValidTimeTest, IsRequestWithinValidTimeValidPeriod1)
+{
+    char periodStr[] = "20150630/20151230";
+    EXPECT_EQ(IOTVTICAL_VALID_ACCESS, IsRequestWithinValidTime(periodStr, NULL));
+}
+
+TEST(IsRequestWithinValidTimeTest, IsRequestWithinValidTimeValidPeriodAndRecur1)
+{
+    //Daily on days MO, WE & FR from 6:00:00am to 8:00:00pm until 20151230
+    char recurStr[] = "FREQ=DAILY; UNTIL=20151230; BYDAY=MO, WE, FR";
+    char periodStr[] = "20150630T060000/20150630T200000";
+
+    time_t rt = time(0);
+    IotvtICalDateTime_t *ct = localtime(&rt);
+
+    int byDay = MONDAY | WEDNESDAY | FRIDAY;
+    int isValidWD = (0x1 << ct->tm_wday) & byDay;
+
+    if(isValidWD && 6 <= ct->tm_hour && 20>= ct->tm_hour)
+    {
+        EXPECT_EQ(IOTVTICAL_VALID_ACCESS, IsRequestWithinValidTime(periodStr, recurStr));
+    }
+    else
+    {
+        EXPECT_EQ(IOTVTICAL_INVALID_ACCESS, IsRequestWithinValidTime(periodStr, recurStr));
+    }
+}
+
+TEST(IsRequestWithinValidTimeTest, IsRequestWithinValidTimeValidPeriodAndRecur2)
+{
+    //Daily forever from 6:00:00am to 8:00:00pm
+    char recurStr[] = "FREQ=DAILY";
+    char periodStr[] = "20150630T060000/20150630T200000";
+
+    time_t rt = time(0);
+    IotvtICalDateTime_t *ct = localtime(&rt);
+
+    if(6 <= ct->tm_hour && 20>= ct->tm_hour)
+    {
+        EXPECT_EQ(IOTVTICAL_VALID_ACCESS, IsRequestWithinValidTime(periodStr, recurStr));
+    }
+    else
+    {
+        EXPECT_EQ(IOTVTICAL_INVALID_ACCESS, IsRequestWithinValidTime(periodStr, recurStr));
+    }
+}
+
+TEST(IsRequestWithinValidTimeTest, IsRequestWithinValidTimeValidPeriodAndRecur3)
+{
+    //Daily until 20151230 from 6:00:00am to 8:00:00pm
+    char recurStr[] = "FREQ=DAILY; UNTIL=20151230";
+    char periodStr[] = "20150630T060000/20150630T200000";
+
+    time_t rt = time(0);
+    IotvtICalDateTime_t *ct = localtime(&rt);
+
+    if(6 <= ct->tm_hour && 20>= ct->tm_hour)
+    {
+        EXPECT_EQ(IOTVTICAL_VALID_ACCESS, IsRequestWithinValidTime(periodStr, recurStr));
+    }
+    else
+    {
+        EXPECT_EQ(IOTVTICAL_INVALID_ACCESS, IsRequestWithinValidTime(periodStr, recurStr));
+    }
+}
+
+TEST(IsRequestWithinValidTimeTest, IsRequestWithinValidTimeValidPeriodAndRecur4)
+{
+    //Daily forever on days MO, WE & Fr from 6:00:00am to 8:00:00pm
+    char recurStr[] = "FREQ=DAILY; BYDAY=MO, WE, FR";
+    char periodStr[] = "20150630T060000/20150630T200000";
+
+    time_t rt = time(0);
+    IotvtICalDateTime_t *ct = localtime(&rt);
+
+    int byDay = MONDAY | WEDNESDAY | FRIDAY;
+    int isValidWD = (0x1 << ct->tm_wday) & byDay;
+
+    if(isValidWD && 6 <= ct->tm_hour && 20>= ct->tm_hour)
+    {
+        EXPECT_EQ(IOTVTICAL_VALID_ACCESS, IsRequestWithinValidTime(periodStr, recurStr));
+    }
+    else
+    {
+        EXPECT_EQ(IOTVTICAL_INVALID_ACCESS, IsRequestWithinValidTime(periodStr, recurStr));
+    }
+}
+
+TEST(IsRequestWithinValidTimeTest, IsRequestWithinValidTimeInValidPeriodAndValidRecur)
+{
+    //Daily forever on days MO, WE & Fr
+    char recurStr[] = "FREQ=DAILY; BYDAY=MO, WE, FR";
+    char periodStr[] = "20150630/20150730";
+
+    EXPECT_EQ(IOTVTICAL_INVALID_ACCESS, IsRequestWithinValidTime(periodStr, recurStr));
+}
+
+#endif
index 9ebfbdd..54cd36a 100644 (file)
                "tm":   48,
                "om":   0,
                "sm":   [3, 1]
-       }
+       },
+
+    "amacl": [
+        {
+            "rsrc": ["/a/led", "/a/fan"],
+            "amss": [
+                "NTU1NTU1NTU1NTU1NTU1NQ==", 
+                "NjY2NjY2NjY2NjY2NjY2Ng=="
+            ],
+                       "ownrs" : [
+                               "MjIyMjIyMjIyMjIyMjIyMg=="
+                       ]
+               },
+        {
+            "rsrc": ["/b/led", "/b/fan"],
+            "amss": [
+                "NTU1NTU1NTU1NTU1NTU1NQ==", 
+                "NjY2NjY2NjY2NjY2NjY2Ng=="
+            ],
+                       "ownrs" : [
+                               "MjIyMjIyMjIyMjIyMjIyMg=="
+                       ]
+               }
+       ],
+
+"svc": [
+        {
+            "svcdid": "NTU1NTU1NTU1NTU1NTU1NQ==",
+                       "svct": 1,
+                       "ownrs" : [
+                               "OTk5OTk5OTk5OTk5OTk5OQ=="
+                       ]
+               },
+        {
+            "svcdid": "NjY2NjY2NjY2NjY2NjY2Ng==",
+                       "svct": 1,
+                       "ownrs" : [
+                               "OTk5OTk5OTk5OTk5OTk5OQ=="
+                       ]
+               }
+       ]
 }
index c899ea5..03c8a68 100644 (file)
@@ -27,6 +27,7 @@
 #include "base64.h"
 #include "cainterface.h"
 #include "secureresourcemanager.h"
+#include "srmtestcommon.h"
 #include "ocpayload.h"
 #include <unistd.h>
 #ifdef __cplusplus
@@ -38,7 +39,6 @@ OCEntityHandlerResult PstatEntityHandler (OCEntityHandlerFlag flag,
                                         OCEntityHandlerRequest * ehRequest);
 char * BinToPstatJSON(const OicSecPstat_t * pstat);
 OicSecPstat_t * JSONToPstatBin(const char * jsonStr);
-char* ReadFile(const char* filename);
 const char* UNIT_TEST_JSON_FILE_NAME = "oic_unittest.json";
 #ifdef __cplusplus
 }
diff --git a/resource/csdk/security/unittest/srmtestcommon.cpp b/resource/csdk/security/unittest/srmtestcommon.cpp
new file mode 100644 (file)
index 0000000..6f51329
--- /dev/null
@@ -0,0 +1,73 @@
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "gtest/gtest.h"
+#include "oic_malloc.h"
+#include "ocstack.h"
+
+char* ReadFile(const char* filename)
+{
+
+    FILE *fp = NULL;
+    char *data = NULL;
+    struct stat st;
+    // TODO: Find the location of the executable and concatenate the SVR file name
+    // before opening it.
+    fp = fopen(filename, "r");
+    if (fp)
+    {
+        if (stat(filename, &st) == 0)
+        {
+            data = (char*)OICMalloc(st.st_size);
+            if (data)
+            {
+                if (fread(data, 1, st.st_size, fp) != (size_t)st.st_size)
+                {
+                    printf("Error in reading file %s", filename);
+                }
+            }
+        }
+        fclose(fp);
+    }
+    else
+    {
+        printf("Unable to open %s file", filename);
+    }
+
+    return data;
+}
+
+void SetPersistentHandler(OCPersistentStorage *ps, bool set)
+{
+    if (set)
+    {
+        ps->open = fopen;
+        ps->read = fread;
+        ps->write = fwrite;
+        ps->close = fclose;
+        ps->unlink = unlink;
+    }
+    else
+    {
+        memset(ps, 0, sizeof(OCPersistentStorage));
+    }
+    EXPECT_EQ(OC_STACK_OK,
+            OCRegisterPersistentStorageHandler(ps));
+}
diff --git a/resource/csdk/security/unittest/srmtestcommon.h b/resource/csdk/security/unittest/srmtestcommon.h
new file mode 100644 (file)
index 0000000..1a8685e
--- /dev/null
@@ -0,0 +1,27 @@
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef IOTVT_SRM_TEST_COMMON_H
+#define IOTVT_SRM_TEST_COMMON_H
+
+char* ReadFile(const char* filename);
+void SetPersistentHandler(OCPersistentStorage *ps, bool set);
+
+#endif //IOTVT_SRM_TEST_COMMON_H
index 225e3e3..0464d5a 100644 (file)
 #include "srmutility.h"
 #include "oic_string.h"
 
-
 //ParseRestQuery Tests
 TEST(ParseRestQueryTest, ParseRestQueryEmpty)
 {
     unsigned char query[] = "";
-    OicParseQueryIter_t parseIter = {0};
+    OicParseQueryIter_t parseIter =  OicParseQueryIter_t();
     ParseQueryIterInit(query, &parseIter);
     EXPECT_EQ(NULL,  GetNextQuery(&parseIter));
 }
 
+
 TEST(ParseRestQueryTest, ParseSingleRestQuery)
 {
     char attr[10], val[10];
     unsigned char query[] = "owned=false";
 
-    OicParseQueryIter_t parseIter = {0};
+    OicParseQueryIter_t parseIter =  OicParseQueryIter_t();
     ParseQueryIterInit(query, &parseIter);
     EXPECT_NE((OicParseQueryIter_t *)NULL,  GetNextQuery(&parseIter));
 
     OICStrcpyPartial(attr, sizeof(attr), (char *)parseIter.attrPos, parseIter.attrLen);
     OICStrcpyPartial(val, sizeof(val), (char *)parseIter.valPos, parseIter.valLen);
     printf("\nAttribute: %s  value: %s\n\n", attr, val);
-
 }
 
 TEST(ParseRestQueryTest, ParseRestMultipleQuery)
 {
     char attr[10], val[10];
-    unsigned char query[] = "oxm=0&owned=true&owner=owner1";
+    unsigned char query[] = "oxm=0;owned=true;owner=owner1";
 
-    OicParseQueryIter_t parseIter = {0};
+    OicParseQueryIter_t parseIter =  OicParseQueryIter_t();
     ParseQueryIterInit(query, &parseIter);
     printf("\n");
     while(GetNextQuery(&parseIter))
diff --git a/resource/csdk/security/unittest/svcresourcetest.cpp b/resource/csdk/security/unittest/svcresourcetest.cpp
new file mode 100644 (file)
index 0000000..5c3f75e
--- /dev/null
@@ -0,0 +1,81 @@
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "gtest/gtest.h"
+#include <pwd.h>
+#include <grp.h>
+#include <linux/limits.h>
+#include <sys/stat.h>
+#include "ocstack.h"
+#include "oic_malloc.h"
+#include "cJSON.h"
+#include "cainterface.h"
+#include "secureresourcemanager.h"
+#include "securevirtualresourcetypes.h"
+#include "srmresourcestrings.h"
+#include "svcresource.h"
+#include "srmtestcommon.h"
+
+using namespace std;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern char * BinToSvcJSON(const OicSecSvc_t * svc);
+extern OicSecSvc_t * JSONToSvcBin(const char * jsonStr);
+extern void DeleteSVCList(OicSecSvc_t* svc);
+#ifdef __cplusplus
+}
+#endif
+
+static const char* JSON_FILE_NAME = "oic_unittest.json";
+
+#define NUM_SVC_IN_JSON_DB (2)
+
+
+// JSON Marshalling Tests
+TEST(SVCResourceTest, JSONMarshallingTests)
+{
+    char *jsonStr1 = ReadFile(JSON_FILE_NAME);
+    if (jsonStr1)
+    {
+        OicSecSvc_t * svc = JSONToSvcBin(jsonStr1);
+        EXPECT_TRUE(NULL != svc);
+
+        int cnt = 0;
+        OicSecSvc_t * tempSvc = svc;
+        while(tempSvc)
+        {
+
+            EXPECT_EQ(tempSvc->svct, ACCESS_MGMT_SERVICE);
+            cnt++;
+            tempSvc = tempSvc->next;
+        }
+        EXPECT_EQ(cnt, NUM_SVC_IN_JSON_DB);
+
+        char * jsonStr2 = BinToSvcJSON(svc);
+        EXPECT_TRUE(NULL != jsonStr2);
+
+        OICFree(jsonStr1);
+        OICFree(jsonStr2);
+        DeleteSVCList(svc);
+    }
+}
+
index 3fed75a..4a07306 100644 (file)
 #include "ocstack.h"
 
 //-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+#define DEFAULT_CONTEXT_VALUE 0x99
+
+//-----------------------------------------------------------------------------
 // Typedefs
 //-----------------------------------------------------------------------------
 
index 37df0ac..a48bc3f 100644 (file)
@@ -30,6 +30,7 @@
 #include "ocserverbasicops.h"
 #include "common.h"
 
+
 int gQuitFlag = 0;
 
 static LEDResource LED;
@@ -226,12 +227,12 @@ OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
 OCEntityHandlerResult
 OCEntityHandlerCb (OCEntityHandlerFlag flag,
         OCEntityHandlerRequest *entityHandlerRequest,
-        void* callbackParam)
+        void* /*callbackParam*/)
 {
     OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
 
     OCEntityHandlerResult ehResult = OC_EH_ERROR;
-    OCEntityHandlerResponse response = {};
+    OCEntityHandlerResponse response = OCEntityHandlerResponse();
 
     // Validate pointer
     if (!entityHandlerRequest)
@@ -311,14 +312,14 @@ FILE* server_fopen(const char *path, const char *mode)
     return fopen(CRED_FILE, mode);
 }
 
-int main(int argc, char* argv[])
+int main(int /*argc*/, char* /*argv*/[])
 {
     struct timespec timeout;
 
     OC_LOG(DEBUG, TAG, "OCServer is starting...");
 
     // Initialize Persistent Storage for SVR database
-    OCPersistentStorage ps = {};
+    OCPersistentStorage ps = OCPersistentStorage();
     ps.open = server_fopen;
     ps.read = fread;
     ps.write = fwrite;
index 17dc43f..5a2cc55 100644 (file)
@@ -8,7 +8,8 @@
                 "/oic/p",
                 "/oic/res/types/d",
                 "/oic/ad",
-                "/oic/sec/acl"
+                "/oic/sec/acl",
+                "/oic/sec/amacl"
                        ],
                        "perms": 2,
                        "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
index 1f8ad5c..8621818 100644 (file)
@@ -8,7 +8,8 @@
                 "/oic/p",
                 "/oic/res/types/d",
                 "/oic/ad",
-                "/oic/sec/acl"
+                "/oic/sec/acl",
+                "/oic/sec/amacl"
                        ],
                        "perms": 2,
                        "ownrs" : ["MTExMTExMTExMTExMTExMQ=="]
         },
         {
             "sub": "MjIyMjIyMjIyMjIyMjIyMg==",
+            "rsrc": ["/oic/sec/acl",
+                      "/oic/sec/cred"],
+            "perms": 8,
+            "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+        },
+        {
+            "sub": "MjIyMjIyMjIyMjIyMjIyMg==",
+            "rsrc": ["/a/led"],
+            "perms": 6,
+            "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+        },
+        {
+            "sub": "MTExMTIyMjIzMzMzNDQ0NA==",
             "rsrc": ["/a/led"],
             "perms": 6,
+            "prds" : ["20150630T060000/20150630T220000", "20150630T060000/20150630T200000"],
+            "recurs" : ["FREQ=DAILY; BYDAY=MO, WE, FR", "FREQ=DAILY; BYDAY=TU, TH; UNTIL=20160630"],
+            "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+        },
+        {
+            "sub": "Nzc3Nzc3Nzc3Nzc3Nzc3Nw==",
+            "rsrc": ["/a/led"],
+            "perms": 6,
+            "prds" : ["20150630T060000/20150630T220000"],
+            "recurs" : ["FREQ=DAILY; UNTIL=20150630"],
             "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
         }
        ],
@@ -43,7 +67,7 @@
                "oxmsel": 0,
                "owned": true,
                "deviceid":     "MTExMTExMTExMTExMTExMQ==",
-               "ownr": "MjIyMjIyMjIyMjIyMjIyMg=="
+               "ownr": "YWRtaW5EZXZpY2VVVUlEAA=="
        },
     "cred":    [{
                "credid": 1,
                "credtyp": 1,
                "pvdata": "QUFBQUFBQUFBQUFBQUFBQQ==",
         "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+       },
+       {
+           "credid": 2,
+           "sub": "MTExMTIyMjIzMzMzNDQ0NA==",
+           "credtyp": 1,
+           "pvdata": "QUFBQUFBQUFBQUFBQUFBQQ==",
+        "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+       },
+       {
+           "credid": 3,
+           "sub": "Nzc3Nzc3Nzc3Nzc3Nzc3Nw==",
+           "credtyp": 1,
+           "pvdata": "QUFBQUFBQUFBQUFBQUFBQQ==",
+        "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
        }]
 }
index a5a7128..9ec2214 100644 (file)
@@ -63,6 +63,7 @@ cp resource/oc_logger/include/targets/oc_console_logger.h %{DEST_INC_DIR}
 cp resource/oc_logger/include/targets/oc_ostream_logger.h %{DEST_INC_DIR}
 cp resource/csdk/stack/include/ocpresence.h %{DEST_INC_DIR}
 cp resource/csdk/stack/include/ocpayload.h %{DEST_INC_DIR}
+cp resource/c_common/platform_features.h %{DEST_INC_DIR}
 cp extlibs/cjson/cJSON.h %{DEST_INC_DIR}
 cp -rf %{ROOTDIR}/com.oic.ri.pc %{DEST_LIB_DIR}/pkgconfig/
 
index 43efdc5..0390061 100644 (file)
@@ -509,6 +509,15 @@ OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
     // Put the JSON prefix and suffix around the payload
     if(ehResponse->payload)
     {
+        if (ehResponse->payload->type == PAYLOAD_TYPE_PRESENCE)
+        {
+            responseInfo.isMulticast = true;
+        }
+        else
+        {
+            responseInfo.isMulticast = false;
+        }
+
         OCStackResult result;
         if((result = OCConvertPayload(ehResponse->payload, &responseInfo.info.payload,
                     &responseInfo.info.payloadSize))
@@ -529,6 +538,7 @@ OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
     }
     else
     {
+        responseInfo.isMulticast = false;
         responseInfo.info.payload = NULL;
         responseInfo.info.payloadSize = 0;
     }
index e438bc6..654b785 100644 (file)
@@ -399,6 +399,7 @@ void CopyEndpointToDevAddr(const CAEndpoint_t *in, OCDevAddr *out)
     out->flags = CAToOCTransportFlags(in->flags);
     OICStrcpy(out->addr, sizeof(out->addr), in->addr);
     out->port = in->port;
+    out->interface = in->interface;
 }
 
 void CopyDevAddrToEndpoint(const OCDevAddr *in, CAEndpoint_t *out)
@@ -410,36 +411,7 @@ void CopyDevAddrToEndpoint(const OCDevAddr *in, CAEndpoint_t *out)
     out->flags = OCToCATransportFlags(in->flags);
     OICStrcpy(out->addr, sizeof(out->addr), in->addr);
     out->port = in->port;
-}
-
-static OCStackResult OCCreateEndpoint(OCDevAddr *devAddr, CAEndpoint_t **endpoint)
-{
-    VERIFY_NON_NULL(devAddr, FATAL, OC_STACK_INVALID_PARAM);
-    VERIFY_NON_NULL(endpoint, FATAL, OC_STACK_INVALID_PARAM);
-
-    CAEndpoint_t *ep = (CAEndpoint_t *)OICMalloc(sizeof (CAEndpoint_t));
-    if (!ep)
-    {
-        return OC_STACK_NO_MEMORY;
-    }
-
-    ep->adapter = (CATransportAdapter_t)devAddr->adapter;
-    if (!ep->adapter)
-    {
-        ep->adapter = CA_ADAPTER_IP;
-    }
-    ep->flags = OCToCATransportFlags(devAddr->flags);
-    OICStrcpy(ep->addr, sizeof(ep->addr), devAddr->addr);
-    ep->port = devAddr->port;
-
-    *endpoint = ep;
-
-    return OC_STACK_OK;
-}
-
-static void OCDestroyEndpoint(CAEndpoint_t *endpoint)
-{
-    free(endpoint);
+    out->interface = in->interface;
 }
 
 void FixUpClientResponse(OCClientResponse *cr)
@@ -832,8 +804,6 @@ OCStackResult HandlePresenceResponse(const CAEndpoint_t *endpoint,
         // check for multiicast presence
         CAEndpoint_t ep = { .adapter = endpoint->adapter,
                             .flags = endpoint->flags };
-        OICStrcpy(ep.addr, sizeof(ep.addr), OC_MULTICAST_IP);
-        ep.port = OC_MULTICAST_PORT;
 
         uriLen = FormCanonicalPresenceUri(&ep, OC_RSRVD_PRESENCE_URI, presenceUri);
 
@@ -2003,7 +1973,7 @@ OCStackResult OCDoResource(OCDoHandle *handle,
     uint8_t tokenLength = CA_MAX_TOKEN_LEN;
     ClientCB *clientCB = NULL;
     OCDoHandle resHandle = NULL;
-    CAEndpoint_t *endpoint = NULL;
+    CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
     OCDevAddr tmpDevAddr = { OC_DEFAULT_ADAPTER };
     uint32_t ttl = 0;
     OCTransportAdapter adapter;
@@ -2141,8 +2111,8 @@ OCStackResult OCDoResource(OCDoHandle *handle,
         requestInfo.info.numOptions = numOptions;
     }
 
-    // create remote endpoint
-    result = OCCreateEndpoint(devAddr, &endpoint);
+    CopyDevAddrToEndpoint(devAddr, &endpoint);
+
     if(payload)
     {
         if((result =
@@ -2159,8 +2129,6 @@ OCStackResult OCDoResource(OCDoHandle *handle,
         requestInfo.info.payloadSize = 0;
     }
 
-
-
     if (result != OC_STACK_OK)
     {
         OC_LOG(ERROR, TAG, PCF("CACreateEndpoint error"));
@@ -2172,7 +2140,7 @@ OCStackResult OCDoResource(OCDoHandle *handle,
     if (method == OC_REST_PRESENCE)
     {
         char *presenceUri = NULL;
-        result = OCPreparePresence(endpoint, resourceUri, &presenceUri);
+        result = OCPreparePresence(&endpoint, resourceUri, &presenceUri);
         if (OC_STACK_OK != result)
         {
             goto exit;
@@ -2198,7 +2166,7 @@ OCStackResult OCDoResource(OCDoHandle *handle,
     resourceType = NULL;  // Client CB list entry now owns it
 
     // send request
-    caResult = CASendRequest(endpoint, &requestInfo);
+    caResult = CASendRequest(&endpoint, &requestInfo);
     if (caResult != CA_STATUS_OK)
     {
         OC_LOG(ERROR, TAG, PCF("CASendRequest"));
@@ -2230,7 +2198,6 @@ exit:
     OICFree(devAddr);
     OICFree(resourceUri);
     OICFree(resourceType);
-    OICFree(endpoint);
     if (hdrOptionMemAlloc)
     {
         OICFree(requestInfo.info.options);
@@ -2259,7 +2226,7 @@ OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption
      *      Remove the callback associated on client side.
      */
     OCStackResult ret = OC_STACK_OK;
-    CAEndpoint_t* endpoint = NULL;
+    CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
     CAResult_t caResult;
     CAInfo_t requestData = {.type = CA_MSG_CONFIRM};
     CARequestInfo_t requestInfo = {.method = CA_GET};
@@ -2306,15 +2273,10 @@ OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption
             requestInfo.method = CA_GET;
             requestInfo.info = requestData;
 
-            ret = OCCreateEndpoint(clientCB->devAddr, &endpoint);
-            if (ret != OC_STACK_OK)
-            {
-                OC_LOG(ERROR, TAG, PCF("CACreateEndpoint error"));
-                goto Error;
-            }
+            CopyDevAddrToEndpoint(clientCB->devAddr, &endpoint);
 
             // send request
-            caResult = CASendRequest(endpoint, &requestInfo);
+            caResult = CASendRequest(&endpoint, &requestInfo);
             if (caResult != CA_STATUS_OK)
             {
                 OC_LOG(ERROR, TAG, PCF("CASendRequest error"));
@@ -2335,7 +2297,6 @@ OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption
     }
 
 Error:
-    OCDestroyEndpoint(endpoint);
     if (requestData.numOptions > 0)
     {
         OICFree(requestData.options);
@@ -2344,7 +2305,6 @@ Error:
     {
         OICFree (requestData.resourceUri);
     }
-
     return ret;
 }
 
@@ -2442,18 +2402,13 @@ OCStackResult OCProcessPresence()
         }
 
         CAResult_t caResult = CA_STATUS_OK;
-        CAEndpoint_t* endpoint = NULL;
+        CAEndpoint_t endpoint = {.adapter = CA_DEFAULT_ADAPTER};
         CAInfo_t requestData = {.type = CA_MSG_CONFIRM};
         CARequestInfo_t requestInfo = {.method = CA_GET};
 
         OC_LOG(DEBUG, TAG, PCF("time to test server presence"));
 
-        result = OCCreateEndpoint(cbNode->devAddr, &endpoint);
-        if (result != OC_STACK_OK)
-        {
-            OC_LOG(ERROR, TAG, PCF("CACreateEndpoint error"));
-            goto exit;
-        }
+        CopyDevAddrToEndpoint(cbNode->devAddr, &endpoint);
 
         requestData.type = CA_MSG_NONCONFIRM;
         requestData.token = cbNode->token;
@@ -2462,8 +2417,7 @@ OCStackResult OCProcessPresence()
         requestInfo.method = CA_GET;
         requestInfo.info = requestData;
 
-        caResult = CASendRequest(endpoint, &requestInfo);
-        OCDestroyEndpoint(endpoint);
+        caResult = CASendRequest(&endpoint, &requestInfo);
 
         if (caResult != CA_STATUS_OK)
         {
@@ -2479,6 +2433,7 @@ exit:
     {
         OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
     }
+
     return result;
 }
 #endif // WITH_PRESENCE
@@ -2522,8 +2477,6 @@ OCStackResult OCStartPresence(const uint32_t ttl)
         presenceState = OC_PRESENCE_INITIALIZED;
 
         OCDevAddr devAddr = { OC_DEFAULT_ADAPTER };
-        OICStrcpy(devAddr.addr, sizeof(devAddr.addr), OC_MULTICAST_IP);
-        devAddr.port = OC_MULTICAST_PORT;
 
         CAToken_t caToken = NULL;
         CAResult_t caResult = CAGenerateToken(&caToken, tokenLength);
index 1ff11a8..3dd175d 100644 (file)
@@ -731,8 +731,14 @@ exit:
 
 OCStackResult BuildStringFromActionSet(OCActionSet* actionset, char** desc)
 {
+    // Can't use the macros here as they are hardcoded to 'exit' and will
+    // result in dereferencing a null pointer.
+    if (!actionset || !desc)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
     char temp[1024] = { 0 };
-    int remaining = 1023;
+    size_t remaining = sizeof(temp) - 1;
     OCStackResult res = OC_STACK_ERROR;
 
     OCAction *action = actionset->head;
@@ -752,6 +758,11 @@ OCStackResult BuildStringFromActionSet(OCActionSet* actionset, char** desc)
 
     while (action != NULL)
     {
+        if (remaining < (strlen("uri=") + strlen(action->resourceUri) + 1))
+        {
+            res = OC_STACK_ERROR;
+            goto exit;
+        }
         strcat(temp, "uri=");
         remaining -= strlen("uri=");
         strcat(temp, action->resourceUri);
@@ -762,16 +773,28 @@ OCStackResult BuildStringFromActionSet(OCActionSet* actionset, char** desc)
         OCCapability *capas = action->head;
         while (capas != NULL)
         {
+            if (remaining < (strlen(capas->capability)
+                             + 1 + strlen(capas->status)))
+            {
+                res = OC_STACK_ERROR;
+                goto exit;
+            }
+
             strcat(temp, capas->capability);
             remaining -= strlen(capas->capability);
             strcat(temp, "=");
             remaining--;
             strcat(temp, capas->status);
-            remaining -= strlen(capas->capability);
+            remaining -= strlen(capas->status);
 
             capas = capas->next;
             if (capas != NULL)
             {
+                if (remaining < 1)
+                {
+                    res = OC_STACK_ERROR;
+                    goto exit;
+                }
                 strcat(temp, "|");
             }
         }
@@ -779,21 +802,24 @@ OCStackResult BuildStringFromActionSet(OCActionSet* actionset, char** desc)
         action = action->next;
         if (action != NULL)
         {
+            if (remaining < strlen(ACTION_DELIMITER))
+            {
+                res = OC_STACK_ERROR;
+                goto exit;
+            }
             strcat(temp, ACTION_DELIMITER);
             remaining--;
         }
     }
 
-    *desc = (char *) OICMalloc(1024 - remaining);
+    *desc = OICStrdup(temp);
     VARIFY_POINTER_NULL(*desc, res, exit);
-    strcpy(*desc, temp);
 
     return OC_STACK_OK;
 
 exit:
     OCFREE(*desc);
     return res;
-
 }
 
 OCStackApplicationResult ActionSetCB(void* context, OCDoHandle handle,
index 4643819..04a1848 100644 (file)
@@ -32,7 +32,7 @@
 namespace OC
 {
     /**
-    * @brief: This namespace contains the main entrance/functionality of the product.
+    * This namespace contains the main entrance/functionality of the product.
     * It may be used with OC::OCPlatform::functionName.  To set a custom configuration,
     * the implementer must make a call to OCPlatform::Configure before the first usage
     * of a function in this namespace.
@@ -41,7 +41,7 @@ namespace OC
     {
         /**
         * API for overwriting the default configuration of the OCPlatform object.
-        * Note: Any calls made to this AFTER the first call to OCPlatform::Instance
+        * @note Any calls made to this AFTER the first call to OCPlatform::Instance
         * will have no affect
         */
         void Configure(const PlatformConfig& config);
@@ -55,10 +55,12 @@ namespace OC
         * @param OCResourceHandle resource handle of the resource
         * @param QualityOfService the quality of communication
         *
-        * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
-        * NOTE: This API is for server side only.
-        * NOTE: OCResourceHandle is defined in ocstack.h.
-        * NOTE: OCStackResult is defined in ocstack.h.
+        * @return Returns ::OC_STACK_OK if success.
+        * @note This API is for server side only.
+        * @note OCResourceHandle is defined in ocstack.h
+        * @note OCStackResult is defined in ocstack.h.
+        * @see notifyAllObservers(OCResourceHandle)
+        * @see notifyAllObservers(OCResourceHandle, QualityOfService)
         */
         OCStackResult notifyAllObservers(OCResourceHandle resourceHandle);
         OCStackResult notifyAllObservers(OCResourceHandle resourceHandle, QualityOfService QoS);
@@ -73,11 +75,10 @@ namespace OC
         * resource change.
         * @param QualityOfService the quality of communication
         *
-        * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
-        *
-        * NOTE: This API is for server side only.
-        * NOTE: OCResourceHandle is defined in ocstack.h.
-        * NOTE: OCStackResult is defined in ocstack.h.
+        * @return Returns ::OC_STACK_OK if success.
+        * @note This API is for server side only.
+        * @note OCResourceHandle is defined in ocstack.h.
+        * @note OCStackResult is defined in ocstack.h.
         */
         OCStackResult notifyListOfObservers(
                     OCResourceHandle resourceHandle,
@@ -91,15 +92,15 @@ namespace OC
 
         /**
         * API for Service and Resource Discovery.
-        * NOTE: This API applies to client side only.
+        * @note This API applies to client side only.
         *
-        * @param host Host IP Address of a service to direct resource discovery query. If null or
+        * @param host Host IP Address of a service to direct resource discovery query. If null or
         *        empty, performs multicast resource discovery query
-        * @param resourceURI name of the resource. If null or empty, performs search for all
+        * @param resourceURI name of the resource. If null or empty, performs search for all
         *       resource names
-        * @param connectivityType - @ref OCConnectivityType type of connectivity indicating the
+        * @param connectivityType ::OCConnectivityType type of connectivity indicating the
         *                           interface. Example: OC_WIFI, OC_ETHERNET, OC_ALL
-        * @param handler - Handles callbacks, success states and failure states.
+        * @param resourceHandler Handles callbacks, success states and failure states.
         *
         *        Four modes of discovery defined as follows:
         *        (NULL/Empty, NULL/Empty) - Performs ALL service discovery AND ALL resource
@@ -112,11 +113,11 @@ namespace OC
         *                                  from a particular service.
         * @param QualityOfService the quality of communication
         *
-        * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
-        * NOTE: First parameter 'host' currently represents an IP address. This will change in
+        * @return Returns ::OC_STACK_OK if success.
+        * @note First parameter 'host' currently represents an IP address. This will change in
         * future and will refer to endpoint interface so that we can refer to other transports such
         * as BTH etc.
-        * NOTE: OCStackResult is defined in ocstack.h.
+        * @note OCStackResult is defined in ocstack.h.
         */
         OCStackResult findResource(const std::string& host, const std::string& resourceURI,
                     OCConnectivityType connectivityType, FindCallback resourceHandler);
@@ -128,14 +129,16 @@ namespace OC
         * API for Device Discovery
         *
         *
-        * @param host Host IP Address. If null or empty, Multicast is performed.
-        * @param deviceURI Uri containing address to the virtual device in C Stack
+        * @param host Host IP Address. If null or empty, Multicast is performed.
+        * @param deviceURI Uri containing address to the virtual device in C Stack
                                 ("/oic/d")
-        * @param connectivityType - @ref OCConnectivityType type of connectivity indicating the
+        * @param connectivityType ::OCConnectivityType type of connectivity indicating the
         *                           interface. Example: OC_WIFI, OC_ETHERNET, OC_ALL
-        * @param deviceInfoHandler device discovery callback
+        * @param deviceInfoHandler device discovery callback
         * @param QoS the quality of communication
         *
+        * @return Returns ::OC_STACK_OK if success.
+        * @note OCStackResult is defined in ocstack.h.
         */
         OCStackResult getDeviceInfo(const std::string& host, const std::string& deviceURI,
                     OCConnectivityType connectivityType, FindDeviceCallback deviceInfoHandler);
@@ -147,14 +150,16 @@ namespace OC
         * API for Platform Discovery
         *
         *
-        * @param host Host IP Address. If null or empty, Multicast is performed.
-        * @param platformURI Uri containing address to the virtual platform in C Stack
+        * @param host Host IP Address. If null or empty, Multicast is performed.
+        * @param platformURI Uri containing address to the virtual platform in C Stack
                                 ("/oic/p")
-        * @param connectivityType - @ref OCConnectivityType type of connectivity indicating the
+        * @param connectivityType ::OCConnectivityType type of connectivity indicating the
         *                           interface. Example: OC_WIFI, OC_ETHERNET, OC_ALL
-        * @param platformInfoHandler platform discovery callback
+        * @param platformInfoHandler platform discovery callback
         * @param QoS the quality of communication
         *
+        * @return Returns ::OC_STACK_OK if success.
+        * @note OCStackResult is defined in ocstack.h.
         */
         OCStackResult getPlatformInfo(const std::string& host, const std::string& platformURI,
                     OCConnectivityType connectivityType, FindPlatformCallback platformInfoHandler);
@@ -164,21 +169,21 @@ namespace OC
 
         /**
         * This API registers a resource with the server
-        * NOTE: This API applies to server side only.
-        *
-        * @param resourceHandle Upon successful registration, resourceHandle will be filled
-        * @param resourceURI The URI of the resource. Example: "a/light". See NOTE below
-        * @param resourceTypeName The resource type. Example: "light"
-        * @param resourceInterface The resource interface (whether it is collection etc).
-        * @param entityHandler entity handler callback.
-        * @param resourceProperty indicates the property of the resource. Defined in ocstack.h.
+        * @note This API applies to server side only.
+        *
+        * @param resourceHandle Upon successful registration, resourceHandle will be filled
+        * @param resourceURI The URI of the resource. Example: "a/light". See NOTE below
+        * @param resourceTypeName The resource type. Example: "light"
+        * @param resourceInterface The resource interface (whether it is collection etc).
+        * @param entityHandler entity handler callback.
+        * @param resourceProperty indicates the property of the resource. Defined in ocstack.h.
         * setting resourceProperty as OC_DISCOVERABLE will allow Discovery of this resource
         * setting resourceProperty as OC_OBSERVABLE will allow observation
         * settings resourceProperty as OC_DISCOVERABLE | OC_OBSERVABLE will allow both discovery and
         * observation
         *
-        * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
-        * NOTE: "a/light" is a relative URI.
+        * @return Returns ::OC_STACK_OK if success.
+        * @note "a/light" is a relative URI.
         * Above relative URI will be prepended (by core) with a host IP + namespace "oic"
         * Therefore, fully qualified URI format would be //HostIP-Address/namespace/relativeURI"
         * Example, a relative URI: 'a/light' will result in a fully qualified URI:
@@ -187,7 +192,7 @@ namespace OC
         * qualified URI OR
         * first parameter can take fully qualified URI and core will take that as is for further
         * operations
-        * NOTE: OCStackResult is defined in ocstack.h.
+        * @note OCStackResult is defined in ocstack.h.
         */
         OCStackResult registerResource(OCResourceHandle& resourceHandle,
                         std::string& resourceURI,
@@ -198,12 +203,13 @@ namespace OC
 
         /**
         * This API registers a resource with the server
-        * NOTE: This API applies to server & client side.
+        * @note This API applies to server & client side.
 
-        * @param resourceHandle Upon successful registration, resourceHandle will be filled
-        * @param OCResource The instance of OCResource that all data filled.
+        * @param resourceHandle Upon successful registration, resourceHandle will be filled
+        * @param OCResource The instance of OCResource that all data filled.
         *
-        * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+        * @return Returns ::OC_STACK_OK if success.
+        * @note OCStackResult is defined in ocstack.h.
         */
         OCStackResult registerResource(OCResourceHandle& resourceHandle,
                         const std::shared_ptr< OCResource > resource);
@@ -211,67 +217,60 @@ namespace OC
         /**
         * Register Device Info
         *
-        * @param deviceInfo - structure containing all the device specific information
-        *
-        * @return
-        *      OC_STACK_OK   - no errors
-        *      OC_STACK_ERROR - stack process error
+        * @param deviceInfo structure containing all the device specific information
+        * @return Returns ::OC_STACK_OK  if no errors and ::OC_STACK_ERROR in case of stack process error
         */
         OCStackResult registerDeviceInfo(const OCDeviceInfo deviceInfo);
 
         /**
         * Register Platform Info
         *
-        * @param platformInfo - structure containing all the platform specific information
-        *
-        * @return
-        *      OC_STACK_OK   - no errors
-        *      OC_STACK_ERROR - stack process error
+        * @param platformInfo structure containing all the platform specific information
+        * @return Returns ::OC_STACK_OK if no errors and ::OC_STACK_ERROR in case of stack process error
         */
         OCStackResult registerPlatformInfo(const OCPlatformInfo platformInfo);
 
         /**
         * Set default device entity handler
         *
-        * @param entityHandler - entity handler to handle requests for
-        *                        any undefined resources or default actions.
-        *                        if NULL is passed it removes the device default entity handler.
-        *
-        * @return
-        *     OC_STACK_OK    - no errors
-        *     OC_STACK_ERROR - stack process error
+        * @param entityHandler entity handler to handle requests for
+        *                      any undefined resources or default actions.
+        *                      if NULL is passed it removes the device default entity handler.
+        * @return Returns ::OC_STACK_OK  if no errors and ::OC_STACK_ERROR in case of stack process error
         */
         OCStackResult setDefaultDeviceEntityHandler(EntityHandler entityHandler);
 
         /**
         * This API unregisters a resource with the server
-        * NOTE: This API applies to server side only.
+        * @note This API applies to server side only.
         *
-        * @param resourceHandle - This is the resource handle which we which to unregister from the
+        * @param resourceHandle This is the resource handle which we need to unregister from the
         * server
         *
-        * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
-        * NOTE: OCStackResult is defined in ocstack.h.
+        * @return Returns ::OC_STACK_OK if success.
+        * @note OCStackResult is defined in ocstack.h.
         */
         OCStackResult unregisterResource(const OCResourceHandle& resourceHandle);
 
         /**
         * Add a resource to a collection resource.
         *
-        * @param collectionHandle - handle to the collection resource
-        * @param resourceHandle - handle to resource to be added to the collection resource
-        *
-        * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.<br>
-        * NOTE: OCStackResult is defined in ocstack.h. <br>
-        * NOTE: bindResource must be used only after the both collection resource and
-        * resource to add under a collections are created and respective handles obtained<br>
-        * <b>Example:</b> <br>
-        * Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
-        *   entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
-        * Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
-        *   entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
-        * Step 3: bindResource(homeResourceHandle, kitchenResourceHandle);<br>
-        * At the end of Step 3, resource "a/home" will contain a reference to "a/kitchen".<br>
+        * @param collectionHandle handle to the collection resource
+        * @param resourceHandle handle to resource to be added to the collection resource
+        *
+        * @return Returns ::OC_STACK_OK if success.
+        * @note OCStackResult is defined in ocstack.h.
+        * @note bindResource must be used only after the both collection resource and
+        * resource to add under a collections are created and respective handles obtained
+        *
+        * @par Example:
+        * -# registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
+        *   entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+        * -# registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
+        *   entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+        * -# bindResource(homeResourceHandle, kitchenResourceHandle);
+        * @par
+        * At the end of Step 3, resource "a/home" will contain a reference to "a/kitchen".
         */
         OCStackResult bindResource(const OCResourceHandle collectionHandle,
                 const OCResourceHandle resourceHandle);
@@ -279,27 +278,29 @@ namespace OC
         /**
         * Add multiple resources to a collection resource.
         *
-        * @param collectionHandle handle to the collection resource
+        * @param collectionHandle handle to the collection resource
         * @param addedResourceHandleList reference to list of resource handles to be added to the
         *   collection resource
         *
-        * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. <br>
-        * NOTE: OCStackResult is defined in ocstack.h. <br>
-        * NOTE: bindResources must be used only after the both collection resource and
+        * @return Returns ::OC_STACK_OK if success.
+        * @note OCStackResult is defined in ocstack.h.
+        * @note bindResources must be used only after the both collection resource and
         * list of resources to add under a collection are created and respective handles
-        * obtained <br>
-        * <b> Example: </b> <br>
-        * Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
-        *   homeEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
-        * Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
-        *   kitchenEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
-        * Step 3: registerResource(roomResourceHandle, "a/room", "room", Link_Interface,
-        *   roomEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
-        * Step 4: std::vector<OCResourceHandle> rList; rList.push_back(kitchenResourceHandle);
-        *   rList.push_back(roomResourceHandle);<br>
-        * Step 5: bindResource(homeResourceHandle, rList);<br>
+        * obtained.
+        *
+        * @par Example:
+        * -# registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
+        *   homeEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+        * -# registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
+        *   kitchenEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+        * -# registerResource(roomResourceHandle, "a/room", "room", Link_Interface,
+        *   roomEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+        * -# std::vector<OCResourceHandle> rList; rList.push_back(kitchenResourceHandle);
+        *   rList.push_back(roomResourceHandle);
+        * -# bindResource(homeResourceHandle, rList);
+        * @par
         * At the end of Step 5, resource "a/home" will contain a references to "a/kitchen" and
-        *   "a/room" <br>
+        *   "a/room"
         */
         OCStackResult bindResources(const OCResourceHandle collectionHandle,
                 const std::vector<OCResourceHandle>& addedResourceHandleList);
@@ -307,21 +308,23 @@ namespace OC
         /**
         * Unbind a resource from a collection resource.
         *
-        * @param collectionHandle handle to the collection resource
+        * @param collectionHandle handle to the collection resource
         * @param resourceHandle resource handle to be unbound from the collection resource
         *
-        * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. <br>
-        * NOTE: OCStackResult is defined in ocstack.h.<br>
-        * NOTE: unbindResource must be used only after the both collection resource and
-        * resource to unbind from a collection are created and respective handles obtained<br>
-        * <b> Example </b> <br>
-        * Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
-        *   entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
-        * Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
-        *   entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
-        * Step 3: bindResource(homeResourceHandle, kitchenResourceHandle);<br>
-        * Step 4: unbindResource(homeResourceHandle, kitchenResourceHandle);<br>
-        * At the end of Step 4, resource "a/home" will no longer reference "a/kitchen". <br>
+        * @return Returns ::OC_STACK_OK if success.
+        * @note OCStackResult is defined in ocstack.h.
+        * @note unbindResource must be used only after the both collection resource and
+        * resource to unbind from a collection are created and respective handles obtained
+        *
+        * @par Example:
+        * -# registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
+        *   entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+        * -# registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
+        *   entityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+        * -# bindResource(homeResourceHandle, kitchenResourceHandle);
+        * -# unbindResource(homeResourceHandle, kitchenResourceHandle);
+        * @par
+        * At the end of Step 4, resource "a/home" will no longer reference "a/kitchen".
         */
         OCStackResult unbindResource(const OCResourceHandle collectionHandle,
                     const OCResourceHandle resourceHandle);
@@ -329,49 +332,50 @@ namespace OC
         /**
         * Unbind resources from a collection resource.
         *
-        * @param collectionHandle handle to the collection resource
+        * @param collectionHandle handle to the collection resource
         * @param resourceHandleList List of resource handles to be unbound from the collection
         *   resource
         *
-        * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. <br>
-        *
-        * NOTE: OCStackResult is defined in ocstack.h.<br>
-        * NOTE: unbindResources must be used only after the both collection resource and
+        * @return Returns ::OC_STACK_OK if success.
+        * @note OCStackResult is defined in ocstack.h.
+        * @note unbindResources must be used only after the both collection resource and
         * list of resources resource to unbind from a collection are created and respective handles
-        *   obtained. <br>
-        * <b>Example</b> <br>
-        * Step 1: registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
-        *   homeEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
-        * Step 2: registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
-        *   kitchenEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
-        * Step 3: registerResource(roomResourceHandle, "a/room", "room", Link_Interface,
-        *   roomEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);<br>
-        * Step 4: std::vector<OCResourceHandle> rList; rList.push_back(kitchenResourceHandle);
-        *   rList.push_back(roomResourceHandle);<br>
-        * Step 5: bindResource(homeResourceHandle, rList);<br>
-        * Step 6: unbindResources(homeResourceHandle, rList);<br>
+        *   obtained.
+        *
+        * @par Example:
+        * -# registerResource(homeResourceHandle, "a/home", "home", Link_Interface,
+        *   homeEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+        * -# registerResource(kitchenResourceHandle, "a/kitchen", "kitchen", Link_Interface,
+        *   kitchenEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+        * -# registerResource(roomResourceHandle, "a/room", "room", Link_Interface,
+        *   roomEntityHandler, OC_DISCOVERABLE | OC_OBSERVABLE);
+        * -# std::vector<OCResourceHandle> rList; rList.push_back(kitchenResourceHandle);
+        *   rList.push_back(roomResourceHandle);
+        * -# bindResource(homeResourceHandle, rList);
+        * -# unbindResources(homeResourceHandle, rList);
+        * @par
         * At the end of Step 6, resource "a/home" will no longer reference to "a/kitchen" and
-        *   "a/room"<br>
+        *   "a/room"
         */
         OCStackResult unbindResources(const OCResourceHandle collectionHandle,
                         const std::vector<OCResourceHandle>& resourceHandleList);
 
         /**
         * Binds a type to a particular resource
-        * @param resourceHandle handle to the resource
-        * @param resourceTypeName new typename to bind to the resource
-
-        * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success <br>
+        * @param resourceHandle handle to the resource
+        * @param resourceTypeName new typename to bind to the resource
+        *
+        * @return Returns ::OC_STACK_OK if success.
         */
         OCStackResult bindTypeToResource(const OCResourceHandle& resourceHandle,
                         const std::string& resourceTypeName);
 
         /**
         * Binds an interface to a particular resource
-        * @param resourceHandle handle to the resource
-        * @param resourceInterfaceName new interface  to bind to the resource
-
-        * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success <br>
+        * @param resourceHandle handle to the resource
+        * @param resourceInterfaceName new interface  to bind to the resource
+        *
+        * @return Returns ::OC_STACK_OK if success.
         */
         OCStackResult bindInterfaceToResource(const OCResourceHandle& resourceHandle,
                         const std::string& resourceInterfaceName);
@@ -380,13 +384,13 @@ namespace OC
         /**
         * Start Presence announcements.
         *
-        * @param ttl time to live
-        * Note: If ttl is '0', then the default stack value will be used (60 Seconds).
-        *
-        *       If ttl is greater than OC_MAX_PRESENCE_TTL_SECONDS, then the ttl will be set to
-        *       OC_MAX_PRESENCE_TTL_SECONDS.
-        *
-        * @return OCStackResult - Returns OCSTACK_OK if success <br>
+        * @param ttl time to live
+        * @par
+        * If ttl is '0', then the default stack value will be used (60 Seconds).
+        * If ttl is greater than OC_MAX_PRESENCE_TTL_SECONDS, then the ttl will be set to
+        * OC_MAX_PRESENCE_TTL_SECONDS.
+        * @par
+        * @return Returns ::OC_STACK_OK if success.
         *
         * Server can call this function when it comes online for the
         * first time, or when it comes back online from offline mode,
@@ -398,7 +402,7 @@ namespace OC
         /**
         * Stop Presence announcements.
         *
-        * @return OCStackResult - Returns OCSTACK_OK if success <br>
+        * @return Returns ::OC_STACK_OK if success.
         *
         * Server can call this function when it is terminating,
         * going offline, or when going away from network.
@@ -411,18 +415,18 @@ namespace OC
         * every time a server adds/removes/alters a resource, starts or is intentionally
         * stopped (potentially more to be added later).
         *
-        * @param presenceHandle a handle object that can be used to identify this subscription
+        * @param presenceHandle a handle object that can be used to identify this subscription
         *               request.  It can be used to unsubscribe from these events in the future.
         *               It will be set upon successful return of this method.
-        * @param host The IP address/addressable name of the server to subscribe to.
+        * @param host The IP address/addressable name of the server to subscribe to.
         *               This should be in the format coap://address:port
-        * @param connectivityType - @ref OCConnectivityType type of connectivity indicating the
+        * @param connectivityType ::OCConnectivityType type of connectivity indicating the
         *                           interface. Example: OC_WIFI, OC_ETHERNET, OC_ALL
-        * @param resourceType a resource type specified as a filter for subscription callbacks.
-        * @param presenceHandler callback function that will receive notifications/subscription
+        * @param resourceType a resource type specified as a filter for subscription callbacks.
+        * @param presenceHandler callback function that will receive notifications/subscription
         *               events
         *
-        * @return OCStackResult - return value of the API.  Returns OCSTACK_OK if success <br>
+        * @return Returns ::OC_STACK_OK if success.
         */
         OCStackResult subscribePresence(OCPresenceHandle& presenceHandle, const std::string& host,
                         OCConnectivityType connectivityType, SubscribeCallback presenceHandler);
@@ -435,10 +439,10 @@ namespace OC
         * you may for a short time still receive events from the server since it may take time
         * for the unsubscribe to take effect.
         *
-        * @param presenceHandle the handle object provided by the subscribePresence call that
+        * @param presenceHandle the handle object provided by the subscribePresence call that
         *               identifies this subscription.
         *
-        * @return OCStackResult - return value of the API.  Returns OCSTACK_OK if success <br>
+        * @return Returns ::OC_STACK_OK if success.
         */
         OCStackResult unsubscribePresence(OCPresenceHandle presenceHandle);
 
@@ -452,23 +456,23 @@ namespace OC
         * to be a Client or Client/Server.  Otherwise, this will return an empty
         * shared ptr.
         *
-        * @param host a string containing a resolvable host address of the server
+        * @param host a string containing a resolvable host address of the server
         *           holding the resource. Currently this should be in the format
         *           coap://address:port, though in the future, we expect this to
         *           change to //address:port
         *
-        * @param uri the rest of the resource's URI that will permit messages to be
+        * @param uri the rest of the resource's URI that will permit messages to be
         *           properly routed.  Example: /a/light
         *
-        * @param connectivityType - @ref OCConnectivityType type of connectivity indicating the
+        * @param connectivityType ::OCConnectivityType type of connectivity indicating the
         *                           interface. Example: OC_WIFI, OC_ETHERNET, OC_ALL
         *
-        * @param isObservable a boolean containing whether the resource supports observation
+        * @param isObservable a boolean containing whether the resource supports observation
         *
-        * @param resourceTypes a collection of resource types implemented by the resource
+        * @param resourceTypes a collection of resource types implemented by the resource
         *
-        * @param interfaces a collection of interfaces that the resource supports/implements
-        * @return OCResource::Ptr a shared pointer to the new resource object
+        * @param interfaces a collection of interfaces that the resource supports/implements
+        * @return OCResource::Ptr a shared pointer to the new resource object
         */
         OCResource::Ptr constructResourceObject(const std::string& host,
                         const std::string& uri,
@@ -479,9 +483,10 @@ namespace OC
         /**
         * Allows application entity handler to send response to an incoming request.
         *
-        * @param pResponse - OCResourceResponse pointer that will permit to set values related
-        * to resource response. <br>
-        * @return OCStackResult - return value of the API. Returns OCSTACK_OK if success <br>
+        * @param pResponse OCResourceResponse pointer that will permit to set values related
+        * to resource response.
+        *
+        * @return Returns ::OC_STACK_OK if success.
         */
         OCStackResult sendResponse(const std::shared_ptr<OCResourceResponse> pResponse);
     }
index 7b23a56..78b95e8 100644 (file)
@@ -96,12 +96,13 @@ namespace OC
         /**
          * API for Device Discovery
          *
-         * @param host Host IP Address. If null or empty, Multicast is performed.
-         * @param resourceURI - Uri containing address to the virtual device in C Stack
+         * @param host Host IP Address. If null or empty, Multicast is performed.
+         * @param deviceURI Uri containing address to the virtual device in C Stack
          *                       ("/oic/d")
-         *
+         * @param deviceInfoHandler device discovery callback
          * @param QualityOfService the quality of communication
-         *
+         * @return Returns ::OC_STACK_OK if success.
+         * @note OCStackResult is defined in ocstack.h.
          */
         OCStackResult getDeviceInfo(const std::string& host, const std::string& deviceURI,
                     FindDeviceCallback deviceInfoHandler);
@@ -111,12 +112,13 @@ namespace OC
         /**
          * API for Platform Discovery
          *
-         * @param host Host IP Address. If null or empty, Multicast is performed.
-         * @param resourceURI - Uri containing address to the virtual platform in C Stack
+         * @param host Host IP Address. If null or empty, Multicast is performed.
+         * @param platformURI Uri containing address to the virtual platform in C Stack
          *                       ("/oic/p")
-         *
+         * @param platformInfoHandler platform discovery callback
          * @param QualityOfService the quality of communication
-         *
+         * @return Returns ::OC_STACK_OK if success.
+         * @note OCStackResult is defined in ocstack.h.
          */
         OCStackResult getPlatformInfo(const std::string& host, const std::string& platformURI,
                     FindPlatformCallback platformInfoHandler);
@@ -125,21 +127,21 @@ namespace OC
 
         /**
         * This API registers a resource with the server
-        * NOTE: This API applies to server side only.
+        * @note This API applies to server side only.
         *
-        * @param resourceHandle Upon successful registration, resourceHandle will be filled
-        * @param resourceURI The URI of the resource. Example: "a/light". See NOTE below
-        * @param resourceTypeName The resource type. Example: "light"
-        * @param resourceInterface The resource interface (whether it is collection etc).
-        * @param entityHandler entity handler callback.
-        * @param resourceProperty indicates the property of the resource. Defined in ocstack.h.
+        * @param resourceHandle Upon successful registration, resourceHandle will be filled
+        * @param resourceURI The URI of the resource. Example: "a/light". See NOTE below
+        * @param resourceTypeName The resource type. Example: "light"
+        * @param resourceInterface The resource interface (whether it is collection etc).
+        * @param entityHandler entity handler callback.
+        * @param resourceProperty indicates the property of the resource. Defined in ocstack.h.
         * setting resourceProperty as OC_DISCOVERABLE will allow Discovery of this resource
         * setting resourceProperty as OC_OBSERVABLE will allow observation
         * settings resourceProperty as OC_DISCOVERABLE | OC_OBSERVABLE will allow both discovery
         * and observation
         *
-        * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
-        * NOTE: "a/light" is a relative URI.
+        * @return Returns ::OC_STACK_OK if success.
+        * @note "a/light" is a relative URI.
         * Above relative URI will be prepended (by core) with a host IP + namespace "oc"
         * Therefore, fully qualified URI format would be //HostIP-Address/namespace/relativeURI"
         * Example, a relative URI: 'a/light' will result in a fully qualified URI:
@@ -148,7 +150,7 @@ namespace OC
         * qualified URI OR
         * first parameter can take fully qualified URI and core will take that as is for further
         * operations
-        * NOTE: OCStackResult is defined in ocstack.h.
+        * @note OCStackResult is defined in ocstack.h.
         */
         OCStackResult registerResource(OCResourceHandle& resourceHandle,
                         std::string& resourceURI,
@@ -163,22 +165,20 @@ namespace OC
         /**
          * This API registers all the device specific information
          *
-         * @param OCDeviceInfo - Structure containing all the device related information
-         *
-         * @return OCStackResult return value of the API. Returns OC_STACK_OK if success
+         * @param deviceInfo Structure containing all the device related information
          *
-         * Note: OCDeviceInfo is defined in OCStack.h
+         * @return Returns ::OC_STACK_OK if success
+         * @note OCDeviceInfo is defined in OCStack.h
          */
         OCStackResult registerDeviceInfo(const OCDeviceInfo deviceInfo);
 
         /**
          * This API registers all the platform specific information
          *
-         * @param OCPlatformInfo - Structure containing all the platform related information
-         *
-         * @return OCStackResult return value of the API. Returns OC_STACK_OK if success
+         * @param platformInfo Structure containing all the platform related information
          *
-         * Note: OCPlatformInfo is defined in OCStack.h
+         * @return Returns ::OC_STACK_OK if success
+         * @note OCPlatformInfo is defined in OCStack.h
          */
         OCStackResult registerPlatformInfo(const OCPlatformInfo platformInfo);
 
index a964e65..cfb7bc9 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <list>
 #include <string>
-#include <boost/atomic.hpp>
+#include <atomic>
 
 #include "BrokerTypes.h"
 #include "ResourcePresence.h"
@@ -49,13 +49,14 @@ namespace OIC
 
             bool isEmptyResourcePresence() const;
             const std::string getAddress() const;
-            DEVICE_STATE getDeviceState() const;
+            DEVICE_STATE getDeviceState() const noexcept;
+
         private:
             std::list<ResourcePresence * > resourcePresenceList;
 
             std::string address;
-            boost::atomic<DEVICE_STATE> state;
-            boost::atomic_bool isRunningTimeOut;
+            std::atomic_int state;
+            std::atomic_bool isRunningTimeOut;
 
             std::mutex timeoutMutex;
             std::condition_variable condition;
@@ -69,6 +70,8 @@ namespace OIC
             void changeAllPresenceMode(BROKER_MODE mode);
             void subscribeCB(OCStackResult ret,const unsigned int seq, const std::string& Hostaddress);
             void timeOutCB(TimerID id);
+
+            void setDeviceState(DEVICE_STATE);
         };
     } // namespace Service
 } // namespace OIC
index 629ef14..aade9e9 100644 (file)
@@ -27,7 +27,7 @@ namespace OIC
     {
         DevicePresence::DevicePresence()
         {
-            state = DEVICE_STATE::REQUESTED;
+            setDeviceState(DEVICE_STATE::REQUESTED);
 
             presenceTimerHandle = 0;
             isRunningTimeOut = false;
@@ -69,10 +69,17 @@ namespace OIC
             presenceTimerHandle
             = presenceTimer.post(BROKER_DEVICE_PRESENCE_TIMEROUT, pTimeoutCB);
         }
-        DEVICE_STATE DevicePresence::getDeviceState() const
+
+        DEVICE_STATE DevicePresence::getDeviceState() const noexcept
         {
-            return state;
+            return static_cast< DEVICE_STATE >(state.load());
         }
+
+        void DevicePresence::setDeviceState(DEVICE_STATE newState)
+        {
+            state = static_cast< int >(newState);
+        }
+
         const std::string DevicePresence::getAddress() const
         {
             OC_LOG_V(DEBUG, BROKER_TAG, "getAddress()");
@@ -130,9 +137,9 @@ namespace OIC
                 case OC_STACK_CONTINUE:
                 {
                     OC_LOG_V(DEBUG, BROKER_TAG, "SEQ# %d",seq);
-                    state = DEVICE_STATE::ALIVE;
+                    setDeviceState(DEVICE_STATE::ALIVE);
                     OC_LOG_V(DEBUG, BROKER_TAG, "device state : %d",
-                            (int)(state.load(boost::memory_order_consume)));
+                            (int)getDeviceState());
                     changeAllPresenceMode(BROKER_MODE::DEVICE_PRESENCE_MODE);
                     presenceTimerHandle
                     = presenceTimer.post(BROKER_DEVICE_PRESENCE_TIMEROUT, pTimeoutCB);
@@ -146,14 +153,14 @@ namespace OIC
                 case OC_STACK_PRESENCE_TIMEOUT:
                 case OC_STACK_PRESENCE_DO_NOT_HANDLE:
                 {
-                    state = DEVICE_STATE::LOST_SIGNAL;
+                    setDeviceState(DEVICE_STATE::LOST_SIGNAL);
                     changeAllPresenceMode(BROKER_MODE::NON_PRESENCE_MODE);
                     break;
                 }
                 default:
                 {
                     OC_LOG_V(DEBUG, BROKER_TAG, "Presence Lost Signal because unknown type");
-                    state = DEVICE_STATE::LOST_SIGNAL;
+                    setDeviceState(DEVICE_STATE::LOST_SIGNAL);
                     changeAllPresenceMode(BROKER_MODE::NON_PRESENCE_MODE);
                     break;
                 }
@@ -168,7 +175,7 @@ namespace OIC
 
             OC_LOG_V(DEBUG, BROKER_TAG,
                     "Timeout execution. will be discard after receiving cb message");
-            state = DEVICE_STATE::LOST_SIGNAL;
+            setDeviceState(DEVICE_STATE::LOST_SIGNAL);
             changeAllPresenceMode(BROKER_MODE::NON_PRESENCE_MODE);
 
             isRunningTimeOut = false;
index 2934a06..966cc12 100644 (file)
@@ -177,7 +177,7 @@ else:
 
        HueBundle = hue_resource_bundle_env.SharedLibrary('HueBundle', hue_resource_bundle_src)
        hue_resource_bundle_env.InstallTarget(HueBundle, 'libHueBundle')
-       lib_env = conf2.Finish()
+lib_env = conf2.Finish()
 
 ######################################################################
 # build resource container unit tests