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>
# 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()
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
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:
--- /dev/null
+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
+
--- /dev/null
+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
+
#include "sha2/sha2.h"
#include "prng.h"
#include "netq.h"
+#include "hmac.h"
#ifndef WITH_CONTIKI
#include <pthread.h>
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) {
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++) {
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) {
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;
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
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];
}
#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,
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 */
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:
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 */
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:
#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
#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
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;
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
#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)
#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.
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));
}
/**
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];
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: {
#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,
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);
#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");
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;
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
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");
}
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);
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),
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);
}
}
#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,
int res;
int ecdsa;
int ecdh_anon;
+ int ecdhe_psk;
res = dtls_send_server_hello(ctx, 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) {
}
}
#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];
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;
#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;
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);
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;
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) {
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) {
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);
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;
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
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
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);
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;
}
}
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
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) {
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 */
}
/**
- * @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)
* @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)
*/
/** 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;
"\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);
}
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;
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)
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());
/* 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);
"\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);
}
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));
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);
{
CAResponseResult_t result; /**< Result for response by resource model */
CAInfo_t info; /**< Information of the response */
+ bool isMulticast;
} CAResponseInfo_t;
/**
return NULL;
}
+ clone->isMulticast = rep->isMulticast;
clone->result = rep->result;
return clone;
}
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
void OICLogShutdown()
{
-#ifdef __linux__
+#if defined(__linux__) || defined(__APPLE__)
if (logCtx && logCtx->destroy)
{
logCtx->destroy(logCtx);
__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);
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
* 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
*
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.
{
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()
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;
}
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.
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");
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)
}
(*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");
}
{
OIC_LOG(DEBUG, EDR_ADAPTER_TAG, "IN");
- // Stop EDR adapter
- CAStopEDR();
// Terminate EDR Network Monitor
CAEDRTerminateNetworkMonitor();
}
}
#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
{
}
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;
}
return NULL;
}
- cadata->type = SEND_TYPE_UNICAST;
+ cadata->type = response->isMulticast ? SEND_TYPE_MULTICAST : SEND_TYPE_UNICAST;
cadata->responseInfo = response;
}
else
{
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)
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)
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;
#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;
}
// 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;
}
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;
// 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;
}
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;
caglobals.ip.threadpool = handle;
CAIPSetPacketReceiveCallback(CAIPPacketReceivedCB);
- CAIPInitializeNetworkMonitor();
#ifdef __WITH_DTLS__
CAAdapterNetDtlsInit();
{
OIC_LOG(DEBUG, TAG, "IN");
+ CAIPStartNetworkMonitor();
#ifdef SINGLE_THREAD
uint16_t unicastPort = 55555;
// Address is hardcoded as we are using Single Interface
CAIPDeinitializeQueueHandles();
#endif
+ CAIPStopNetworkMonitor();
CAIPStopServer();
OIC_LOG(DEBUG, TAG, "OUT");
{
OIC_LOG(DEBUG, TAG, "IN");
- CAIPTerminateNetworkMonitor();
-
#ifdef __WITH_DTLS__
CADTLSSetAdapterCallbacks(NULL, NULL, 0);
#endif
{
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));
+ }
}
}
inaddr.s_addr = ifitem->ipv4addr;
applyMulticastToInterface4(inaddr);
}
-
static void CAHandleNetlink()
{
#ifdef __linux__
#define TAG "IP_MONITOR"
-CAResult_t CAIPInitializeNetworkMonitor()
+CAResult_t CAIPStartNetworkMonitor()
{
return CA_STATUS_OK;
}
-CAResult_t CAIPTerminateNetworkMonitor()
+CAResult_t CAIPStopNetworkMonitor()
{
return CA_STATUS_OK;
}
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);
#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)
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");
+}
######################################################################
libocsrm_env.PrependUnique(CPPPATH = [
'../../../extlibs/cjson/',
-# '../../../extlibs/tinydtls/',
+ '../../../extlibs/tinydtls/',
'../logger/include',
'../ocrandom/include',
'../stack/include',
# 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)
--- /dev/null
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#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
+
+
*/
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
* @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__ */
/**
#ifndef IOTVT_SRM_DOXM_H
#define IOTVT_SRM_DOXM_H
+#include "octypes.h"
+
#ifdef __cplusplus
extern "C" {
#endif
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;
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;
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;
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;
//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;
--- /dev/null
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#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
+
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#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
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#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
+
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#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_
#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)
{
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
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
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;
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
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;
};
/**
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
#define IOTVT_SRM_UTILITY_H
#include "ocstack.h"
+#include "cJSON.h"
+#include "securevirtualresourcetypes.h"
#ifdef __cplusplus
extern "C"
{
* @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
* @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
*/
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
--- /dev/null
+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.
+
'../../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'
# 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')
*
* *****************************************************************/
-#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,
#ifdef __cplusplus
}
#endif
-#endif //SP_CREDENTIAL_GENERATOR_H
+#endif //PM_CREDENTIAL_GENERATOR_H
--- /dev/null
+/* *****************************************************************\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
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#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
--- /dev/null
+/* *****************************************************************\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
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#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
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#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
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#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
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#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_
+++ /dev/null
-/* *****************************************************************
- *
- * Copyright 2015 Samsung Electronics All Rights Reserved.
- *
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * *****************************************************************/
-
-#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
'../../../logger/include',
'../../../stack/include',
'../../../security/include',
+ '../../../security/provisioning/include/internal',
'../../../../oc_logger/include',
'../include',
+ '../include/oxm',
'../../include',
'../../../../../extlibs/tinydtls',
'../../../../../extlibs/cjson',
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'])
######################################################################
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')
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'))
--- /dev/null
+{
+ "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=="
+ }
+}
--- /dev/null
+{
+ "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=="
+ }
+}
--- /dev/null
+{
+ "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=="
+ }
+}
#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;
}
}
*
* @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')
}
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");
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
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++)
{
}
}
}
- 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;
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;
}
--- /dev/null
+/******************************************************************
+*
+* Copyright 2015 Samsung Electronics All Rights Reserved.
+*
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+******************************************************************/
+///////////////////////////////////////////////////////////////////////
+//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;
+}
--- /dev/null
+/******************************************************************
+*
+* Copyright 2015 Samsung Electronics All Rights Reserved.
+*
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+******************************************************************/
+///////////////////////////////////////////////////////////////////////
+//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;
+}
*
* *****************************************************************/
#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;
}
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+#include <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;
+
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+// 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;
+
+}
+
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#include <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;
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+
+#include <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;
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+#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;
+}
+++ /dev/null
-/* *****************************************************************
- *
- * Copyright 2015 Samsung Electronics All Rights Reserved.
- *
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * *****************************************************************/
-
-// 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;;
-}
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include <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;
+}
'../../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',
######################################################################
# 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])
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+#include "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);
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+#include "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
+++ /dev/null
-/* *****************************************************************
- *
- * Copyright 2015 Samsung Electronics All Rights Reserved.
- *
- *
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * *****************************************************************/
-
-#include "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));
-}
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+#include "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
#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)
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);
}
}
}
// 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());
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);
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
// 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;
}
}
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.
OCEntityHandlerRequest * ehRequest,
void* callbackParameter)
{
+ OC_LOG(INFO, TAG, PCF("Received request ACLEntityHandler"));
(void)callbackParameter;
OCEntityHandlerResult ehRet = OC_EH_ERROR;
ehRet = HandleACLPostRequest(ehRequest);
break;
+ case OC_REST_DELETE:
+ ehRet = HandleACLDeleteRequest(ehRequest);
+ break;
+
default:
ehRet = OC_EH_ERROR;
SendSRMResponse(ehRequest, ehRet, NULL);
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;
--- /dev/null
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include <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;
+}
#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);
}
}
}
//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));
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
exit:
return 0;
}
+
+
/**
* This function adds the new cred to the credential list.
*
OCStackResult AddCredential(OicSecCred_t * newCred)
{
OCStackResult ret = OC_STACK_ERROR;
- char * jsonStr = NULL;
VERIFY_SUCCESS(TAG, NULL != newCred, ERROR);
//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)
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)
case OC_REST_POST:
ret = HandlePostRequest(ehRequest);
break;
+ case OC_REST_DELETE:
+ ret = HandleDeleteRequest(ehRequest);
+ break;
default:
ret = OC_EH_ERROR;
break;
{
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;
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);
}
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__ */
#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>
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
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
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);
}
return false;
}
- OicParseQueryIter_t parseIter = {0};
+ OicParseQueryIter_t parseIter = {.attrPos = NULL};
ParseQueryIterInit(query, &parseIter);
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)
{
*
*/
#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))
#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:
--- /dev/null
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+//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
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+#include "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;
+}
--- /dev/null
+/* *****************************************************************
+ *
+ * Copyright 2015 Samsung Electronics All Rights Reserved.
+ *
+ *
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * *****************************************************************/
+#include <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 *)#
+ 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;
+}
+
#include "aclresource.h"
#include "srmutility.h"
#include "doxmresource.h"
+#include "iotvticalendar.h"
#include <string.h>
#define TAG PCF("SRM-PE")
}
/**
- * 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.
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;
+ }
}
}
}
{
OCStackResult ret = OC_STACK_ERROR;
cJSON *jsonSVRDb = NULL;
+ OCPersistentStorage* ps = NULL;
// Read SVR database from PS
char* jsonSVRDbStr = GetSVRDatabase();
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);
// 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!! "));
}
}
*/
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;
#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"
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}};
{
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
OCPersistentStorage* SRMGetPersistentStorageHandler()
{
- OC_LOG(INFO, TAG, PCF("SRMGetPersistentStorageHandler !!"));
return gPersistentStorageHandler;
}
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";
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";
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;
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 = '=';
+
#include "srmutility.h"
#include "srmresourcestrings.h"
#include "logger.h"
+#include "oic_malloc.h"
+#include "base64.h"
#define TAG PCF("SRM-UTILITY")
(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
}
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;
+
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "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;
+}
+
'securityresourcemanager.cpp',
'credentialresource.cpp',
'srmutility.cpp',
- 'base64tests.cpp'])
+ 'iotvticalendartest.cpp',
+ 'base64tests.cpp',
+ 'svcresourcetest.cpp',
+ 'srmtestcommon.cpp'])
Alias("test", [unittest])
#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,
#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)
{
// '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
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);
+}
#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")
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;
}
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
json = BinToCredJSON(cred);
+ OC_LOG_V(INFO, TAG, PCF("BinToCredJSON:%s\n"), json);
EXPECT_TRUE(json != NULL);
DeleteCredList(cred);
OICFree(json);
EXPECT_TRUE(json != NULL);
OicSecCred_t *cred2 = JSONToCredBin(json);
- EXPECT_TRUE(cred2 == NULL);
+ EXPECT_TRUE(cred2 != NULL);
DeleteCredList(cred1);
DeleteCredList(cred2);
OICFree(json);
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";
privateKey, 1, owners);
printCred(cred);
+ EXPECT_TRUE(NULL != cred);
DeleteCredList(cred);
}
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";
#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,
}
#endif
+
OicSecDoxm_t * getBinDoxm()
{
OicSecDoxm_t * doxm = (OicSecDoxm_t*)OICCalloc(1, sizeof(OicSecDoxm_t));
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));
OicSecDoxm_t * doxm = getBinDoxm();
char * json = BinToDoxmJSON(doxm);
+ OC_LOG_V(INFO, TAG, PCF("BinToDoxmJSON:%s"), json);
EXPECT_TRUE(json != NULL);
DeleteDoxmBinData(doxm);
--- /dev/null
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+//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
"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=="
+ ]
+ }
+ ]
}
#include "base64.h"
#include "cainterface.h"
#include "secureresourcemanager.h"
+#include "srmtestcommon.h"
#include "ocpayload.h"
#include <unistd.h>
#ifdef __cplusplus
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
}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "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));
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#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
#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))
--- /dev/null
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "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);
+ }
+}
+
#include "ocstack.h"
//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+#define DEFAULT_CONTEXT_VALUE 0x99
+
+//-----------------------------------------------------------------------------
// Typedefs
//-----------------------------------------------------------------------------
#include "ocserverbasicops.h"
#include "common.h"
+
int gQuitFlag = 0;
static LEDResource LED;
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)
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;
"/oic/p",
"/oic/res/types/d",
"/oic/ad",
- "/oic/sec/acl"
+ "/oic/sec/acl",
+ "/oic/sec/amacl"
],
"perms": 2,
"ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
"/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=="]
}
],
"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=="]
}]
}
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/
// 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))
}
else
{
+ responseInfo.isMulticast = false;
responseInfo.info.payload = NULL;
responseInfo.info.payloadSize = 0;
}
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)
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)
// 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);
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;
requestInfo.info.numOptions = numOptions;
}
- // create remote endpoint
- result = OCCreateEndpoint(devAddr, &endpoint);
+ CopyDevAddrToEndpoint(devAddr, &endpoint);
+
if(payload)
{
if((result =
requestInfo.info.payloadSize = 0;
}
-
-
if (result != OC_STACK_OK)
{
OC_LOG(ERROR, TAG, PCF("CACreateEndpoint error"));
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;
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"));
OICFree(devAddr);
OICFree(resourceUri);
OICFree(resourceType);
- OICFree(endpoint);
if (hdrOptionMemAlloc)
{
OICFree(requestInfo.info.options);
* 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};
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"));
}
Error:
- OCDestroyEndpoint(endpoint);
if (requestData.numOptions > 0)
{
OICFree(requestData.options);
{
OICFree (requestData.resourceUri);
}
-
return ret;
}
}
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;
requestInfo.method = CA_GET;
requestInfo.info = requestData;
- caResult = CASendRequest(endpoint, &requestInfo);
- OCDestroyEndpoint(endpoint);
+ caResult = CASendRequest(&endpoint, &requestInfo);
if (caResult != CA_STATUS_OK)
{
{
OC_LOG(ERROR, TAG, PCF("OCProcessPresence error"));
}
+
return result;
}
#endif // WITH_PRESENCE
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);
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;
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);
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, "|");
}
}
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,
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.
{
/**
* 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);
* @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);
* 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,
/**
* 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
* 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);
* 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);
* 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);
/**
* 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:
* 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,
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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,
/**
* 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.
* 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);
* 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);
* 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,
/**
* 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);
}
/**
* 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);
/**
* 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);
/**
* 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:
* 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,
/**
* 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);
#include <list>
#include <string>
-#include <boost/atomic.hpp>
+#include <atomic>
#include "BrokerTypes.h"
#include "ResourcePresence.h"
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;
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
{
DevicePresence::DevicePresence()
{
- state = DEVICE_STATE::REQUESTED;
+ setDeviceState(DEVICE_STATE::REQUESTED);
presenceTimerHandle = 0;
isRunningTimeOut = false;
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()");
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);
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;
}
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;
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