Merging security-M3 to master
authorSachin Agrawal <sachin.agrawal@intel.com>
Thu, 4 Jun 2015 16:51:01 +0000 (09:51 -0700)
committerSachin Agrawal <sachin.agrawal@intel.com>
Thu, 4 Jun 2015 23:51:56 +0000 (23:51 +0000)
Added support for resource access control, anonymous ECDH,
and Just Works Provisioning.

Patch 1 : Squashed all security-M3 patches and rebased to
          common ancestor of security-M3 and master.
Patch 2 : Rebased to master. (Arduino build fails).
Patch 3-4 : Fix the unit test failures.
Patch 5 : Fix the previsioning server send request issue
          by adding token length.
Patch 6 : Fixed Arduino compilation.
Patch 7 : Fixed DTLS handshake issue.
Patch 8 : Fix the build issue.
Patch 9 : Replaced strncmp with memcmp, As token handling is
          from null terminated string to byte buffer.
Patch 10: Rebased with master.
Patch 11-12: OSX Build Failure Fixes.
Patch 13: Updated README related to secure-Iotivity stack.
Patch 14: Fixed issues identified in Patch 5.
Patch 15: Rebased with master to avoid merge conflicts.
Patch 16: Updated commit message

Change-Id: Icae698c3bf377862b561d6ebba1d784058d28adb
Signed-off-by: Sachin Agrawal <sachin.agrawal@intel.com>
Signed-off-by: Sakthivel Samidurai <sakthivel.samidurai@intel.com>
Signed-off-by: Randeep Singh <randeep.s@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/1071

100 files changed:
build_common/SConscript [changed mode: 0644->0755]
extlibs/tinydtls/0001-Added-anonymous-ecdh-cipher-suite-into-tinydtls.patch [new file with mode: 0644]
extlibs/tinydtls/aes/rijndael.h
extlibs/tinydtls/crypto.c
extlibs/tinydtls/crypto.h
extlibs/tinydtls/dtls.c
extlibs/tinydtls/dtls.h
extlibs/tinydtls/ecc/Makefile.contiki [changed mode: 0644->0755]
extlibs/tinydtls/ecc/Makefile.ecc [changed mode: 0644->0755]
extlibs/tinydtls/ecc/test_helper.c [deleted file]
extlibs/tinydtls/ecc/test_helper.h [deleted file]
extlibs/tinydtls/ecc/testecc.c [deleted file]
extlibs/tinydtls/ecc/testfield.c [deleted file]
extlibs/tinydtls/global.h
extlibs/tinydtls/tests/dtls-client.c
extlibs/tinydtls/tests/dtls-server.c
extlibs/tinydtls/tinydtls.h
extlibs/tinydtls/uthash.h
extlibs/tinydtls/utlist.h
resource/SConscript
resource/csdk/SConscript
resource/csdk/connectivity/api/cacommon.h
resource/csdk/connectivity/api/cainterface.h
resource/csdk/connectivity/inc/caadapternetdtls.h
resource/csdk/connectivity/inc/caipinterface.h
resource/csdk/connectivity/samples/linux/SConscript [changed mode: 0644->0755]
resource/csdk/connectivity/src/SConscript [changed mode: 0644->0755]
resource/csdk/connectivity/src/adapter_util/caadapternetdtls.c
resource/csdk/connectivity/src/adapter_util/caadapterutils.c
resource/csdk/connectivity/src/caconnectivitymanager.c
resource/csdk/connectivity/src/ip_adapter/caipadapter.c
resource/csdk/connectivity/src/ip_adapter/caipserver.c
resource/csdk/security/README-building-and-running-secure-IoTivity-stack.txt [new file with mode: 0644]
resource/csdk/security/SConscript [new file with mode: 0644]
resource/csdk/security/include/base64.h [new file with mode: 0644]
resource/csdk/security/include/internal/aclresource.h [new file with mode: 0755]
resource/csdk/security/include/internal/credresource.h [new file with mode: 0644]
resource/csdk/security/include/internal/doxmresource.h [new file with mode: 0644]
resource/csdk/security/include/internal/policyengine.h [new file with mode: 0644]
resource/csdk/security/include/internal/psinterface.h [moved from resource/csdk/security/include/internal/ocsecurityinternal.h with 50% similarity]
resource/csdk/security/include/internal/pstatresource.h [new file with mode: 0644]
resource/csdk/security/include/internal/resourcemanager.h [new file with mode: 0644]
resource/csdk/security/include/internal/secureresourcemanager.h [new file with mode: 0644]
resource/csdk/security/include/internal/srmresourcestrings.h [new file with mode: 0644]
resource/csdk/security/include/ocsecurityconfig.h [deleted file]
resource/csdk/security/include/securevirtualresourcetypes.h [new file with mode: 0644]
resource/csdk/security/include/srmutility.h [moved from resource/csdk/security/include/ocsecurity.h with 50% similarity]
resource/csdk/security/provisioning/SConscript [new file with mode: 0644]
resource/csdk/security/provisioning/include/internal/credentialgenerator.h [new file with mode: 0644]
resource/csdk/security/provisioning/include/provisioningmanager.h [new file with mode: 0644]
resource/csdk/security/provisioning/sample/SConscript [new file with mode: 0755]
resource/csdk/security/provisioning/sample/oic_svr_db.json [new file with mode: 0755]
resource/csdk/security/provisioning/sample/provisioningclient.c [new file with mode: 0755]
resource/csdk/security/provisioning/src/credentialgenerator.c [new file with mode: 0644]
resource/csdk/security/provisioning/src/provisioningmanager.c [new file with mode: 0644]
resource/csdk/security/provisioning/unittest/SConscript [new file with mode: 0644]
resource/csdk/security/provisioning/unittest/provisioningmanager.cpp [new file with mode: 0644]
resource/csdk/security/src/aclresource.c [new file with mode: 0644]
resource/csdk/security/src/base64.c [new file with mode: 0644]
resource/csdk/security/src/credresource.c [new file with mode: 0755]
resource/csdk/security/src/doxmresource.c [new file with mode: 0755]
resource/csdk/security/src/ocsecurity.c [deleted file]
resource/csdk/security/src/policyengine.c [new file with mode: 0644]
resource/csdk/security/src/psinterface.c [new file with mode: 0644]
resource/csdk/security/src/pstatresource.c [new file with mode: 0644]
resource/csdk/security/src/resourcemanager.c [new file with mode: 0644]
resource/csdk/security/src/secureresourcemanager.c [new file with mode: 0644]
resource/csdk/security/src/srmresourcestrings.c [new file with mode: 0644]
resource/csdk/security/unittest/SConscript [new file with mode: 0644]
resource/csdk/security/unittest/aclresourcetest.cpp [new file with mode: 0644]
resource/csdk/security/unittest/base64tests.cpp [new file with mode: 0644]
resource/csdk/security/unittest/credentialresource.cpp [new file with mode: 0644]
resource/csdk/security/unittest/doxmresource.cpp [new file with mode: 0644]
resource/csdk/security/unittest/oic_svr_db.json [new file with mode: 0644]
resource/csdk/security/unittest/oic_unittest.json [new file with mode: 0644]
resource/csdk/security/unittest/oic_unittest_acl1.json [new file with mode: 0644]
resource/csdk/security/unittest/oic_unittest_default_acl.json [new file with mode: 0644]
resource/csdk/security/unittest/policyengine.cpp [new file with mode: 0644]
resource/csdk/security/unittest/pstatresource.cpp [new file with mode: 0644]
resource/csdk/security/unittest/securityresourcemanager.cpp [new file with mode: 0644]
resource/csdk/stack/include/ocstack.h
resource/csdk/stack/include/octypes.h
resource/csdk/stack/samples/arduino/SimpleClientServer/ocserver/SConscript
resource/csdk/stack/samples/linux/SimpleClientServer/SConscript
resource/csdk/stack/samples/linux/SimpleClientServer/occlientbasicops.cpp
resource/csdk/stack/samples/linux/SimpleClientServer/ocserverbasicops.cpp
resource/csdk/stack/samples/linux/secure/SConscript
resource/csdk/stack/samples/linux/secure/common.cpp
resource/csdk/stack/samples/linux/secure/common.h
resource/csdk/stack/samples/linux/secure/gen_sec_bin.cpp [deleted file]
resource/csdk/stack/samples/linux/secure/occlientbasicops.cpp
resource/csdk/stack/samples/linux/secure/ocserverbasicops.cpp
resource/csdk/stack/samples/linux/secure/oic_svr_db_client.json [new file with mode: 0644]
resource/csdk/stack/samples/linux/secure/oic_svr_db_server.json [new file with mode: 0644]
resource/csdk/stack/src/ocserverrequest.c
resource/csdk/stack/src/ocstack.c
resource/csdk/stack/test/SConscript
resource/csdk/stack/test/stacktests.cpp
resource/unit_tests.scons
resource/unittests/SConscript

old mode 100644 (file)
new mode 100755 (executable)
diff --git a/extlibs/tinydtls/0001-Added-anonymous-ecdh-cipher-suite-into-tinydtls.patch b/extlibs/tinydtls/0001-Added-anonymous-ecdh-cipher-suite-into-tinydtls.patch
new file mode 100644 (file)
index 0000000..ba75317
--- /dev/null
@@ -0,0 +1,1164 @@
+From bdfe0e312f9c2cd34df7bfff070dfe8a9e82d147 Mon Sep 17 00:00:00 2001
+From: leechul <chuls.lee@samsung.com>
+Date: Thu, 9 Apr 2015 16:25:43 +0900
+Subject: [PATCH 1/1] Added anonymous ecdh cipher suite into tinydtls
+
+Change-Id: I80fa2985587618ebe7debdacba45996614c4cf1b
+Signed-off-by: leechul <chuls.lee@samsung.com>
+Signed-off-by: Sachin Agrawal <sachin.agrawal@intel.com>
+---
+ extlibs/tinydtls/aes/rijndael.h      |    1 +
+ extlibs/tinydtls/crypto.c            |  173 ++++++++++++++++---
+ extlibs/tinydtls/crypto.h            |   15 +-
+ extlibs/tinydtls/dtls.c              |  301 +++++++++++++++++++++++++---------
+ extlibs/tinydtls/dtls.h              |   28 +++-
+ extlibs/tinydtls/global.h            |    6 +
+ extlibs/tinydtls/tests/dtls-client.c |   42 ++++-
+ extlibs/tinydtls/tests/dtls-server.c |   21 ++-
+ 8 files changed, 468 insertions(+), 119 deletions(-)
+ mode change 100755 => 100644 extlibs/tinydtls/crypto.c
+
+diff --git a/extlibs/tinydtls/aes/rijndael.h b/extlibs/tinydtls/aes/rijndael.h
+index 60e9bef..712798b 100755
+--- a/extlibs/tinydtls/aes/rijndael.h
++++ b/extlibs/tinydtls/aes/rijndael.h
+@@ -30,6 +30,7 @@
+ #include <stdint.h>
++#define WITH_AES_DECRYPT 1
+ #define AES_MAXKEYBITS        (256)
+ #define AES_MAXKEYBYTES       (AES_MAXKEYBITS>>3)
+ /* for 256-bit keys we need 14 rounds for a 128 we only need 10 round */
+diff --git a/extlibs/tinydtls/crypto.c b/extlibs/tinydtls/crypto.c
+old mode 100755
+new mode 100644
+index 0113342..0ea1546
+--- a/extlibs/tinydtls/crypto.c
++++ b/extlibs/tinydtls/crypto.c
+@@ -54,6 +54,8 @@
+ #include "crypto.h"
+ #include "ccm.h"
+ #include "ecc/ecc.h"
++#include "aes/rijndael.h"
++#include "sha2/sha2.h"
+ #include "prng.h"
+ #include "netq.h"
+@@ -292,7 +294,7 @@ dtls_mac(dtls_hmac_context_t *hmac_ctx,
+ }
+ static size_t
+-dtls_ccm_encrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src, size_t srclen,
++dtls_ccm_encrypt(aes128_t *ccm_ctx, const unsigned char *src, size_t srclen,
+                unsigned char *buf,
+                unsigned char *nounce,
+                const unsigned char *aad, size_t la) {
+@@ -309,7 +311,7 @@ dtls_ccm_encrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src, size_t srclen,
+ }
+ static size_t
+-dtls_ccm_decrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src,
++dtls_ccm_decrypt(aes128_t *ccm_ctx, const unsigned char *src,
+                size_t srclen, unsigned char *buf,
+                unsigned char *nounce,
+                const unsigned char *aad, size_t la) {
+@@ -325,6 +327,95 @@ dtls_ccm_decrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src,
+   return len;
+ }
++static size_t
++dtls_cbc_encrypt(aes128_t *aes_ctx,
++                 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;
++    int i, j;
++    int blocks;
++
++    pos = buf;
++
++    dtls_hash_init(&shactx);
++    dtls_hash_update(&shactx, src, srclen);
++    dtls_hash_finalize(pos + srclen, &shactx);
++
++    memcpy(cbc, iv, DTLS_BLK_LENGTH);
++    blocks = (srclen + SHA256_DIGEST_LENGTH) / DTLS_BLK_LENGTH;
++
++    for (i = 0; i < blocks; i++) {
++        for (j = 0; j < DTLS_BLK_LENGTH; j++) {
++            cbc[j] ^= pos[j];
++        }
++
++        rijndael_encrypt(&aes_ctx->ctx, cbc, tmp);
++        memcpy(cbc, tmp, DTLS_BLK_LENGTH);
++        memcpy(pos, cbc, DTLS_BLK_LENGTH);
++        pos += DTLS_BLK_LENGTH;
++    }
++
++    dtls_debug_dump("Encrypted Data:", buf, srclen + SHA256_DIGEST_LENGTH);
++
++    return srclen + SHA256_DIGEST_LENGTH;
++}
++
++
++static size_t
++dtls_cbc_decrypt(aes128_t *aes_ctx,
++                 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 *pos;
++    dtls_hash_ctx shactx;
++    int i, j;
++    int blocks;
++
++    pos = buf;
++    memcpy(pos, src, srclen);
++
++    memcpy(cbc, iv, DTLS_BLK_LENGTH);
++    blocks = srclen / DTLS_BLK_LENGTH;
++
++    for (i = 0; i < blocks; i++)
++    {
++        memcpy(tmp, pos, DTLS_BLK_LENGTH);
++        rijndael_decrypt(&aes_ctx->ctx, pos, tmp2);
++        memcpy(pos, tmp2, DTLS_BLK_LENGTH);
++
++        for (j = 0; j < DTLS_BLK_LENGTH; j++) {
++            pos[j] ^= cbc[j];
++        }
++
++        memcpy(cbc, tmp, 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);
++
++    if(memcmp(msg_hash, buf + (srclen - SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH) != 0)
++    {
++        dtls_warn("message is broken\n");
++        return -1;
++    }
++
++    return srclen - SHA256_DIGEST_LENGTH;
++}
++
+ #ifdef DTLS_PSK
+ int
+ dtls_psk_pre_master_secret(unsigned char *key, size_t keylen,
+@@ -432,13 +523,10 @@ 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];
+-
+   uECC_sign(privateKey, hashValue, sign);
+   memcpy(point_r, sign, 32);
+   memcpy(point_s, sign + 32, 32);
+@@ -505,21 +593,37 @@ dtls_encrypt(const unsigned char *src, size_t length,
+            unsigned char *buf,
+            unsigned char *nounce,
+            unsigned char *key, size_t keylen,
+-           const unsigned char *aad, size_t la)
++           const unsigned char *aad, size_t la,
++           const dtls_cipher_t cipher)
+ {
+-  int ret;
++  int ret = 0;
+   struct dtls_cipher_context_t *ctx = dtls_cipher_context_get();
+-  ret = rijndael_set_key_enc_only(&ctx->data.ctx, key, 8 * keylen);
+-  if (ret < 0) {
+-    /* cleanup everything in case the key has the wrong size */
+-    dtls_warn("cannot set rijndael key\n");
+-    goto error;
++  if(cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ||
++     cipher == TLS_PSK_WITH_AES_128_CCM_8) {
++      ret = rijndael_set_key_enc_only(&ctx->data.ctx, key, 8 * keylen);
++      if (ret < 0) {
++        /* cleanup everything in case the key has the wrong size */
++        dtls_warn("cannot set rijndael key\n");
++        goto error;
++      }
++
++      if (src != 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) {
++      ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
++      if (ret < 0) {
++        /* cleanup everything in case the key has the wrong size */
++        dtls_warn("cannot set rijndael key\n");
++        goto error;
++      }
++
++      if (src != buf)
++        memmove(buf, src, length);
++      ret = dtls_cbc_encrypt(&ctx->data, nounce, src, length, buf);
+   }
+-
+-  if (src != buf)
+-    memmove(buf, src, length);
+-  ret = dtls_ccm_encrypt(&ctx->data, src, length, buf, nounce, aad, la);
+ error:
+   dtls_cipher_context_release();
+@@ -531,21 +635,38 @@ dtls_decrypt(const unsigned char *src, size_t length,
+            unsigned char *buf,
+            unsigned char *nounce,
+            unsigned char *key, size_t keylen,
+-           const unsigned char *aad, size_t la)
++           const unsigned char *aad, size_t la,
++           const dtls_cipher_t cipher)
+ {
+-  int ret;
++  int ret = 0;
+   struct dtls_cipher_context_t *ctx = dtls_cipher_context_get();
+-  ret = rijndael_set_key_enc_only(&ctx->data.ctx, key, 8 * keylen);
+-  if (ret < 0) {
+-    /* cleanup everything in case the key has the wrong size */
+-    dtls_warn("cannot set rijndael key\n");
+-    goto error;
++  if(cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ||
++     cipher == TLS_PSK_WITH_AES_128_CCM_8) {
++      ret = rijndael_set_key_enc_only(&ctx->data.ctx, key, 8 * keylen);
++      if (ret < 0) {
++        /* cleanup everything in case the key has the wrong size */
++        dtls_warn("cannot set rijndael key\n");
++        goto error;
++      }
++
++      if (src != buf)
++        memmove(buf, src, length);
++      ret = dtls_ccm_decrypt(&ctx->data, src, length, buf, nounce, aad, la);
+   }
+-  if (src != buf)
+-    memmove(buf, src, length);
+-  ret = dtls_ccm_decrypt(&ctx->data, src, length, buf, nounce, aad, la);
++  if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA) {
++      ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
++      if (ret < 0) {
++        /* cleanup everything in case the key has the wrong size */
++        dtls_warn("cannot set rijndael key\n");
++        goto error;
++      }
++
++      if (src != buf)
++        memmove(buf, src, length);
++      ret = dtls_cbc_decrypt(&ctx->data, nounce, src, length, buf);
++    }
+ error:
+   dtls_cipher_context_release();
+diff --git a/extlibs/tinydtls/crypto.h b/extlibs/tinydtls/crypto.h
+index 972a174..dd13ffa 100644
+--- a/extlibs/tinydtls/crypto.h
++++ b/extlibs/tinydtls/crypto.h
+@@ -69,11 +69,11 @@ typedef enum {
+ /** Crypto context for TLS_PSK_WITH_AES_128_CCM_8 cipher suite. */
+ typedef struct {
+   rijndael_ctx ctx;                  /**< AES-128 encryption context */
+-} aes128_ccm_t;
++} aes128_t;
+ typedef struct dtls_cipher_context_t {
+   /** numeric identifier of this cipher suite in host byte order. */
+-  aes128_ccm_t data;          /**< The crypto context */
++  aes128_t data;              /**< The crypto context */
+ } dtls_cipher_context_t;
+ typedef struct {
+@@ -82,7 +82,8 @@ typedef struct {
+   uint8 other_eph_pub_y[32];
+   uint8 other_pub_x[32];
+   uint8 other_pub_y[32];
+-} dtls_handshake_parameters_ecdsa_t;
++} dtls_handshake_parameters_ecc_t;
++
+ /* This is the maximal supported length of the psk client identity and psk
+  * server identity hint */
+@@ -129,7 +130,7 @@ typedef struct {
+   unsigned int do_client_auth:1;
+   union {
+ #ifdef DTLS_ECC
+-    dtls_handshake_parameters_ecdsa_t ecdsa;
++    dtls_handshake_parameters_ecc_t ecc;
+ #endif /* DTLS_ECC */
+ #ifdef DTLS_PSK
+     dtls_handshake_parameters_psk_t psk;
+@@ -265,7 +266,8 @@ int dtls_encrypt(const unsigned char *src, size_t length,
+                unsigned char *buf,
+                unsigned char *nounce,
+                unsigned char *key, size_t keylen,
+-               const unsigned char *aad, size_t aad_length);
++               const unsigned char *aad, size_t aad_length,
++               const dtls_cipher_t cipher);
+ /** 
+  * Decrypts the given buffer \p src of given \p length, writing the
+@@ -289,7 +291,8 @@ int dtls_decrypt(const unsigned char *src, size_t length,
+                unsigned char *buf,
+                unsigned char *nounce,
+                unsigned char *key, size_t keylen,
+-               const unsigned char *a_data, size_t a_data_length);
++               const unsigned char *a_data, size_t a_data_length,
++               const dtls_cipher_t cipher);
+ /* helper functions */
+diff --git a/extlibs/tinydtls/dtls.c b/extlibs/tinydtls/dtls.c
+index a87d7f1..f9a9a0b 100644
+--- a/extlibs/tinydtls/dtls.c
++++ b/extlibs/tinydtls/dtls.c
+@@ -79,6 +79,7 @@
+ #define DTLS_SH_LENGTH (2 + DTLS_RANDOM_LENGTH + 1 + 2 + 1)
+ #define DTLS_CE_LENGTH (3 + 3 + 27 + DTLS_EC_KEY_SIZE + DTLS_EC_KEY_SIZE)
+ #define DTLS_SKEXEC_LENGTH (1 + 2 + 1 + 1 + DTLS_EC_KEY_SIZE + DTLS_EC_KEY_SIZE + 1 + 1 + 2 + 70)
++#define DTLS_SKEXEC_ECDH_ANON_LENGTH (1 + 2 + 1 + 1 + DTLS_EC_KEY_SIZE + DTLS_EC_KEY_SIZE)
+ #define DTLS_SKEXECPSK_LENGTH_MIN 2
+ #define DTLS_SKEXECPSK_LENGTH_MAX 2 + DTLS_PSK_MAX_CLIENT_IDENTITY_LEN
+ #define DTLS_CKXPSK_LENGTH_MIN 2
+@@ -167,6 +168,24 @@ dtls_init() {
+   peer_init();
+ }
++ void
++ dtls_enables_anon_ecdh(dtls_context_t* ctx, dtls_cipher_enable_t is_enable)
++{
++    if(ctx)
++    {
++        ctx->is_anon_ecdh_eabled = is_enable;
++    }
++}
++
++void
++dtls_select_cipher(dtls_context_t* ctx, const dtls_cipher_t cipher)
++{
++    if(ctx)
++    {
++        ctx->selected_cipher = cipher;
++    }
++}
++
+ /* Calls cb_alert() with given arguments if defined, otherwise an
+  * error message is logged and the result is -1. This is just an
+  * internal helper.
+@@ -477,6 +496,17 @@ 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)
++{
++#ifdef DTLS_ECC
++    return cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
++#else
++    return 0;
++#endif
++}
++
++
+ /** returns true if the application is configured for psk */
+ static inline int is_psk_supported(dtls_context_t *ctx)
+ {
+@@ -509,6 +539,16 @@ static inline int is_ecdsa_client_auth_supported(dtls_context_t *ctx)
+ #endif /* DTLS_ECC */
+ }
++/** returns true if ecdh_anon_with_aes_128_cbc_sha is supported */
++static inline int is_ecdh_anon_supported(dtls_context_t *ctx)
++{
++#ifdef DTLS_ECC
++    return ctx &&  (ctx->is_anon_ecdh_eabled == DTLS_CIPHER_ENABLE);
++#else
++    return 0;
++#endif
++}
++
+ /**
+  * Returns @c 1 if @p code is a cipher suite other than @c
+  * TLS_NULL_WITH_NULL_NULL that we recognize.
+@@ -522,11 +562,15 @@ static int
+ known_cipher(dtls_context_t *ctx, dtls_cipher_t code, int is_client) {
+   int psk;
+   int ecdsa;
++  int ecdh_anon;
+   psk = is_psk_supported(ctx);
+   ecdsa = is_ecdsa_supported(ctx, is_client);
++  ecdh_anon = is_ecdh_anon_supported(ctx);
++
+   return (psk && is_tls_psk_with_aes_128_ccm_8(code)) ||
+-       (ecdsa && is_tls_ecdhe_ecdsa_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));
+ }
+ /**
+@@ -674,11 +718,12 @@ calculate_key_block(dtls_context_t *ctx,
+   }
+ #endif /* DTLS_PSK */
+ #ifdef DTLS_ECC
+-  case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: {
+-    pre_master_len = dtls_ecdh_pre_master_secret(handshake->keyx.ecdsa.own_eph_priv,
+-                                               handshake->keyx.ecdsa.other_eph_pub_x,
+-                                               handshake->keyx.ecdsa.other_eph_pub_y,
+-                                               sizeof(handshake->keyx.ecdsa.own_eph_priv),
++  case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
++  case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: {
++    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,
++                                               sizeof(handshake->keyx.ecc.own_eph_priv),
+                                                pre_master_secret,
+                                                MAX_KEYBLOCK_LENGTH);
+     if (pre_master_len < 0) {
+@@ -1038,7 +1083,8 @@ check_client_keyexchange(dtls_context_t *ctx,
+                        uint8 *data, size_t length) {
+ #ifdef DTLS_ECC
+-  if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher)) {
++  if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher) ||
++       is_tls_ecdh_anon_with_aes_128_cbc_sha(handshake->cipher) ) {
+     if (length < DTLS_HS_LENGTH + DTLS_CKXEC_LENGTH) {
+       dtls_debug("The client key exchange is too short\n");
+@@ -1058,13 +1104,13 @@ check_client_keyexchange(dtls_context_t *ctx,
+     }
+     data += sizeof(uint8);
+-    memcpy(handshake->keyx.ecdsa.other_eph_pub_x, data,
+-         sizeof(handshake->keyx.ecdsa.other_eph_pub_x));
+-    data += sizeof(handshake->keyx.ecdsa.other_eph_pub_x);
++    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.ecdsa.other_eph_pub_y, data,
+-         sizeof(handshake->keyx.ecdsa.other_eph_pub_y));
+-    data += sizeof(handshake->keyx.ecdsa.other_eph_pub_y);
++    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 /* DTLS_ECC */
+ #ifdef DTLS_PSK
+@@ -1253,6 +1299,8 @@ 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");
+     }
+@@ -1332,9 +1380,10 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
+     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),
+-                     A_DATA, A_DATA_LEN);
++               dtls_kb_local_write_key(security, peer->role),
++               dtls_kb_key_size(security, peer->role),
++               A_DATA, A_DATA_LEN,
++               security->cipher);
+     if (res < 0)
+       return res;
+@@ -1753,8 +1802,8 @@ check_client_certificate_verify(dtls_context_t *ctx,
+   dtls_hash_finalize(sha256hash, &hs_hash);
+-  ret = dtls_ecdsa_verify_sig_hash(config->keyx.ecdsa.other_pub_x, config->keyx.ecdsa.other_pub_y,
+-                          sizeof(config->keyx.ecdsa.other_pub_x),
++  ret = dtls_ecdsa_verify_sig_hash(config->keyx.ecc.other_pub_x, config->keyx.ecc.other_pub_y,
++                          sizeof(config->keyx.ecc.other_pub_x),
+                           sha256hash, sizeof(sha256hash),
+                           result_r, result_s);
+@@ -1866,7 +1915,7 @@ dtls_send_server_hello(dtls_context_t *ctx, dtls_peer_t *peer)
+ #ifdef DTLS_ECC
+ static int
+ dtls_send_certificate_ecdsa(dtls_context_t *ctx, dtls_peer_t *peer,
+-                          const dtls_ecdsa_key_t *key)
++                          const dtls_ecc_key_t *key)
+ {
+   uint8 buf[DTLS_CE_LENGTH];
+   uint8 *p;
+@@ -1956,7 +2005,7 @@ dtls_add_ecdsa_signature_elem(uint8 *p, uint32_t *point_r, uint32_t *point_s)
+ static int
+ dtls_send_server_key_exchange_ecdh(dtls_context_t *ctx, dtls_peer_t *peer,
+-                                 const dtls_ecdsa_key_t *key)
++                                 const dtls_ecc_key_t *key)
+ {
+   /* The ASN.1 Integer representation of an 32 byte unsigned int could be
+    * 33 bytes long add space for that */
+@@ -1967,9 +2016,11 @@ dtls_send_server_key_exchange_ecdh(dtls_context_t *ctx, dtls_peer_t *peer,
+   uint8 *ephemeral_pub_y;
+   uint32_t point_r[9];
+   uint32_t point_s[9];
++  int ecdsa;
+   dtls_handshake_parameters_t *config = peer->handshake_params;
+-  /* ServerKeyExchange 
++  ecdsa = is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher);
++  /* ServerKeyExchange
+    *
+    * Start message construction at beginning of buffer. */
+   p = buf;
+@@ -1998,18 +2049,20 @@ dtls_send_server_key_exchange_ecdh(dtls_context_t *ctx, dtls_peer_t *peer,
+   ephemeral_pub_y = p;
+   p += DTLS_EC_KEY_SIZE;
+-  dtls_ecdsa_generate_key(config->keyx.ecdsa.own_eph_priv,
+-                        ephemeral_pub_x, ephemeral_pub_y,
+-                        DTLS_EC_KEY_SIZE);
++  dtls_ecdsa_generate_key(config->keyx.ecc.own_eph_priv,
++              ephemeral_pub_x, ephemeral_pub_y,
++              DTLS_EC_KEY_SIZE);
+-  /* sign the ephemeral and its paramaters */
+-  dtls_ecdsa_create_sig(key->priv_key, DTLS_EC_KEY_SIZE,
+-                     config->tmp.random.client, DTLS_RANDOM_LENGTH,
+-                     config->tmp.random.server, DTLS_RANDOM_LENGTH,
+-                     key_params, p - key_params,
+-                     point_r, point_s);
++  if(ecdsa) {
++      /* sign the ephemeral and its paramaters */
++           dtls_ecdsa_create_sig(key->priv_key, DTLS_EC_KEY_SIZE,
++               config->tmp.random.client, DTLS_RANDOM_LENGTH,
++               config->tmp.random.server, DTLS_RANDOM_LENGTH,
++               key_params, p - key_params,
++               point_r, point_s);
+-  p = dtls_add_ecdsa_signature_elem(p, point_r, point_s);
++      p = dtls_add_ecdsa_signature_elem(p, point_r, point_s);
++  }
+   assert(p - buf <= sizeof(buf));
+@@ -2107,6 +2160,8 @@ static int
+ dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
+ {
+   int res;
++  int ecdsa;
++  int ecdh_anon;
+   res = dtls_send_server_hello(ctx, peer);
+@@ -2115,9 +2170,20 @@ dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
+     return res;
+   }
++  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);
++
+ #ifdef DTLS_ECC
+-  if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher)) {
+-    const dtls_ecdsa_key_t *ecdsa_key;
++  if(ecdh_anon) {
++      res = dtls_send_server_key_exchange_ecdh(ctx, peer, NULL);
++
++      if (res < 0) {
++        dtls_debug("dtls_server_hello(with ECDH): cannot prepare Server Key Exchange record\n");
++        return res;
++      }
++  }
++  else if (ecdsa) {
++    const dtls_ecc_key_t *ecdsa_key;
+     res = CALL(ctx, get_ecdsa_key, &peer->session, &ecdsa_key);
+     if (res < 0) {
+@@ -2144,7 +2210,7 @@ dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
+       res = dtls_send_server_certificate_request(ctx, peer);
+       if (res < 0) {
+-        dtls_debug("dtls_server_hello: cannot prepare certificate Request record\n");
++        dtls_debug("dtls_server_hello(with ECDSA): cannot prepare certificate Request record\n");
+         return res;
+       }
+     }
+@@ -2233,7 +2299,8 @@ 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_ECDHE_ECDSA_WITH_AES_128_CCM_8:
++  case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: {
+     uint8 *ephemeral_pub_x;
+     uint8 *ephemeral_pub_y;
+@@ -2249,7 +2316,7 @@ dtls_send_client_key_exchange(dtls_context_t *ctx, dtls_peer_t *peer)
+     ephemeral_pub_y = p;
+     p += DTLS_EC_KEY_SIZE;
+-    dtls_ecdsa_generate_key(peer->handshake_params->keyx.ecdsa.own_eph_priv,
++    dtls_ecdsa_generate_key(peer->handshake_params->keyx.ecc.own_eph_priv,
+                           ephemeral_pub_x, ephemeral_pub_y,
+                           DTLS_EC_KEY_SIZE);
+@@ -2270,7 +2337,7 @@ dtls_send_client_key_exchange(dtls_context_t *ctx, dtls_peer_t *peer)
+ #ifdef DTLS_ECC
+ static int
+ dtls_send_certificate_verify_ecdh(dtls_context_t *ctx, dtls_peer_t *peer,
+-                                 const dtls_ecdsa_key_t *key)
++                                 const dtls_ecc_key_t *key)
+ {
+   /* The ASN.1 Integer representation of an 32 byte unsigned int could be
+    * 33 bytes long add space for that */
+@@ -2342,16 +2409,32 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
+   uint8 *p = buf;
+   uint8_t cipher_size;
+   uint8_t extension_size;
+-  int psk;
+-  int ecdsa;
++  int psk = 0;
++  int ecdsa = 0;
++  int ecdh_anon = 0;
+   dtls_handshake_parameters_t *handshake = peer->handshake_params;
+   dtls_tick_t now;
+-  psk = is_psk_supported(ctx);
+-  ecdsa = is_ecdsa_supported(ctx, 1);
++  switch(ctx->selected_cipher)
++  {
++      case TLS_PSK_WITH_AES_128_CCM_8:
++        psk = is_psk_supported(ctx);
++        break;
++      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:
++        ecdh_anon = is_ecdh_anon_supported(ctx);
++        break;
++      default:
++        psk = is_psk_supported(ctx);
++        ecdsa = is_ecdsa_supported(ctx, 1);
++        ecdh_anon = is_ecdh_anon_supported(ctx);
++        break;
++   }
+-  cipher_size = 2 + ((ecdsa) ? 2 : 0) + ((psk) ? 2 : 0);
+-  extension_size = (ecdsa) ? 2 + 6 + 6 + 8 + 6: 0;
++  cipher_size = 2 + (ecdsa ? 2 : 0) + (psk ? 2 : 0) + (ecdh_anon ? 2 : 0);
++  extension_size = (ecdsa) ? (2 + 6 + 6 + 8 + 6) : 0;
+   if (cipher_size == 0) {
+     dtls_crit("no cipher callbacks implemented\n");
+@@ -2393,14 +2476,18 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
+   dtls_int_to_uint16(p, cipher_size - 2);
+   p += sizeof(uint16);
+-  if (ecdsa) {
+-    dtls_int_to_uint16(p, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
++  if (ecdh_anon) {
++    dtls_int_to_uint16(p, TLS_ECDH_anon_WITH_AES_128_CBC_SHA);
+     p += sizeof(uint16);
+   }
+   if (psk) {
+     dtls_int_to_uint16(p, TLS_PSK_WITH_AES_128_CCM_8);
+     p += sizeof(uint16);
+   }
++  if (ecdsa) {
++    dtls_int_to_uint16(p, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
++    p += sizeof(uint16);
++  }
+   /* compression method */
+   dtls_int_to_uint8(p, 1);
+@@ -2611,18 +2698,18 @@ check_server_certificate(dtls_context_t *ctx,
+   }
+   data += sizeof(cert_asn1_header);
+-  memcpy(config->keyx.ecdsa.other_pub_x, data,
+-       sizeof(config->keyx.ecdsa.other_pub_x));
+-  data += sizeof(config->keyx.ecdsa.other_pub_x);
++  memcpy(config->keyx.ecc.other_pub_x, data,
++       sizeof(config->keyx.ecc.other_pub_x));
++  data += sizeof(config->keyx.ecc.other_pub_x);
+-  memcpy(config->keyx.ecdsa.other_pub_y, data,
+-       sizeof(config->keyx.ecdsa.other_pub_y));
+-  data += sizeof(config->keyx.ecdsa.other_pub_y);
++  memcpy(config->keyx.ecc.other_pub_y, data,
++       sizeof(config->keyx.ecc.other_pub_y));
++  data += sizeof(config->keyx.ecc.other_pub_y);
+   err = CALL(ctx, verify_ecdsa_key, &peer->session,
+-           config->keyx.ecdsa.other_pub_x,
+-           config->keyx.ecdsa.other_pub_y,
+-           sizeof(config->keyx.ecdsa.other_pub_x));
++           config->keyx.ecc.other_pub_x,
++           config->keyx.ecc.other_pub_y,
++           sizeof(config->keyx.ecc.other_pub_x));
+   if (err < 0) {
+     dtls_warn("The certificate was not accepted\n");
+     return err;
+@@ -2682,13 +2769,13 @@ check_server_key_exchange_ecdsa(dtls_context_t *ctx,
+   data += sizeof(uint8);
+   data_length -= sizeof(uint8);
+-  memcpy(config->keyx.ecdsa.other_eph_pub_x, data, sizeof(config->keyx.ecdsa.other_eph_pub_y));
+-  data += sizeof(config->keyx.ecdsa.other_eph_pub_y);
+-  data_length -= sizeof(config->keyx.ecdsa.other_eph_pub_y);
++  memcpy(config->keyx.ecc.other_eph_pub_x, 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);
+-  memcpy(config->keyx.ecdsa.other_eph_pub_y, data, sizeof(config->keyx.ecdsa.other_eph_pub_y));
+-  data += sizeof(config->keyx.ecdsa.other_eph_pub_y);
+-  data_length -= sizeof(config->keyx.ecdsa.other_eph_pub_y);
++  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);
+   ret = dtls_check_ecdsa_signature_elem(data, data_length, &result_r, &result_s);
+   if (ret < 0) {
+@@ -2697,8 +2784,8 @@ check_server_key_exchange_ecdsa(dtls_context_t *ctx,
+   data += ret;
+   data_length -= ret;
+-  ret = dtls_ecdsa_verify_sig(config->keyx.ecdsa.other_pub_x, config->keyx.ecdsa.other_pub_y,
+-                          sizeof(config->keyx.ecdsa.other_pub_x),
++  ret = dtls_ecdsa_verify_sig(config->keyx.ecc.other_pub_x, config->keyx.ecc.other_pub_y,
++                          sizeof(config->keyx.ecc.other_pub_x),
+                           config->tmp.random.client, DTLS_RANDOM_LENGTH,
+                           config->tmp.random.server, DTLS_RANDOM_LENGTH,
+                           key_params,
+@@ -2711,6 +2798,64 @@ check_server_key_exchange_ecdsa(dtls_context_t *ctx,
+   }
+   return 0;
+ }
++
++static int
++check_server_key_exchange_ecdh(dtls_context_t *ctx,
++                              dtls_peer_t *peer,
++                              uint8 *data, size_t data_length)
++{
++  dtls_handshake_parameters_t *config = peer->handshake_params;
++
++  update_hs_hash(peer, data, data_length);
++
++  assert(is_tls_ecdh_anon_with_aes_128_cbc_sha(config->cipher));
++
++  data += DTLS_HS_LENGTH;
++
++  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 /* DTLS_ECC */
+ #ifdef DTLS_PSK
+@@ -2838,7 +2983,7 @@ check_server_hellodone(dtls_context_t *ctx,
+ {
+   int res;
+ #ifdef DTLS_ECC
+-  const dtls_ecdsa_key_t *ecdsa_key;
++  const dtls_ecc_key_t *ecdsa_key;
+ #endif /* DTLS_ECC */
+   dtls_handshake_parameters_t *handshake = peer->handshake_params;
+@@ -2848,7 +2993,7 @@ check_server_hellodone(dtls_context_t *ctx,
+   update_hs_hash(peer, data, data_length);
+ #ifdef DTLS_ECC
+-  if (handshake->do_client_auth) {
++  if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher) && handshake->do_client_auth) {
+     res = CALL(ctx, get_ecdsa_key, &peer->session, &ecdsa_key);
+     if (res < 0) {
+@@ -2874,7 +3019,7 @@ check_server_hellodone(dtls_context_t *ctx,
+   }
+ #ifdef DTLS_ECC
+-  if (handshake->do_client_auth) {
++  if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher) && handshake->do_client_auth) {
+     res = dtls_send_certificate_verify_ecdh(ctx, peer, ecdsa_key);
+@@ -2961,12 +3106,13 @@ decrypt_verify(dtls_peer_t *peer, uint8 *packet, size_t length,
+     clen = dtls_decrypt(*cleartext, clen, *cleartext, nonce,
+                      dtls_kb_remote_write_key(security, peer->role),
+                      dtls_kb_key_size(security, peer->role),
+-                     A_DATA, A_DATA_LEN);
++                     A_DATA, A_DATA_LEN,
++               security->cipher);
+     if (clen < 0)
+       dtls_warn("decryption failed\n");
+     else {
+ #ifndef NDEBUG
+-      printf("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);
+@@ -3071,9 +3217,11 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, session_t *session,
+       return err;
+     }
+     if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher))
+-      peer->state = DTLS_STATE_WAIT_SERVERCERTIFICATE;
++      peer->state = DTLS_STATE_WAIT_SERVERCERTIFICATE; //ecdsa
++    else if (is_tls_ecdh_anon_with_aes_128_cbc_sha(peer->handshake_params->cipher))
++        peer->state = DTLS_STATE_WAIT_SERVERKEYEXCHANGE; //ecdh
+     else
+-      peer->state = DTLS_STATE_WAIT_SERVERHELLODONE;
++      peer->state = DTLS_STATE_WAIT_SERVERHELLODONE; //psk
+     /* update_hs_hash(peer, data, data_length); */
+     break;
+@@ -3109,6 +3257,13 @@ 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 (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 */
+ #ifdef DTLS_PSK
+     if (is_tls_psk_with_aes_128_ccm_8(peer->handshake_params->cipher)) {
+@@ -3218,9 +3373,9 @@ 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) &&
+       is_ecdsa_client_auth_supported(ctx))
+-      peer->state = DTLS_STATE_WAIT_CERTIFICATEVERIFY;
++      peer->state = DTLS_STATE_WAIT_CERTIFICATEVERIFY; //ecdsa
+     else
+-      peer->state = DTLS_STATE_WAIT_CHANGECIPHERSPEC;
++      peer->state = DTLS_STATE_WAIT_CHANGECIPHERSPEC; //psk || ecdh_anon
+     break;
+ #ifdef DTLS_ECC
+@@ -3341,9 +3496,9 @@ 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) &&
+       is_ecdsa_client_auth_supported(ctx))
+-      peer->state = DTLS_STATE_WAIT_CLIENTCERTIFICATE;
++      peer->state = DTLS_STATE_WAIT_CLIENTCERTIFICATE; //ecdhe
+     else
+-      peer->state = DTLS_STATE_WAIT_CLIENTKEYEXCHANGE;
++      peer->state = DTLS_STATE_WAIT_CLIENTKEYEXCHANGE; //psk, ecdh_anon
+     /* after sending the ServerHelloDone, we expect the
+      * ClientKeyExchange (possibly containing the PSK id),
+diff --git a/extlibs/tinydtls/dtls.h b/extlibs/tinydtls/dtls.h
+index 7ebde6b..4d82f72 100644
+--- a/extlibs/tinydtls/dtls.h
++++ b/extlibs/tinydtls/dtls.h
+@@ -60,12 +60,12 @@ typedef enum dtls_credentials_type_t {
+   DTLS_PSK_HINT, DTLS_PSK_IDENTITY, DTLS_PSK_KEY
+ } dtls_credentials_type_t;
+-typedef struct dtls_ecdsa_key_t {
++typedef struct dtls_ecc_key_t {
+   dtls_ecdh_curve curve;
+   const unsigned char *priv_key;      /** < private key as bytes > */
+   const unsigned char *pub_key_x;     /** < x part of the public key for the given private key > */
+   const unsigned char *pub_key_y;     /** < y part of the public key for the given private key > */
+-} dtls_ecdsa_key_t;
++} dtls_ecc_key_t;
+ /** Length of the secret that is used for generating Hello Verify cookies. */
+ #define DTLS_COOKIE_SECRET_LENGTH 12
+@@ -183,7 +183,7 @@ typedef struct {
+    */
+   int (*get_ecdsa_key)(struct dtls_context_t *ctx, 
+                      const session_t *session,
+-                     const dtls_ecdsa_key_t **result);
++                     const dtls_ecc_key_t **result);
+   /**
+    * Called during handshake to check the peer's pubic key in this
+@@ -238,6 +238,10 @@ 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_t selected_cipher; /**< selected ciper suite for handshake */
++
+   unsigned char readbuf[DTLS_MAX_BUF];
+ } dtls_context_t;
+@@ -263,6 +267,24 @@ static inline void dtls_set_handler(dtls_context_t *ctx, dtls_handler_t *h) {
+   ctx->h = h;
+ }
++ /**
++  * @brief Enabling the TLS_ECDH_anon_WITH_AES_128_CBC_SHA
++  *
++  * @param ctx              The DTLS context to use.
++  * @param is_enable    DTLS_CIPHER_ENABLE(1) or DTLS_CIPHER_DISABLE(0)
++  */
++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)
++ *                                  TLS_PSK_WITH_AES_128_CCM_8 (0xX0A8)
++ *                                  TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 (0xC0AE)
++ */
++void dtls_select_cipher(dtls_context_t* ctx, const dtls_cipher_t cipher);
++
+ /**
+  * Establishes a DTLS channel with the specified remote peer @p dst.
+  * This function returns @c 0 if that channel already exists, a value
+diff --git a/extlibs/tinydtls/global.h b/extlibs/tinydtls/global.h
+index f0977c8..441710f 100644
+--- a/extlibs/tinydtls/global.h
++++ b/extlibs/tinydtls/global.h
+@@ -73,10 +73,16 @@ 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_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;
++typedef enum {
++    DTLS_CIPHER_DISABLE = 0,
++    DTLS_CIPHER_ENABLE = 1
++} dtls_cipher_enable_t;
++
+ /** Known compression suites.*/
+ typedef enum {
+   TLS_COMPRESSION_NULL = 0x0000               /* NULL compression */
+diff --git a/extlibs/tinydtls/tests/dtls-client.c b/extlibs/tinydtls/tests/dtls-client.c
+index 65b0275..3a3e4ca 100644
+--- a/extlibs/tinydtls/tests/dtls-client.c
++++ b/extlibs/tinydtls/tests/dtls-client.c
+@@ -147,8 +147,8 @@ get_psk_info(struct dtls_context_t *ctx UNUSED_PARAM,
+ static int
+ get_ecdsa_key(struct dtls_context_t *ctx,
+             const session_t *session,
+-            const dtls_ecdsa_key_t **result) {
+-  static const dtls_ecdsa_key_t ecdsa_key = {
++            const dtls_ecc_key_t **result) {
++  static const dtls_ecc_key_t ecdsa_key = {
+     .curve = DTLS_ECDH_CURVE_SECP256R1,
+     .priv_key = ecdsa_priv_key,
+     .pub_key_x = ecdsa_pub_key_x,
+@@ -294,9 +294,9 @@ usage( const char *program, const char *version) {
+   fprintf(stderr, "%s v%s -- DTLS client implementation\n"
+         "(c) 2011-2014 Olaf Bergmann <bergmann@tzi.org>\n\n"
+ #ifdef DTLS_PSK
+-        "usage: %s [-i file] [-s file] [-k file] [-o file] [-p port] [-v num] addr [port]\n"
++        "usage: %s [-i file] [-s file] [-k file] [-o file] [-p port] [-v num] [-c num] addr [port]\n"
+ #else /*  DTLS_PSK */
+-        "usage: %s [-o file] [-p port] [-v num] addr [port]\n"
++        "usage: %s [-o file] [-p port] [-v num] [-c num] addr [port]\n"
+ #endif /* DTLS_PSK */
+ #ifdef DTLS_PSK
+         "\t-i file\t\tread PSK Client identity from file\n"
+@@ -305,7 +305,11 @@ usage( const char *program, const char *version) {
+ #endif /* DTLS_PSK */
+         "\t-o file\t\toutput received data to this file (use '-' for STDOUT)\n"
+         "\t-p port\t\tlisten on specified port (default is %d)\n"
+-        "\t-v num\t\tverbosity level (default: 3)\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\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);
+ }
+@@ -334,6 +338,8 @@ 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_enable_t ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
+   int opt, res;
+   session_t dst;
+@@ -349,7 +355,7 @@ main(int argc, char **argv) {
+   memcpy(psk_key, PSK_DEFAULT_KEY, psk_key_length);
+ #endif /* DTLS_PSK */
+-  while ((opt = getopt(argc, argv, "p:o:v:" PSK_OPTIONS)) != -1) {
++  while ((opt = getopt(argc, argv, "p:o:v:c:" PSK_OPTIONS)) != -1) {
+     switch (opt) {
+ #ifdef DTLS_PSK
+     case 'i' : {
+@@ -399,6 +405,23 @@ main(int argc, char **argv) {
+     case 'v' :
+       log_level = strtol(optarg, NULL, 10);
+       break;
++    case 'c':
++      if( strcmp(optarg, "1") == 0)
++      {
++          selected_cipher = TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
++          ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
++      }
++      else if( strcmp(optarg, "2") == 0)
++      {
++          selected_cipher = TLS_PSK_WITH_AES_128_CCM_8 ;
++          ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
++      }
++      else if( strcmp(optarg, "3") == 0)
++      {
++          selected_cipher = TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ;
++          ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
++      }
++      break;
+     default:
+       usage(argv[0], dtls_package_version());
+       exit(1);
+@@ -464,6 +487,13 @@ main(int argc, char **argv) {
+     exit(-1);
+   }
++
++  /* select cipher suite */
++  dtls_select_cipher(dtls_context, selected_cipher);
++
++  /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha */
++  dtls_enables_anon_ecdh(dtls_context, ecdh_anon_enalbe);
++
+   dtls_set_handler(dtls_context, &cb);
+   dtls_connect(dtls_context, &dst);
+diff --git a/extlibs/tinydtls/tests/dtls-server.c b/extlibs/tinydtls/tests/dtls-server.c
+index ae1283e..d3da1a7 100644
+--- a/extlibs/tinydtls/tests/dtls-server.c
++++ b/extlibs/tinydtls/tests/dtls-server.c
+@@ -113,8 +113,8 @@ get_psk_info(struct dtls_context_t *ctx, const session_t *session,
+ static int
+ get_ecdsa_key(struct dtls_context_t *ctx,
+             const session_t *session,
+-            const dtls_ecdsa_key_t **result) {
+-  static const dtls_ecdsa_key_t ecdsa_key = {
++            const dtls_ecc_key_t **result) {
++  static const dtls_ecc_key_t ecdsa_key = {
+     .curve = DTLS_ECDH_CURVE_SECP256R1,
+     .priv_key = ecdsa_priv_key,
+     .pub_key_x = ecdsa_pub_key_x,
+@@ -249,10 +249,13 @@ usage(const char *program, const char *version) {
+   fprintf(stderr, "%s v%s -- DTLS server implementation\n"
+         "(c) 2011-2014 Olaf Bergmann <bergmann@tzi.org>\n\n"
+-        "usage: %s [-A address] [-p port] [-v num]\n"
++        "usage: %s [-A address] [-p port] [-v num] [-a enable|disable]\n"
+         "\t-A address\t\tlisten on specified address (default is ::)\n"
+         "\t-p port\t\tlisten on specified port (default is %d)\n"
+-        "\t-v num\t\tverbosity level (default: 3)\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",
+          program, version, program, DEFAULT_PORT);
+ }
+@@ -277,6 +280,7 @@ main(int argc, char **argv) {
+   struct timeval timeout;
+   int fd, opt, result;
+   int on = 1;
++  int ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
+   struct sockaddr_in6 listen_addr;
+   memset(&listen_addr, 0, sizeof(struct sockaddr_in6));
+@@ -290,7 +294,7 @@ main(int argc, char **argv) {
+   listen_addr.sin6_port = htons(DEFAULT_PORT);
+   listen_addr.sin6_addr = in6addr_any;
+-  while ((opt = getopt(argc, argv, "A:p:v:")) != -1) {
++  while ((opt = getopt(argc, argv, "A:p:v:a:")) != -1) {
+     switch (opt) {
+     case 'A' :
+       if (resolve_address(optarg, (struct sockaddr *)&listen_addr) < 0) {
+@@ -304,6 +308,10 @@ main(int argc, char **argv) {
+     case 'v' :
+       log_level = strtol(optarg, NULL, 10);
+       break;
++    case 'a':
++      if( strcmp(optarg, "enable") == 0)
++          ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
++      break;
+     default:
+       usage(argv[0], dtls_package_version());
+       exit(1);
+@@ -348,6 +356,9 @@ main(int argc, char **argv) {
+   the_context = dtls_new_context(&fd);
++  /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha */
++  dtls_enables_anon_ecdh(the_context, ecdh_anon_enalbe);
++
+   dtls_set_handler(the_context, &cb);
+   while (1) {
+-- 
+1.7.9.5
+
index 60e9bef..712798b 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <stdint.h>
 
+#define WITH_AES_DECRYPT 1
 #define AES_MAXKEYBITS (256)
 #define AES_MAXKEYBYTES        (AES_MAXKEYBITS>>3)
 /* for 256-bit keys we need 14 rounds for a 128 we only need 10 round */
index 0113342..5082535 100644 (file)
@@ -54,6 +54,8 @@
 #include "crypto.h"
 #include "ccm.h"
 #include "ecc/ecc.h"
+#include "aes/rijndael.h"
+#include "sha2/sha2.h"
 #include "prng.h"
 #include "netq.h"
 
@@ -292,7 +294,7 @@ dtls_mac(dtls_hmac_context_t *hmac_ctx,
 }
 
 static size_t
-dtls_ccm_encrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src, size_t srclen,
+dtls_ccm_encrypt(aes128_t *ccm_ctx, const unsigned char *src, size_t srclen,
                 unsigned char *buf,
                 unsigned char *nounce,
                 const unsigned char *aad, size_t la) {
@@ -309,7 +311,7 @@ dtls_ccm_encrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src, size_t srclen,
 }
 
 static size_t
-dtls_ccm_decrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src,
+dtls_ccm_decrypt(aes128_t *ccm_ctx, const unsigned char *src,
                 size_t srclen, unsigned char *buf,
                 unsigned char *nounce,
                 const unsigned char *aad, size_t la) {
@@ -325,6 +327,95 @@ dtls_ccm_decrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src,
   return len;
 }
 
+static size_t
+dtls_cbc_encrypt(aes128_t *aes_ctx,
+                 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;
+    int i, j;
+    int blocks;
+
+    pos = buf;
+
+    dtls_hash_init(&shactx);
+    dtls_hash_update(&shactx, src, srclen);
+    dtls_hash_finalize(pos + srclen, &shactx);
+
+    memcpy(cbc, iv, DTLS_BLK_LENGTH);
+    blocks = (srclen + SHA256_DIGEST_LENGTH) / DTLS_BLK_LENGTH;
+
+    for (i = 0; i < blocks; i++) {
+        for (j = 0; j < DTLS_BLK_LENGTH; j++) {
+            cbc[j] ^= pos[j];
+        }
+
+        rijndael_encrypt(&aes_ctx->ctx, cbc, tmp);
+        memcpy(cbc, tmp, DTLS_BLK_LENGTH);
+        memcpy(pos, cbc, DTLS_BLK_LENGTH);
+        pos += DTLS_BLK_LENGTH;
+    }
+
+    dtls_debug_dump("Encrypted Data:", buf, srclen + SHA256_DIGEST_LENGTH);
+
+    return srclen + SHA256_DIGEST_LENGTH;
+}
+
+
+static size_t
+dtls_cbc_decrypt(aes128_t *aes_ctx,
+                 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 *pos;
+    dtls_hash_ctx shactx;
+    int i, j;
+    int blocks;
+
+    pos = buf;
+    memcpy(pos, src, srclen);
+
+    memcpy(cbc, iv, DTLS_BLK_LENGTH);
+    blocks = srclen / DTLS_BLK_LENGTH;
+
+    for (i = 0; i < blocks; i++)
+    {
+        memcpy(tmp, pos, DTLS_BLK_LENGTH);
+        rijndael_decrypt(&aes_ctx->ctx, pos, tmp2);
+        memcpy(pos, tmp2, DTLS_BLK_LENGTH);
+
+        for (j = 0; j < DTLS_BLK_LENGTH; j++) {
+            pos[j] ^= cbc[j];
+        }
+
+        memcpy(cbc, tmp, 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);
+
+    if(memcmp(msg_hash, buf + (srclen - SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH) != 0)
+    {
+        dtls_warn("message is broken\n");
+        return -1;
+    }
+
+    return srclen - SHA256_DIGEST_LENGTH;
+}
+
 #ifdef DTLS_PSK
 int
 dtls_psk_pre_master_secret(unsigned char *key, size_t keylen,
@@ -505,21 +596,37 @@ dtls_encrypt(const unsigned char *src, size_t length,
             unsigned char *buf,
             unsigned char *nounce,
             unsigned char *key, size_t keylen,
-            const unsigned char *aad, size_t la)
+            const unsigned char *aad, size_t la,
+            const dtls_cipher_t cipher)
 {
-  int ret;
+  int ret = 0;
   struct dtls_cipher_context_t *ctx = dtls_cipher_context_get();
 
-  ret = rijndael_set_key_enc_only(&ctx->data.ctx, key, 8 * keylen);
-  if (ret < 0) {
-    /* cleanup everything in case the key has the wrong size */
-    dtls_warn("cannot set rijndael key\n");
-    goto error;
+  if(cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ||
+     cipher == TLS_PSK_WITH_AES_128_CCM_8) {
+      ret = rijndael_set_key_enc_only(&ctx->data.ctx, key, 8 * keylen);
+      if (ret < 0) {
+        /* cleanup everything in case the key has the wrong size */
+        dtls_warn("cannot set rijndael key\n");
+        goto error;
+      }
+
+      if (src != 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) {
+      ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
+      if (ret < 0) {
+        /* cleanup everything in case the key has the wrong size */
+        dtls_warn("cannot set rijndael key\n");
+        goto error;
+      }
+
+      if (src != buf)
+        memmove(buf, src, length);
+      ret = dtls_cbc_encrypt(&ctx->data, nounce, src, length, buf);
   }
-
-  if (src != buf)
-    memmove(buf, src, length);
-  ret = dtls_ccm_encrypt(&ctx->data, src, length, buf, nounce, aad, la);
 
 error:
   dtls_cipher_context_release();
@@ -531,21 +638,38 @@ dtls_decrypt(const unsigned char *src, size_t length,
             unsigned char *buf,
             unsigned char *nounce,
             unsigned char *key, size_t keylen,
-            const unsigned char *aad, size_t la)
+            const unsigned char *aad, size_t la,
+            const dtls_cipher_t cipher)
 {
-  int ret;
+  int ret = 0;
   struct dtls_cipher_context_t *ctx = dtls_cipher_context_get();
 
-  ret = rijndael_set_key_enc_only(&ctx->data.ctx, key, 8 * keylen);
-  if (ret < 0) {
-    /* cleanup everything in case the key has the wrong size */
-    dtls_warn("cannot set rijndael key\n");
-    goto error;
+  if(cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ||
+     cipher == TLS_PSK_WITH_AES_128_CCM_8) {
+      ret = rijndael_set_key_enc_only(&ctx->data.ctx, key, 8 * keylen);
+      if (ret < 0) {
+        /* cleanup everything in case the key has the wrong size */
+        dtls_warn("cannot set rijndael key\n");
+        goto error;
+      }
+
+      if (src != buf)
+        memmove(buf, src, length);
+      ret = dtls_ccm_decrypt(&ctx->data, src, length, buf, nounce, aad, la);
   }
 
-  if (src != buf)
-    memmove(buf, src, length);
-  ret = dtls_ccm_decrypt(&ctx->data, src, length, buf, nounce, aad, la);
+  if(cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA) {
+      ret = rijndael_set_key(&ctx->data.ctx, key, 8 * keylen);
+      if (ret < 0) {
+        /* cleanup everything in case the key has the wrong size */
+        dtls_warn("cannot set rijndael key\n");
+        goto error;
+      }
+
+      if (src != buf)
+        memmove(buf, src, length);
+      ret = dtls_cbc_decrypt(&ctx->data, nounce, src, length, buf);
+    }
 
 error:
   dtls_cipher_context_release();
index 972a174..dd13ffa 100644 (file)
@@ -69,11 +69,11 @@ typedef enum {
 /** Crypto context for TLS_PSK_WITH_AES_128_CCM_8 cipher suite. */
 typedef struct {
   rijndael_ctx ctx;                   /**< AES-128 encryption context */
-} aes128_ccm_t;
+} aes128_t;
 
 typedef struct dtls_cipher_context_t {
   /** numeric identifier of this cipher suite in host byte order. */
-  aes128_ccm_t data;           /**< The crypto context */
+  aes128_t data;               /**< The crypto context */
 } dtls_cipher_context_t;
 
 typedef struct {
@@ -82,7 +82,8 @@ typedef struct {
   uint8 other_eph_pub_y[32];
   uint8 other_pub_x[32];
   uint8 other_pub_y[32];
-} dtls_handshake_parameters_ecdsa_t;
+} dtls_handshake_parameters_ecc_t;
+
 
 /* This is the maximal supported length of the psk client identity and psk
  * server identity hint */
@@ -129,7 +130,7 @@ typedef struct {
   unsigned int do_client_auth:1;
   union {
 #ifdef DTLS_ECC
-    dtls_handshake_parameters_ecdsa_t ecdsa;
+    dtls_handshake_parameters_ecc_t ecc;
 #endif /* DTLS_ECC */
 #ifdef DTLS_PSK
     dtls_handshake_parameters_psk_t psk;
@@ -265,7 +266,8 @@ int dtls_encrypt(const unsigned char *src, size_t length,
                 unsigned char *buf,
                 unsigned char *nounce,
                 unsigned char *key, size_t keylen,
-                const unsigned char *aad, size_t aad_length);
+                const unsigned char *aad, size_t aad_length,
+                const dtls_cipher_t cipher);
 
 /** 
  * Decrypts the given buffer \p src of given \p length, writing the
@@ -289,7 +291,8 @@ int dtls_decrypt(const unsigned char *src, size_t length,
                 unsigned char *buf,
                 unsigned char *nounce,
                 unsigned char *key, size_t keylen,
-                const unsigned char *a_data, size_t a_data_length);
+                const unsigned char *a_data, size_t a_data_length,
+                const dtls_cipher_t cipher);
 
 /* helper functions */
 
index a923386..41e68a5 100644 (file)
@@ -79,6 +79,7 @@
 #define DTLS_SH_LENGTH (2 + DTLS_RANDOM_LENGTH + 1 + 2 + 1)
 #define DTLS_CE_LENGTH (3 + 3 + 27 + DTLS_EC_KEY_SIZE + DTLS_EC_KEY_SIZE)
 #define DTLS_SKEXEC_LENGTH (1 + 2 + 1 + 1 + DTLS_EC_KEY_SIZE + DTLS_EC_KEY_SIZE + 1 + 1 + 2 + 70)
+#define DTLS_SKEXEC_ECDH_ANON_LENGTH (1 + 2 + 1 + 1 + DTLS_EC_KEY_SIZE + DTLS_EC_KEY_SIZE)
 #define DTLS_SKEXECPSK_LENGTH_MIN 2
 #define DTLS_SKEXECPSK_LENGTH_MAX 2 + DTLS_PSK_MAX_CLIENT_IDENTITY_LEN
 #define DTLS_CKXPSK_LENGTH_MIN 2
@@ -167,6 +168,24 @@ dtls_init() {
   peer_init();
 }
 
+ void
+ dtls_enables_anon_ecdh(dtls_context_t* ctx, dtls_cipher_enable_t is_enable)
+{
+    if(ctx)
+    {
+        ctx->is_anon_ecdh_eabled = is_enable;
+    }
+}
+
+void
+dtls_select_cipher(dtls_context_t* ctx, const dtls_cipher_t cipher)
+{
+    if(ctx)
+    {
+        ctx->selected_cipher = cipher;
+    }
+}
+
 /* Calls cb_alert() with given arguments if defined, otherwise an
  * error message is logged and the result is -1. This is just an
  * internal helper.
@@ -477,6 +496,17 @@ 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)
+{
+#ifdef DTLS_ECC
+    return cipher == TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
+#else
+    return 0;
+#endif
+}
+
+
 /** returns true if the application is configured for psk */
 static inline int is_psk_supported(dtls_context_t *ctx)
 {
@@ -509,6 +539,16 @@ static inline int is_ecdsa_client_auth_supported(dtls_context_t *ctx)
 #endif /* DTLS_ECC */
 }
 
+/** returns true if ecdh_anon_with_aes_128_cbc_sha is supported */
+static inline int is_ecdh_anon_supported(dtls_context_t *ctx)
+{
+#ifdef DTLS_ECC
+    return ctx &&  (ctx->is_anon_ecdh_eabled == DTLS_CIPHER_ENABLE);
+#else
+    return 0;
+#endif
+}
+
 /**
  * Returns @c 1 if @p code is a cipher suite other than @c
  * TLS_NULL_WITH_NULL_NULL that we recognize.
@@ -522,11 +562,15 @@ static int
 known_cipher(dtls_context_t *ctx, dtls_cipher_t code, int is_client) {
   int psk;
   int ecdsa;
+  int ecdh_anon;
 
   psk = is_psk_supported(ctx);
   ecdsa = is_ecdsa_supported(ctx, is_client);
+  ecdh_anon = is_ecdh_anon_supported(ctx);
+
   return (psk && is_tls_psk_with_aes_128_ccm_8(code)) ||
-        (ecdsa && is_tls_ecdhe_ecdsa_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));
 }
 
 /**
@@ -674,11 +718,12 @@ calculate_key_block(dtls_context_t *ctx,
   }
 #endif /* DTLS_PSK */
 #ifdef DTLS_ECC
-  case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: {
-    pre_master_len = dtls_ecdh_pre_master_secret(handshake->keyx.ecdsa.own_eph_priv,
-                                                handshake->keyx.ecdsa.other_eph_pub_x,
-                                                handshake->keyx.ecdsa.other_eph_pub_y,
-                                                sizeof(handshake->keyx.ecdsa.own_eph_priv),
+  case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
+  case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: {
+    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,
+                                                sizeof(handshake->keyx.ecc.own_eph_priv),
                                                 pre_master_secret,
                                                 MAX_KEYBLOCK_LENGTH);
     if (pre_master_len < 0) {
@@ -1038,7 +1083,8 @@ check_client_keyexchange(dtls_context_t *ctx,
                         uint8 *data, size_t length) {
 
 #ifdef DTLS_ECC
-  if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher)) {
+  if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher) ||
+       is_tls_ecdh_anon_with_aes_128_cbc_sha(handshake->cipher) ) {
 
     if (length < DTLS_HS_LENGTH + DTLS_CKXEC_LENGTH) {
       dtls_debug("The client key exchange is too short\n");
@@ -1058,13 +1104,13 @@ check_client_keyexchange(dtls_context_t *ctx,
     }
     data += sizeof(uint8);
 
-    memcpy(handshake->keyx.ecdsa.other_eph_pub_x, data,
-          sizeof(handshake->keyx.ecdsa.other_eph_pub_x));
-    data += sizeof(handshake->keyx.ecdsa.other_eph_pub_x);
+    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.ecdsa.other_eph_pub_y, data,
-          sizeof(handshake->keyx.ecdsa.other_eph_pub_y));
-    data += sizeof(handshake->keyx.ecdsa.other_eph_pub_y);
+    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 /* DTLS_ECC */
 #ifdef DTLS_PSK
@@ -1253,6 +1299,8 @@ 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");
     }
@@ -1332,9 +1380,10 @@ dtls_prepare_record(dtls_peer_t *peer, dtls_security_parameters_t *security,
     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),
-                      A_DATA, A_DATA_LEN);
+               dtls_kb_local_write_key(security, peer->role),
+               dtls_kb_key_size(security, peer->role),
+               A_DATA, A_DATA_LEN,
+               security->cipher);
 
     if (res < 0)
       return res;
@@ -1754,8 +1803,8 @@ check_client_certificate_verify(dtls_context_t *ctx,
 
   dtls_hash_finalize(sha256hash, &hs_hash);
 
-  ret = dtls_ecdsa_verify_sig_hash(config->keyx.ecdsa.other_pub_x, config->keyx.ecdsa.other_pub_y,
-                           sizeof(config->keyx.ecdsa.other_pub_x),
+  ret = dtls_ecdsa_verify_sig_hash(config->keyx.ecc.other_pub_x, config->keyx.ecc.other_pub_y,
+                           sizeof(config->keyx.ecc.other_pub_x),
                            sha256hash, sizeof(sha256hash),
                            result_r, result_s);
 
@@ -1867,7 +1916,7 @@ dtls_send_server_hello(dtls_context_t *ctx, dtls_peer_t *peer)
 #ifdef DTLS_ECC
 static int
 dtls_send_certificate_ecdsa(dtls_context_t *ctx, dtls_peer_t *peer,
-                           const dtls_ecdsa_key_t *key)
+                           const dtls_ecc_key_t *key)
 {
   uint8 buf[DTLS_CE_LENGTH];
   uint8 *p;
@@ -1957,7 +2006,7 @@ dtls_add_ecdsa_signature_elem(uint8 *p, uint32_t *point_r, uint32_t *point_s)
 
 static int
 dtls_send_server_key_exchange_ecdh(dtls_context_t *ctx, dtls_peer_t *peer,
-                                  const dtls_ecdsa_key_t *key)
+                                  const dtls_ecc_key_t *key)
 {
   /* The ASN.1 Integer representation of an 32 byte unsigned int could be
    * 33 bytes long add space for that */
@@ -1968,9 +2017,11 @@ dtls_send_server_key_exchange_ecdh(dtls_context_t *ctx, dtls_peer_t *peer,
   uint8 *ephemeral_pub_y;
   uint32_t point_r[9];
   uint32_t point_s[9];
+  int ecdsa;
   dtls_handshake_parameters_t *config = peer->handshake_params;
 
-  /* ServerKeyExchange 
+  ecdsa = is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher);
+  /* ServerKeyExchange
    *
    * Start message construction at beginning of buffer. */
   p = buf;
@@ -1999,18 +2050,20 @@ dtls_send_server_key_exchange_ecdh(dtls_context_t *ctx, dtls_peer_t *peer,
   ephemeral_pub_y = p;
   p += DTLS_EC_KEY_SIZE;
 
-  dtls_ecdsa_generate_key(config->keyx.ecdsa.own_eph_priv,
-                         ephemeral_pub_x, ephemeral_pub_y,
-                         DTLS_EC_KEY_SIZE);
+  dtls_ecdsa_generate_key(config->keyx.ecc.own_eph_priv,
+              ephemeral_pub_x, ephemeral_pub_y,
+              DTLS_EC_KEY_SIZE);
 
-  /* sign the ephemeral and its paramaters */
-  dtls_ecdsa_create_sig(key->priv_key, DTLS_EC_KEY_SIZE,
-                      config->tmp.random.client, DTLS_RANDOM_LENGTH,
-                      config->tmp.random.server, DTLS_RANDOM_LENGTH,
-                      key_params, p - key_params,
-                      point_r, point_s);
+  if(ecdsa) {
+      /* sign the ephemeral and its paramaters */
+           dtls_ecdsa_create_sig(key->priv_key, DTLS_EC_KEY_SIZE,
+               config->tmp.random.client, DTLS_RANDOM_LENGTH,
+               config->tmp.random.server, DTLS_RANDOM_LENGTH,
+               key_params, p - key_params,
+               point_r, point_s);
 
-  p = dtls_add_ecdsa_signature_elem(p, point_r, point_s);
+      p = dtls_add_ecdsa_signature_elem(p, point_r, point_s);
+  }
 
   assert(p - buf <= sizeof(buf));
 
@@ -2108,6 +2161,8 @@ static int
 dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
 {
   int res;
+  int ecdsa;
+  int ecdh_anon;
 
   res = dtls_send_server_hello(ctx, peer);
 
@@ -2116,9 +2171,20 @@ dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
     return res;
   }
 
+  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);
+
 #ifdef DTLS_ECC
-  if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher)) {
-    const dtls_ecdsa_key_t *ecdsa_key;
+  if(ecdh_anon) {
+      res = dtls_send_server_key_exchange_ecdh(ctx, peer, NULL);
+
+      if (res < 0) {
+        dtls_debug("dtls_server_hello(with ECDH): cannot prepare Server Key Exchange record\n");
+        return res;
+      }
+  }
+  else if (ecdsa) {
+    const dtls_ecc_key_t *ecdsa_key;
 
     res = CALL(ctx, get_ecdsa_key, &peer->session, &ecdsa_key);
     if (res < 0) {
@@ -2145,7 +2211,7 @@ dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
       res = dtls_send_server_certificate_request(ctx, peer);
 
       if (res < 0) {
-        dtls_debug("dtls_server_hello: cannot prepare certificate Request record\n");
+        dtls_debug("dtls_server_hello(with ECDSA): cannot prepare certificate Request record\n");
         return res;
       }
     }
@@ -2234,7 +2300,8 @@ 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_ECDHE_ECDSA_WITH_AES_128_CCM_8:
+  case TLS_ECDH_anon_WITH_AES_128_CBC_SHA: {
     uint8 *ephemeral_pub_x;
     uint8 *ephemeral_pub_y;
 
@@ -2250,7 +2317,7 @@ dtls_send_client_key_exchange(dtls_context_t *ctx, dtls_peer_t *peer)
     ephemeral_pub_y = p;
     p += DTLS_EC_KEY_SIZE;
 
-    dtls_ecdsa_generate_key(peer->handshake_params->keyx.ecdsa.own_eph_priv,
+    dtls_ecdsa_generate_key(peer->handshake_params->keyx.ecc.own_eph_priv,
                            ephemeral_pub_x, ephemeral_pub_y,
                            DTLS_EC_KEY_SIZE);
 
@@ -2271,7 +2338,7 @@ dtls_send_client_key_exchange(dtls_context_t *ctx, dtls_peer_t *peer)
 #ifdef DTLS_ECC
 static int
 dtls_send_certificate_verify_ecdh(dtls_context_t *ctx, dtls_peer_t *peer,
-                                  const dtls_ecdsa_key_t *key)
+                                  const dtls_ecc_key_t *key)
 {
   /* The ASN.1 Integer representation of an 32 byte unsigned int could be
    * 33 bytes long add space for that */
@@ -2343,16 +2410,32 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
   uint8 *p = buf;
   uint8_t cipher_size;
   uint8_t extension_size;
-  int psk;
-  int ecdsa;
+  int psk = 0;
+  int ecdsa = 0;
+  int ecdh_anon = 0;
   dtls_handshake_parameters_t *handshake = peer->handshake_params;
   dtls_tick_t now;
 
-  psk = is_psk_supported(ctx);
-  ecdsa = is_ecdsa_supported(ctx, 1);
+  switch(ctx->selected_cipher)
+  {
+      case TLS_PSK_WITH_AES_128_CCM_8:
+        psk = is_psk_supported(ctx);
+        break;
+      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:
+        ecdh_anon = is_ecdh_anon_supported(ctx);
+        break;
+      default:
+        psk = is_psk_supported(ctx);
+        ecdsa = is_ecdsa_supported(ctx, 1);
+        ecdh_anon = is_ecdh_anon_supported(ctx);
+        break;
+   }
 
-  cipher_size = 2 + ((ecdsa) ? 2 : 0) + ((psk) ? 2 : 0);
-  extension_size = (ecdsa) ? 2 + 6 + 6 + 8 + 6: 0;
+  cipher_size = 2 + (ecdsa ? 2 : 0) + (psk ? 2 : 0) + (ecdh_anon ? 2 : 0);
+  extension_size = (ecdsa) ? (2 + 6 + 6 + 8 + 6) : 0;
 
   if (cipher_size == 0) {
     dtls_crit("no cipher callbacks implemented\n");
@@ -2394,14 +2477,18 @@ dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
   dtls_int_to_uint16(p, cipher_size - 2);
   p += sizeof(uint16);
 
-  if (ecdsa) {
-    dtls_int_to_uint16(p, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
+  if (ecdh_anon) {
+    dtls_int_to_uint16(p, TLS_ECDH_anon_WITH_AES_128_CBC_SHA);
     p += sizeof(uint16);
   }
   if (psk) {
     dtls_int_to_uint16(p, TLS_PSK_WITH_AES_128_CCM_8);
     p += sizeof(uint16);
   }
+  if (ecdsa) {
+    dtls_int_to_uint16(p, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
+    p += sizeof(uint16);
+  }
 
   /* compression method */
   dtls_int_to_uint8(p, 1);
@@ -2612,18 +2699,18 @@ check_server_certificate(dtls_context_t *ctx,
   }
   data += sizeof(cert_asn1_header);
 
-  memcpy(config->keyx.ecdsa.other_pub_x, data,
-        sizeof(config->keyx.ecdsa.other_pub_x));
-  data += sizeof(config->keyx.ecdsa.other_pub_x);
+  memcpy(config->keyx.ecc.other_pub_x, data,
+        sizeof(config->keyx.ecc.other_pub_x));
+  data += sizeof(config->keyx.ecc.other_pub_x);
 
-  memcpy(config->keyx.ecdsa.other_pub_y, data,
-        sizeof(config->keyx.ecdsa.other_pub_y));
-  data += sizeof(config->keyx.ecdsa.other_pub_y);
+  memcpy(config->keyx.ecc.other_pub_y, data,
+        sizeof(config->keyx.ecc.other_pub_y));
+  data += sizeof(config->keyx.ecc.other_pub_y);
 
   err = CALL(ctx, verify_ecdsa_key, &peer->session,
-            config->keyx.ecdsa.other_pub_x,
-            config->keyx.ecdsa.other_pub_y,
-            sizeof(config->keyx.ecdsa.other_pub_x));
+            config->keyx.ecc.other_pub_x,
+            config->keyx.ecc.other_pub_y,
+            sizeof(config->keyx.ecc.other_pub_x));
   if (err < 0) {
     dtls_warn("The certificate was not accepted\n");
     return err;
@@ -2683,13 +2770,13 @@ check_server_key_exchange_ecdsa(dtls_context_t *ctx,
   data += sizeof(uint8);
   data_length -= sizeof(uint8);
 
-  memcpy(config->keyx.ecdsa.other_eph_pub_x, data, sizeof(config->keyx.ecdsa.other_eph_pub_y));
-  data += sizeof(config->keyx.ecdsa.other_eph_pub_y);
-  data_length -= sizeof(config->keyx.ecdsa.other_eph_pub_y);
+  memcpy(config->keyx.ecc.other_eph_pub_x, 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);
 
-  memcpy(config->keyx.ecdsa.other_eph_pub_y, data, sizeof(config->keyx.ecdsa.other_eph_pub_y));
-  data += sizeof(config->keyx.ecdsa.other_eph_pub_y);
-  data_length -= sizeof(config->keyx.ecdsa.other_eph_pub_y);
+  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);
 
   ret = dtls_check_ecdsa_signature_elem(data, data_length, &result_r, &result_s);
   if (ret < 0) {
@@ -2698,8 +2785,8 @@ check_server_key_exchange_ecdsa(dtls_context_t *ctx,
   data += ret;
   data_length -= ret;
 
-  ret = dtls_ecdsa_verify_sig(config->keyx.ecdsa.other_pub_x, config->keyx.ecdsa.other_pub_y,
-                           sizeof(config->keyx.ecdsa.other_pub_x),
+  ret = dtls_ecdsa_verify_sig(config->keyx.ecc.other_pub_x, config->keyx.ecc.other_pub_y,
+                           sizeof(config->keyx.ecc.other_pub_x),
                            config->tmp.random.client, DTLS_RANDOM_LENGTH,
                            config->tmp.random.server, DTLS_RANDOM_LENGTH,
                            key_params,
@@ -2712,6 +2799,64 @@ check_server_key_exchange_ecdsa(dtls_context_t *ctx,
   }
   return 0;
 }
+
+static int
+check_server_key_exchange_ecdh(dtls_context_t *ctx,
+                               dtls_peer_t *peer,
+                               uint8 *data, size_t data_length)
+{
+  dtls_handshake_parameters_t *config = peer->handshake_params;
+
+  update_hs_hash(peer, data, data_length);
+
+  assert(is_tls_ecdh_anon_with_aes_128_cbc_sha(config->cipher));
+
+  data += DTLS_HS_LENGTH;
+
+  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 /* DTLS_ECC */
 
 #ifdef DTLS_PSK
@@ -2839,7 +2984,7 @@ check_server_hellodone(dtls_context_t *ctx,
 {
   int res;
 #ifdef DTLS_ECC
-  const dtls_ecdsa_key_t *ecdsa_key;
+  const dtls_ecc_key_t *ecdsa_key;
 #endif /* DTLS_ECC */
 
   dtls_handshake_parameters_t *handshake = peer->handshake_params;
@@ -2849,7 +2994,7 @@ check_server_hellodone(dtls_context_t *ctx,
   update_hs_hash(peer, data, data_length);
 
 #ifdef DTLS_ECC
-  if (handshake->do_client_auth) {
+  if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher) && handshake->do_client_auth) {
 
     res = CALL(ctx, get_ecdsa_key, &peer->session, &ecdsa_key);
     if (res < 0) {
@@ -2875,7 +3020,7 @@ check_server_hellodone(dtls_context_t *ctx,
   }
 
 #ifdef DTLS_ECC
-  if (handshake->do_client_auth) {
+  if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(handshake->cipher) && handshake->do_client_auth) {
 
     res = dtls_send_certificate_verify_ecdh(ctx, peer, ecdsa_key);
 
@@ -2962,12 +3107,13 @@ decrypt_verify(dtls_peer_t *peer, uint8 *packet, size_t length,
     clen = dtls_decrypt(*cleartext, clen, *cleartext, nonce,
                       dtls_kb_remote_write_key(security, peer->role),
                       dtls_kb_key_size(security, peer->role),
-                      A_DATA, A_DATA_LEN);
+                      A_DATA, A_DATA_LEN,
+               security->cipher);
     if (clen < 0)
       dtls_warn("decryption failed\n");
     else {
 #ifndef NDEBUG
-      printf("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);
@@ -3072,9 +3218,11 @@ handle_handshake_msg(dtls_context_t *ctx, dtls_peer_t *peer, session_t *session,
       return err;
     }
     if (is_tls_ecdhe_ecdsa_with_aes_128_ccm_8(peer->handshake_params->cipher))
-      peer->state = DTLS_STATE_WAIT_SERVERCERTIFICATE;
+      peer->state = DTLS_STATE_WAIT_SERVERCERTIFICATE; //ecdsa
+    else if (is_tls_ecdh_anon_with_aes_128_cbc_sha(peer->handshake_params->cipher))
+        peer->state = DTLS_STATE_WAIT_SERVERKEYEXCHANGE; //ecdh
     else
-      peer->state = DTLS_STATE_WAIT_SERVERHELLODONE;
+      peer->state = DTLS_STATE_WAIT_SERVERHELLODONE; //psk
     /* update_hs_hash(peer, data, data_length); */
 
     break;
@@ -3110,6 +3258,13 @@ 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 (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 */
 #ifdef DTLS_PSK
     if (is_tls_psk_with_aes_128_ccm_8(peer->handshake_params->cipher)) {
@@ -3219,9 +3374,9 @@ 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) &&
        is_ecdsa_client_auth_supported(ctx))
-      peer->state = DTLS_STATE_WAIT_CERTIFICATEVERIFY;
+      peer->state = DTLS_STATE_WAIT_CERTIFICATEVERIFY; //ecdsa
     else
-      peer->state = DTLS_STATE_WAIT_CHANGECIPHERSPEC;
+      peer->state = DTLS_STATE_WAIT_CHANGECIPHERSPEC; //psk || ecdh_anon
     break;
 
 #ifdef DTLS_ECC
@@ -3342,9 +3497,9 @@ 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) &&
        is_ecdsa_client_auth_supported(ctx))
-      peer->state = DTLS_STATE_WAIT_CLIENTCERTIFICATE;
+      peer->state = DTLS_STATE_WAIT_CLIENTCERTIFICATE; //ecdhe
     else
-      peer->state = DTLS_STATE_WAIT_CLIENTKEYEXCHANGE;
+      peer->state = DTLS_STATE_WAIT_CLIENTKEYEXCHANGE; //psk, ecdh_anon
 
     /* after sending the ServerHelloDone, we expect the
      * ClientKeyExchange (possibly containing the PSK id),
@@ -4030,6 +4185,44 @@ dtls_check_retransmit(dtls_context_t *context, clock_time_t *next) {
     *next = node->t;
 }
 
+size_t
+dtls_prf_with_current_keyblock(dtls_context_t *ctx, session_t *session,
+                               const uint8_t* label, const uint32_t labellen,
+                               const uint8_t* random1, const uint32_t random1len,
+                               const uint8_t* random2, const uint32_t random2len,
+                               uint8_t* buf, const uint32_t buflen) {
+  dtls_peer_t *peer = NULL;
+  dtls_security_parameters_t *security = NULL;
+  size_t keysize = 0;
+
+  if(!ctx || !session || !label || !buf || labellen == 0 || buflen == 0) {
+    dtls_warn("dtls_prf_with_current_keyblock(): invalid parameter\n");
+    return 0;
+  }
+
+  peer = dtls_get_peer(ctx, session);
+  if (!peer) {
+    dtls_warn("dtls_prf_with_current_keyblock(): cannot find peer\n");
+    return 0;
+  }
+
+  security = dtls_security_params(peer);
+  if (!security) {
+    dtls_crit("dtls_prf_with_current_keyblock(): peer has empty security parameters\n");
+    return 0;
+  }
+
+  /* note that keysize should never be zero as bad things will happen */
+  keysize = dtls_kb_size(security, peer->role);
+  assert(keysize > 0);
+
+  return dtls_prf(security->key_block, keysize,
+                 label, labellen,
+                 random1, random1len,
+                 random2, random2len,
+                 buf, buflen);
+}
+
 #ifdef WITH_CONTIKI
 /*---------------------------------------------------------------------------*/
 /* message retransmission */
index 7ebde6b..a2ab86e 100644 (file)
@@ -60,12 +60,12 @@ typedef enum dtls_credentials_type_t {
   DTLS_PSK_HINT, DTLS_PSK_IDENTITY, DTLS_PSK_KEY
 } dtls_credentials_type_t;
 
-typedef struct dtls_ecdsa_key_t {
+typedef struct dtls_ecc_key_t {
   dtls_ecdh_curve curve;
   const unsigned char *priv_key;       /** < private key as bytes > */
   const unsigned char *pub_key_x;      /** < x part of the public key for the given private key > */
   const unsigned char *pub_key_y;      /** < y part of the public key for the given private key > */
-} dtls_ecdsa_key_t;
+} dtls_ecc_key_t;
 
 /** Length of the secret that is used for generating Hello Verify cookies. */
 #define DTLS_COOKIE_SECRET_LENGTH 12
@@ -183,7 +183,7 @@ typedef struct {
    */
   int (*get_ecdsa_key)(struct dtls_context_t *ctx, 
                       const session_t *session,
-                      const dtls_ecdsa_key_t **result);
+                      const dtls_ecc_key_t **result);
 
   /**
    * Called during handshake to check the peer's pubic key in this
@@ -238,6 +238,10 @@ 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_t selected_cipher; /**< selected ciper suite for handshake */
+
   unsigned char readbuf[DTLS_MAX_BUF];
 } dtls_context_t;
 
@@ -263,6 +267,24 @@ static inline void dtls_set_handler(dtls_context_t *ctx, dtls_handler_t *h) {
   ctx->h = h;
 }
 
+ /**
+  * @brief Enabling the TLS_ECDH_anon_WITH_AES_128_CBC_SHA
+  *
+  * @param ctx              The DTLS context to use.
+  * @param is_enable    DTLS_CIPHER_ENABLE(1) or DTLS_CIPHER_DISABLE(0)
+  */
+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)
+ *                                  TLS_PSK_WITH_AES_128_CCM_8 (0xX0A8)
+ *                                  TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 (0xC0AE)
+ */
+void dtls_select_cipher(dtls_context_t* ctx, const dtls_cipher_t cipher);
+
 /**
  * Establishes a DTLS channel with the specified remote peer @p dst.
  * This function returns @c 0 if that channel already exists, a value
@@ -415,6 +437,30 @@ int dtls_handle_message(dtls_context_t *ctx, session_t *session,
 dtls_peer_t *dtls_get_peer(const dtls_context_t *context,
                           const session_t *session);
 
+/**
+* Invokes the DTLS PRF using the current key block for @p session as
+* key and @p label + @p random1 + @p random2 as its input. This function
+* writes upto @p buflen bytes into the given output buffer @p buf.
+*
+* @param ctx The dtls context to use.
+* @param session The session whose key shall be used.
+* @param label A PRF label.
+* @param labellen Actual length of @p label.
+* @param random1 Random seed.
+* @param random1len Actual length of @p random1 (may be zero).
+* @param random2 Random seed.
+* @param random2len Actual length of @p random2 (may be zero).
+* @param buf Output buffer for generated random data.
+* @param buflen Maximum size of @p buf.
+*
+* @return The actual number of bytes written to @p buf or @c 0 on error.
+*/
+size_t dtls_prf_with_current_keyblock(dtls_context_t *ctx, session_t *session,
+                                      const uint8_t* label, const uint32_t labellen,
+                                      const uint8_t* random1, const uint32_t random1len,
+                                      const uint8_t* random2, const uint32_t random2len,
+                                      uint8_t* buf, const uint32_t buflen);
+
 
 #endif /* _DTLS_DTLS_H_ */
 
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/extlibs/tinydtls/ecc/test_helper.c b/extlibs/tinydtls/ecc/test_helper.c
deleted file mode 100644 (file)
index bda44ba..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 2009 Chris K Cockrum <ckc@cockrum.net>
- *
- * Copyright (c) 2013 Jens Trillmann <jtrillma@tzi.de>
- * Copyright (c) 2013 Marc Müller-Weinhardt <muewei@tzi.de>
- * Copyright (c) 2013 Lars Schmertmann <lars@tzi.de>
- * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- *
- * This implementation is based in part on the paper Implementation of an
- * Elliptic Curve Cryptosystem on an 8-bit Microcontroller [0] by
- * Chris K Cockrum <ckc@cockrum.net>.
- *
- * [0]: http://cockrum.net/Implementation_of_ECC_on_an_8-bit_microcontroller.pdf
- *
- * This is a efficient ECC implementation on the secp256r1 curve for 32 Bit CPU
- * architectures. It provides basic operations on the secp256r1 curve and support
- * for ECDH and ECDSA.
- */
-#include "test_helper.h"
-#include "ecc.h"
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-void ecc_printNumber(const uint32_t *x, int numberLength){ //here the values are turned to MSB!
-       int n;
-
-       for(n = numberLength - 1; n >= 0; n--){
-               printf("%08x", x[n]);
-       }
-       printf("\n");
-}
-
-void ecc_setRandom(uint32_t *secret){
-       int i;
-
-       for (i = 0; i < arrayLength; ++i)
-       {
-               secret[i] = rand();
-       }
-}
-const uint32_t ecc_prime_m[8] = {0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
-                                0x00000000, 0x00000000, 0x00000001, 0xffffffff};
-
-                                                       
-/* This is added after an static byte addition if the answer has a carry in MSB*/
-const uint32_t ecc_prime_r[8] = {0x00000001, 0x00000000, 0x00000000, 0xffffffff,
-                                0xffffffff, 0xffffffff, 0xfffffffe, 0x00000000};
-
-#ifdef CONTIKI
-void
-test_assert(const char *file, int lineno)
-{
-  printf("Assertion failed: file %s, line %d.\n", file, lineno);
-  /*
-   * loop for a while;
-   * call _reset_vector__();
-   */
-}
-#endif
diff --git a/extlibs/tinydtls/ecc/test_helper.h b/extlibs/tinydtls/ecc/test_helper.h
deleted file mode 100644 (file)
index 38a194e..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2009 Chris K Cockrum <ckc@cockrum.net>
- *
- * Copyright (c) 2013 Jens Trillmann <jtrillma@tzi.de>
- * Copyright (c) 2013 Marc Müller-Weinhardt <muewei@tzi.de>
- * Copyright (c) 2013 Lars Schmertmann <lars@tzi.de>
- * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- *
- * This implementation is based in part on the paper Implementation of an
- * Elliptic Curve Cryptosystem on an 8-bit Microcontroller [0] by
- * Chris K Cockrum <ckc@cockrum.net>.
- *
- * [0]: http://cockrum.net/Implementation_of_ECC_on_an_8-bit_microcontroller.pdf
- *
- * This is a efficient ECC implementation on the secp256r1 curve for 32 Bit CPU
- * architectures. It provides basic operations on the secp256r1 curve and support
- * for ECDH and ECDSA.
- */
-#include <inttypes.h>
-
-extern const uint32_t ecc_prime_m[8];
-extern const uint32_t ecc_prime_r[8];
-
-//debug function to print long numbers
-void ecc_printNumber(const uint32_t *x, int numberLength);
-void ecc_setRandom(uint32_t *secret);
-
-#ifdef CONTIKI
-#undef assert
-#define assert(e) ((e) ? (void)0 : test_assert(__FILE__, __LINE__))
-void test_assert(const char *, int);
-#endif
diff --git a/extlibs/tinydtls/ecc/testecc.c b/extlibs/tinydtls/ecc/testecc.c
deleted file mode 100644 (file)
index b36d46b..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2009 Chris K Cockrum <ckc@cockrum.net>
- *
- * Copyright (c) 2013 Jens Trillmann <jtrillma@tzi.de>
- * Copyright (c) 2013 Marc Müller-Weinhardt <muewei@tzi.de>
- * Copyright (c) 2013 Lars Schmertmann <lars@tzi.de>
- * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- *
- * This implementation is based in part on the paper Implementation of an
- * Elliptic Curve Cryptosystem on an 8-bit Microcontroller [0] by
- * Chris K Cockrum <ckc@cockrum.net>.
- *
- * [0]: http://cockrum.net/Implementation_of_ECC_on_an_8-bit_microcontroller.pdf
- *
- * This is a efficient ECC implementation on the secp256r1 curve for 32 Bit CPU
- * architectures. It provides basic operations on the secp256r1 curve and support
- * for ECDH and ECDSA.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include "ecc.h"
-#include "test_helper.h"
-
-#ifdef CONTIKI
-#include "contiki.h"
-#else
-#include <time.h>
-#endif /* CONTIKI */
-
-//These are testvalues taken from the NIST P-256 definition
-//6b17d1f2 e12c4247 f8bce6e5 63a440f2 77037d81 2deb33a0 f4a13945 d898c296
-uint32_t BasePointx[8] = {     0xd898c296, 0xf4a13945, 0x2deb33a0, 0x77037d81,
-                                                       0x63a440f2, 0xf8bce6e5, 0xe12c4247, 0x6b17d1f2};
-
-//4fe342e2 fe1a7f9b 8ee7eb4a 7c0f9e16 2bce3357 6b315ece cbb64068 37bf51f5
-uint32_t BasePointy[8] = {     0x37bf51f5, 0xcbb64068, 0x6b315ece, 0x2bce3357,
-                                                       0x7c0f9e16, 0x8ee7eb4a, 0xfe1a7f9b, 0x4fe342e2};
-
-//de2444be bc8d36e6 82edd27e 0f271508 617519b3 221a8fa0 b77cab39 89da97c9
-uint32_t Sx[8] = {     0x89da97c9, 0xb77cab39, 0x221a8fa0, 0x617519b3, 
-                                       0x0f271508, 0x82edd27e, 0xbc8d36e6, 0xde2444be};
-
-//c093ae7f f36e5380 fc01a5aa d1e66659 702de80f 53cec576 b6350b24 3042a256
-uint32_t Sy[8] = {     0x3042a256, 0xb6350b24, 0x53cec576, 0x702de80f,
-                                       0xd1e66659, 0xfc01a5aa, 0xf36e5380, 0xc093ae7f};
-
-//55a8b00f 8da1d44e 62f6b3b2 5316212e 39540dc8 61c89575 bb8cf92e 35e0986b
-uint32_t Tx[8] = {     0x35e0986b, 0xbb8cf92e, 0x61c89575, 0x39540dc8,
-                                       0x5316212e, 0x62f6b3b2, 0x8da1d44e, 0x55a8b00f};
-
-//5421c320 9c2d6c70 4835d82a c4c3dd90 f61a8a52 598b9e7a b656e9d8 c8b24316
-uint32_t Ty[8] = {     0xc8b24316, 0xb656e9d8, 0x598b9e7a, 0xf61a8a52,
-                                       0xc4c3dd90, 0x4835d82a, 0x9c2d6c70, 0x5421c320};
-
-//c51e4753 afdec1e6 b6c6a5b9 92f43f8d d0c7a893 3072708b 6522468b 2ffb06fd
-uint32_t secret[8] = { 0x2ffb06fd, 0x6522468b, 0x3072708b, 0xd0c7a893,
-                                               0x92f43f8d, 0xb6c6a5b9, 0xafdec1e6, 0xc51e4753};
-                                                       
-//72b13dd4 354b6b81 745195e9 8cc5ba69 70349191 ac476bd4 553cf35a 545a067e
-uint32_t resultAddx[8] = {     0x545a067e, 0x553cf35a, 0xac476bd4, 0x70349191,
-                                                       0x8cc5ba69, 0x745195e9, 0x354b6b81, 0x72b13dd4};
-
-//8d585cbb 2e1327d7 5241a8a1 22d7620d c33b1331 5aa5c9d4 6d013011 744ac264
-uint32_t resultAddy[8] = {     0x744ac264, 0x6d013011, 0x5aa5c9d4, 0xc33b1331,
-                                                       0x22d7620d, 0x5241a8a1, 0x2e1327d7, 0x8d585cbb};
-
-//7669e690 1606ee3b a1a8eef1 e0024c33 df6c22f3 b17481b8 2a860ffc db6127b0
-uint32_t resultDoublex[8] = {  0xdb6127b0, 0x2a860ffc, 0xb17481b8, 0xdf6c22f3,
-                                                               0xe0024c33, 0xa1a8eef1, 0x1606ee3b, 0x7669e690};
-
-//fa878162 187a54f6 c39f6ee0 072f33de 389ef3ee cd03023d e10ca2c1 db61d0c7
-uint32_t resultDoubley[8] = {  0xdb61d0c7, 0xe10ca2c1, 0xcd03023d, 0x389ef3ee,
-                                                               0x072f33de, 0xc39f6ee0, 0x187a54f6, 0xfa878162};
-
-//51d08d5f 2d427888 2946d88d 83c97d11 e62becc3 cfc18bed acc89ba3 4eeca03f
-uint32_t resultMultx[8] = {    0x4eeca03f, 0xacc89ba3, 0xcfc18bed, 0xe62becc3,
-                                                       0x83c97d11, 0x2946d88d, 0x2d427888, 0x51d08d5f};
-
-//75ee68eb 8bf626aa 5b673ab5 1f6e744e 06f8fcf8 a6c0cf30 35beca95 6a7b41d5
-uint32_t resultMulty[8] = {    0x6a7b41d5, 0x35beca95, 0xa6c0cf30, 0x06f8fcf8,
-                                                       0x1f6e744e, 0x5b673ab5, 0x8bf626aa, 0x75ee68eb};
-
-static const uint32_t ecdsaTestMessage[] = { 0x65637572, 0x20612073, 0x68206F66, 0x20686173, 0x69732061, 0x68697320, 0x6F2C2054, 0x48616C6C};
-
-static const uint32_t ecdsaTestSecret[] = {0x94A949FA, 0x401455A1, 0xAD7294CA, 0x896A33BB, 0x7A80E714, 0x4321435B, 0x51247A14, 0x41C1CB6B};
-
-static const uint32_t ecdsaTestRand1[] = { 0x1D1E1F20, 0x191A1B1C, 0x15161718, 0x11121314, 0x0D0E0F10, 0x090A0B0C, 0x05060708, 0x01020304};
-static const uint32_t ecdsaTestresultR1[] = { 0xC3B4035F, 0x515AD0A6, 0xBF375DCA, 0x0CC1E997, 0x7F54FDCD, 0x04D3FECA, 0xB9E396B9, 0x515C3D6E};
-static const uint32_t ecdsaTestresultS1[] = { 0x5366B1AB, 0x0F1DBF46, 0xB0C8D3C4, 0xDB755B6F, 0xB9BF9243, 0xE644A8BE, 0x55159A59, 0x6F9E52A6};
-
-static const uint32_t ecdsaTestRand2[] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x01FFFFFF};
-static const uint32_t ecdsaTestresultR2[] = { 0x14146C91, 0xE878724D, 0xCD4FF928, 0xCC24BC04, 0xAC403390, 0x650C0060, 0x4A30B3F1, 0x9C69B726};
-static const uint32_t ecdsaTestresultS2[] = { 0x433AAB6F, 0x808250B1, 0xE46F90F4, 0xB342E972, 0x18B2F7E4, 0x2DB981A2, 0x6A288FA4, 0x41CF59DB};
-
-void addTest(){
-       uint32_t tempx[8];
-       uint32_t tempy[8];
-
-       ecc_ec_add(Tx, Ty, Sx, Sy, tempx, tempy);
-       assert(ecc_isSame(tempx, resultAddx, arrayLength));
-       assert(ecc_isSame(tempy, resultAddy, arrayLength));
-}
-
-void doubleTest(){
-       uint32_t tempx[8];
-       uint32_t tempy[8];
-
-       ecc_ec_double(Sx, Sy, tempx, tempy);
-       assert(ecc_isSame(tempx, resultDoublex, arrayLength));
-       assert(ecc_isSame(tempy, resultDoubley, arrayLength));
-}
-
-void multTest(){
-       uint32_t tempx[8];
-       uint32_t tempy[8];
-
-       ecc_ec_mult(Sx, Sy, secret, tempx, tempy);
-       assert(ecc_isSame(tempx, resultMultx, arrayLength));
-       assert(ecc_isSame(tempy, resultMulty, arrayLength));
-}
-
-void eccdhTest(){
-       uint32_t tempx[8];
-       uint32_t tempy[8];
-       uint32_t tempAx2[8];
-       uint32_t tempAy2[8];
-       uint32_t tempBx1[8];
-       uint32_t tempBy1[8];
-       uint32_t tempBx2[8];
-       uint32_t tempBy2[8];    
-       uint32_t secretA[8];
-       uint32_t secretB[8];
-       ecc_setRandom(secretA);
-       ecc_printNumber(secretA, 8);
-       ecc_setRandom(secretB);
-       ecc_printNumber(secretB, 8);
-       ecc_ec_mult(BasePointx, BasePointy, secretA, tempx, tempy);
-       ecc_ec_mult(BasePointx, BasePointy, secretB, tempBx1, tempBy1);
-       //public key exchange
-       ecc_ec_mult(tempBx1, tempBy1, secretA, tempAx2, tempAy2);
-       ecc_ec_mult(tempx, tempy, secretB, tempBx2, tempBy2);
-       assert(ecc_isSame(tempAx2, tempBx2, arrayLength));
-       assert(ecc_isSame(tempAy2, tempBy2, arrayLength));
-
-}
-
-void ecdsaTest() {
-       int ret __attribute__((unused));
-       uint32_t tempx[9];
-       uint32_t tempy[9];
-       uint32_t pub_x[8];
-       uint32_t pub_y[8];
-
-       ecc_ec_mult(BasePointx, BasePointy, ecdsaTestSecret, pub_x, pub_y);
-
-       ret = ecc_ecdsa_sign(ecdsaTestSecret, ecdsaTestMessage, ecdsaTestRand1, tempx, tempy);
-       assert(ecc_isSame(tempx, ecdsaTestresultR1, arrayLength));
-       assert(ecc_isSame(tempy, ecdsaTestresultS1, arrayLength));
-       assert(ret == 0);
-
-       ret = ecc_ecdsa_validate(pub_x, pub_y, ecdsaTestMessage, tempx, tempy);
-       assert(!ret);
-
-
-       ret = ecc_ecdsa_sign(ecdsaTestSecret, ecdsaTestMessage, ecdsaTestRand2, tempx, tempy);
-       assert(ecc_isSame(tempx, ecdsaTestresultR2, arrayLength));
-       assert(ecc_isSame(tempy, ecdsaTestresultS2, arrayLength));
-       assert(ret == 0);
-
-       ret = ecc_ecdsa_validate(pub_x, pub_y, ecdsaTestMessage, tempx, tempy);
-       assert(!ret);
-}
-
-#ifdef CONTIKI
-PROCESS(ecc_filed_test, "ECC test");
-AUTOSTART_PROCESSES(&ecc_filed_test);
-PROCESS_THREAD(ecc_filed_test, ev, d)
-{
-       PROCESS_BEGIN();
-
-       srand(1234);
-       addTest();
-       doubleTest();
-       multTest();
-       eccdhTest();
-       ecdsaTest();
-       printf("%s\n", "All Tests successful.");
-
-       PROCESS_END();
-}
-#else /* CONTIKI */
-int main(int argc, char const *argv[])
-{
-       srand(time(NULL));
-       addTest();
-       doubleTest();
-       multTest();
-       eccdhTest();
-       ecdsaTest();
-       printf("%s\n", "All Tests successful.");
-       return 0;
-}
-#endif /* CONTIKI */
diff --git a/extlibs/tinydtls/ecc/testfield.c b/extlibs/tinydtls/ecc/testfield.c
deleted file mode 100644 (file)
index 30a690e..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright (c) 2009 Chris K Cockrum <ckc@cockrum.net>
- *
- * Copyright (c) 2013 Jens Trillmann <jtrillma@tzi.de>
- * Copyright (c) 2013 Marc Müller-Weinhardt <muewei@tzi.de>
- * Copyright (c) 2013 Lars Schmertmann <lars@tzi.de>
- * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- *
- * This implementation is based in part on the paper Implementation of an
- * Elliptic Curve Cryptosystem on an 8-bit Microcontroller [0] by
- * Chris K Cockrum <ckc@cockrum.net>.
- *
- * [0]: http://cockrum.net/Implementation_of_ECC_on_an_8-bit_microcontroller.pdf
- *
- * This is a efficient ECC implementation on the secp256r1 curve for 32 Bit CPU
- * architectures. It provides basic operations on the secp256r1 curve and support
- * for ECDH and ECDSA.
- */
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-#include "ecc.h"
-#include "test_helper.h"
-
-#ifdef CONTIKI
-#include "contiki.h"
-#endif /* CONTIKI */
-
-//arbitrary test values and results
-uint32_t null[8] = {   0x00000000,0x00000000,0x00000000,0x00000000,
-                                               0x00000000,0x00000000,0x00000000,0x00000000};
-uint32_t null64[16] = {        0x00000000,0x00000000,0x00000000,0x00000000,
-                                               0x00000000,0x00000000,0x00000000,0x00000000,
-                                               0x00000000,0x00000000,0x00000000,0x00000000,
-                                               0x00000000,0x00000000,0x00000000,0x00000000};
-uint32_t one[8] = {    0x00000001,0x00000000,0x00000000,0x00000000,
-                                       0x00000000,0x00000000,0x00000000,0x00000000};
-uint32_t one64[16] = { 0x00000001,0x00000000,0x00000000,0x00000000,
-                                               0x00000000,0x00000000,0x00000000,0x00000000,
-                                               0x00000000,0x00000000,0x00000000,0x00000000,
-                                               0x00000000,0x00000000,0x00000000,0x00000000};
-uint32_t two[8] = {    0x00000002,0x00000000,0x00000000,0x00000000,
-                                       0x00000000,0x00000000,0x00000000,0x00000000};
-uint32_t two64[16] = { 0x00000002,0x00000000,0x00000000,0x00000000,
-                                               0x00000000,0x00000000,0x00000000,0x00000000,
-                                               0x00000000,0x00000000,0x00000000,0x00000000,
-                                               0x00000000,0x00000000,0x00000000,0x00000000};
-uint32_t three[8] = {  0x00000003,0x00000000,0x00000000,0x00000000,
-                                               0x00000000,0x00000000,0x00000000,0x00000000};
-uint32_t four[8] = {0x00000004,0x00000000,0x00000000,0x00000000,
-                                       0x00000000,0x00000000,0x00000000,0x00000000};
-uint32_t four64[16] = {        0x00000004,0x00000000,0x00000000,0x00000000,
-                                               0x00000000,0x00000000,0x00000000,0x00000000,
-                                               0x00000000,0x00000000,0x00000000,0x00000000,
-                                               0x00000000,0x00000000,0x00000000,0x00000000};
-uint32_t six[8] = {    0x00000006,0x00000000,0x00000000,0x00000000,
-                                       0x00000000,0x00000000,0x00000000,0x00000000};
-uint32_t eight[8] = {  0x00000008,0x00000000,0x00000000,0x00000000,
-                                               0x00000000,0x00000000,0x00000000,0x00000000};
-uint32_t full[8] = {   0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,
-                                               0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
-//00000000fffffffeffffffffffffffffffffffff000000000000000000000001_16
-uint32_t resultFullAdd[8] = {  0x00000001,0x00000000,0x00000000,0xFFFFFFFF,
-                                                               0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFE,0x00000000};
-uint32_t primeMinusOne[8]=     {       0xfffffffe,0xffffffff,0xffffffff,0x00000000,
-                                                               0x00000000,0x00000000,0x00000001,0xffffffff};
-uint32_t resultDoubleMod[8] = { 0xfffffffd,0xffffffff,0xffffffff,0x00000000,
-                                                               0x00000000,0x00000000,0x00000001,0xffffffff};
-//fffffffe00000002fffffffe0000000100000001fffffffe00000001fffffffc00000003fffffffcfffffffffffffffffffffffc000000000000000000000004_16
-uint32_t resultQuadMod[16] = { 0x00000004,0x00000000,0x00000000,0xFFFFFFFC,
-                                                               0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFC,0x00000003,
-                                                               0xFFFFFFFC,0x00000001,0xFFFFFFFE,0x00000001,
-                                                               0x00000001,0xFFFFFFFE,0x00000002,0xFFFFFFFE};
-//00000002fffffffffffffffffffffffefffffffdffffffff0000000000000002_16
-uint32_t resultFullMod[8] = {  0x00000002,0x00000000,0xFFFFFFFF,0xFFFFFFFD,
-                                                               0xFFFFFFFE,0xFFFFFFFF,0xFFFFFFFF,0x00000002};
-
-static const uint32_t orderMinusOne[8] = {0xFC632550, 0xF3B9CAC2, 0xA7179E84, 0xBCE6FAAD,
-                                       0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF};
-static const uint32_t orderResultDoubleMod[8] = {0xFC63254F, 0xF3B9CAC2, 0xA7179E84, 0xBCE6FAAD, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF};
-
-uint32_t temp[8];
-uint32_t temp2[16];
-
-void nullEverything(){
-       memset(temp, 0, sizeof(temp));
-       memset(temp2, 0, sizeof(temp));
-}
-
-void fieldAddTest(){
-       assert(ecc_isSame(one, one, arrayLength));
-       ecc_fieldAdd(one, null, ecc_prime_r, temp);
-       assert(ecc_isSame(temp, one, arrayLength));
-       nullEverything();
-       ecc_fieldAdd(one, one, ecc_prime_r, temp);
-       assert(ecc_isSame(temp, two, arrayLength));
-       nullEverything();
-       ecc_add(full, one, temp, 32);
-       assert(ecc_isSame(null, temp, arrayLength));
-       nullEverything();
-       ecc_fieldAdd(full, one, ecc_prime_r, temp);
-       assert(ecc_isSame(temp, resultFullAdd, arrayLength));
-}
-
-void fieldSubTest(){
-       assert(ecc_isSame(one, one, arrayLength));
-       ecc_fieldSub(one, null, ecc_prime_m, temp);
-       assert(ecc_isSame(one, temp, arrayLength));
-       nullEverything();
-       ecc_fieldSub(one, one, ecc_prime_m, temp);
-       assert(ecc_isSame(null, temp, arrayLength));
-       nullEverything();
-       ecc_fieldSub(null, one, ecc_prime_m, temp);
-       assert(ecc_isSame(primeMinusOne, temp, arrayLength));
-}
-
-void fieldMultTest(){
-       ecc_fieldMult(one, null, temp2, arrayLength);
-       assert(ecc_isSame(temp2, null64, arrayLength * 2));
-       nullEverything();
-       ecc_fieldMult(one, two, temp2, arrayLength);
-       assert(ecc_isSame(temp2, two64, arrayLength * 2));
-       nullEverything();
-       ecc_fieldMult(two, two, temp2, arrayLength);
-       assert(ecc_isSame(temp2, four64, arrayLength * 2));
-       nullEverything();
-       ecc_fieldMult(primeMinusOne, primeMinusOne, temp2, arrayLength);
-       assert(ecc_isSame(temp2, resultQuadMod, arrayLength * 2));
-       nullEverything();
-       ecc_fieldInv(two, ecc_prime_m, ecc_prime_r, temp);
-       ecc_fieldMult(temp, two, temp2, arrayLength);
-       ecc_fieldModP(temp, temp2);
-       assert(ecc_isSame(temp, one, arrayLength));
-}
-
-void fieldModPTest(){
-       ecc_fieldMult(primeMinusOne, primeMinusOne, temp2, arrayLength);
-       ecc_fieldModP(temp, temp2);
-       assert(ecc_isSame(temp, one, arrayLength));
-       nullEverything();
-       ecc_fieldModP(temp, one64);
-       assert(ecc_isSame(temp, one, arrayLength));
-       nullEverything();
-       ecc_fieldMult(two, primeMinusOne, temp2, arrayLength);
-       ecc_fieldModP(temp, temp2);
-       assert(ecc_isSame(temp, resultDoubleMod, arrayLength));
-       nullEverything();
-       /*fieldMult(full, full, temp2, arrayLength); //not working, maybe because of the number bigger than p^2?
-       fieldModP(temp, temp2);
-       assert(ecc_isSame(temp, resultFullMod, arrayLength));*/
-}
-
-void fieldModOTest(){
-       ecc_fieldMult(orderMinusOne, orderMinusOne, temp2, arrayLength);
-       ecc_fieldModO(temp2, temp, arrayLength * 2);
-       assert(ecc_isSame(temp, one, arrayLength));
-       nullEverything();
-       ecc_fieldModO(one64, temp, arrayLength * 2);
-       assert(ecc_isSame(temp, one, arrayLength));
-       nullEverything();
-       ecc_fieldMult(two, orderMinusOne, temp2, arrayLength);
-       ecc_fieldModO(temp2, temp, arrayLength * 2);
-       assert(ecc_isSame(temp, orderResultDoubleMod, arrayLength));
-       nullEverything();
-}
-
-
-// void rShiftTest(){
-//     printNumber(full, 32);
-//     rshift(full);
-//     printNumber(full, 32);
-//     printNumber(two, 32);
-//     rshift(two);
-//     printNumber(two, 32);
-//     printNumber(four, 32);
-//     rshift(four);
-//     printNumber(four, 32);
-// }
-
-// void isOneTest(){
-//     printf("%d\n", isone(one));
-//     printf("%d\n", isone(two));
-//     printf("%d\n", isone(four));
-//     printf("%d\n", isone(full));
-//     printf("%d\n", isone(null));
-// }
-
-void fieldInvTest(){
-       nullEverything();
-       ecc_fieldInv(two, ecc_prime_m, ecc_prime_r, temp);
-       ecc_fieldMult(temp, two, temp2, arrayLength);
-       ecc_fieldModP(temp, temp2);
-       assert(ecc_isSame(one, temp, arrayLength));
-       nullEverything();
-       ecc_fieldInv(eight, ecc_prime_m, ecc_prime_r, temp);
-       ecc_fieldMult(temp, eight, temp2, arrayLength);
-       ecc_fieldModP(temp, temp2);
-       assert(ecc_isSame(one, temp, arrayLength));
-       nullEverything();
-       ecc_fieldInv(three, ecc_prime_m, ecc_prime_r, temp);
-       ecc_fieldMult(temp, three, temp2, arrayLength);
-       ecc_fieldModP(temp, temp2);
-       assert(ecc_isSame(one, temp, arrayLength));
-       nullEverything();
-       ecc_fieldInv(six, ecc_prime_m, ecc_prime_r, temp);
-       ecc_fieldMult(temp, six, temp2, arrayLength);
-       ecc_fieldModP(temp, temp2);
-       assert(ecc_isSame(one, temp, arrayLength));
-       nullEverything();
-       ecc_fieldInv(primeMinusOne, ecc_prime_m, ecc_prime_r, temp);
-       ecc_fieldMult(temp, primeMinusOne, temp2, arrayLength);
-       ecc_fieldModP(temp, temp2);
-       assert(ecc_isSame(one, temp, arrayLength));
-}
-
-// void randomStuff(){
-
-// }
-
-#ifdef CONTIKI
-PROCESS(ecc_filed_test, "ECC field test");
-AUTOSTART_PROCESSES(&ecc_filed_test);
-PROCESS_THREAD(ecc_filed_test, ev, d)
-{
-       PROCESS_BEGIN();
-
-       nullEverything();
-       //randomStuff();
-       nullEverything();
-       fieldAddTest();
-       nullEverything();
-       fieldSubTest();
-       nullEverything();
-       fieldMultTest();
-       nullEverything();
-       fieldModPTest();
-       nullEverything();
-       fieldModOTest();
-       nullEverything();
-       fieldInvTest();
-       nullEverything();
-       //rShiftTest();
-       //isOneTest();
-       printf("%s\n", "All Tests succesfull!");
-
-       PROCESS_END();
-}
-#else /* CONTIKI */
-int main(int argc, char const *argv[])
-{
-       nullEverything();
-       //randomStuff();
-       nullEverything();
-       fieldAddTest();
-       nullEverything();
-       fieldSubTest();
-       nullEverything();
-       fieldMultTest();
-       nullEverything();
-       fieldModPTest();
-       nullEverything();
-       fieldModOTest();
-       nullEverything();
-       fieldInvTest();
-       nullEverything();
-       //rShiftTest();
-       //isOneTest();
-       printf("%s\n", "All Tests succesfull!");
-       return 0;
-}
-#endif /* CONTIKI */
index f0977c8..441710f 100644 (file)
@@ -73,10 +73,16 @@ 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_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;
 
+typedef enum {
+    DTLS_CIPHER_DISABLE = 0,
+    DTLS_CIPHER_ENABLE = 1
+} dtls_cipher_enable_t;
+
 /** Known compression suites.*/
 typedef enum {
   TLS_COMPRESSION_NULL = 0x0000                /* NULL compression */
index 1c48c1a..35521e9 100644 (file)
@@ -148,8 +148,8 @@ get_psk_info(struct dtls_context_t *ctx UNUSED_PARAM,
 static int
 get_ecdsa_key(struct dtls_context_t *ctx,
              const session_t *session,
-             const dtls_ecdsa_key_t **result) {
-  static const dtls_ecdsa_key_t ecdsa_key = {
+             const dtls_ecc_key_t **result) {
+  static const dtls_ecc_key_t ecdsa_key = {
     .curve = DTLS_ECDH_CURVE_SECP256R1,
     .priv_key = ecdsa_priv_key,
     .pub_key_x = ecdsa_pub_key_x,
@@ -296,9 +296,9 @@ usage( const char *program, const char *version) {
   fprintf(stderr, "%s v%s -- DTLS client implementation\n"
          "(c) 2011-2014 Olaf Bergmann <bergmann@tzi.org>\n\n"
 #ifdef DTLS_PSK
-         "usage: %s [-i file] [-s file] [-k file] [-o file] [-p port] [-v num] addr [port]\n"
+         "usage: %s [-i file] [-s file] [-k file] [-o file] [-p port] [-v num] [-c num] addr [port]\n"
 #else /*  DTLS_PSK */
-         "usage: %s [-o file] [-p port] [-v num] addr [port]\n"
+         "usage: %s [-o file] [-p port] [-v num] [-c num] addr [port]\n"
 #endif /* DTLS_PSK */
 #ifdef DTLS_PSK
          "\t-i file\t\tread PSK Client identity from file\n"
@@ -307,7 +307,11 @@ usage( const char *program, const char *version) {
 #endif /* DTLS_PSK */
          "\t-o file\t\toutput received data to this file (use '-' for STDOUT)\n"
          "\t-p port\t\tlisten on specified port (default is %d)\n"
-         "\t-v num\t\tverbosity level (default: 3)\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\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);
 }
 
@@ -333,6 +337,7 @@ static dtls_handler_t cb = {
  * Below command tests this feature.
  */
 #define DTLS_CLIENT_CMD_REHANDSHAKE "client:rehandshake"
+
 int 
 main(int argc, char **argv) {
   fd_set rfds, wfds;
@@ -342,6 +347,8 @@ 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_enable_t ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
   int opt, res;
   session_t dst;
 
@@ -357,7 +364,7 @@ main(int argc, char **argv) {
   memcpy(psk_key, PSK_DEFAULT_KEY, psk_key_length);
 #endif /* DTLS_PSK */
 
-  while ((opt = getopt(argc, argv, "p:o:v:" PSK_OPTIONS)) != -1) {
+  while ((opt = getopt(argc, argv, "p:o:v:c:" PSK_OPTIONS)) != -1) {
     switch (opt) {
 #ifdef DTLS_PSK
     case 'i' : {
@@ -407,6 +414,23 @@ main(int argc, char **argv) {
     case 'v' :
       log_level = strtol(optarg, NULL, 10);
       break;
+    case 'c':
+      if( strcmp(optarg, "1") == 0)
+      {
+          selected_cipher = TLS_ECDH_anon_WITH_AES_128_CBC_SHA;
+          ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
+      }
+      else if( strcmp(optarg, "2") == 0)
+      {
+          selected_cipher = TLS_PSK_WITH_AES_128_CCM_8 ;
+          ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
+      }
+      else if( strcmp(optarg, "3") == 0)
+      {
+          selected_cipher = TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 ;
+          ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
+      }
+      break;
     default:
       usage(argv[0], dtls_package_version());
       exit(1);
@@ -472,6 +496,13 @@ main(int argc, char **argv) {
     exit(-1);
   }
 
+
+  /* select cipher suite */
+  dtls_select_cipher(dtls_context, selected_cipher);
+
+  /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha */
+  dtls_enables_anon_ecdh(dtls_context, ecdh_anon_enalbe);
+
   dtls_set_handler(dtls_context, &cb);
 
   dtls_connect(dtls_context, &dst);
index ae1283e..d3da1a7 100644 (file)
@@ -113,8 +113,8 @@ get_psk_info(struct dtls_context_t *ctx, const session_t *session,
 static int
 get_ecdsa_key(struct dtls_context_t *ctx,
              const session_t *session,
-             const dtls_ecdsa_key_t **result) {
-  static const dtls_ecdsa_key_t ecdsa_key = {
+             const dtls_ecc_key_t **result) {
+  static const dtls_ecc_key_t ecdsa_key = {
     .curve = DTLS_ECDH_CURVE_SECP256R1,
     .priv_key = ecdsa_priv_key,
     .pub_key_x = ecdsa_pub_key_x,
@@ -249,10 +249,13 @@ usage(const char *program, const char *version) {
 
   fprintf(stderr, "%s v%s -- DTLS server implementation\n"
          "(c) 2011-2014 Olaf Bergmann <bergmann@tzi.org>\n\n"
-         "usage: %s [-A address] [-p port] [-v num]\n"
+         "usage: %s [-A address] [-p port] [-v num] [-a enable|disable]\n"
          "\t-A address\t\tlisten on specified address (default is ::)\n"
          "\t-p port\t\tlisten on specified port (default is %d)\n"
-         "\t-v num\t\tverbosity level (default: 3)\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",
           program, version, program, DEFAULT_PORT);
 }
 
@@ -277,6 +280,7 @@ main(int argc, char **argv) {
   struct timeval timeout;
   int fd, opt, result;
   int on = 1;
+  int ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
   struct sockaddr_in6 listen_addr;
 
   memset(&listen_addr, 0, sizeof(struct sockaddr_in6));
@@ -290,7 +294,7 @@ main(int argc, char **argv) {
   listen_addr.sin6_port = htons(DEFAULT_PORT);
   listen_addr.sin6_addr = in6addr_any;
 
-  while ((opt = getopt(argc, argv, "A:p:v:")) != -1) {
+  while ((opt = getopt(argc, argv, "A:p:v:a:")) != -1) {
     switch (opt) {
     case 'A' :
       if (resolve_address(optarg, (struct sockaddr *)&listen_addr) < 0) {
@@ -304,6 +308,10 @@ main(int argc, char **argv) {
     case 'v' :
       log_level = strtol(optarg, NULL, 10);
       break;
+    case 'a':
+      if( strcmp(optarg, "enable") == 0)
+          ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
+      break;
     default:
       usage(argv[0], dtls_package_version());
       exit(1);
@@ -348,6 +356,9 @@ main(int argc, char **argv) {
 
   the_context = dtls_new_context(&fd);
 
+  /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha */
+  dtls_enables_anon_ecdh(the_context, ecdh_anon_enalbe);
+
   dtls_set_handler(the_context, &cb);
 
   while (1) {
index 3fa228a..b1b8cdf 100644 (file)
@@ -34,7 +34,7 @@
 #define _DTLS_TINYDTLS_H_
 
 /** Defined to 1 if tinydtls is built with support for ECC */
-/* #undef DTLS_ECC */
+#define DTLS_ECC 1
 
 /** Defined to 1 if tinydtls is built with support for PSK */
 #define DTLS_PSK 1
index 786c956..5125cc6 100644 (file)
@@ -21,8 +21,8 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#ifndef _DTLS_UTHASH_H
-#define _DTLS_UTHASH_H 
+#ifndef UTHASH_H
+#define UTHASH_H
 
 #include <string.h>   /* memcmp,strlen */
 #include <stddef.h>   /* ptrdiff_t */
@@ -48,7 +48,7 @@ do {
   char **_da_dst = (char**)(&(dst));                                             \
   *_da_dst = (char*)(src);                                                       \
 } while(0)
-#else 
+#else
 #define DECLTYPE_ASSIGN(dst,src)                                                 \
 do {                                                                             \
   (dst) = DECLTYPE(dst)(src);                                                    \
@@ -119,9 +119,9 @@ do {
   HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
 
 #else
-#define HASH_BLOOM_MAKE(tbl) 
-#define HASH_BLOOM_FREE(tbl) 
-#define HASH_BLOOM_ADD(tbl,hashv) 
+#define HASH_BLOOM_MAKE(tbl)
+#define HASH_BLOOM_FREE(tbl)
+#define HASH_BLOOM_ADD(tbl,hashv)
 #define HASH_BLOOM_TEST(tbl,hashv) (1)
 #endif
 
@@ -146,7 +146,7 @@ do {
 
 #define HASH_ADD(hh,head,fieldname,keylen_in,add)                                \
         HASH_ADD_KEYPTR(hh,head,&add->fieldname,keylen_in,add)
+
 #define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add)                            \
 do {                                                                             \
  unsigned _ha_bkt;                                                               \
@@ -298,10 +298,10 @@ do {
     }                                                                            \
 } while (0)
 #else
-#define HASH_FSCK(hh,head) 
+#define HASH_FSCK(hh,head)
 #endif
 
-/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to 
+/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
  * the descriptor to which this macro is defined for tuning the hash function.
  * The app can #include <unistd.h> to get the prototype for write(2). */
 #ifdef HASH_EMIT_KEYS
@@ -311,12 +311,12 @@ do {
     write(HASH_EMIT_KEYS, &_klen, sizeof(_klen));                                \
     write(HASH_EMIT_KEYS, keyptr, fieldlen);                                     \
 } while (0)
-#else 
-#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)                    
+#else
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
 #endif
 
 /* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
-#ifdef HASH_FUNCTION 
+#ifdef HASH_FUNCTION
 #define HASH_FCN HASH_FUNCTION
 #else
 #define HASH_FCN HASH_JEN
@@ -333,7 +333,7 @@ do {
 } while (0)
 
 
-/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at 
+/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
  * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
 #define HASH_SAX(key,keylen,num_bkts,hashv,bkt)                                  \
 do {                                                                             \
@@ -354,7 +354,7 @@ do {
       hashv = (hashv * 16777619) ^ _hf_key[_fn_i];                               \
   bkt = hashv & (num_bkts-1);                                                    \
 } while(0);
+
 #define HASH_OAT(key,keylen,num_bkts,hashv,bkt)                                  \
 do {                                                                             \
   unsigned _ho_i;                                                                \
@@ -484,14 +484,14 @@ do {
 /* The MurmurHash exploits some CPU's (e.g. x86) tolerance for unaligned reads.
  * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
  * So MurmurHash comes in two versions, the faster unaligned one and the slower
- * aligned one. We only use the faster one on CPU's where we know it's safe. 
+ * aligned one. We only use the faster one on CPU's where we know it's safe.
  *
  * Note the preprocessor built-in defines can be emitted using:
  *
  *   gcc -m64 -dM -E - < /dev/null                  (on gcc)
  *   cc -## a.c (where a.c is a simple test file)   (Sun Studio)
  */
-#if (defined(__i386__) || defined(__x86_64__)) 
+#if (defined(__i386__) || defined(__x86_64__))
 #define HASH_MUR HASH_MUR_UNALIGNED
 #else
 #define HASH_MUR HASH_MUR_ALIGNED
@@ -630,7 +630,7 @@ do {
 #endif  /* HASH_USING_NO_STRICT_ALIASING */
 
 /* key comparison function; return 0 if keys equal */
-#define HASH_KEYCMP(a,b,len) memcmp(a,b,len) 
+#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
 
 /* iterate over items in a known bucket to find desired item */
 #define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out)                       \
@@ -671,36 +671,36 @@ do {
     }                                                                            \
     if (hh_del->hh_next) {                                                       \
         hh_del->hh_next->hh_prev = hh_del->hh_prev;                              \
-    }                                                                
+    }
 
 /* Bucket expansion has the effect of doubling the number of buckets
  * and redistributing the items into the new buckets. Ideally the
  * items will distribute more or less evenly into the new buckets
  * (the extent to which this is true is a measure of the quality of
- * the hash function as it applies to the key domain). 
- * 
+ * the hash function as it applies to the key domain).
+ *
  * With the items distributed into more buckets, the chain length
  * (item count) in each bucket is reduced. Thus by expanding buckets
- * the hash keeps a bound on the chain length. This bounded chain 
+ * the hash keeps a bound on the chain length. This bounded chain
  * length is the essence of how a hash provides constant time lookup.
- * 
+ *
  * The calculation of tbl->ideal_chain_maxlen below deserves some
  * explanation. First, keep in mind that we're calculating the ideal
  * maximum chain length based on the *new* (doubled) bucket count.
  * In fractions this is just n/b (n=number of items,b=new num buckets).
- * Since the ideal chain length is an integer, we want to calculate 
+ * Since the ideal chain length is an integer, we want to calculate
  * ceil(n/b). We don't depend on floating point arithmetic in this
  * hash, so to calculate ceil(n/b) with integers we could write
- * 
+ *
  *      ceil(n/b) = (n/b) + ((n%b)?1:0)
- * 
+ *
  * and in fact a previous version of this hash did just that.
  * But now we have improved things a bit by recognizing that b is
  * always a power of two. We keep its base 2 log handy (call it lb),
  * so now we can write this with a bit shift and logical AND:
- * 
+ *
  *      ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
- * 
+ *
  */
 #define HASH_EXPAND_BUCKETS(tbl)                                                 \
 do {                                                                             \
@@ -752,7 +752,7 @@ do {
 
 
 /* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
-/* Note that HASH_SORT assumes the hash handle name to be hh. 
+/* Note that HASH_SORT assumes the hash handle name to be hh.
  * HASH_SRT was added to allow the hash handle name to be passed in. */
 #define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
 #define HASH_SRT(hh,head,cmpfcn)                                                 \
@@ -834,10 +834,10 @@ do {
  }                                                                               \
 } while (0)
 
-/* This function selects items from one hash into another hash. 
- * The end result is that the selected items have dual presence 
- * in both hashes. There is no copy of the items made; rather 
- * they are added into the new hash through a secondary hash 
+/* This function selects items from one hash into another hash.
+ * The end result is that the selected items have dual presence
+ * in both hashes. There is no copy of the items made; rather
+ * they are added into the new hash through a secondary hash
  * hash handle that must be present in the structure. */
 #define HASH_SELECT(hh_dst, dst, hh_src, src, cond)                              \
 do {                                                                             \
@@ -890,7 +890,7 @@ do {
 #ifdef NO_DECLTYPE
 #define HASH_ITER(hh,head,el,tmp)                                                \
 for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL);       \
-  el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL)) 
+  el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
 #else
 #define HASH_ITER(hh,head,el,tmp)                                                \
 for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL);                 \
@@ -898,7 +898,7 @@ for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL);
 #endif
 
 /* obtain a count of items in the hash */
-#define HASH_COUNT(head) HASH_CNT(hh,head) 
+#define HASH_COUNT(head) HASH_CNT(hh,head)
 #define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
 
 typedef struct UT_hash_bucket {
@@ -907,7 +907,7 @@ typedef struct UT_hash_bucket {
 
    /* expand_mult is normally set to 0. In this situation, the max chain length
     * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
-    * the bucket's chain exceeds this length, bucket expansion is triggered). 
+    * the bucket's chain exceeds this length, bucket expansion is triggered).
     * However, setting expand_mult to a non-zero value delays bucket expansion
     * (that would be triggered by additions to this particular bucket)
     * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
@@ -915,7 +915,7 @@ typedef struct UT_hash_bucket {
     * multiplier is to reduce bucket expansions, since they are expensive, in
     * situations where we know that a particular bucket tends to be overused.
     * It is better to let its chain length grow to a longer yet-still-bounded
-    * value, than to do an O(n) bucket expansion too often. 
+    * value, than to do an O(n) bucket expansion too often.
     */
    unsigned expand_mult;
 
@@ -941,7 +941,7 @@ typedef struct UT_hash_table {
     * hash distribution; reaching them in a chain traversal takes >ideal steps */
    unsigned nonideal_items;
 
-   /* ineffective expands occur when a bucket doubling was performed, but 
+   /* ineffective expands occur when a bucket doubling was performed, but
     * afterward, more than half the items in the hash had nonideal chain
     * positions. If this happens on two consecutive expansions we inhibit any
     * further expansion, as it's not helping; this happens when the hash
index 8b03b6b..9cd4532 100644 (file)
@@ -21,12 +21,12 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
-#ifndef _DTLS_UTLIST_H
-#define _DTLS_UTLIST_H
+#ifndef UTLIST_H
+#define UTLIST_H
 
 #define UTLIST_VERSION 1.9.1
 
-/* 
+/*
  * This file contains macros to manipulate singly and doubly-linked lists.
  *
  * 1. LL_ macros:  singly-linked lists.
@@ -36,7 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * To use singly-linked lists, your structure must have a "next" pointer.
  * To use doubly-linked lists, your structure must "prev" and "next" pointers.
  * Either way, the pointer to the head of the list must be initialized to NULL.
- * 
+ *
  * ----------------.EXAMPLE -------------------------
  * struct item {
  *      int id;
@@ -83,7 +83,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define _PREVASGN(elt,list,to) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
 #define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
 #define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
-#else 
+#else
 #define _SV(elt,list)
 #define _NEXT(elt,list) ((elt)->next)
 #define _NEXTASGN(elt,list,to) ((elt)->next)=(to)
@@ -369,14 +369,14 @@ do {
     LL_FOREACH(head,out) {                                                                     \
       if ((out)->field == (val)) break;                                                        \
     }                                                                                          \
-} while(0) 
+} while(0)
 
 #define LL_SEARCH(head,out,elt,cmp)                                                            \
 do {                                                                                           \
     LL_FOREACH(head,out) {                                                                     \
       if ((cmp(out,elt))==0) break;                                                            \
     }                                                                                          \
-} while(0) 
+} while(0)
 
 /******************************************************************************
  * doubly linked list macros (non-circular)                                   *
@@ -465,7 +465,7 @@ do {
 } while (0);
 
 #define CDL_FOREACH(head,el)                                                                   \
-    for(el=head;el;el=(el->next==head ? 0L : el->next)) 
+    for(el=head;el;el=(el->next==head ? 0L : el->next))
 
 #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2)                                                    \
   for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL);                                        \
@@ -477,14 +477,14 @@ do {
     CDL_FOREACH(head,out) {                                                                    \
       if ((out)->field == (val)) break;                                                        \
     }                                                                                          \
-} while(0) 
+} while(0)
 
 #define CDL_SEARCH(head,out,elt,cmp)                                                           \
 do {                                                                                           \
     CDL_FOREACH(head,out) {                                                                    \
       if ((cmp(out,elt))==0) break;                                                            \
     }                                                                                          \
-} while(0) 
+} while(0)
 
 #endif /* _DTLS_UTLIST_H */
 
index d86a982..6a189b2 100644 (file)
@@ -42,6 +42,9 @@ SConscript('c_common/SConscript')
 # Build connectivity
 SConscript('csdk/connectivity/SConscript')
 
+# Build libocsrm
+SConscript('csdk/security/SConscript')
+
 # Build liboctbstack
 SConscript('csdk/SConscript')
 
index a357e85..23635bc 100644 (file)
@@ -49,10 +49,13 @@ liboctbstack_env.PrependUnique(CPPPATH = [
                'connectivity/lib/libcoap-4.1.1',
                'connectivity/inc',
                'connectivity/api',
+               'connectivity/external/inc',
                'security/include',
                'security/include/internal',
                ])
 
+liboctbstack_env.AppendUnique(LIBS = ['ocsrm'])
+
 if target_os not in ['arduino', 'windows', 'winrt']:
        liboctbstack_env.AppendUnique(CPPDEFINES  = ['WITH_POSIX'])
        liboctbstack_env.AppendUnique(CFLAGS = ['-std=c99'])
@@ -105,7 +108,6 @@ liboctbstack_src = [
        OCTBSTACK_SRC + 'ocserverrequest.c',
        OCTBSTACK_SRC + 'occollection.c',
        OCTBSTACK_SRC + 'oicgroup.c',
-       'security/src/ocsecurity.c',
        'logger/src/logger.c',
        'ocrandom/src/ocrandom.c'
        ]
index d503b5a..ea05c4a 100644 (file)
@@ -75,6 +75,11 @@ extern "C"
 #endif
 
 /**
+ *@brief Maximum length of the remoteEndpoint identity
+ */
+#define CA_MAX_ENDPOINT_IDENTITY_LEN   (32)
+
+/**
  * @brief option types - the highest option number 63
  */
 #define CA_OPTION_IF_MATCH 1
@@ -158,6 +163,15 @@ typedef union
     } IP;
 } CAAddress_t;
 
+/*
+ * @brief remoteEndpoint identity
+ */
+typedef struct
+{
+    uint16_t id_length;
+    unsigned char id[CA_MAX_ENDPOINT_IDENTITY_LEN];
+}CARemoteId_t;
+
 /**
  * @enum CAMessageType_t
  * @brief Message Type for Base source code
@@ -191,8 +205,9 @@ typedef struct
 
     CAURI_t resourceUri;                    /**< Resource URI information **/
     CAAddress_t addressInfo;                /**< Remote Endpoint address **/
-    CATransportType_t transportType;  /**< Transport Type of the endpoint**/
-    bool isSecured;                     /**< Secure connection**/
+    CATransportType_t transportType;  /**< Connectivity of the endpoint**/
+    bool isSecured;                         /**< Secure connection**/
+    CARemoteId_t identity;                  /**< Endpoint identity **/
 } CARemoteEndpoint_t;
 
 
@@ -252,7 +267,9 @@ typedef enum
     CA_CREATED = 201,                /**< Created */
     CA_DELETED = 202,                /**< Deleted */
     CA_BAD_REQ = 400,                /**< Bad Request */
+    CA_UNAUTHORIZED_REQ = 401,       /**< Unauthorized Request */
     CA_BAD_OPT = 402,                /**< Bad Option */
+    CA_FORBIDDEN_REQ = 403,          /**< Forbidden Request */
     CA_NOT_FOUND = 404,              /**< Not found */
     CA_INTERNAL_SERVER_ERROR = 500,  /**< Internal Server Error */
     CA_RETRANSMIT_TIMEOUT = 504      /**< Retransmit timeout */
index 7cb0a4f..760df09 100644 (file)
@@ -142,8 +142,7 @@ void CARegisterHandler(CARequestCallback ReqHandler, CAResponseCallback RespHand
  * @param   GetDTLSCredentials   [IN] GetDTLS Credetials callback
  * @return  #CA_STATUS_OK
  */
-CAResult_t CARegisterDTLSCredentialsHandler(
-                                                   CAGetDTLSCredentialsHandler GetDTLSCredentials);
+CAResult_t CARegisterDTLSCredentialsHandler(CAGetDTLSCredentialsHandler GetDTLSCredentials);
 #endif //__WITH_DTLS__
 
 /**
@@ -284,6 +283,92 @@ CAResult_t CAGetNetworkInformation(CALocalConnectivity_t **info, uint32_t *size)
  */
 CAResult_t CAHandleRequestResponse();
 
+
+#ifdef __WITH_DTLS__
+
+/**
+ * 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
+ *                               0xC0A8 : TLS_PSK_WITH_AES_128_CCM_8
+ *                               0xC0AE : TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+ *
+ * @retval  CA_STATUS_OK    Successful
+ * @retval  CA_STATUS_INVALID_PARAM  Invalid input argumets
+ * @retval  CA_STATUS_FAILED Operation failed
+ */
+CAResult_t CASelectCipherSuite(const uint16_t cipher);
+
+/**
+ * Enable TLS_ECDH_anon_WITH_AES_128_CBC_SHA cipher suite in dtls
+ *
+ * @param[IN] enable  TRUE/FALSE enables/disables anonymous cipher suite
+ *
+ * @retval  CA_STATUS_OK    Successful
+ * @retval  CA_STATUS_FAILED Operation failed
+ *
+ * @note anonymous cipher suite should only be enabled for 'JustWorks' provisioning.
+ */
+CAResult_t CAEnableAnonECDHCipherSuite(const bool enable);
+
+
+/**
+ * Generate ownerPSK using PRF
+ * OwnerPSK = TLS-PRF('master key' , 'oic.sec.doxm.jw',
+ *                                    'ID of new device(Resource Server)',
+ *                                    'ID of owner smart-phone(Provisioning Server)')
+ *
+ * @param[IN] addrInfo  information of network address
+ * @param[IN] transportType  transport type
+ * @param[IN] label  Ownership transfer method e.g)"oic.sec.doxm.jw"
+ * @param[IN] labelLen  Byte length of label
+ * @param[IN] rsrcServerDeviceID  ID of new device(Resource Server)
+ * @param[IN] rsrcServerDeviceIDLen  Byte length of rsrcServerDeviceID
+ * @param[IN] provServerDeviceID  label of previous owner
+ * @param[IN] provServerDeviceIDLen  byte length of provServerDeviceID
+ * @param[IN,OUT] ownerPSK  Output buffer for owner PSK
+ * @param[IN] ownerPSKSize  Byte length of the ownerPSK to be generated
+ *
+ * @retval  CA_STATUS_OK    Successful
+ * @retval  CA_STATUS_FAILED Operation failed
+ */
+CAResult_t CAGenerateOwnerPSK(const CAAddress_t* addrInfo,
+                              const CATransportType_t transportType,
+                              const uint8_t* label, const size_t labelLen,
+                              const uint8_t* rsrcServerDeviceID,
+                              const size_t rsrcServerDeviceIDLen,
+                              const uint8_t* provServerDeviceID,
+                              const size_t provServerDeviceIDLen,
+                              uint8_t* ownerPSK, const size_t ownerPSKSize);
+
+/**
+ * Initiate DTLS handshake with selected cipher suite
+ *
+ * @param[IN] addrInfo    information of network address
+ * @param[IN] transportType  transport type
+ *
+ * @retval  CA_STATUS_OK    Successful
+ * @retval  CA_STATUS_FAILED Operation failed
+ */
+CAResult_t CAInitiateHandshake(const CAAddress_t* addrInfo,
+                               const CATransportType_t transportType);
+
+/**
+ * Close the DTLS session
+ *
+ * @param[IN] addrInfo       information of network address
+ * @param[IN] transportType  transport type
+ *
+ * @retval  CA_STATUS_OK    Successful
+ * @retval  CA_STATUS_FAILED Operation failed
+ */
+CAResult_t CACloseDtlsSession(const CAAddress_t* addrInfo,
+                              const CATransportType_t transportType);
+
+
+#endif /* __WITH_DTLS__ */
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
index debf3d3..f9f99d8 100644 (file)
@@ -26,6 +26,7 @@
 #include "caadapterutils.h"
 #include "ocsecurityconfig.h"
 #include "cainterface.h"
+#include "cacommon.h"
 
 /**
  *   Currently DTLS supported adapters(2) WIFI and ETHENET for linux platform.
 extern void OCGetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo);
 
 typedef void (*CAPacketReceivedCallback)(const char *ipAddress, const uint16_t port,
-         const void *data, const uint32_t dataLength, const bool isSecured);
+                                         const void *data, const uint32_t dataLength,
+                                         const bool isSecured, const CARemoteId_t *identity);
 
 typedef uint32_t (*CAPacketSendCallback)(const char *ipAddress, const uint16_t port,
-        const void *data, const uint32_t dataLength);
+                                         const void *data, const uint32_t dataLength);
 
 /**
  * @struct stCAAdapterCallbacks_t
@@ -60,6 +62,8 @@ typedef struct CAAdapterCallbacks
  */
 typedef struct stCADtlsContext
 {
+    u_arraylist_t *peerInfoList;        /**< peerInfo list which holds the mapping between
+                                             peer id to it's n/w address */
     u_arraylist_t *cacheList;            /**< PDU's are cached until DTLS session is formed. */
     struct dtls_context_t *dtlsContext;  /**< Pointer to tinyDTLS context. */
     struct stPacketInfo *packetInfo;     /**< used by callback during
@@ -116,20 +120,20 @@ typedef struct CACacheMessage
 {
     void *data;
     uint32_t dataLen;
-    stCADtlsAddrInfo_t *destSession;
+    stCADtlsAddrInfo_t destSession;
 } stCACacheMessage_t;
 
+
 /**
- * @enum eDtlsAdapterType_t
- * @brief This enum is used as array index for storing adapter level callbacks.
- *        So Keeping 0 instead of "1 << 0". It is not going to be used as addition
- *        and removal of adapter.
- *
+ * @struct stCADtlsPeerInfo_t
+ * @brief structure associates the peer psk id with peer n/w address
  */
-typedef enum
+typedef struct stCADtlsPeerInfo
 {
-    DTLS_IP = 0,
-} eDtlsAdapterType_t;
+    CAAddress_t address;
+    CARemoteId_t identity;
+}stCADtlsPeerInfo_t;
+
 
 /**
  * @fn  CADTLSSetAdapterCallbacks
@@ -143,7 +147,7 @@ typedef enum
  *
  */
 void CADTLSSetAdapterCallbacks(CAPacketReceivedCallback recvCallback,
-                               CAPacketSendCallback sendCallback, eDtlsAdapterType_t type);
+                               CAPacketSendCallback sendCallback, CATransportType_t type);
 
 /**
  * @brief   Register callback to get DTLS PSK credentials.
@@ -153,6 +157,76 @@ void CADTLSSetAdapterCallbacks(CAPacketReceivedCallback recvCallback,
 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
+ *                             0xC0A8 : TLS_PSK_WITH_AES_128_CCM_8
+ *                             0xC0AE : TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+ *
+ * @retval  CA_STATUS_OK for success, otherwise some error value
+ */
+CAResult_t CADtlsSelectCipherSuite(const dtls_cipher_t cipher);
+
+/**
+ * Enable anonymous ECDH cipher suite for dtls handshake
+ *
+ * @param[in] enable  TRUE/FALSE enables/disables anonymous cipher suite
+ *
+ * @retval  CA_STATUS_OK for success, otherwise some error value
+ */
+CAResult_t CADtlsEnableAnonECDHCipherSuite(const bool enable);
+
+/**
+ * Initiate DTLS handshake with selected cipher suite
+ *
+ * @param[in] addrInfo  information of network address
+ * @param[in] transportType  transport type
+ *
+ * @retval  CA_STATUS_OK for success, otherwise some error value
+ */
+CAResult_t CADtlsInitiateHandshake(const CAAddress_t* addrInfo,
+                                   const CATransportType_t transportType);
+
+/**
+ * Close the DTLS session
+ *
+ * @param[in] addrInfo  information of network address
+ * @param[in] transportType  transport type
+ *
+ * @retval  CA_STATUS_OK for success, otherwise some error value
+ */
+CAResult_t CADtlsClose(const CAAddress_t* addrInfo,
+                       const CATransportType_t transportType);
+
+/**
+ * Generate ownerPSK using PRF
+ * OwnerPSK = TLS-PRF('master key' , 'oic.sec.doxm.jw',
+ *                                    'ID of new device(Resource Server)',
+ *                                    'ID of owner smart-phone(Provisioning Server)')
+ *
+ * @param[in] addrInfo  information of network address
+ * @param[in] transportType  transport type
+ * @param[in] label  Ownership transfer method e.g)"oic.sec.doxm.jw"
+ * @param[in] labelLen  Byte length of label
+ * @param[in] rsrcServerDeviceID  ID of new device(Resource Server)
+ * @param[in] rsrcServerDeviceIDLen  Byte length of rsrcServerDeviceID
+ * @param[in] provServerDeviceID  label of previous owner
+ * @param[in] provServerDeviceIDLen  byte length of provServerDeviceID
+ * @param[in,out] ownerPSK  Output buffer for owner PSK
+ * @param[in] ownerPSKSize  Byte length of the ownerPSK to be generated
+ *
+ * @retval  CA_STATUS_OK for success, otherwise some error value
+ */
+CAResult_t CADtlsGenerateOwnerPSK(const CAAddress_t* addrInfo,
+                    const CATransportType_t transportType,
+                    const uint8_t* label, const size_t labelLen,
+                    const uint8_t* rsrcServerDeviceID, const size_t rsrcServerDeviceIDLen,
+                    const uint8_t* provServerDeviceID, const size_t provServerDeviceIDLen,
+                    uint8_t* ownerPSK, const size_t ownerPSKSize);
+;
+
+/**
  * @fn  CAAdapterNetDtlsInit
  * @brief  initialize tinyDTLS library and other necessary intialization.
  *
@@ -185,11 +259,8 @@ void CAAdapterNetDtlsDeInit();
  * @param[in]  port  port to which data will be sent.
  * @param[in]  data  length of data.
  * @param[in]  dataLen  length of given data
- * @param[out]  decdata  output variable to store the starting address
- *                        of decrypted plaintext.
- * @param[out]  cacheFlag  utput variable to indicate if pdu
- *                        is cached and inform the caller to
- *                       NOT free the memory holding pdu.
+ * @param[in]  type  transport at which packet needs to be send
+ *
  * @return  0 on success otherwise a positive error value.
  * @retval  CA_STATUS_OK  Successful
  * @retval  CA_STATUS_INVALID_PARAM  Invalid input argumets
@@ -201,8 +272,7 @@ CAResult_t CAAdapterNetDtlsEncrypt(const char *remoteAddress,
                                    const uint16_t port,
                                    void *data,
                                    uint32_t dataLen,
-                                   uint8_t *cacheFlag,
-                                   eDtlsAdapterType_t type);
+                                   CATransportType_t type);
 
 /**
  * @fn  CAAdapterNetDtlsDecrypt
@@ -223,7 +293,7 @@ CAResult_t CAAdapterNetDtlsDecrypt(const char *remoteAddress,
                                    const uint16_t port,
                                    uint8_t *data,
                                    uint32_t dataLen,
-                                   eDtlsAdapterType_t type);
+                                   CATransportType_t type);
 
 #endif /* CA_ADAPTER_NET_DTLS_H_ */
 
index 092a51e..b440285 100644 (file)
@@ -56,13 +56,14 @@ typedef enum
  * @param  data         [IN] Data received from remote OIC device.
  * @param  dataLength   [IN] Length of data in bytes.
  * @param  isSecured    [IN] Indicates the data is secure or not.
+ * @param  identity     [IN] Identity of the remote OIC device.
  *
  * @return NONE
  * @pre  Callback must be registered using CAIPSetPacketReceiveCallback()
  */
 typedef void (*CAIPPacketReceivedCallback)(const char *ipAddress, uint16_t port,
                                            const void *data, uint32_t dataLength,
-                                           bool isSecured);
+                                           bool isSecured, const CARemoteId_t *identity);
 
 /**
  * @brief  Callback to be notified when exception occures on multicast/unicast server.
old mode 100644 (file)
new mode 100755 (executable)
index 9c0a0a3..b859463
@@ -11,7 +11,6 @@ ca_transport = sample_env.get('TARGET_TRANSPORT')
 secured = sample_env.get('SECURED')
 root_dir = './../../'
 
-
 #####################################################################
 # Source files and Target(s)
 ######################################################################
@@ -41,6 +40,7 @@ sample_env.PrependUnique(RPATH = [sample_env.get('BUILD_DIR'), '.',])
 sample_env.PrependUnique(LIBS = ['connectivity_abstraction', 'coap', 'pthread', 'rt'])
 
 if secured == '1':
+       current_dir=env.get('SRC_DIR')
        sample_env.AppendUnique(CPPPATH = [root_dir + 'external/inc/'])
        sample_env.AppendUnique(LIBS = ['tinydtls'])
        casample =sample_env.Program('casample', [sample_src])
old mode 100644 (file)
new mode 100755 (executable)
index a95b933..9d2be70
@@ -83,8 +83,6 @@ else:
                        env.AppendUnique(CPPPATH = [extlib_dir + '/extlibs/tinydtls'])
 env.AppendUnique(CA_SRC = ca_common_src)
 
-
-
 if 'ALL' in ca_transport:
        env.SConscript(ca_path + 'ip_adapter/SConscript')
        env.SConscript(ca_path + 'bt_edr_adapter/SConscript')
index 562a5fa..8f01c06 100644 (file)
@@ -22,6 +22,7 @@
 #include "caipinterface.h"
 #include "dtls.h"
 #include "oic_malloc.h"
+#include "global.h"
 
 /**
  * @def NET_DTLS_TAG
@@ -41,11 +42,6 @@ static stCADtlsContext_t *g_caDtlsContext = NULL;
  */
 static ca_mutex g_dtlsContextMutex = NULL;
 
-/**
- * @var g_dtlsListMutex
- * @brief Mutex to synchronize access to DTLS Cache.
- */
-static ca_mutex g_dtlsListMutex = NULL;
 
 /**
  * @var g_getCredentialsCallback
@@ -53,6 +49,115 @@ static ca_mutex g_dtlsListMutex = NULL;
  */
 static CAGetDTLSCredentialsHandler g_getCredentialsCallback = NULL;
 
+static stCADtlsPeerInfo_t * GetPeerInfo(const char *peerAddr, uint32_t port)
+{
+    uint32_t list_index = 0;
+    uint32_t list_length = 0;
+
+    if(NULL == peerAddr || 0 == port)
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "CAPeerInfoListContains invalid parameters");
+        return NULL;
+    }
+
+    stCADtlsPeerInfo_t *peerInfo;
+    list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
+    for (list_index = 0; list_index < list_length; list_index++)
+    {
+        peerInfo = (stCADtlsPeerInfo_t *)u_arraylist_get(g_caDtlsContext->peerInfoList, list_index);
+        if (NULL == peerInfo)
+        {
+            continue;
+        }
+
+        if((0 == strncmp(peerAddr, peerInfo->address.IP.ipAddress, CA_IPADDR_SIZE)) &&
+                (port == peerInfo->address.IP.port))
+        {
+            return peerInfo;
+        }
+    }
+    return NULL;
+}
+
+static CAResult_t CAAddIdToPeerInfoList(const char *peerAddr, uint32_t port,
+       const unsigned char * id,uint16_t id_length)
+{
+    if(NULL == peerAddr || NULL == id || 0 == port || 0 == id_length)
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList invalid parameters");
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    if(NULL != GetPeerInfo(peerAddr, port))
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "CAAddIdToPeerInfoList peer already exist");
+        return CA_STATUS_FAILED;
+    }
+
+    stCADtlsPeerInfo_t *peerInfo = (stCADtlsPeerInfo_t *)
+                                    OICCalloc(1, sizeof(stCADtlsPeerInfo_t));
+    if (NULL == peerInfo)
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfo malloc failed!");
+        return CA_MEMORY_ALLOC_FAILED;
+    }
+
+    strncpy(peerInfo->address.IP.ipAddress, peerAddr, CA_IPADDR_SIZE);
+    peerInfo->address.IP.port = port;
+    memcpy(peerInfo->identity.id, id, id_length);
+    peerInfo->identity.id_length = id_length;
+
+    CAResult_t result = u_arraylist_add(g_caDtlsContext->peerInfoList, (void *)peerInfo);
+
+    if (CA_STATUS_OK != result)
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
+        OICFree(peerInfo);
+    }
+
+    return result;
+}
+
+
+static void CAFreePeerInfoList()
+{
+    uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
+    for (uint32_t list_index = 0; list_index < list_length; list_index++)
+    {
+        stCADtlsPeerInfo_t * peerInfo = (stCADtlsPeerInfo_t *)u_arraylist_get(
+                                g_caDtlsContext->peerInfoList, list_index);
+        OICFree(peerInfo);
+    }
+    u_arraylist_free(&(g_caDtlsContext->peerInfoList));
+    g_caDtlsContext->peerInfoList = NULL;
+}
+
+static void CARemovePeerFromPeerInfoList(const char * addr, uint32_t port)
+{
+    if(NULL == addr || 0 >= port)
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "CADTLSGetPeerPSKId invalid parameters");
+        return;
+    }
+
+    uint32_t list_length = u_arraylist_length(g_caDtlsContext->peerInfoList);
+    for (uint32_t list_index = 0; list_index < list_length; list_index++)
+    {
+        stCADtlsPeerInfo_t * peerInfo = (stCADtlsPeerInfo_t *)u_arraylist_get(
+                                g_caDtlsContext->peerInfoList,list_index);
+        if (NULL == peerInfo)
+        {
+            continue;
+        }
+        if((0 == strncmp(addr, peerInfo->address.IP.ipAddress, CA_IPADDR_SIZE)) &&
+                (port == peerInfo->address.IP.port))
+        {
+            OICFree(u_arraylist_remove(g_caDtlsContext->peerInfoList, list_index));
+            return;
+        }
+    }
+}
+
 static eDtlsRet_t CAAdapterNetDtlsEncryptInternal(const stCADtlsAddrInfo_t *dstSession,
         uint8_t *data, uint32_t dataLen)
 {
@@ -67,19 +172,15 @@ static eDtlsRet_t CAAdapterNetDtlsEncryptInternal(const stCADtlsAddrInfo_t *dstS
         return DTLS_FAIL;
     }
 
-    ca_mutex_lock(g_dtlsContextMutex);
     if (NULL == g_caDtlsContext)
     {
         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
-        ca_mutex_unlock(g_dtlsContextMutex);
         return DTLS_FAIL;
     }
 
     int retLen = dtls_write(g_caDtlsContext->dtlsContext, (session_t *)dstSession, data,
                                 dataLen);
     OIC_LOG_V(DEBUG, NET_DTLS_TAG, "dtls_write retun len [%d]", retLen);
-    ca_mutex_unlock(g_dtlsContextMutex);
-
     if (0 == retLen)
     {
         // A new DTLS session was initiated by tinyDTLS library and wait for callback.
@@ -110,7 +211,6 @@ static eDtlsRet_t CAAdapterNetDtlsDecryptInternal(const stCADtlsAddrInfo_t *srcS
 
     eDtlsRet_t ret = DTLS_FAIL;
 
-    ///  TODO: how to protect g_caDtlsContext as dtls_handle_message is blocking call
     if (dtls_handle_message(g_caDtlsContext->dtlsContext, (session_t *)srcSession, buf, bufLen) == 0)
     {
         OIC_LOG(DEBUG, NET_DTLS_TAG, "dtls_handle_message success");
@@ -126,7 +226,6 @@ static void CAFreeCacheMsg(stCACacheMessage_t *msg)
     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
     VERIFY_NON_NULL_VOID(msg, NET_DTLS_TAG, "msg");
 
-    OICFree(msg->destSession);
     OICFree(msg->data);
     OICFree(msg);
 
@@ -138,11 +237,9 @@ static void CAClearCacheList()
     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
     uint32_t list_index = 0;
     uint32_t list_length = 0;
-    ca_mutex_lock(g_dtlsListMutex);
     if (NULL == g_caDtlsContext)
     {
         OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
-        ca_mutex_unlock(g_dtlsListMutex);
         return;
     }
     list_length = u_arraylist_length(g_caDtlsContext->cacheList);
@@ -157,7 +254,6 @@ static void CAClearCacheList()
     }
     u_arraylist_free(&g_caDtlsContext->cacheList);
     g_caDtlsContext->cacheList = NULL;
-    ca_mutex_unlock(g_dtlsListMutex);
     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
 }
 
@@ -165,11 +261,9 @@ static CAResult_t CADtlsCacheMsg(stCACacheMessage_t *msg)
 {
     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
 
-    ca_mutex_lock(g_dtlsListMutex);
     if (NULL == g_caDtlsContext)
     {
         OIC_LOG(ERROR, NET_DTLS_TAG, "Dtls Context is NULL");
-        ca_mutex_unlock(g_dtlsListMutex);
         return CA_STATUS_FAILED;
     }
 
@@ -178,7 +272,6 @@ static CAResult_t CADtlsCacheMsg(stCACacheMessage_t *msg)
     {
         OIC_LOG(ERROR, NET_DTLS_TAG, "u_arraylist_add failed!");
     }
-    ca_mutex_unlock(g_dtlsListMutex);
 
     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
     return result;
@@ -200,15 +293,14 @@ static void CASendCachedMsg(const stCADtlsAddrInfo_t *dstSession)
 
     uint32_t list_index = 0;
     uint32_t list_length = 0;
-    ca_mutex_lock(g_dtlsListMutex);
     list_length = u_arraylist_length(g_caDtlsContext->cacheList);
     for (list_index = 0; list_index < list_length;)
     {
         stCACacheMessage_t *msg = (stCACacheMessage_t *)u_arraylist_get(g_caDtlsContext->cacheList,
                                   list_index);
-        if ((NULL != msg) && (true == CAIsAddressMatching(msg->destSession, dstSession)))
+        if ((NULL != msg) && (true == CAIsAddressMatching(&(msg->destSession), dstSession)))
         {
-            eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(msg->destSession,
+            eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&(msg->destSession),
                              msg->data, msg->dataLen);
             if (ret == DTLS_OK)
             {
@@ -237,7 +329,6 @@ static void CASendCachedMsg(const stCADtlsAddrInfo_t *dstSession)
             ++list_index;
         }
     }
-    ca_mutex_unlock(g_dtlsListMutex);
 
     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
 }
@@ -256,27 +347,28 @@ static int32_t CAReadDecryptedPayload(dtls_context_t *dtlsContext,
 
     char *remoteAddress = inet_ntoa(addrInfo->addr.sin.sin_addr);
     uint32_t port = ntohs(addrInfo->addr.sin.sin_port);
-    eDtlsAdapterType_t type = (eDtlsAdapterType_t)addrInfo->ifIndex;
+    CATransportType_t type = (CATransportType_t)addrInfo->ifIndex;
 
-    ca_mutex_lock(g_dtlsContextMutex);
     if (NULL == g_caDtlsContext)
     {
         OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
-        ca_mutex_unlock(g_dtlsContextMutex);
         return 0;
     }
 
     if ((0 <= type) && (MAX_SUPPORTED_ADAPTERS > type) &&
         (NULL != g_caDtlsContext->adapterCallbacks[type].recvCallback))
     {
+        // Get identity of sthe source of packet
+        stCADtlsPeerInfo_t * peerInfo = GetPeerInfo(remoteAddress, port);
+
         g_caDtlsContext->adapterCallbacks[type].recvCallback(remoteAddress, port,
-                buf,  bufLen, true);
+                buf,  bufLen, true,
+                (peerInfo) ? &(peerInfo->identity) : NULL);
     }
     else
     {
         OIC_LOG_V(DEBUG, NET_DTLS_TAG, "recvCallback Callback or adapter type is wrong [%d]", type);
     }
-    ca_mutex_unlock(g_dtlsContextMutex);
 
     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
     return 0;
@@ -302,7 +394,7 @@ static int32_t CASendSecureData(dtls_context_t *dtlsContext,
 
     char *remoteAddress = inet_ntoa(addrInfo->addr.sin.sin_addr);
     uint16_t port = ntohs(addrInfo->addr.sin.sin_port);
-    eDtlsAdapterType_t type = (eDtlsAdapterType_t)addrInfo->ifIndex;
+    CATransportType_t type = (CATransportType_t)addrInfo->ifIndex;
 
     //Mutex is not required for g_caDtlsContext. It will be called in same thread.
     int32_t sentLen = 0;
@@ -341,6 +433,17 @@ static int32_t CAHandleSecureEvent(dtls_context_t *dtlsContext,
         CASendCachedMsg((stCADtlsAddrInfo_t *)session);
     }
 
+    if(DTLS_ALERT_LEVEL_FATAL == level && DTLS_ALERT_CLOSE_NOTIFY == code)
+    {
+        OIC_LOG(INFO, NET_DTLS_TAG, "Peer closing connection");
+
+        stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
+        char *peerAddr = inet_ntoa(addrInfo->addr.sin.sin_addr);
+        uint32_t port = ntohs(addrInfo->addr.sin.sin_port);
+
+        CARemovePeerFromPeerInfoList(peerAddr, port);
+    }
+
     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
     return 0;
 }
@@ -355,6 +458,11 @@ static int32_t CAGetPskCredentials(dtls_context_t *ctx,
     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
 
     int32_t ret  = -1;
+    if(NULL == ctx || NULL == session || NULL == result)
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "CAGetPskCredentials invalid parameters");
+        return ret;
+    }
 
     VERIFY_NON_NULL_RET(g_getCredentialsCallback, NET_DTLS_TAG, "GetCredential callback", -1);
     VERIFY_NON_NULL_RET(result, NET_DTLS_TAG, "result", -1);
@@ -391,6 +499,22 @@ static int32_t CAGetPskCredentials(dtls_context_t *ctx,
         {
             if (memcmp(desc, credInfo->creds[index].id, DTLS_PSK_ID_LEN) == 0)
             {
+                if(NULL != ctx->peers && DTLS_SERVER == ctx->peers->role )
+                {
+                    // TODO SRM needs identity of the remote end-point with every data packet to
+                    // perform access control management. tinyDTLS 'frees' the handshake parameters
+                    // data structure when handshake completes. Therefore, currently this is a
+                    // workaround to cache remote end-point identity when tinyDTLS asks for PSK.
+                    stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)session;
+                    char *peerAddress = inet_ntoa(addrInfo->addr.sin.sin_addr);
+                    uint32_t port = ntohs(addrInfo->addr.sin.sin_port);
+
+                    CAResult_t result = CAAddIdToPeerInfoList(peerAddress, port, desc, descLen);
+                    if(CA_STATUS_OK != result )
+                    {
+                        OIC_LOG(ERROR, NET_DTLS_TAG, "Fail to add peer id to gDtlsPeerInfoList");
+                    }
+                }
                 memcpy(result, credInfo->creds[index].psk, DTLS_PSK_PSK_LEN);
                 ret = DTLS_PSK_PSK_LEN;
             }
@@ -409,7 +533,7 @@ static int32_t CAGetPskCredentials(dtls_context_t *ctx,
 }
 
 void CADTLSSetAdapterCallbacks(CAPacketReceivedCallback recvCallback,
-                               CAPacketSendCallback sendCallback, eDtlsAdapterType_t type)
+                               CAPacketSendCallback sendCallback, CATransportType_t type)
 {
     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
     ca_mutex_lock(g_dtlsContextMutex);
@@ -433,15 +557,199 @@ void CADTLSSetAdapterCallbacks(CAPacketReceivedCallback recvCallback,
 
 void CADTLSSetCredentialsCallback(CAGetDTLSCredentialsHandler credCallback)
 {
+    // TODO Does this method needs protection of DtlsContextMutex ?
     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
     g_getCredentialsCallback = credCallback;
     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
 }
 
+CAResult_t CADtlsSelectCipherSuite(const dtls_cipher_t cipher)
+{
+    OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsSelectCipherSuite");
+
+    ca_mutex_lock(g_dtlsContextMutex);
+    if (NULL == g_caDtlsContext)
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
+        ca_mutex_unlock(g_dtlsContextMutex);
+        return CA_STATUS_FAILED;
+    }
+    dtls_select_cipher(g_caDtlsContext->dtlsContext, cipher);
+    ca_mutex_unlock(g_dtlsContextMutex);
+
+    OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Selected cipher suite is 0x%02X%02X\n",
+        ((uint8_t*)(&cipher))[1], ((uint8_t*)(&cipher))[0]);
+    OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsSelectCipherSuite");
+
+    return CA_STATUS_OK ;
+}
+
+CAResult_t CADtlsEnableAnonECDHCipherSuite(const bool enable)
+{
+    OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsEnablesAnonEcdh");
+
+    ca_mutex_lock(g_dtlsContextMutex);
+    if (NULL == g_caDtlsContext)
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
+        ca_mutex_unlock(g_dtlsContextMutex);
+        return CA_STATUS_FAILED;
+    }
+    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",
+        enable ? "enabled" : "disabled");
+
+    OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsEnablesAnonEcdh");
+
+    return CA_STATUS_OK ;
+}
+
+CAResult_t CADtlsInitiateHandshake(const CAAddress_t* addrInfo,
+                                   const CATransportType_t transportType)
+{
+    stCADtlsAddrInfo_t dst = {};
+
+    OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsInitiateHandshake");
+
+    if(!addrInfo)
+    {
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    if(inet_aton(addrInfo->IP.ipAddress, &dst.addr.sin.sin_addr) == 0)
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to convert from ASCII to Network Address");
+        return CA_STATUS_FAILED;
+    }
+    dst.addr.sin.sin_family = AF_INET;
+    dst.addr.sin.sin_port = htons(addrInfo->IP.port);
+    dst.size = sizeof(dst.addr);
+
+    dst.ifIndex = transportType;
+
+    ca_mutex_lock(g_dtlsContextMutex);
+    if(NULL == g_caDtlsContext)
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
+        ca_mutex_unlock(g_dtlsContextMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    if(0 > dtls_connect(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to connect");
+        ca_mutex_unlock(g_dtlsContextMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    ca_mutex_unlock(g_dtlsContextMutex);
+
+    OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsInitiateHandshake");
+
+    return CA_STATUS_OK;
+}
+
+CAResult_t CADtlsClose(const CAAddress_t* addrInfo, const CATransportType_t transportType)
+{
+    stCADtlsAddrInfo_t dst = {};
+
+    OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsDisconnect");
+
+    if(!addrInfo)
+    {
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    if(inet_aton(addrInfo->IP.ipAddress, &dst.addr.sin.sin_addr) == 0)
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to convert from ASCII to Network Address");
+        return CA_STATUS_FAILED;
+    }
+    dst.addr.sin.sin_family = AF_INET;
+    dst.addr.sin.sin_port = htons(addrInfo->IP.port);
+    dst.size = sizeof(dst.addr);
+
+    dst.ifIndex = transportType;
+
+    ca_mutex_lock(g_dtlsContextMutex);
+    if(NULL == g_caDtlsContext)
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
+        ca_mutex_unlock(g_dtlsContextMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    if(0 > dtls_close(g_caDtlsContext->dtlsContext, (session_t*)(&dst)))
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to close the session");
+        ca_mutex_unlock(g_dtlsContextMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    ca_mutex_unlock(g_dtlsContextMutex);
+
+    OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsDisconnect");
+
+    return CA_STATUS_OK;
+}
+
+CAResult_t CADtlsGenerateOwnerPSK(const CAAddress_t* addrInfo,
+                    const CATransportType_t transportType,
+                    const uint8_t* label, const size_t labelLen,
+                    const uint8_t* rsrcServerDeviceID, const size_t rsrcServerDeviceIDLen,
+                    const uint8_t* provServerDeviceID, const size_t provServerDeviceIDLen,
+                    uint8_t* ownerPSK, const size_t ownerPSKSize)
+{
+    OIC_LOG(DEBUG, NET_DTLS_TAG, "IN CADtlsGenerateOwnerPSK");
+
+    if(!addrInfo || !label || 0 == labelLen || !ownerPSK || 0 == ownerPSKSize)
+    {
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    stCADtlsAddrInfo_t dst = {};
+
+    if(inet_aton(addrInfo->IP.ipAddress, &dst.addr.sin.sin_addr) == 0)
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to convert from ASCII to Network Address");
+        return CA_STATUS_FAILED;
+    }
+    dst.addr.sin.sin_family = AF_INET;
+    dst.addr.sin.sin_port = htons(addrInfo->IP.port);
+    dst.size = sizeof(dst.addr);
+
+    dst.ifIndex = transportType;
+
+    ca_mutex_lock(g_dtlsContextMutex);
+    if (NULL == g_caDtlsContext)
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
+        ca_mutex_unlock(g_dtlsContextMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    if( 0 == dtls_prf_with_current_keyblock(g_caDtlsContext->dtlsContext, (session_t*)(&dst),
+                 label, labelLen, rsrcServerDeviceID, rsrcServerDeviceIDLen,
+                 provServerDeviceID, provServerDeviceIDLen, ownerPSK, ownerPSKSize))
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to DTLS PRF");
+        ca_mutex_unlock(g_dtlsContextMutex);
+        return CA_STATUS_FAILED;
+    }
+    ca_mutex_unlock(g_dtlsContextMutex);
+
+    OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT CADtlsGenerateOwnerPSK");
+
+    return CA_STATUS_OK;
+}
+
 CAResult_t CAAdapterNetDtlsInit()
 {
     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
 
+    // Initialize mutex for DtlsContext
     if (NULL == g_dtlsContextMutex)
     {
         g_dtlsContextMutex = ca_mutex_new();
@@ -454,47 +762,40 @@ CAResult_t CAAdapterNetDtlsInit()
         return CA_STATUS_OK;
     }
 
-    if (NULL == g_dtlsListMutex)
-    {
-        g_dtlsListMutex = ca_mutex_new();
-        if (NULL == g_dtlsListMutex)
-        {
-            OIC_LOG(ERROR, NET_DTLS_TAG, "g_dtlsListMutex malloc failed");
-            ca_mutex_free(g_dtlsContextMutex);
-            return CA_MEMORY_ALLOC_FAILED;
-        }
-    }
-
+    // Lock DtlsContext mutex and create DtlsContext
     ca_mutex_lock(g_dtlsContextMutex);
     g_caDtlsContext = (stCADtlsContext_t *)OICCalloc(1, sizeof(stCADtlsContext_t));
 
     if (NULL == g_caDtlsContext)
     {
         OIC_LOG(ERROR, NET_DTLS_TAG, "Context malloc failed");
-        ca_mutex_free(g_dtlsListMutex);
         ca_mutex_unlock(g_dtlsContextMutex);
         ca_mutex_free(g_dtlsContextMutex);
         return CA_MEMORY_ALLOC_FAILED;
     }
 
-    ca_mutex_lock(g_dtlsListMutex);
+
+    // Create PeerInfoList and CacheList
+    g_caDtlsContext->peerInfoList = u_arraylist_create();
     g_caDtlsContext->cacheList = u_arraylist_create();
 
-    if (NULL == g_caDtlsContext->cacheList)
+    if( (NULL == g_caDtlsContext->peerInfoList) ||
+        (NULL == g_caDtlsContext->cacheList))
     {
-        OIC_LOG(ERROR, NET_DTLS_TAG, "cacheList initialization failed!");
-        ca_mutex_unlock(g_dtlsListMutex);
-        ca_mutex_free(g_dtlsListMutex);
-        ca_mutex_unlock(g_dtlsContextMutex);
-        ca_mutex_free(g_dtlsContextMutex);
+        OIC_LOG(ERROR, NET_DTLS_TAG, "peerInfoList or cacheList initialization failed!");
+        CAClearCacheList();
+        CAFreePeerInfoList();
         OICFree(g_caDtlsContext);
         g_caDtlsContext = NULL;
+        ca_mutex_unlock(g_dtlsContextMutex);
+        ca_mutex_free(g_dtlsContextMutex);
         return CA_STATUS_FAILED;
     }
-    ca_mutex_unlock(g_dtlsListMutex);
+
     // Initialize clock, crypto and other global vars in tinyDTLS library
     dtls_init();
 
+    // Create tinydtls Context
     g_caDtlsContext->dtlsContext = dtls_new_context(g_caDtlsContext);
 
     if (NULL ==  g_caDtlsContext->dtlsContext)
@@ -521,19 +822,28 @@ void CAAdapterNetDtlsDeInit()
     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
 
     VERIFY_NON_NULL_VOID(g_caDtlsContext, NET_DTLS_TAG, "context is NULL");
+    VERIFY_NON_NULL_VOID(g_dtlsContextMutex, NET_DTLS_TAG, "context mutex is NULL");
 
+    //Lock DtlsContext mutex
     ca_mutex_lock(g_dtlsContextMutex);
+
+    // Clear all lists
+    CAFreePeerInfoList();
     CAClearCacheList();
+
+    // De-initialize tinydtls context
     dtls_free_context(g_caDtlsContext->dtlsContext);
     g_caDtlsContext->dtlsContext = NULL;
+
+    // De-initialize DtlsContext
     OICFree(g_caDtlsContext);
     g_caDtlsContext = NULL;
-    ca_mutex_unlock(g_dtlsContextMutex);
 
+    // Unlock DtlsContext mutex and de-initialize it
+    ca_mutex_unlock(g_dtlsContextMutex);
     ca_mutex_free(g_dtlsContextMutex);
     g_dtlsContextMutex = NULL;
-    ca_mutex_free(g_dtlsListMutex);
-    g_dtlsListMutex = NULL;
+
     OIC_LOG(DEBUG, NET_DTLS_TAG, "OUT");
 }
 
@@ -541,8 +851,7 @@ CAResult_t CAAdapterNetDtlsEncrypt(const char *remoteAddress,
                                    const uint16_t port,
                                    void *data,
                                    uint32_t dataLen,
-                                   uint8_t *cacheFlag,
-                                   eDtlsAdapterType_t adapterType)
+                                   CATransportType_t transportType)
 {
 
     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
@@ -559,30 +868,35 @@ CAResult_t CAAdapterNetDtlsEncrypt(const char *remoteAddress,
 
     OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Data to be encrypted dataLen [%d]", dataLen);
 
-    stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)OICCalloc(1, sizeof(stCADtlsAddrInfo_t));
+    stCADtlsAddrInfo_t addrInfo = {};
 
-    VERIFY_NON_NULL_RET(addrInfo, NET_DTLS_TAG, "malloc failed" , CA_MEMORY_ALLOC_FAILED);
-
-    addrInfo->addr.sin.sin_family = AF_INET;
-    addrInfo->addr.sin.sin_port = htons(port);
+    addrInfo.addr.sin.sin_family = AF_INET;
+    addrInfo.addr.sin.sin_port = htons(port);
     // Conversion from ASCII format to Network format
-    if (inet_aton(remoteAddress, &addrInfo->addr.sin.sin_addr) == 0)
+    if (inet_aton(remoteAddress, &addrInfo.addr.sin.sin_addr) == 0)
     {
         OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to convert from ASCII to Network Address");
-        OICFree(addrInfo);
         return CA_STATUS_FAILED;
     }
-    addrInfo->size = sizeof(addrInfo->addr);
-    addrInfo->ifIndex = adapterType;
+    addrInfo.size = sizeof(addrInfo.addr);
+    addrInfo.ifIndex = transportType;
 
-    eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(addrInfo, data, dataLen);
+    ca_mutex_lock(g_dtlsContextMutex);
+    if(NULL == g_caDtlsContext)
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
+        ca_mutex_unlock(g_dtlsContextMutex);
+        return CA_STATUS_FAILED;
+    }
+
+    eDtlsRet_t ret = CAAdapterNetDtlsEncryptInternal(&addrInfo, data, dataLen);
     if (ret == DTLS_SESSION_INITIATED)
     {
         stCACacheMessage_t *message = (stCACacheMessage_t *)OICCalloc(1, sizeof(stCACacheMessage_t));
         if (NULL == message)
         {
             OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
-            OICFree(addrInfo);
+            ca_mutex_unlock(g_dtlsContextMutex);
             return CA_MEMORY_ALLOC_FAILED;
         }
 
@@ -590,8 +904,8 @@ CAResult_t CAAdapterNetDtlsEncrypt(const char *remoteAddress,
         if (NULL == message->data)
         {
             OIC_LOG(ERROR, NET_DTLS_TAG, "calloc failed!");
-            OICFree(addrInfo);
             OICFree(message);
+            ca_mutex_unlock(g_dtlsContextMutex);
             return CA_MEMORY_ALLOC_FAILED;
         }
         memcpy(message->data, data, dataLen);
@@ -599,23 +913,17 @@ CAResult_t CAAdapterNetDtlsEncrypt(const char *remoteAddress,
         message->destSession = addrInfo;
 
         CAResult_t result = CADtlsCacheMsg(message);
-        if (CA_STATUS_OK == result)
-        {
-            if (cacheFlag)
-            {
-                *cacheFlag = 1;
-            }
-        }
-        else
+        if (CA_STATUS_OK != result)
         {
             OIC_LOG(DEBUG, NET_DTLS_TAG, "CADtlsCacheMsg failed!");
             CAFreeCacheMsg(message);
         }
         OIC_LOG_V(DEBUG, NET_DTLS_TAG, "OUT Initiating Dtls session [%d]", result);
+        ca_mutex_unlock(g_dtlsContextMutex);
         return result;
     }
 
-    OICFree(addrInfo);
+    ca_mutex_unlock(g_dtlsContextMutex);
 
     if (ret == DTLS_OK)
     {
@@ -632,30 +940,35 @@ CAResult_t CAAdapterNetDtlsDecrypt(const char *remoteAddress,
                                    const uint16_t port,
                                    uint8_t *data,
                                    uint32_t dataLen,
-                                   eDtlsAdapterType_t adapterType)
+                                   CATransportType_t transportType)
 {
     OIC_LOG(DEBUG, NET_DTLS_TAG, "IN");
 
-    stCADtlsAddrInfo_t *addrInfo = (stCADtlsAddrInfo_t *)OICCalloc(1, sizeof(stCADtlsAddrInfo_t));
+    stCADtlsAddrInfo_t addrInfo = {};
 
-    VERIFY_NON_NULL_RET(addrInfo, NET_DTLS_TAG, "calloc failed" , CA_MEMORY_ALLOC_FAILED);
-
-    addrInfo->addr.sin.sin_family = AF_INET;
-    addrInfo->addr.sin.sin_port = htons(port);
+    addrInfo.addr.sin.sin_family = AF_INET;
+    addrInfo.addr.sin.sin_port = htons(port);
 
     // Conversion from ASCII format to Network format
-    if (inet_aton(remoteAddress, &addrInfo->addr.sin.sin_addr) == 0)
+    if (inet_aton(remoteAddress, &addrInfo.addr.sin.sin_addr) == 0)
     {
         OIC_LOG(ERROR, NET_DTLS_TAG, "Failed to convert from ASCII to Network Address");
-        OICFree(addrInfo);
         return CA_STATUS_FAILED;
     }
-    addrInfo->size = sizeof(addrInfo->addr);
-    addrInfo->ifIndex = adapterType;
+    addrInfo.size = sizeof(addrInfo.addr);
+    addrInfo.ifIndex = transportType;
+
+    ca_mutex_lock(g_dtlsContextMutex);
+    if(NULL == g_caDtlsContext)
+    {
+        OIC_LOG(ERROR, NET_DTLS_TAG, "Context is NULL");
+        ca_mutex_unlock(g_dtlsContextMutex);
+        return CA_STATUS_FAILED;
+    }
 
-    eDtlsRet_t ret = CAAdapterNetDtlsDecryptInternal(addrInfo, data, dataLen);
+    eDtlsRet_t ret = CAAdapterNetDtlsDecryptInternal(&addrInfo, data, dataLen);
+    ca_mutex_unlock(g_dtlsContextMutex);
 
-    OICFree(addrInfo);
     if (DTLS_OK == ret || DTLS_HS_MSG == ret)
     {
         OIC_LOG_V(DEBUG, NET_DTLS_TAG, "Successfully Decrypted or Handshake msg recvd [%d]", ret);
@@ -667,4 +980,3 @@ CAResult_t CAAdapterNetDtlsDecrypt(const char *remoteAddress,
     return CA_STATUS_FAILED;
 }
 
-
index c073b62..8479c55 100644 (file)
@@ -263,6 +263,7 @@ CARemoteEndpoint_t *CAAdapterCopyRemoteEndpoint(const CARemoteEndpoint_t *remote
     }
 
     info->isSecured = remoteEndpoint->isSecured;
+    info->identity  = remoteEndpoint->identity;
     return info;
 }
 
index 264b885..c5dd281 100644 (file)
@@ -30,6 +30,9 @@
 #include "canetworkconfigurator.h"
 #include "cainterfacecontroller.h"
 #include "logger.h"
+#ifdef __WITH_DTLS__
+#include "caadapternetdtls.h"
+#endif
 
 #define TAG PCF("CA")
 
@@ -351,3 +354,95 @@ CAResult_t CAHandleRequestResponse()
     return CA_STATUS_OK;
 }
 
+#ifdef __WITH_DTLS__
+
+CAResult_t CASelectCipherSuite(const uint16_t cipher)
+{
+    OIC_LOG_V(DEBUG, TAG, "CASelectCipherSuite");
+
+    return CADtlsSelectCipherSuite(cipher);
+}
+
+CAResult_t CAEnableAnonECDHCipherSuite(const bool enable)
+{
+    OIC_LOG_V(DEBUG, TAG, "CAEnableAnonECDHCipherSuite");
+
+    return CADtlsEnableAnonECDHCipherSuite(enable);
+}
+
+CAResult_t CAGenerateOwnerPSK(const CAAddress_t* addrInfo,
+                    const CATransportType_t transportType,
+                    const uint8_t* label, const size_t labelLen,
+                    const uint8_t* rsrcServerDeviceID, const size_t rsrcServerDeviceIDLen,
+                    const uint8_t* provServerDeviceID, const size_t provServerDeviceIDLen,
+                    uint8_t* ownerPSK, const size_t ownerPSKSize)
+{
+    OIC_LOG_V(DEBUG, TAG, "IN : CAGenerateOwnerPSK");
+
+    CAResult_t res = CA_STATUS_OK;
+
+    //newOwnerLabel and prevOwnerLabe can be NULL
+    if(!addrInfo || !label || 0 == labelLen || !ownerPSK || 0 == ownerPSKSize)
+    {
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    res = CADtlsGenerateOwnerPSK(addrInfo, transportType, label, labelLen,
+                                  rsrcServerDeviceID, rsrcServerDeviceIDLen,
+                                  provServerDeviceID, provServerDeviceIDLen,
+                                  ownerPSK, ownerPSKSize);
+    if(CA_STATUS_OK != res)
+    {
+        OIC_LOG_V(ERROR, TAG, "Failed to CAGenerateOwnerPSK : %d", res);
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "OUT : CAGenerateOwnerPSK");
+
+    return res;
+}
+
+CAResult_t CAInitiateHandshake(const CAAddress_t* addrInfo,
+                               const CATransportType_t transportType)
+{
+    OIC_LOG_V(DEBUG, TAG, "IN : CAInitiateHandshake");
+    CAResult_t res = CA_STATUS_OK;
+
+    if(!addrInfo)
+    {
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    res = CADtlsInitiateHandshake(addrInfo, transportType);
+    if(CA_STATUS_OK != res)
+    {
+        OIC_LOG_V(ERROR, TAG, "Failed to CADtlsInitiateHandshake : %d", res);
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "OUT : CAInitiateHandshake");
+
+    return res;
+}
+
+CAResult_t CACloseDtlsSession(const CAAddress_t* addrInfo,
+                              const CATransportType_t transportType)
+{
+    OIC_LOG_V(DEBUG, TAG, "IN : CACloseDtlsSession");
+    CAResult_t res = CA_STATUS_OK;
+
+    if(!addrInfo)
+    {
+        return CA_STATUS_INVALID_PARAM;
+    }
+
+    res = CADtlsClose(addrInfo, transportType);
+    if(CA_STATUS_OK != res)
+    {
+        OIC_LOG_V(ERROR, TAG, "Failed to CADtlsClose : %d", res);
+    }
+
+    OIC_LOG_V(DEBUG, TAG, "OUT : CACloseDtlsSession");
+
+    return res;
+}
+
+#endif /* __WITH_DTLS__ */
index bd9af23..0a455f4 100644 (file)
@@ -110,7 +110,8 @@ static void CAIPNotifyNetworkChange(const char *address, uint16_t port,
 static void CAIPConnectionStateCB(const char *ipAddress, CANetworkStatus_t status);
 
 static void CAIPPacketReceivedCB(const char *ipAddress, uint16_t port, const void *data,
-                                       uint32_t dataLength, bool isSecured);
+                                       uint32_t dataLength, bool isSecured,
+                                       const CARemoteId_t *identity);
 #ifdef __WITH_DTLS__
 static uint32_t CAIPPacketSendCB(const char *ipAddress, uint16_t port,
                                        const void *data, uint32_t dataLength);
@@ -277,7 +278,8 @@ uint32_t CAIPPacketSendCB(const char *ipAddress, uint16_t port,
 #endif
 
 void CAIPPacketReceivedCB(const char *ipAddress, uint16_t port, const void *data,
-                                uint32_t dataLength, bool isSecured)
+                                uint32_t dataLength, bool isSecured,
+                                const CARemoteId_t *identity)
 {
     OIC_LOG(DEBUG, IP_ADAPTER_TAG, "IN");
 
@@ -296,6 +298,11 @@ void CAIPPacketReceivedCB(const char *ipAddress, uint16_t port, const void *data
     }
     endPoint->addressInfo.IP.port = port;
     endPoint->isSecured = isSecured;
+    if (identity)
+    {
+        endPoint->identity = *identity;
+    }
+
 
     void *buf = OICCalloc(dataLength + 1, sizeof(char));
     if (!buf)
@@ -352,7 +359,7 @@ CAResult_t CAInitializeIP(CARegisterConnectivityCallback registerCallback,
 #ifdef __WITH_DTLS__
     CAAdapterNetDtlsInit();
 
-    CADTLSSetAdapterCallbacks(CAIPPacketReceivedCB, CAIPPacketSendCB, DTLS_IP);
+    CADTLSSetAdapterCallbacks(CAIPPacketReceivedCB, CAIPPacketSendCB, CA_IPV4);
 #endif
 
     CAConnectivityHandler_t ipHandler;
@@ -703,7 +710,7 @@ void CATerminateIP()
     CAStopIP();
 
 #ifdef __WITH_DTLS__
-    CADTLSSetAdapterCallbacks(NULL, NULL, DTLS_IP);
+    CADTLSSetAdapterCallbacks(NULL, NULL, CA_IPV4);
 #endif
 
     CAIPSetPacketReceiveCallback(NULL);
@@ -749,17 +756,15 @@ void CAIPSendDataThread(void *threadData)
         else
         {
             OIC_LOG(DEBUG, IP_ADAPTER_TAG, "CAAdapterNetDtlsEncrypt called!");
-            uint8_t cacheFlag = 0;
             CAResult_t result = CAAdapterNetDtlsEncrypt(address, port, ipData->data,
-                                                        ipData->dataLen, &cacheFlag,
-                                                        DTLS_IP);
+                                                        ipData->dataLen, CA_IPV4);
 
             if (CA_STATUS_OK != result)
             {
                 OIC_LOG(ERROR, IP_ADAPTER_TAG, "CAAdapterNetDtlsEncrypt failed!");
             }
             OIC_LOG_V(DEBUG, IP_ADAPTER_TAG,
-                      "CAAdapterNetDtlsEncrypt returned with cache[%d]", cacheFlag);
+                      "CAAdapterNetDtlsEncrypt returned with result[%d]", result);
         }
 #else
         CAIPSendData(address, port, ipData->data, ipData->dataLen, false,
index 38f164c..e08faed 100644 (file)
@@ -266,7 +266,7 @@ static void CAReceiveHandler(void *data)
 #ifdef __WITH_DTLS__
                     CAResult_t ret = CAAdapterNetDtlsDecrypt(srcIPAddress, srcPort,
                                                              (uint8_t *)recvBuffer, recvLen,
-                                                             DTLS_IP);
+                                                             CA_IPV4);
                     OIC_LOG_V(DEBUG, IP_SERVER_TAG,
                               "CAAdapterNetDtlsDecrypt returns [%d]", ret);
 #endif
@@ -279,7 +279,7 @@ static void CAReceiveHandler(void *data)
                     {
                         g_adapterEthServerContext->packetReceivedCallback(srcIPAddress, srcPort,
                                                                           recvBuffer, recvLen,
-                                                                          false);
+                                                                          false, NULL);
                     }
 
                     ca_mutex_unlock(g_mutexAdapterServerContext);
diff --git a/resource/csdk/security/README-building-and-running-secure-IoTivity-stack.txt b/resource/csdk/security/README-building-and-running-secure-IoTivity-stack.txt
new file mode 100644 (file)
index 0000000..9def457
--- /dev/null
@@ -0,0 +1,17 @@
+LAST UPDATED 5/27/2015
+
+To build the IoTivity stack with the security features enabled:
+
+1) Build IoTivity with security enabled:
+       $ cd <iotivity-base>
+       $ scons resource SECURED=1
+
+2) Verify functionality using secure sample apps:
+       $ cd <iotivity-base>/out/<...>/release/resource/csdk/stack/samples/linux/secure
+       $ export LD_LIBRARY_PATH=<iotivity-base>/out/<...>/release
+       $ ./ocserverbasicops &
+       $ ./occlientbasicops -t 1
+        Message "INFO: occlientbasicops: Secure -- YES" indicates success!
+       $ ./occlientbasicops -t 2
+        Completion of 'GET' and 'PUT' query successfully indicates success!
+
diff --git a/resource/csdk/security/SConscript b/resource/csdk/security/SConscript
new file mode 100644 (file)
index 0000000..24b4be1
--- /dev/null
@@ -0,0 +1,102 @@
+# //******************************************************************
+# //
+# // 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.
+# //
+# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+# libocsrm (share library) build script
+##
+
+Import('env')
+
+lib_env = env.Clone()
+SConscript(env.get('SRC_DIR') + '/resource/third_party_libs.scons', 'lib_env')
+
+libocsrm_env = lib_env.Clone()
+
+target_os = env.get('TARGET_OS')
+# As in the source code, it includes arduino Time library (C++)
+# It requires compile the .c with g++
+if target_os == 'arduino':
+       libocsrm_env.Replace(CC = env.get('CXX'))
+       libocsrm_env.Replace(CFLAGS = env.get('CXXFLAGS'))
+
+######################################################################
+# Build flags
+######################################################################
+libocsrm_env.PrependUnique(CPPPATH = [
+               '../../../extlibs/cjson/',
+               '../logger/include',
+               '../ocrandom/include',
+               '../stack/include',
+               '../stack/include/internal',
+               '../../oc_logger/include',
+               '../connectivity/lib/libcoap-4.1.1',
+               '../connectivity/external/inc',
+               '../connectivity/inc',
+               '../connectivity/api',
+               '../security/include',
+               '../security/include/internal',
+               ])
+
+if target_os not in ['arduino', 'windows', 'winrt']:
+       libocsrm_env.AppendUnique(CPPDEFINES  = ['WITH_POSIX'])
+       libocsrm_env.AppendUnique(CFLAGS = ['-std=c99'])
+
+if target_os not in ['windows', 'winrt']:
+       libocsrm_env.AppendUnique(CFLAGS = ['-Wall'])
+
+libocsrm_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+libocsrm_env.AppendUnique(LIBS = ['coap', 'm'])
+
+if target_os == 'arduino':
+       libocsrm_env.AppendUnique(CPPDEFINES = ['NDEBUG', 'WITH_ARDUINO'])
+else:
+       libocsrm_env.AppendUnique(CFLAGS = ['-fPIC'])
+
+if target_os in ['darwin', 'ios']:
+       libocsrm_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE'])
+       libocsrm_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+       libocsrm_env.AppendUnique(LIBS = ['coap'])
+
+if not env.get('RELEASE'):
+       libocsrm_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+
+######################################################################
+# 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 + 'base64.c'
+       ]
+
+libocsrm = libocsrm_env.StaticLibrary('libocsrm', libocsrm_src)
+
+libocsrm_env.InstallTarget(libocsrm, 'libocsrm')
+
+if env.get('SECURED') == '1':
+        SConscript('provisioning/SConscript')
+
diff --git a/resource/csdk/security/include/base64.h b/resource/csdk/security/include/base64.h
new file mode 100644 (file)
index 0000000..4d5837d
--- /dev/null
@@ -0,0 +1,88 @@
+ /******************************************************************
+  *
+  * 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 _IOTVT_B64_H_
+#define _IOTVT_B64_H_
+
+#include <stdint.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Macro to calculate the size of 'output' buffer required for
+ * a 'input' buffer of length x during Base64 encoding operation.
+ */
+#define B64ENCODE_OUT_SAFESIZE(x) ((((x) + 3 - 1)/3) * 4 + 1)
+
+/**
+ * Macro to calculate the size of 'output' buffer required for
+ * a 'input' buffer of length x during Base64 decoding operation.
+ */
+#define B64DECODE_OUT_SAFESIZE(x) (((x)*3)/4)
+
+/**
+ * Result code of base64 functions
+ */
+typedef enum {
+    B64_OK = 0,
+    B64_INVALID_PARAM,
+    B64_OUTPUT_BUFFER_TOO_SMALL,
+    B64_ERROR
+}B64Result;
+
+/**
+ * Encode the plain message in base64.
+ *
+ * @param[in] in  Plain message
+ * @param[in] inLen  Byte length of 'in'
+ * @param[in,out] outBuf Output buffer
+ *                Base64 encoded message will be written into 'outBuf'
+ *                NOTE : This method adds a NULL to the string configuration
+ * @param[in] outBufSize Size of output buffer
+ * @param[out] outLen  Byte length of encoded message
+ *
+ * @return  B64_OK for Success, otherwise some error value
+ */
+B64Result b64Encode(const uint8_t* in, const size_t inLen,
+               char* outBuf, const size_t outBufSize, uint32_t *outLen);
+
+/**
+ * Decode the encoded message in base64.
+ *
+ * @param[in] in  Base64 encoded message
+ * @param[in] inLen  Byte lenth of 'in'
+ * @param[in, out] outBuf  Output buffer
+ *                 Base64 decoded message will be written into 'outBuf'
+ * @param[in] outBufSize Size of output buffer
+ * @param[out] outLen  Byte length of decoded message
+ *
+ * @return  B64_OK for Success, otherwise some error value
+ */
+B64Result b64Decode(const char* in, const size_t inLen,
+               uint8_t* outBuf, size_t outBufSize, uint32_t *outLen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  //IOTVT_B64_H
diff --git a/resource/csdk/security/include/internal/aclresource.h b/resource/csdk/security/include/internal/aclresource.h
new file mode 100755 (executable)
index 0000000..ce9fa60
--- /dev/null
@@ -0,0 +1,71 @@
+//******************************************************************
+//
+// 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_ACLR_H
+#define IOTVT_SRM_ACLR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Initialize ACL resource by loading data from persistent storage.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitACLResource();
+
+/**
+ * Perform cleanup for ACL resources.
+ *
+ * @retval  none
+ */
+void DeInitACLResource();
+
+/**
+ * This method is used by PolicyEngine to retrieve ACL for a Subject.
+ *
+ * @param subjectId ID of the subject for which ACL is required.
+ * @param savePtr is used internally by @ref GetACLResourceData to maintain index between
+ *                successive calls for same subjectId.
+ *
+ * @retval  reference to @ref OicSecAcl_t if ACL is found, else NULL
+ *
+ * @note On the first call to @ref GetACLResourceData, savePtr should point to NULL
+ */
+const OicSecAcl_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAcl_t **savePtr);
+
+/**
+ * This function converts ACL data into JSON format.
+ * Caller needs to invoke 'free' when done using
+ * returned string.
+ * @param acl  instance of OicSecAcl_t structure.
+ *
+ * @retval  pointer to ACL in json format.
+ */
+char* BinToAclJSON(const OicSecAcl_t * acl);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //IOTVT_SRM_ACLR_H
+
+
diff --git a/resource/csdk/security/include/internal/credresource.h b/resource/csdk/security/include/internal/credresource.h
new file mode 100644 (file)
index 0000000..9ae31bd
--- /dev/null
@@ -0,0 +1,133 @@
+//******************************************************************
+//
+// 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_CREDR_H
+#define IOTVT_SRM_CREDR_H
+
+#include "ocsecurityconfig.h"
+#include "cainterface.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Initialize credential resource by loading data from persistent storage.
+ *
+ * @retval
+ *     OC_STACK_OK    - no errors
+ *     OC_STACK_ERROR - stack process error
+ */
+OCStackResult InitCredResource();
+
+/**
+ * Perform cleanup for credential resources.
+ *
+ * @retval
+ *     OC_STACK_OK              - no errors
+ *     OC_STACK_ERROR           - stack process error
+ *     OC_STACK_NO_RESOURCE     - resource not found
+ *     OC_STACK_INVALID_PARAM   - invalid param
+ */
+OCStackResult DeInitCredResource();
+
+/**
+ * This method is used by tinydtls/SRM to retrieve credential for given Subject.
+ *
+ * @param subject - subject for which credential is required.
+ *
+ * @retval
+ *     reference to OicSecCred_t - if credential is found
+ *     NULL                      - if credential not found
+ */
+const OicSecCred_t* GetCredResourceData(const OicUuid_t* subjectId);
+
+/**
+ * This function converts credential data into JSON format.
+ * Caller needs to invoke 'free' when done using
+ * returned string.
+ * @param cred  pointer to instance of OicSecCred_t structure.
+ *
+ * @retval
+ *      pointer to JSON credential representation - if credential for subjectId found
+ *      NULL                                      - if credential for subjectId not found
+ */
+char* BinToCredJSON(const OicSecCred_t* cred);
+
+/**
+ * This function generates the bin credential data.
+ *
+ * @param subject pointer to subject of this credential.
+ * @param credType credential type.
+ * @param publicData public data such as public key.
+ * @param privateData private data such as private key.
+ * @param ownersLen length of owners array
+ * @param owners array of owners.
+ *
+ * @retval
+ *      pointer to instance of OicSecCred_t  - success
+ *      NULL                                 - error
+ */
+OicSecCred_t * GenerateCredential(const OicUuid_t* subject, OicSecCredType_t credType,
+                     const char * publicData, const char * privateData, size_t ownersLen,
+                     const OicUuid_t * owners);
+
+/**
+ * This function adds the new cred to the credential list.
+ *
+ * @param cred pointer to new credential.
+ *
+ * @retval
+ *      OC_STACK_OK     - cred not NULL and persistent storage gets updated
+ *      OC_STACK_ERROR  - cred is NULL or fails to update persistent storage
+ */
+OCStackResult AddCredential(OicSecCred_t * cred);
+
+#if defined(__WITH_DTLS__)
+/**
+ * This internal callback is used by lower stack (i.e. CA layer) to
+ * retrieve PSK credentials from RI security layer.
+ *
+ * Note: When finished, caller should initialize memory to zeroes and
+ * invoke OCFree to delete @p credInfo.
+ *
+ * @param credInfo
+ *     binary blob containing PSK credentials
+ *
+ * @retval none
+ */
+void GetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo);
+#endif /* __WITH_DTLS__ */
+
+/**
+ * Function to deallocate allocated memory to OicSecCred_t
+ *
+ * @param cred pointer to cred type
+ *
+ */
+void DeleteCredList(OicSecCred_t* cred);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //IOTVT_SRM_CREDR_H
+
+
diff --git a/resource/csdk/security/include/internal/doxmresource.h b/resource/csdk/security/include/internal/doxmresource.h
new file mode 100644 (file)
index 0000000..cd8477e
--- /dev/null
@@ -0,0 +1,102 @@
+//******************************************************************
+//
+// 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_DOXM_H
+#define IOTVT_SRM_DOXM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Initialize DOXM resource by loading data from persistent storage.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitDoxmResource();
+
+/**
+ * Perform cleanup for DOXM resources.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult DeInitDoxmResource();
+
+/**
+ * This method is used by SRM to retrieve DOXM resource data..
+ *
+ * @retval  reference to @ref OicSecDoxm_t, binary format of Doxm resource data
+ */
+const OicSecDoxm_t* GetDoxmResourceData();
+
+/**
+ * This method converts JSON DOXM into binary DOXM.
+ * The JSON DOXM can be from persistent database or
+ * or received as PUT/POST request.
+ *
+ * @param[in] jsonStr  doxm data in json string.
+ * @return pointer to OicSecDoxm_t.
+ *
+ * @note Caller needs to invoke OCFree after done
+ *       using the return pointer
+ */
+OicSecDoxm_t * JSONToDoxmBin(const char * jsonStr);
+
+/**
+ * This method converts DOXM data into JSON format.
+ * Caller needs to invoke 'free' when finished done using
+ * return string
+ *
+ * @param[in] doxm  Pointer to OicSecDoxm_t.
+ * @return pointer to json string.
+ *
+ * @note Caller needs to invoke OCFree after done
+ *       using the return pointer
+ */
+char * BinToDoxmJSON(const OicSecDoxm_t * doxm);
+
+/**
+ * This method returns the SRM device ID for this device.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult GetDoxmDeviceID(OicUuid_t *deviceID);
+
+/**
+ * @brief Gets the OicUuid_t value for the owner of this device.
+ *
+ * @return OC_STACK_OK if devOwner is a valid UUID, otherwise OC_STACK_ERROR.
+ */
+OCStackResult GetDoxmDevOwnerId(OicUuid_t *devOwner);
+
+/** This function deallocates the memory for OicSecDoxm_t .
+ *
+ * @param[in] doxm  Pointer to OicSecDoxm_t.
+ */
+void DeleteDoxmBinData(OicSecDoxm_t* doxm);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //IOTVT_SRM_DOXMR_H
+
+
diff --git a/resource/csdk/security/include/internal/policyengine.h b/resource/csdk/security/include/internal/policyengine.h
new file mode 100644 (file)
index 0000000..a792bfa
--- /dev/null
@@ -0,0 +1,88 @@
+//******************************************************************
+//
+// 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_PE_H
+#define IOTVT_SRM_PE_H
+
+#include "ocstack.h"
+#include "logger.h"
+#include "securevirtualresourcetypes.h"
+#include "cainterface.h"
+#include <stdlib.h>
+#include <stdint.h>
+
+
+typedef enum PEState
+{
+    STOPPED = 0,
+    AWAITING_REQUEST,
+    BUSY
+} PEState_t;
+
+typedef struct PEContext
+{
+    PEState_t   state;
+    OicUuid_t   *subject;
+    char        *resource;
+    uint16_t    permission;
+    bool        matchingAclFound;
+    SRMAccessResponse_t retVal;
+} PEContext_t;
+
+/**
+ * Check whether a request should be allowed.
+ *
+ * @param   context     Pointer to Policy Engine context to use.
+ * @param   subjectId   Pointer to Id of the requesting entity.
+ * @param   resource    Pointer to URI of Resource being requested.
+ * @param   permission  Requested permission.
+ *
+ * @return  ACCESS_GRANTED if request should go through,
+ *          otherwise some flavor of ACCESS_DENIED
+ */
+SRMAccessResponse_t CheckPermission(
+    PEContext_t     *context,
+    const OicUuid_t *subjectId,
+    const char      *resource,
+    const uint16_t  requestedPermission);
+
+/**
+ * Initialize the Policy Engine. Call this before calling CheckPermission().
+ * TODO Eventually this and DeInit() need to be called from a new
+ *      "SRMInit(SRMContext_t *)" function, TBD after BeachHead.
+ * @param   context     Pointer to Policy Engine context to initialize.
+ * @return  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitPolicyEngine(PEContext_t *context);
+
+/**
+ * De-Initialize the Policy Engine. Call this before exiting to allow Policy
+ * Engine to do cleanup on context.
+ * @param   context     Pointer to Policy Engine context to de-initialize.
+ * @return  none
+ */
+void DeInitPolicyEngine(PEContext_t *context);
+
+/**
+ * Return the uint16_t CRUDN permission corresponding to passed CAMethod_t.
+ */
+uint16_t GetPermissionFromCAMethod_t(const CAMethod_t method);
+
+#endif //IOTVT_SRM_PE_H
@@ -1,6 +1,6 @@
 //******************************************************************
 //
-// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 //
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-#ifndef OC_SECURITY_INTERNAL_H
-#define OC_SECURITY_INTERNAL_H
-
-#include "ocsecurityconfig.h"
+#ifndef IOTVT_SRM_PSI_H
+#define IOTVT_SRM_PSI_H
 
 /**
- * This callback is used by lower stack (i.e. CA layer) to retrieve PSK
- * credentials from RI security layer.
- *
- * Note: When finished, caller should initialize memory to zeroes and
- * invoke OCFree to delete @p credInfo.
+ * Reads the Secure Virtual Database from PS into dynamically allocated
+ * memory buffer.
  *
- * @param credInfo
- *     binary blob containing PSK credentials
+ * @note Caller of this method MUST use OCFree() method to release memory
+ *       referenced by return value.
  *
- * @retval none
+ * @retval  reference to memory buffer containing SVR database.
  */
-#ifdef __WITH_DTLS__
-void GetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo);
-#endif //__WITH_DTLS__
-
+char * GetSVRDatabase();
 
 /**
- * This internal API removes/clears the global variable holding the security
- * config data. This needs to be invoked when OIC stack is shutting down.
+ * This method is used by a entity handlers of SVR's to update
+ * SVR database.
  *
- * @retval none
+ * @param rsrcName string denoting the SVR name ("acl", "cred", "pstat" etc).
+ * @param jsonObj JSON object containing the SVR contents.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
  */
-void DeinitOCSecurityInfo();
-
-#endif //OC_SECURITY_INTERNAL_H
+OCStackResult UpdateSVRDatabase(const char* rsrcName, cJSON* jsonObj);
 
+#endif //IOTVT_SRM_PSI_H
diff --git a/resource/csdk/security/include/internal/pstatresource.h b/resource/csdk/security/include/internal/pstatresource.h
new file mode 100644 (file)
index 0000000..40c41ab
--- /dev/null
@@ -0,0 +1,71 @@
+//******************************************************************
+//
+// 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_PSTATR_H
+#define IOTVT_SRM_PSTATR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Initialize Pstat resource by loading data from persistent storage.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitPstatResource();
+
+/**
+ * Perform cleanup for Pstat resources.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult DeInitPstatResource();
+
+/**
+ * This method converts JSON PSTAT into binary PSTAT.
+ *
+ * @param[in] jsonStr  pstat data in json string.
+ * @return pointer to OicSecPstat_t.
+ */
+OicSecPstat_t * JSONToPstatBin(const char * jsonStr);
+
+/**
+ * This method converts pstat data into JSON format.
+ *
+ * @param[in] pstat  pstat data in binary format.
+ * @return pointer to pstat json string.
+ */
+char * BinToPstatJSON(const OicSecPstat_t * pstat);
+
+/** This function deallocates the memory for OicSecPstat_t.
+ *
+ * @param[in] pstat  Pointer to OicSecPstat_t.
+ */
+void DeletePstatBinData(OicSecPstat_t* pstat);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //IOTVT_SRM_PSTATR_H
+
+
diff --git a/resource/csdk/security/include/internal/resourcemanager.h b/resource/csdk/security/include/internal/resourcemanager.h
new file mode 100644 (file)
index 0000000..3e946f5
--- /dev/null
@@ -0,0 +1,56 @@
+//******************************************************************
+//
+// 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_RM_H
+#define IOTVT_SRM_RM_H
+
+#include <stdlib.h>
+#include "ocstack.h"
+#include "securevirtualresourcetypes.h"
+
+/**
+ * Initialize all secure resources ( /oic/sec/cred, /oic/sec/acl, /oic/sec/pstat etc).
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitSecureResources();
+
+/**
+ * Perform cleanup for secure resources ( /oic/sec/cred, /oic/sec/acl, /oic/sec/pstat etc).
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult DestroySecureResources();
+
+/**
+ * This method is used by all secure resource modules to send responses to REST queries.
+ *
+ * @param ehRequest pointer to entity handler request data structure.
+ * @param ehRet result code from entity handler.
+ * @param rspPayload response payload in JSON.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult SendSRMResponse(const OCEntityHandlerRequest *ehRequest,
+        OCEntityHandlerResult ehRet, const char *rspPayload);
+
+#endif //IOTVT_SRM_RM_H
+
+
diff --git a/resource/csdk/security/include/internal/secureresourcemanager.h b/resource/csdk/security/include/internal/secureresourcemanager.h
new file mode 100644 (file)
index 0000000..f07579e
--- /dev/null
@@ -0,0 +1,86 @@
+//******************************************************************
+//
+// 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 SECURITYRESOURCEMANAGER_H_
+#define SECURITYRESOURCEMANAGER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief   Register Persistent storage callback.
+ * @param   persistentStorageHandler [IN] Pointers to open, read, write, close & unlink handlers.
+ * @return
+ *     OC_STACK_OK    - No errors; Success
+ *     OC_STACK_INVALID_PARAM - Invalid parameter
+ */
+OCStackResult SRMRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler);
+
+/**
+ * @brief   Get Persistent storage handler pointer.
+ * @return
+ *     The pointer to Persistent Storage callback handler
+ */
+OCPersistentStorage* SRMGetPersistentStorageHandler();
+
+/**
+ * @brief   Register request and response callbacks.
+ *          Requests and responses are delivered in these callbacks.
+ * @param   reqHandler   [IN] Request handler callback ( for GET,PUT ..etc)
+ * @param   respHandler  [IN] Response handler callback.
+ * @param   errHandler   [IN] Error handler callback.
+ * @return
+ *     OC_STACK_OK    - No errors; Success
+ *     OC_STACK_INVALID_PARAM - Invalid parameter
+ */
+OCStackResult SRMRegisterHandler(CARequestCallback reqHandler,
+                                 CAResponseCallback respHandler,
+                                 CAErrorCallback errHandler);
+
+/**
+ * @brief   Initialize all secure resources ( /oic/sec/cred, /oic/sec/acl, /oic/sec/pstat etc).
+ * @return  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult SRMInitSecureResources();
+
+/**
+ * @brief   Perform cleanup for secure resources ( /oic/sec/cred, /oic/sec/acl, /oic/sec/pstat etc).
+ * @return  none
+ */
+void SRMDeInitSecureResources();
+
+/**
+ * @brief   Initialize Policy Engine context.
+ * @return  OC_STACK_OK for Success, otherwise some error value.
+ */
+OCStackResult SRMInitPolicyEngine();
+
+/**
+ * @brief   Cleanup Policy Engine context.
+ * @return  none
+ */
+void SRMDeInitPolicyEngine();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SECURITYRESOURCEMANAGER_H_ */
diff --git a/resource/csdk/security/include/internal/srmresourcestrings.h b/resource/csdk/security/include/internal/srmresourcestrings.h
new file mode 100644 (file)
index 0000000..51f3720
--- /dev/null
@@ -0,0 +1,91 @@
+//******************************************************************
+//
+// 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_RSRC_STRINGS_H
+#define IOTVT_SRM_RSRC_STRINGS_H
+
+#include "securevirtualresourcetypes.h"
+
+extern const char * SVR_DB_FILE_NAME;
+extern const char * OIC_MI_DEF;
+
+extern const char * OIC_RSRC_CORE_URI;
+extern const char * OIC_RSRC_CORE_D_URI;
+extern const char * OIC_RSRC_CORE_P_URI;
+extern const char * OIC_RSRC_PRESENCE_URI;
+extern const char * OIC_RSRC_TYPES_D_URI;
+
+//ACL
+extern const char * OIC_RSRC_TYPE_SEC_ACL;
+extern const char * OIC_RSRC_ACL_URI;
+extern const char * OIC_JSON_ACL_NAME;
+
+//PSTAT
+extern const char * OIC_RSRC_TYPE_SEC_PSTAT;
+extern const char * OIC_RSRC_PSTAT_URI;
+extern const char * OIC_JSON_PSTAT_NAME;
+
+
+//DOXM
+extern const char * OIC_RSRC_TYPE_SEC_DOXM;
+extern const char * OIC_RSRC_DOXM_URI;
+extern const char * OIC_JSON_DOXM_NAME;
+
+//cred
+extern const char * OIC_RSRC_TYPE_SEC_CRED;
+extern const char * OIC_RSRC_CRED_URI;
+extern const char * OIC_JSON_CRED_NAME;
+
+extern const char * OIC_JSON_SUBJECT_NAME;
+extern const char * OIC_JSON_RESOURCES_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_OWNED_NAME;
+extern const char * OIC_JSON_OXM_NAME;
+extern const char * OIC_JSON_OXM_TYPE_NAME;
+extern const char * OIC_JSON_OXM_SEL_NAME;
+extern const char * OIC_JSON_DEVICE_ID_FORMAT_NAME;
+extern const char * OIC_JSON_CREDID_NAME;
+extern const char * OIC_JSON_ROLEIDS_NAME;
+extern const char * OIC_JSON_CREDTYPE_NAME;
+extern const char * OIC_JSON_PUBLICDATA_NAME;
+extern const char * OIC_JSON_PRIVATEDATA_NAME;
+extern const char * OIC_JSON_PERIOD_NAME;
+extern const char * OIC_JSON_ISOP_NAME;
+extern const char * OIC_JSON_COMMIT_HASH_NAME;
+extern const char * OIC_JSON_DEVICE_ID_NAME;
+extern const char * OIC_JSON_CM_NAME;
+extern const char * OIC_JSON_TM_NAME;
+extern const char * OIC_JSON_OM_NAME;
+extern const char * OIC_JSON_SM_NAME;
+
+extern 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;
+
+#endif //IOTVT_SRM_RSRC_STRINGS_H
+
diff --git a/resource/csdk/security/include/ocsecurityconfig.h b/resource/csdk/security/include/ocsecurityconfig.h
deleted file mode 100644 (file)
index fa5d164..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-//******************************************************************
-//
-// Copyright 2014 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 OC_SECURITY_CONFIG_H
-#define OC_SECURITY_CONFIG_H
-
-#include <stdint.h>
-
-#define DTLS_PSK_ID_LEN 16
-#define DTLS_PSK_PSK_LEN 16
-
-#define OCSecConfigVer_1 1 /**< Initial version supporting PSK Credentials */
-#define OCSecConfigVer_CurrentVersion OCSecConfigVer_1
-
-typedef enum{
-    OC_BLOB_TYPE_PSK = 1,   /**< Security blob holding PSK data */
-} OCBlobType;
-
-
-/**
- * Credentials of a peer device. Includes identity and the associated PSK.
- */
-typedef struct
-{
-    unsigned char id[DTLS_PSK_ID_LEN];      /**< identity of the peer device */
-    unsigned char psk[DTLS_PSK_PSK_LEN];    /**< psk of the peer device */
-} OCDtlsPskCreds;
-
-
-/**
- * Binary blob containing device identity and the credentials for all devices
- * trusted by this device.
- */
-typedef struct
-{
-    unsigned char identity[DTLS_PSK_ID_LEN]; /**< identity of self */
-    uint32_t num;                            /**< number of credentials in this blob */
-    OCDtlsPskCreds creds[1];                 /**< list of credentials. Size of this
-                                                 array is determined by 'num' variable. */
-} OCDtlsPskCredsBlob;
-
-
-/**
- * Generic definition of a security blob. A security blob can contain
- * info of various types, such as : PSK info, certificates,
- * access control lists(ACL) etc.
- */
-typedef struct
-{
-    uint16_t  type;     /**< Type of blob */
-    uint16_t  len;   /**< length of blob data */
-    uint8_t   val[1];   /**< A variable size array holding blob data */
-} OCSecBlob;
-
-
-/**
- * This structure defines the security related configuration data for
- * Iotivity applications.
- */
-typedef struct
-{
-   uint16_t    version;  /**< version of the config data */
-   uint16_t    numBlob;  /**< number of security blobs in this config data */
-   uint8_t     blob[1];  /**< A variable size array holding a blob */
-} OCSecConfigData;
-
-/**
- * Interprets @p blob as pointer to a OCSecBlob and advances to
- * the next blob in the OCSecConfigData
- */
-#define config_data_next_blob(blob) \
-            ((OCSecBlob*)((blob)->val + (blob)->len));
-
-/**
- * Configuration data for security will be stored in below fashion in a
- * flat file on persistent storage.
- *
- *  --------------------------------------------------------------
- *  | OCSecConfigData| OCSecBlob #1 | OCSecBlob #2 | OCSecBlob #3|
- *  --------------------------------------------------------------
- */
-
-#endif //OC_SECURITY_CONFIG_H
-
-
-
diff --git a/resource/csdk/security/include/securevirtualresourcetypes.h b/resource/csdk/security/include/securevirtualresourcetypes.h
new file mode 100644 (file)
index 0000000..6df713b
--- /dev/null
@@ -0,0 +1,418 @@
+//******************************************************************
+//
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/**
+ * Data type definitions for all oic.sec.* types defined in the
+ * OIC Security Specification.
+ *
+ * Note that throughout, ptrs are used rather than arrays.  There
+ * are two primary reasons for this:
+ * 1) The Spec defines many structures with optional fields, so pre-
+ *    allocating these would be wasteful.
+ * 2) There are in many cases arrays of Strings or arrays of Structs,
+ *    which could not be defined as variable length arrays (e.g. array[])
+ *    without breaking from the structure order and definition in the Spec.
+ *
+ * The primary drawback to this decision is that marshalling functions
+ * will have to be written by hand to marshal these structures (e.g. to/from
+ * Persistent Storage, or across memory boundaries).
+ *
+ * TODO reconcile against latest OIC Security Spec to ensure all fields correct.
+ * (Last checked against v0.95)
+ */
+
+#ifndef OC_SECURITY_RESOURCE_TYPES_H
+#define OC_SECURITY_RESOURCE_TYPES_H
+
+#include <stdint.h> // for uint8_t typedef
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief   Values used to create bit-maskable enums for single-value
+ *          response with embedded code.
+ */
+#define ACCESS_GRANTED_DEF            (1 << 0)
+#define ACCESS_DENIED_DEF             (1 << 1)
+#define INSUFFICIENT_PERMISSION_DEF   (1 << 2)
+#define SUBJECT_NOT_FOUND_DEF         (1 << 3)
+#define RESOURCE_NOT_FOUND_DEF        (1 << 4)
+#define POLICY_ENGINE_ERROR_DEF       (1 << 5)
+#define REASON_MASK_DEF               (INSUFFICIENT_PERMISSION_DEF | \
+                                       SUBJECT_NOT_FOUND_DEF | \
+                                       RESOURCE_NOT_FOUND_DEF | \
+                                       POLICY_ENGINE_ERROR_DEF)
+
+
+/**
+ * Access policy in least significant bits (from Spec):
+ * 1st lsb:  C (Create)
+ * 2nd lsb:  R (Read, Observe, Discover)
+ * 3rd lsb:  U (Write, Update)
+ * 4th lsb:  D (Delete)
+ * 5th lsb:  N (Notify)
+ */
+#define PERMISSION_CREATE       (1 << 0)
+#define PERMISSION_READ         (1 << 1)
+#define PERMISSION_WRITE        (1 << 2)
+#define PERMISSION_DELETE       (1 << 3)
+#define PERMISSION_NOTIFY       (1 << 4)
+#define PERMISSION_FULL_CONTROL (PERMISSION_CREATE | \
+                                 PERMISSION_READ | \
+                                 PERMISSION_WRITE | \
+                                 PERMISSION_DELETE | \
+                                 PERMISSION_NOTIFY)
+
+/**
+ * @brief   Response type for all Action requests from CA layer;
+ *          may include a reason code.
+ *
+ * To extract codes use GetReasonCode function on SRMAccessResponse:
+ *
+ * SRMAccessResponse_t response = SRMRequestHandler(obj, info);
+ * if(SRM_TRUE == IsAccessGranted(response)) {
+ *     SRMAccessResponseReasonCode_t reason = GetReasonCode(response);
+ *     switch(reason) {
+ *         case INSUFFICIENT_PERMISSION:
+ *         ...etc.
+ *     }
+ * }
+ */
+typedef enum
+{
+    ACCESS_GRANTED = ACCESS_GRANTED_DEF,
+    ACCESS_DENIED = ACCESS_DENIED_DEF,
+    ACCESS_DENIED_INSUFFICIENT_PERMISSION = ACCESS_DENIED_DEF
+        | INSUFFICIENT_PERMISSION_DEF,
+    ACCESS_DENIED_SUBJECT_NOT_FOUND = ACCESS_DENIED_DEF
+        | SUBJECT_NOT_FOUND_DEF,
+    ACCESS_DENIED_RESOURCE_NOT_FOUND = ACCESS_DENIED_DEF
+        | RESOURCE_NOT_FOUND_DEF,
+    ACCESS_DENIED_POLICY_ENGINE_ERROR = ACCESS_DENIED_DEF
+        | POLICY_ENGINE_ERROR_DEF,
+} SRMAccessResponse_t;
+
+/**
+ * Reason code for SRMAccessResponse.
+ */
+typedef enum
+{
+    NO_REASON_GIVEN = 0,
+    INSUFFICIENT_PERMISSION = INSUFFICIENT_PERMISSION_DEF,
+    SUBJECT_NOT_FOUND = SUBJECT_NOT_FOUND_DEF,
+    RESOURCE_NOT_FOUND = RESOURCE_NOT_FOUND_DEF,
+} SRMAccessResponseReasonCode_t;
+
+/**
+ * Extract Reason Code from Access Response.
+ */
+static inline SRMAccessResponseReasonCode_t GetReasonCode(
+    SRMAccessResponse_t response)
+{
+    SRMAccessResponseReasonCode_t reason =
+        (SRMAccessResponseReasonCode_t)(response & REASON_MASK_DEF);
+    return reason;
+}
+
+/**
+ * Returns 'true' iff request should be passed on to RI layer.
+ */
+static inline bool IsAccessGranted(SRMAccessResponse_t response)
+{
+    if(ACCESS_GRANTED == (response & ACCESS_GRANTED))
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+typedef struct OicSecAcl OicSecAcl_t;
+
+typedef struct OicSecAmacl OicSecAmacl_t;
+
+typedef struct OicSecCred OicSecCred_t;
+
+/**
+ * @brief   /oic/sec/credtype (Credential Type) data type.
+ *          Derived from OIC Security Spec /oic/sec/cred; see Spec for details.
+ *              0:  no security mode
+ *              1:  symmetric pair-wise key
+ *              2:  symmetric group key
+ *              4:  asymmetric key
+ *              8:  signed asymmetric key (aka certificate)
+ *              16: PIN /password
+ */
+typedef uint16_t OicSecCredType_t;
+
+/**
+ * Aid for assigning/testing vals with OicSecCredType_t.
+ * Example:
+ *  OicSecCredType_t ct = PIN_PASSWORD | ASYMMETRIC_KEY;
+ *  if((ct & PIN_PASSWORD) == PIN_PASSWORD)
+ *  {
+ *      // ct contains PIN_PASSWORD flag.
+ *  }
+ */
+typedef enum OSCTBitmask
+{
+    NO_SECURITY_MODE                = 0x0,
+    SYMMETRIC_PAIR_WISE_KEY         = (0x1 << 0),
+    SYMMETRIC_GROUP_KEY             = (0x1 << 1),
+    ASYMMETRIC_KEY                  = (0x1 << 2),
+    SIGNED_ASYMMETRIC_KEY           = (0x1 << 3),
+    PIN_PASSWORD                    = (0x1 << 4),
+} OSCTBitmask_t;
+
+typedef struct OicSecDoxm OicSecDoxm_t;
+
+typedef enum OicSecDpm
+{
+    NORMAL                          = 0x0,
+    RESET                           = (0x1 << 0),
+    TAKE_OWNER                      = (0x1 << 1),
+    BOOTSTRAP_SERVICE               = (0x1 << 2),
+    SECURITY_MANAGEMENT_SERVICES    = (0x1 << 3),
+    PROVISION_CREDENTIALS           = (0x1 << 4),
+    PROVISION_ACLS                  = (0x1 << 5),
+    // << 6 THROUGH 15 RESERVED
+} OicSecDpm_t;
+
+typedef enum OicSecDpom
+{
+    MULTIPLE_SERVICE_SERVER_DRIVEN  = 0x0,
+    SINGLE_SERVICE_SERVER_DRIVEN    = 0x1,
+    MULTIPLE_SERVICE_CLIENT_DRIVEN  = 0x2,
+    SINGLE_SERVICE_CLIENT_DRIVEN    = 0x3,
+} OicSecDpom_t;
+
+//TODO: Need more clarification on deviceIDFormat field type.
+#if 0
+typedef enum
+{
+    URN = 0x0
+}OicSecDvcIdFrmt_t;
+#endif
+
+typedef enum
+{
+    OIC_JUST_WORKS                          = 0x0,
+    OIC_MODE_SWITCH                         = 0x1,
+    OIC_RANDOM_DEVICE_PIN                   = 0x2,
+    OIC_PRE_PROVISIONED_DEVICE_PIN          = 0x3,
+    OIC_PRE_PROVISION_STRONG_CREDENTIAL     = 0x4
+}OicSecOxm_t;
+
+typedef struct OicSecJwk OicSecJwk_t;
+
+typedef struct OicSecPstat OicSecPstat_t;
+
+typedef struct OicSecRole OicSecRole_t;
+
+typedef struct OicSecSacl OicSecSacl_t;
+
+typedef struct OicSecSvc OicSecSvc_t;
+
+typedef char *OicUrn_t; //TODO is URN type defined elsewhere?
+
+typedef struct OicUuid OicUuid_t; //TODO is UUID type defined elsewhere?
+
+
+/**
+ * @brief   /oic/uuid (Universal Unique Identifier) data type.
+ */
+#define UUID_LENGTH 128/8 // 128-bit GUID length
+//TODO: Confirm the length and type of ROLEID.
+#define ROLEID_LENGTH 128/8 // 128-bit ROLEID length
+#define OWNER_PSK_LENGTH_128 128/8 //byte size of 128-bit key size
+#define OWNER_PSK_LENGTH_256 256/8 //byte size of 256-bit key size
+
+struct OicUuid
+{
+    // <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
+    //TODO fill in unless this is defined elsewhere?
+    uint8_t             id[UUID_LENGTH];
+};
+
+/**
+ * @brief   /oic/sec/jwk (JSON Web Key) data type.
+ *          See JSON Web Key (JWK)  draft-ietf-jose-json-web-key-41
+ */
+#define JWK_LENGTH 256/8 // 256 bit key length
+struct OicSecJwk
+{
+    char                *data;
+};
+
+/**
+ * @brief   /oic/sec/acl (Access Control List) data type.
+ *          Derived from OIC Security Spec; see Spec for details.
+ */
+struct OicSecAcl
+{
+    // <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
+    OicUuid_t           subject;        // 0:R:S:Y:uuid TODO: this deviates
+                                        // from spec and needs to be updated
+                                        // in spec (where it's a String).
+    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              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
+    // SRM version only; this will change to Svc type for full implementation.
+    //TODO change Owners type to oic.sec.svc
+    //OicSecSvc_t         *Owners;        // 6:R:M:Y:oic.sec.svc
+    OicSecAcl_t         *next;
+};
+
+/**
+ * @brief   /oic/sec/amacl (Access Manager Service Accesss Control List)
+ *          data type.
+ *          Derived from OIC Security Spec; see Spec for details.
+ */
+struct OicSecAmacl
+{
+    // <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
+    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
+    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
+};
+
+/**
+ * @brief   /oic/sec/cred (Credential) data type.
+ *          Derived from OIC Security Spec; see Spec for details.
+ */
+struct OicSecCred
+{
+    // <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
+    uint16_t            credId;         // 0:R:S:Y:UINT16
+    OicUuid_t           subject;        // 1:R:S:Y:oic.uuid
+    //Note: Need further clarification on roleID data type
+    //NOTE: Need further clarification on roleId datatype.
+    //size_t              roleIdsLen;     // the number of elts in RoleIds
+    //OicSecRole_t        *roleIds;       // 2:R:M:N:oic.sec.role
+    OicSecCredType_t    credType;       // 3:R:S:Y:oic.sec.credtype
+    OicSecJwk_t         publicData;     // 5:R:S:N:oic.sec.jwk
+    OicSecJwk_t         privateData;    // 6:R:S:N:oic.sec.jwk
+    char                *period;        // 7:R:S: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
+    // SRM version only; this will change to Svc type for full implementation.
+    //OicSecSvc_t         *Owners;        // 8:R:M:Y:oic.sec.svc
+    //TODO change Owners type to oic.sec.svc
+    OicSecCred_t        *next;
+};
+
+/**
+ * @brief   /oic/sec/doxm (Device Owner Transfer Methods) data type
+ *          Derived from OIC Security Spec; see Spec for details.
+ */
+struct OicSecDoxm
+{
+    // <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
+    OicUrn_t            *oxmType;       // 0:R:M:N:URN
+    size_t              oxmTypeLen;     // the number of elts in OxmType
+    OicSecOxm_t         *oxm;           // 1:R:M:N:UINT16
+    size_t              oxmLen;         // the number of elts in Oxm
+    OicSecOxm_t         oxmSel;         // 2:R/W:S:Y:UINT16
+    bool                owned;          // 3:R:S:Y:Boolean
+    //TODO: Need more clarification on deviceIDFormat field type.
+    //OicSecDvcIdFrmt_t   deviceIDFormat; // 4:R:S:Y:UINT8
+    OicUuid_t           deviceID;       // 5:R:S:Y:oic.uuid
+    OicUuid_t           owner;         // 6:R:S:Y:oic.uuid
+    // NOTE: we are using UUID for Owner instead of Svc type for mid-April
+    // SRM version only; this will change to Svc type for full implementation.
+    //OicSecSvc_t       Owner;        // 5:R:S:Y:oic.sec.svc
+    //TODO change Owner type to oic.sec.svc
+};
+
+/**
+ * @brief   /oic/sec/pstat (Provisioning Status) data type.
+ * NOTE: this struct is ahead of Spec v0.95 in definition to include Sm.
+ * TODO: change comment when reconciled to Spec v0.96.
+ */
+struct OicSecPstat
+{
+    // <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
+    bool                isOp;           // 0:R:S:Y:Boolean
+    OicSecDpm_t         cm;             // 1:R:S:Y:oic.sec.dpm
+    OicSecDpm_t         tm;             // 2:RW:S:Y:oic.sec.dpm
+    OicUuid_t           deviceID;       // 3:R:S:Y:oic.uuid
+    OicSecDpom_t        om;             // 4:RW:M:Y:oic.sec.dpom
+    size_t              smLen;          // the number of elts in Sm
+    OicSecDpom_t        *sm;            // 5:R:M:Y:oic.sec.dpom
+    uint16_t            commitHash;     // 6:R:S:Y:oic.sec.sha256
+    //TODO: this is supposed to be a 256-bit uint; temporarily use uint16_t
+    //TODO: need to decide which 256 bit and 128 bit types to use... boost?
+};
+
+/**
+ * @brief   /oic/sec/role (Role) data type.
+ *          Derived from OIC Security Spec; see Spec for details.
+ */
+struct OicSecRole
+{
+    // <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
+    //TODO fill in with Role definition
+    uint8_t             id[ROLEID_LENGTH];
+};
+
+/**
+ * @brief   /oic/sec/sacl (Signed Access Control List) data type.
+ *          Derived from OIC Security Spec; see Spec for details.
+ */
+struct OicSecSacl
+{
+    // <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
+    //TODO fill in from OIC Security Spec
+};
+
+/**
+ * @brief   /oic/sec/svc (Service requiring a secure connection) data type.
+ *          Derived from OIC Security Spec; see Spec for details.
+ */
+struct OicSecSvc
+{
+    // <Attribute ID>:<Read/Write>:<Multiple/Single>:<Mandatory?>:<Type>
+    //TODO fill in from OIC Security Spec
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //OC_SECURITY_RESOURCE_TYPES_H
similarity index 50%
rename from resource/csdk/security/include/ocsecurity.h
rename to resource/csdk/security/include/srmutility.h
index 1d1b3e4..34f3237 100644 (file)
@@ -1,6 +1,6 @@
 //******************************************************************
 //
-// Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
+// Copyright 2015 Intel Mobile Communications GmbH All Rights Reserved.
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 //
 //
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
-#ifndef OC_SECURITY_H
-#define OC_SECURITY_H
+#ifndef IOTVT_SRM_UTILITY_H
+#define IOTVT_SRM_UTILITY_H
 
 #include "ocstack.h"
-#include "ocsecurityconfig.h"
-#include <stdio.h>
+#include "uthash.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif // __cplusplus
 
 /**
- * Provides the Security Configuration data to OC stack.
+ * @def VERIFY_SUCCESS
+ * @brief Macro to verify success of operation.
+ * eg: VERIFY_SUCCESS(TAG, OC_STACK_OK == foo(), ERROR);
+ * @note Invoking function must define "exit:" label for goto functionality to work correctly.
  *
- * @param cfgData
- *     binary blob containing config data
- * @param len
- *     length of binary blob
+ */
+#define VERIFY_SUCCESS(tag, op, logLevel) { if (!(op)) \
+            {OC_LOG((logLevel), tag, PCF(#op " failed!!")); goto exit;} }
+
+/**
+ * @def VERIFY_NON_NULL
+ * @brief Macro to verify argument is not equal to NULL.
+ * eg: VERIFY_NON_NULL(TAG, ptrData, ERROR);
+ * @note Invoking function must define "exit:" label for goto functionality to work correctly.
  *
- * @retval OC_STACK_OK for Success, otherwise some error value
  */
-OCStackResult OCSecSetConfigData(const OCSecConfigData *cfgData,
-                size_t len);
+#define VERIFY_NON_NULL(tag, arg, logLevel) { if (NULL == (arg)) \
+            { OC_LOG((logLevel), tag, PCF(#arg " is NULL")); goto exit; } }
+
 
 #ifdef __cplusplus
 }
 #endif // __cplusplus
 
-#endif //OC_SECURITY_H
-
+#endif //IOTVT_SRM_UTILITY_H
diff --git a/resource/csdk/security/provisioning/SConscript b/resource/csdk/security/provisioning/SConscript
new file mode 100644 (file)
index 0000000..dea14c7
--- /dev/null
@@ -0,0 +1,87 @@
+# //******************************************************************
+# //
+# // 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.
+# //
+# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+
+Import('env')
+
+provisioning_env = env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+provisioning_env.AppendUnique(CPPPATH = [
+               '../../stack/include',
+               '../../ocrandom/include',
+               '../../logger/include',
+               '../../../oc_logger/include',
+               '../../ocmalloc/include',
+               'include',
+               'include/internal',
+               '../../resource/csdk/security/include',
+               '../../../../extlibs/cjson/',
+               '../../../../../extlibs/tinydtlsra/',
+               '../../connectivity/inc',
+               '../../connectivity/external/inc',
+               '../../connectivity/common/inc',
+               '../../connectivity/api',
+               '../include',
+               '../include/internal'
+               ])
+target_os = env.get('TARGET_OS')
+provisioning_env.AppendUnique(CFLAGS = ['-D__WITH_DTLS__'])
+provisioning_env.AppendUnique(CFLAGS = ['-std=c99'])
+if target_os not in ['windows', 'winrt']:
+       provisioning_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread', '-D__WITH_DTLS__'])
+
+       # Note: 'pthread' is in libc for android. On other platform, if use
+       # new gcc(>4.9?) it isn't required, otherwise, it's required
+       if target_os != 'android':
+               provisioning_env.AppendUnique(LIBS = ['-lpthread'])
+
+
+provisioning_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+provisioning_env.PrependUnique(LIBS = ['oc', 'octbstack', 'oc_logger', 'connectivity_abstraction', 'coap'])
+
+provisioning_env.AppendUnique(LIBS = ['tinydtls'])
+
+provisioning_env.ParseConfig('pkg-config --libs glib-2.0');
+
+if target_os == 'android':
+       provisioning_env.AppendUnique(CXXFLAGS = ['-frtti', '-fexceptions'])
+       provisioning_env.AppendUnique(LIBS = ['gnustl_static'])
+
+       if not env.get('RELEASE'):
+               provisioning_env.AppendUnique(LIBS = ['log'])
+
+if target_os in ['darwin', 'ios']:
+       provisioning_env.AppendUnique(CPPDEFINES = ['_DARWIN_C_SOURCE'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+provisioning_src = [
+       'src/provisioningmanager.c',
+    'src/credentialgenerator.c'
+       ]
+provisioningserver = provisioning_env.StaticLibrary('ocspapi', provisioning_src)
+
+provisioning_env.InstallTarget(provisioningserver, 'libocspapi')
+
+SConscript('sample/SConscript')
diff --git a/resource/csdk/security/provisioning/include/internal/credentialgenerator.h b/resource/csdk/security/provisioning/include/internal/credentialgenerator.h
new file mode 100644 (file)
index 0000000..259a608
--- /dev/null
@@ -0,0 +1,48 @@
+/* *****************************************************************
+ *
+ * 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_CREDENTIAL_GENERATOR_H
+#define SP_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]  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
+ */
+SPResult SPGeneratePairWiseCredentials(OicSecCredType_t type, const OicUuid_t *ptDeviceId,
+                                       const OicUuid_t *firstDeviceId,
+                                       const OicUuid_t *secondDeviceId,
+                                       OicSecCred_t **firstCred,
+                                       OicSecCred_t **secondCred);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //SP_CREDENTIAL_GENERATOR_H
diff --git a/resource/csdk/security/provisioning/include/provisioningmanager.h b/resource/csdk/security/provisioning/include/provisioningmanager.h
new file mode 100644 (file)
index 0000000..ccf85fa
--- /dev/null
@@ -0,0 +1,174 @@
+/* *****************************************************************
+ *
+ * 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;
+
+/**
+ * Connectivity types.
+ */
+typedef enum
+{
+    SP_IPV4         = (1 << 0),
+    SP_IPV6         = (1 << 1),
+    SP_CONN_EDR     = (1 << 2),
+    SP_CONN_LE      = (1 << 3)
+} SPConnectivityType;
+
+typedef struct SPTargetDeviceInfo SPTargetDeviceInfo_t;
+typedef struct SPDevInfo SPDevInfo_t;
+
+/**
+ * Device Info structure.
+ */
+struct SPTargetDeviceInfo
+{
+    char ip[DEV_ADDR_SIZE_MAX];            /**< IP address in IPv4 dot-decimal notation. **/
+    int port;                              /**< Remote endpoint port. **/
+    SPConnectivityType connType;           /**< Connectivity type. **/
+    OicSecPstat_t *pstat;                  /**< Pointer to target's pstat resource. **/
+    OicSecDoxm_t *doxm;                    /**< Pointer to target's doxm resource. **/
+    SPTargetDeviceInfo_t *next;            /**< Next pointer. **/
+};
+
+/**
+ * Owned target device info
+ */
+struct SPDevInfo
+{
+    OicUuid_t deviceId;                    /**< Device ID. **/
+    char ip[DEV_ADDR_SIZE_MAX];            /**< IP address in IPv4 dot-decimal notation. **/
+    int port;                              /**< Remote endpoint port. **/
+    SPConnectivityType connType;           /**< Connectivity type. **/
+    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
diff --git a/resource/csdk/security/provisioning/sample/SConscript b/resource/csdk/security/provisioning/sample/SConscript
new file mode 100755 (executable)
index 0000000..1152bd9
--- /dev/null
@@ -0,0 +1,75 @@
+# //******************************************************************
+# //
+# // 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.
+# //
+# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+
+Import('env')
+
+provisioning_env = env.Clone()
+
+######################################################################
+# Build flags
+######################################################################
+provisioning_env.AppendUnique(CPPPATH = [
+               '../../../stack/include',
+               '../../../ocrandom/include',
+               '../../../logger/include',
+               '../../../stack/include',
+               '../../../security/include',
+               '../../../../oc_logger/include',
+               '../include',
+               '../../include',
+               '../../../../../extlibs/tinydtls',
+               '../../../../../extlibs/cjson',
+               '../../../../../extlibs/base64',
+               '../../../connectivity/inc',
+               '../../../connectivity/common/inc',
+               '../../../connectivity/lib/libcoap-4.1.1',
+               '../../../connectivity/api'
+               ])
+
+provisioning_env.AppendUnique(CFLAGS = ['-D__WITH_DTLS__','-std=c99'])
+provisioning_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread', '-fpermissive'])
+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'])
+
+if env.get('SECURED') == '1':
+    provisioning_env.AppendUnique(LIBS = ['tinydtls'])
+provisioning_env.ParseConfig('pkg-config --libs glib-2.0');
+
+provisioning_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+
+provisioningclient = provisioning_env.Program('provisioningclient', 'provisioningclient.c')
+
+Alias("sample", [provisioningclient])
+
+provisioning_env.AppendTarget('samples')
+
+src_dir = provisioning_env.get('SRC_DIR')
+sec_provisioning_src_dir = src_dir + '/resource/csdk/security/provisioning/sample/'
+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.json'))
diff --git a/resource/csdk/security/provisioning/sample/oic_svr_db.json b/resource/csdk/security/provisioning/sample/oic_svr_db.json
new file mode 100755 (executable)
index 0000000..8e92810
--- /dev/null
@@ -0,0 +1,43 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/d",
+                "/oic/p",
+                "/oic/res/types/d",
+                "/oic/ad"
+                       ],
+                       "perms": 2,
+                       "ownrs" : ["YWRtaW5EZXZpY2VVVUlE"]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat",
+                "/oic/sec/acl",
+                "/oic/sec/cred"
+             ],
+             "perms": 7,
+             "ownrs" : ["YWRtaW5EZXZpY2VVVUlE"]
+        }
+       ],
+       "pstat":        {
+               "isop": true,
+               "deviceid":     "YWRtaW5EZXZpY2VVVUlE",
+               "commithash": 0,
+               "cm":   0,
+               "tm":   0,
+               "om":   3,
+               "sm":   [3]
+       },
+       "doxm": {
+               "oxm":  [0],
+               "oxmsel": 0,
+               "owned": true,
+               "deviceid":     "YWRtaW5EZXZpY2VVVUlE",
+               "ownr": "YWRtaW5EZXZpY2VVVUlE"
+       }
+}
diff --git a/resource/csdk/security/provisioning/sample/provisioningclient.c b/resource/csdk/security/provisioning/sample/provisioningclient.c
new file mode 100755 (executable)
index 0000000..2284155
--- /dev/null
@@ -0,0 +1,326 @@
+/******************************************************************
+*
+* Copyright 2015 Samsung Electronics All Rights Reserved.
+*
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+******************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+#include "logger.h"
+#include "oic_malloc.h"
+#include "utlist.h"
+#include "securevirtualresourcetypes.h"
+#include "provisioningmanager.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 TAG  "provisioningclient"
+
+static OicSecAcl_t        *gAcl = NULL;
+static char CRED_FILE[] = "oic_svr_db.json";
+
+/**
+ * Perform cleanup for ACL list
+ *
+ * @param[in]    ACL list
+ */
+static void DeleteACLList(OicSecAcl_t *acl)
+{
+    if (acl)
+    {
+        OicSecAcl_t *aclTmp1 = NULL;
+        OicSecAcl_t *aclTmp2 = NULL;
+        LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
+        {
+            LL_DELETE(acl, aclTmp1);
+
+            /* Clean Resources */
+            for (int i = 0; i < aclTmp1->resourcesLen; i++)
+            {
+                OICFree(aclTmp1->resources[i]);
+            }
+            OICFree(aclTmp1->resources);
+
+            /* Clean Owners */
+            OICFree(aclTmp1->owners);
+
+            /* Clean ACL node itself */
+            OICFree(aclTmp1);
+        }
+        acl = NULL;
+    }
+}
+
+/**
+ * Calculate ACL permission from string to bit
+ *
+ * @param[in] temp_psm    Input data of ACL permission string
+ * @param[in,out] pms    The pointer of ACL permission value
+ * @return  0 on success otherwise a positive error value
+ * @retval  SP_RESULT_SUCCESS    Successful
+ * @retval  SP_RESULT_INVALID_PARAM    Invaild input arguments
+ */
+static SPResult CalculateAclPermission(const char *temp_pms, uint16_t *pms)
+{
+    int i = 0;
+
+    if (NULL == temp_pms || NULL == pms)
+    {
+        return SP_RESULT_INVALID_PARAM;
+    }
+    *pms = 0;
+    while (temp_pms[i] != '\0')
+    {
+        switch (temp_pms[i])
+        {
+            case 'C':
+                {
+                    *pms += CREATE;
+                    i++;
+                    break;
+                }
+            case 'R':
+                {
+                    *pms += READ;
+                    i++;
+                    break;
+                }
+            case 'U':
+                {
+                    *pms += UPDATE;
+                    i++;
+                    break;
+                }
+            case 'D':
+                {
+                    *pms += DELETE;
+                    i++;
+                    break;
+                }
+            case 'N':
+                {
+                    *pms += NOTIFY;
+                    i++;
+                    break;
+                }
+            case '_':
+                {
+                    i++;
+                    break;
+                }
+            default:
+                {
+                    return SP_RESULT_INVALID_PARAM;
+                }
+        }
+    }
+    return SP_RESULT_SUCCESS;
+}
+
+/**
+ * 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
+ */
+static SPResult InputACL(OicSecAcl_t *acl)
+{
+    int unused __attribute__((unused));
+    char temp_id [MAX_INPUT_ID_LENGTH + 4] = {0,};
+    char temp_rsc[MAX_URI_LENGTH + 1] = {0,};
+    char temp_pms[MAX_PERMISSION_LENGTH + 1] = {0,};
+    printf("******************************************************************************\n");
+    printf("-Set ACL policy for target device\n");
+    printf("******************************************************************************\n");
+    //Set Subject.
+    printf("-URN identifying the subject\n");
+    printf("ex) 1111-1111-1111-1111 (16 Numbers except to '-')\n");
+    printf("Subject : ");
+    unused = scanf("%19s", temp_id);
+    int j = 0;
+    for (int i = 0; temp_id[i] != '\0'; i++)
+    {
+        if (DASH != temp_id[i])
+            acl->subject.id[j++] = temp_id[i];
+    }
+
+    //Set Resource.
+    printf("Num. of Resource : ");
+    unused = 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 *));
+    if (NULL == acl->resources)
+    {
+        OC_LOG(ERROR, TAG, "Error while memory allocation");
+        return SP_RESULT_MEM_ALLOCATION_FAIL;
+    }
+    for (int 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));
+        if (NULL == acl->resources[i])
+        {
+            OC_LOG(ERROR, TAG, "Error while memory allocation");
+            return SP_RESULT_MEM_ALLOCATION_FAIL;
+        }
+        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);
+    }
+    while (SP_RESULT_SUCCESS != CalculateAclPermission(temp_pms, &(acl->permission)) );
+    // Set Rowner
+    printf("Num. of Rowner : ");
+    unused = 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;
+    }
+    for (int i = 0; i < acl->ownersLen; i++)
+    {
+        printf("[%d]Rowner : ", i + 1);
+        unused = scanf("%19s", temp_id);
+        j = 0;
+        for (int k = 0; temp_id[k] != '\0'; k++)
+        {
+            if (DASH != temp_id[k])
+            {
+                acl->owners[i].id[j++] = temp_id[k];
+            }
+        }
+    }
+    return SP_RESULT_SUCCESS;
+}
+
+FILE* client_fopen(const char *path, const char *mode)
+{
+    (void)path;
+    return fopen(CRED_FILE, mode);
+}
+
+/**
+ * Provisioning client sample using ProvisioningAPI on provisioningmanager.c
+ * To change network type use command line option -w for Wifi and -e for Ethernet
+ */
+int main(int argc, char **argv)
+{
+    SPResult res = SP_RESULT_SUCCESS;
+    SPTargetDeviceInfo_t *pDeviceList = NULL;
+    gAcl = (OicSecAcl_t *)OICMalloc(sizeof(OicSecAcl_t));
+
+    // Initialize Persistent Storage for SVR database
+    OCPersistentStorage ps = {};
+    ps.open = client_fopen;
+    ps.read = fread;
+    ps.write = fwrite;
+    ps.close = fclose;
+    ps.unlink = unlink;
+    OCRegisterPersistentStorageHandler(&ps);
+
+    if (OCInit(NULL, 0, OC_CLIENT_SERVER) != OC_STACK_OK)
+    {
+        OC_LOG(ERROR, TAG, "OCStack init error");
+        return 0;
+    }
+
+    if (NULL == gAcl)
+    {
+        OC_LOG(ERROR, TAG, "Error while memory allocation");
+        return SP_RESULT_MEM_ALLOCATION_FAIL;
+    }
+
+    res = SPProvisioningDiscovery(PREDEFINED_TIMEOUT, &pDeviceList);
+    if (SP_RESULT_SUCCESS == res)
+    {
+        while (pDeviceList != NULL)
+        {
+            printf("-Provisioning device ID : ");
+            for (int i = 0; i < MAX_INPUT_ID_LENGTH; i++)
+            {
+                if (pDeviceList->doxm->deviceID.id[i] == '\0')
+                {
+                     break;
+                }
+                printf("%c", pDeviceList->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;
+        }
+    }
+    else
+    {
+        OC_LOG(ERROR, TAG, "Error while Provisioning Discovery");
+        goto error;
+    }
+
+error:
+    DeleteACLList(gAcl);
+    SPTerminateProvisioning();
+    return 0;
+}
diff --git a/resource/csdk/security/provisioning/src/credentialgenerator.c b/resource/csdk/security/provisioning/src/credentialgenerator.c
new file mode 100644 (file)
index 0000000..8e96518
--- /dev/null
@@ -0,0 +1,76 @@
+/* *****************************************************************
+ *
+ * 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 "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
+
+SPResult SPGeneratePairWiseCredentials(OicSecCredType_t type, const OicUuid_t *ptDeviceId,
+                                       const OicUuid_t *firstDeviceId,
+                                       const OicUuid_t *secondDeviceId,
+                                       OicSecCred_t **firstCred,
+                                       OicSecCred_t **secondCred)
+{
+
+    if (NULL == ptDeviceId || NULL == firstDeviceId || NULL == secondDeviceId)
+    {
+        return SP_RESULT_INVALID_PARAM;
+    }
+    uint8_t privData[KEY_LENGTH] = {0,};
+    OCFillRandomMem(privData, KEY_LENGTH);
+
+    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;
+    }
+
+    // TODO currently owner array is 1. only provisioning tool's id.
+    OicSecCred_t *tempFirstCred =  GenerateCredential(secondDeviceId, type, NULL, base64Buff, 1,
+                                   ptDeviceId);
+    if (NULL == tempFirstCred)
+    {
+        OC_LOG(ERROR, TAG, "Error while generating credential.");
+        return SP_RESULT_INTERNAL_ERROR;
+    }
+    // TODO currently owner array is 1. only provisioning tool's id.
+    OicSecCred_t *tempSecondCred =  GenerateCredential(firstDeviceId, type, NULL, base64Buff, 1,
+                                    ptDeviceId);
+    if (NULL == tempSecondCred)
+    {
+        DeleteCredList(tempFirstCred);
+        OC_LOG(ERROR, TAG, "Error while generating credential.");
+        return SP_RESULT_INTERNAL_ERROR;
+    }
+    *firstCred = tempFirstCred;
+    *secondCred = tempSecondCred;
+    return SP_RESULT_SUCCESS;
+}
diff --git a/resource/csdk/security/provisioning/src/provisioningmanager.c b/resource/csdk/security/provisioning/src/provisioningmanager.c
new file mode 100644 (file)
index 0000000..defe4e6
--- /dev/null
@@ -0,0 +1,1592 @@
+/* *****************************************************************
+ *
+ * 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 "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"
+
+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),
+    SP_PROV_ACL_STARTED       = (0x1 << 16),
+    SP_PROV_ACL_ERROR         = (0x1 << 17),
+    SP_PROV_ACL_DONE          = (0x1 << 18),
+    SP_UP_HASH_STARTED        = (0x1 << 19),
+    SP_UP_HASH_ERROR          = (0x1 << 20),
+    SP_UP_HASH_DONE           = (0x1 << 21),
+    SP_PROV_CRED_STARTED      = (0x1 << 22),
+    SP_PROV_CRED_ERROR        = (0x1 << 23),
+    SP_PROV_CRED_DONE         = (0x1 << 24)
+
+} SPProvisioningStates;
+
+#define SP_MAX_BUF_LEN 1024
+#define TAG "SPProvisionAPI"
+#define COAP_QUERY "coap://%s:%d%s"
+#define COAPS_QUERY "coaps://%s:%d%s"
+#define CA_SECURE_PORT   5684
+
+void (*handler)(const CARemoteEndpoint_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;
+            }
+    }
+}
+
+/**
+ * Convert SP network types to CA network types,
+ *
+ * @param[in]  connType   connection type.
+ * @return  CA connectivity type corresponding to SP connectivity type.
+ */
+static CATransportType_t getConnectivity(SPConnectivityType connType)
+{
+    switch (connType)
+    {
+        case SP_IPV4:
+            {
+                return CA_IPV4;
+            }
+        case SP_IPV6:
+            {
+                return CA_IPV6;
+            }
+        case SP_CONN_EDR:
+            {
+                return CA_EDR;
+            }
+        case SP_CONN_LE:
+            {
+                return CA_LE;
+            }
+        default:
+            {
+                return CA_IPV4;
+            }
+    }
+    return CA_IPV4;
+}
+
+/**
+ * Convert CA network types to SP network types,
+ *
+ * @param[in]  connType   connection type.
+ * @return  SPConnectitivty type corresponding to CATransportType_t.
+ */
+static SPConnectivityType getConnectivitySP(CATransportType_t connType)
+{
+    switch (connType)
+    {
+        case CA_IPV4:
+            {
+                return SP_IPV4;
+            }
+        case CA_IPV6:
+            {
+                return SP_IPV6;
+            }
+        case CA_EDR:
+            {
+                return SP_CONN_EDR;
+            }
+        case CA_LE:
+            {
+                return SP_CONN_LE;
+            }
+        default:
+            {
+                return SP_IPV4;
+            }
+    }
+    return SP_IPV4;
+}
+
+/**
+ * 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] uri             Request URI.
+ * @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.
+ * @param[in] token           CA token.
+ * @param[in] method          method to be used for sending rquest.
+ * @param[in] conntype        Connectivity type.
+ * @return  CA_STATUS_OK on success, otherwise error code.
+ */
+static CAResult_t sendCARequest(CAURI_t uri, char *payload, int payloadLen,
+                                CAToken_t token, CAMethod_t method, SPConnectivityType conntype)
+{
+    CARemoteEndpoint_t *endpoint = NULL;
+    CATransportType_t caConnType = getConnectivity(conntype);
+    if (CA_STATUS_OK != CACreateRemoteEndpoint(uri, caConnType, &endpoint) || !endpoint)
+    {
+        OC_LOG(ERROR, TAG, "Failed to create remote endpoint");
+        CADestroyRemoteEndpoint(endpoint);
+        return CA_STATUS_FAILED;
+    }
+    // TODO: it can be CA_MSG_NONCONFIRM or CA_MSG_CONFIRM. Pass it as a parameter.
+    CAMessageType_t msgType = CA_MSG_NONCONFIRM;
+    CAInfo_t requestData = { 0 };
+    requestData.token = token;
+    requestData.tokenLength  = CA_MAX_TOKEN_LEN;
+    if (payload && '\0' != (*(payload + payloadLen)))
+    {
+        OC_LOG(ERROR, TAG, "Payload not properly terminated.");
+        CADestroyRemoteEndpoint(endpoint);
+        return CA_STATUS_INVALID_PARAM;
+    }
+    requestData.payload = payload;
+    requestData.type = msgType;
+    CARequestInfo_t requestInfo = { 0 };
+    requestInfo.method = method;
+    requestInfo.info = requestData;
+    CAResult_t caResult = CA_STATUS_OK;
+    caResult = CASendRequest(endpoint, &requestInfo);
+    if (CA_STATUS_OK != caResult)
+    {
+        OC_LOG(ERROR, TAG, "Send Request Error !!");
+    }
+    CADestroyRemoteEndpoint(endpoint);
+    return caResult;
+}
+
+/**
+ * addDevice to list.
+ *
+ * @param[in] ip                    IP of target device.
+ * @param[in] port                  port of remote server.
+ * @param[in] connType              connectivity type of endpoint.
+ * @param[in] doxm                  pointer to doxm instance.
+ * @return SP_RESULT_SUCCESS for success and errorcode otherwise.
+ */
+static SPResult addDevice(const char *ip, int port, SPConnectivityType connType, OicSecDoxm_t *doxm)
+{
+    if (NULL == ip || 0 >= port)
+    {
+        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;
+    }
+
+    SPStringCopy(ptr->ip, ip, sizeof(ptr->ip));
+    ptr->port = port;
+    ptr->connType = connType;
+
+    ptr->doxm = doxm;
+
+    ptr->next = NULL;
+
+    if (NULL == gStartOfDiscoveredDevices)
+    {
+        gStartOfDiscoveredDevices = ptr;
+        gCurrent = ptr;
+    }
+    else
+    {
+        gCurrent->next = ptr;
+        gCurrent = ptr;
+    }
+    return SP_RESULT_SUCCESS;
+}
+
+/**
+ * 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.
+ */
+static void ProvisionDiscoveryHandler(const CARemoteEndpoint_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");
+                return;
+            }
+            // temp logic for trimming oc attribute from the json.
+            // JSONToBin should handle oc attribute.
+            char *pTempPayload = (char *)OICMalloc(strlen(responseInfo->info.payload));
+            if (NULL == pTempPayload)
+            {
+                OC_LOG(ERROR, TAG, "Error while Memory allocation.");
+                gStateManager = gStateManager | SP_DISCOVERY_ERROR;
+                return;
+            }
+
+            strcpy(pTempPayload, responseInfo->info.payload + 8);
+            pTempPayload[strlen(pTempPayload) - 2] = '\0';
+            OC_LOG_V(DEBUG, TAG, "Trimmed payload: %s", pTempPayload);
+            OicSecDoxm_t *ptrDoxm = JSONToDoxmBin(pTempPayload);
+
+            if (NULL == ptrDoxm)
+            {
+                OC_LOG(ERROR, TAG, "Error while converting doxm json to binary");
+                OICFree(pTempPayload);
+                gStateManager = gStateManager | SP_DISCOVERY_ERROR;
+                return;
+            }
+            OC_LOG(DEBUG, TAG, "Successfully converted pstat json to bin.");
+            OICFree(pTempPayload);
+
+            SPConnectivityType connType = getConnectivitySP(object->transportType);
+            SPResult res = addDevice(object->addressInfo.IP.ipAddress, object->addressInfo.IP.port,
+                                     connType, ptrDoxm);
+            if (SP_RESULT_SUCCESS != res)
+            {
+                OC_LOG(ERROR, TAG, "Error while adding data to linkedlist.");
+                gStateManager = gStateManager | SP_DISCOVERY_ERROR;
+                DeleteDoxmBinData(ptrDoxm);
+                return;
+            }
+            OC_LOG(INFO, TAG, "Exiting ProvisionDiscoveryHandler.");
+            gStateManager |= SP_DISCOVERY_DONE;
+        }
+    }
+}
+
+/**
+ * Response handler ownership transfer.
+ *
+ * @param[in] object       Remote endpoint object
+ * @param[in] requestInfo  Datastructure containing request information.
+ */
+static void OwnerShipTransferModeHandler(const CARemoteEndpoint_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.");
+            }
+        }
+    }
+}
+
+/**
+ * Response handler list methods.
+ *
+ * @param[in] object       Remote endpoint object
+ * @param[in] requestInfo  Datastructure containing request information.
+ */
+static void ListMethodsHandler(const CARemoteEndpoint_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;
+                }
+
+                char *pTempPayload = (char *)OICMalloc(strlen(responseInfo->info.payload));
+                if (NULL == pTempPayload)
+                {
+                    OC_LOG(ERROR, TAG, "Error in memory allocation.");
+                    gStateManager |= SP_LIST_METHODS_ERROR;
+                    return;
+                }
+
+                strcpy(pTempPayload, responseInfo->info.payload + 8);
+                pTempPayload[strlen(pTempPayload) - 2] = '\0';
+
+                OicSecPstat_t *pstat =  JSONToPstatBin(pTempPayload);
+                if (NULL == pstat)
+                {
+                    OC_LOG(ERROR, TAG, "Error while converting json to pstat bin");
+                    OICFree(pTempPayload);
+                    gStateManager |= SP_LIST_METHODS_ERROR;
+                    return;
+                }
+                OICFree(pTempPayload);
+                DeletePstatBinData(gPstat);
+
+                gPstat = pstat;
+                gStateManager |= SP_LIST_METHODS_DONE;
+
+                OC_LOG(INFO, TAG, "Exiting ListMethodsHandler.");
+            }
+        }
+    }
+}
+
+/**
+ * Response handler for update operation mode.
+ *
+ * @param[in] object       Remote endpoint object
+ * @param[in] requestInfo  Datastructure containing request information.
+ */
+static void OperationModeUpdateHandler(const CARemoteEndpoint_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.");
+            }
+        }
+    }
+}
+
+/**
+ * Response handler for ownership transfer.
+ *
+ * @param[in] object       Remote endpoint object
+ * @param[in] requestInfo  Datastructure containing request information.
+ */
+static void OwnerShipUpdateHandler(const CARemoteEndpoint_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.");
+            }
+        }
+    }
+}
+
+/**
+ * Response handler for ACL provisioning.
+ *
+ * @param[in] object       Remote endpoint object
+ * @param[in] requestInfo  Datastructure containing request information.
+ */
+static void ACLProvisioningHandler(const CARemoteEndpoint_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;
+            }
+        }
+    }
+}
+
+/**
+ * Response handler for provisioning finalization.
+ *
+ * @param[in] object       Remote endpoint object
+ * @param[in] requestInfo  Datastructure containing request information.
+ */
+static void FinalizeProvisioningHandler(const CARemoteEndpoint_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.");
+            }
+        }
+    }
+}
+
+/**
+ * Response handler for Credential provisioning.
+ *
+ * @param[in] object        Remote endpoint object
+ * @param[in] requestInfo   Datastructure containing request information.
+ */
+static void CredProvisioningHandler(const CARemoteEndpoint_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.");
+            }
+        }
+    }
+}
+
+/**
+ * Response Handler
+ *
+ * @param[in] object        Remote endpoint object
+ * @param[in] responseInfo  Datastructure containing response information.
+ */
+static void SPResponseHandler(const CARemoteEndpoint_t *object,
+                              const CAResponseInfo_t *responseInfo)
+{
+    if ((NULL != responseInfo) && (NULL != responseInfo->info.token))
+    {
+        handler(object, responseInfo);
+    }
+}
+
+/**
+ * Error Handler
+ *
+ * @param[in] object     Remote endpoint object
+ * @param[in] errorInfo  Datastructure containing error information.
+ */
+static void SPErrorHandler(const CARemoteEndpoint_t *object,
+                           const CAErrorInfo_t *errorInfo)
+{
+    OC_LOG(INFO, TAG, "Error Handler.");
+}
+
+/**
+ * Request Handler
+ *
+ * @param[in] object       Remote endpoint object
+ * @param[in] requestInfo  Datastructure containing request information.
+ */
+static void SPRequestHandler(const CARemoteEndpoint_t *object, const CARequestInfo_t *requestInfo)
+{
+    OC_LOG(INFO, TAG, "Request Handler.");
+}
+
+/**
+ * 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;
+    }
+    res = CAFindResource(DOXM_OWNED_FALSE_MULTICAST_QUERY, gToken, CA_MAX_TOKEN_LEN);
+    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 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;
+    char uri[CA_MAX_URI_LENGTH] = {0};
+    size_t uriLen = sizeof(uri);
+    snprintf(uri, uriLen - 1, COAP_QUERY, deviceInfo->ip,
+             deviceInfo->port, OIC_RSRC_DOXM_URI);
+    uri[uriLen - 1] = '\0';
+
+    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);
+
+    CAMethod_t method = CA_PUT;
+    if (CA_STATUS_OK != CAGenerateToken(&gToken, CA_MAX_TOKEN_LEN))
+    {
+        OC_LOG(ERROR, TAG, "Error while generating token");
+        OICFree(payload);
+        return SP_RESULT_INTERNAL_ERROR;
+    }
+    handler = &OwnerShipTransferModeHandler;
+    gStateManager |= SP_UP_OWN_TR_METH_STARTED;
+
+    CAResult_t result = sendCARequest(uri, payload, payloadLen, gToken, method,
+                                      deviceInfo->connType);
+    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)
+{
+    char uri[CA_MAX_URI_LENGTH] = {0};
+    size_t uriLen = sizeof(uri);
+    snprintf(uri, uriLen - 1, COAP_QUERY, deviceInfo->ip,
+             deviceInfo->port, OIC_RSRC_PSTAT_URI);
+    uri[uriLen - 1] = '\0';
+    CAMethod_t method = CA_GET;
+    if (CA_STATUS_OK != CAGenerateToken(&gToken, CA_MAX_TOKEN_LEN))
+    {
+        OC_LOG(ERROR, TAG, "Error while generating token");
+        return SP_RESULT_INTERNAL_ERROR;
+    }
+    handler = &ListMethodsHandler;
+    gStateManager |= SP_LIST_METHODS_STARTED;
+    CAResult_t result = sendCARequest(uri, NULL, 0, gToken, method, deviceInfo->connType);
+    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;
+
+    char uri[CA_MAX_URI_LENGTH] = {0};
+    size_t uriLen = sizeof(uri);
+    snprintf(uri, uriLen - 1, COAP_QUERY, deviceInfo->ip,
+             deviceInfo->port , OIC_RSRC_PSTAT_URI);
+    uri[uriLen - 1] = '\0';
+
+
+    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);
+
+    CAMethod_t method = CA_PUT;
+    if (CA_STATUS_OK != CAGenerateToken(&gToken, CA_MAX_TOKEN_LEN))
+    {
+        OC_LOG(ERROR, TAG, "Error while generating token");
+        if (payloadBuffer)
+        {
+            OICFree(payloadBuffer);
+        }
+        return SP_RESULT_INTERNAL_ERROR;
+    }
+    handler = &OperationModeUpdateHandler;
+    gStateManager |= SP_UPDATE_OP_MODE_STARTED;
+    CAResult_t result = sendCARequest(uri, payloadBuffer, payloadLen, gToken, method,
+                                      deviceInfo->connType);
+    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 SPTargetDeviceInfo_t *deviceInfo)
+{
+    CAResult_t caresult = CASelectCipherSuite(TLS_ECDH_anon_WITH_AES_128_CBC_SHA);
+
+    if (CA_STATUS_OK != caresult)
+    {
+        OC_LOG(ERROR, TAG, "Unable to select cipher suite");
+        return SP_RESULT_INTERNAL_ERROR;
+    }
+    OC_LOG(INFO, TAG, "Anonymous cipher suite selected. ");
+    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.");
+
+    CAAddress_t address = {};
+    strncpy(address.IP.ipAddress, deviceInfo->ip, DEV_ADDR_SIZE_MAX);
+    address.IP.ipAddress[DEV_ADDR_SIZE_MAX - 1] = '\0';
+    address.IP.port = CA_SECURE_PORT;
+
+    caresult = CAInitiateHandshake(&address, deviceInfo->connType);
+    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)
+{
+    char uri[CA_MAX_URI_LENGTH] = {0};
+    size_t uriLen = sizeof(uri);
+    snprintf(uri, uriLen - 1, COAPS_QUERY, selectedDeviceInfo->ip,
+             CA_SECURE_PORT, OIC_RSRC_DOXM_URI);
+    uri[uriLen - 1] = '\0';
+
+    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);
+
+    CAMethod_t method = CA_PUT;
+    if (CA_STATUS_OK != CAGenerateToken(&gToken, CA_MAX_TOKEN_LEN))
+    {
+        OC_LOG(ERROR, TAG, "Error while generating token");
+        OICFree(payloadBuffer);
+        return SP_RESULT_INTERNAL_ERROR;
+
+    }
+    handler = &OwnerShipUpdateHandler;
+    gStateManager |= SP_UPDATE_OWNER_STARTED;
+
+    CAResult_t result = sendCARequest(uri, payloadBuffer, payloadLen, gToken, method,
+                                      selectedDeviceInfo->connType);
+    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;
+    CAAddress_t address = {};
+    strncpy(address.IP.ipAddress, selectedDeviceInfo->ip, DEV_ADDR_SIZE_MAX);
+    address.IP.ipAddress[DEV_ADDR_SIZE_MAX - 1] = '\0';
+    address.IP.port = CA_SECURE_PORT;
+
+    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(&address, selectedDeviceInfo->connType,
+            (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)
+    {
+        res = initiateDtlsHandshake(selectedDeviceInfo);
+        if (SP_RESULT_SUCCESS != res)
+        {
+            OC_LOG(ERROR, TAG, "Error while DTLS handshake.");
+            return SP_RESULT_INTERNAL_ERROR;
+        }
+
+        res = sendOwnershipInfo(timeout, selectedDeviceInfo);
+        if (SP_RESULT_SUCCESS != res)
+        {
+            OC_LOG(ERROR, TAG, "Error while updating ownership information.");
+            return SP_RESULT_INTERNAL_ERROR;
+        }
+
+        saveOwnerPSK(selectedDeviceInfo);
+    }
+    return SP_RESULT_SUCCESS;
+
+}
+
+/**
+ * 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;
+    }
+
+    char uri[CA_MAX_URI_LENGTH] = {0};
+    size_t uriLen = sizeof(uri);
+    snprintf(uri, uriLen - 1, COAPS_QUERY, deviceInfo->ip,
+             CA_SECURE_PORT, OIC_RSRC_CRED_URI);
+    uri[uriLen - 1] = '\0';
+
+    int payloadLen = strlen(credJson);
+    CAMethod_t method = CA_POST;
+    if (CA_STATUS_OK != CAGenerateToken(&gToken, CA_MAX_TOKEN_LEN))
+    {
+        OC_LOG(ERROR, TAG, "Error while generating token");
+        return SP_RESULT_INTERNAL_ERROR;
+    }
+    handler = &CredProvisioningHandler;
+    gStateManager |= SP_PROV_CRED_STARTED;
+    CAResult_t result = sendCARequest(uri, credJson, payloadLen, gToken, method,
+                                      deviceInfo->connType);
+    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);
+    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");
+    }
+
+    CARegisterHandler(SPRequestHandler, SPResponseHandler, SPErrorHandler);
+    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;
+    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;
+    }
+
+    char uri[CA_MAX_URI_LENGTH] = {0};
+    size_t uriLen = sizeof(uri);
+    snprintf(uri, uriLen - 1, COAPS_QUERY, selectedDeviceInfo->ip,
+             CA_SECURE_PORT, OIC_RSRC_ACL_URI);
+    uri[uriLen - 1] = '\0';
+
+    int payloadLen = strlen(aclString);
+    CAMethod_t method = CA_POST;
+    if (CA_STATUS_OK != CAGenerateToken(&gToken, CA_MAX_TOKEN_LEN))
+    {
+        OC_LOG(ERROR, TAG, "Error while generating token");
+        OICFree(aclString);
+        return SP_RESULT_INTERNAL_ERROR;
+
+    }
+    handler = &ACLProvisioningHandler;
+    gStateManager |= SP_PROV_ACL_STARTED;
+
+    CAResult_t result = sendCARequest(uri, aclString, payloadLen, gToken, method,
+                                      selectedDeviceInfo->connType);
+    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;
+    }
+    char uri[CA_MAX_URI_LENGTH] = {0};
+    size_t uriLen = sizeof(uri);
+    snprintf(uri, uriLen - 1, COAPS_QUERY, selectedDeviceInfo->ip,
+             CA_SECURE_PORT, OIC_RSRC_PSTAT_URI);
+    uri[uriLen - 1] = '\0';
+
+    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);
+
+    CAMethod_t method = CA_PUT;
+    if (CA_STATUS_OK != CAGenerateToken(&gToken, CA_MAX_TOKEN_LEN))
+    {
+        OC_LOG(ERROR, TAG, "Error while generating token");
+        OICFree(payloadBuffer);
+        return SP_RESULT_INTERNAL_ERROR;
+    }
+    handler = &FinalizeProvisioningHandler;
+    gStateManager |= SP_UP_HASH_STARTED;
+    CAResult_t result = sendCARequest(uri, payloadBuffer, payloadLen, gToken, method,
+                                      selectedDeviceInfo->connType);
+    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;
+    }
+
+    CAAddress_t address = {};
+    strncpy(address.IP.ipAddress, selectedDeviceInfo->ip, DEV_ADDR_SIZE_MAX);
+    address.IP.ipAddress[DEV_ADDR_SIZE_MAX - 1] = '\0';
+    address.IP.port = CA_SECURE_PORT;
+
+    result = CACloseDtlsSession(&address, selectedDeviceInfo->connType);
+    if (CA_STATUS_OK != result)
+    {
+        OC_LOG_V(ERROR, TAG, "DTLS handshake failure.");
+    }
+
+    CADestroyToken(gToken);
+    gStateManager = 0;
+    gPstat = NULL;
+    return res;
+}
+
+SPResult SPTerminateProvisioning()
+{
+    deleteList();
+    return SP_RESULT_SUCCESS;;
+}
diff --git a/resource/csdk/security/provisioning/unittest/SConscript b/resource/csdk/security/provisioning/unittest/SConscript
new file mode 100644 (file)
index 0000000..e6b59ed
--- /dev/null
@@ -0,0 +1,83 @@
+# //******************************************************************
+# //
+# // 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.
+# //
+# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+
+Import('env')
+import os
+import os.path
+sptest_env = env.Clone()
+
+src_dir = sptest_env.get('SRC_DIR')
+
+######################################################################
+# Build flags
+######################################################################
+sptest_env.PrependUnique(CPPPATH = [
+               '../../../connectivity/inc',
+               '../../../connectivity/api',
+               '../../include',
+               '../../../../../extlibs/tinydtls',
+               '../include/internal',
+               '../../../logger/include',
+               '../../../stack/include',
+               '../../../../oc_logger/include',
+               '../../../../../extlibs/gtest/gtest-1.7.0/include',
+               '../include'
+               ])
+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',
+                                    'ocsrm',
+                                    'octbstack',
+                                    'oc_logger',
+                                    'connectivity_abstraction',
+                                    'coap',
+                                    'gtest',
+                                    'gtest_main'])
+
+if env.get('SECURED') == '1':
+    sptest_env.AppendUnique(LIBS = ['tinydtls'])
+
+if not env.get('RELEASE'):
+       sptest_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+unittest = sptest_env.Program('unittest', ['provisioningmanager.cpp'])
+
+Alias("test", [unittest])
+
+env.AppendTarget('test')
+if env.get('TEST') == '1':
+       target_os = env.get('TARGET_OS')
+       if target_os == 'linux':
+               out_dir = env.get('BUILD_DIR')
+               result_dir = env.get('BUILD_DIR') + '/test_out/'
+               if not os.path.isdir(result_dir):
+                       os.makedirs(result_dir)
+               sptest_env.AppendENVPath('GTEST_OUTPUT', ['xml:'+ result_dir])
+               sptest_env.AppendENVPath('LD_LIBRARY_PATH', [out_dir])
+               sptest_env.AppendENVPath('LD_LIBRARY_PATH', ['./extlibs/gtest/gtest-1.7.0/lib/.libs'])
+               ut = sptest_env.Command ('ut', None, out_dir + '/resource/csdk/security/unittest/unittest')
+               AlwaysBuild ('ut')
+
diff --git a/resource/csdk/security/provisioning/unittest/provisioningmanager.cpp b/resource/csdk/security/provisioning/unittest/provisioningmanager.cpp
new file mode 100644 (file)
index 0000000..f38b085
--- /dev/null
@@ -0,0 +1,56 @@
+/* *****************************************************************
+ *
+ * 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;
+
+TEST(SPProvisioningDiscoveryTest, NullConectivity)
+{
+    EXPECT_EQ(SP_RESULT_INVALID_PARAM, SPProvisioningDiscovery(0, NULL));
+}
+
+TEST(SPInitProvisionContextTest, NullDeviceInfo)
+{
+    EXPECT_EQ(SP_RESULT_INVALID_PARAM, SPInitProvisionContext(0, NULL));
+}
+
+TEST(SPProvisionACLTest, NullDeviceInfo)
+{
+    EXPECT_EQ(SP_RESULT_INVALID_PARAM, SPProvisionACL(0, NULL, &acl));
+}
+
+TEST(SPFinalizeProvisioningTest, NullDeviceInfo)
+{
+    EXPECT_EQ(SP_RESULT_INVALID_PARAM, SPFinalizeProvisioning(0, NULL));
+}
+
+TEST(SPTerminateProvisioningTest, ValidCase)
+{
+    EXPECT_EQ(SP_RESULT_SUCCESS, SPTerminateProvisioning());
+}
+
+TEST(SPProvisionCredentialsTest, NullList)
+{
+    EXPECT_EQ(SP_RESULT_INVALID_PARAM, SPProvisionCredentials(0, 0, NULL));
+}
diff --git a/resource/csdk/security/src/aclresource.c b/resource/csdk/security/src/aclresource.c
new file mode 100644 (file)
index 0000000..679151b
--- /dev/null
@@ -0,0 +1,595 @@
+//******************************************************************
+//
+// 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 "cJSON.h"
+#include "base64.h"
+#include "resourcemanager.h"
+#include "aclresource.h"
+#include "psinterface.h"
+#include "utlist.h"
+#include "srmresourcestrings.h"
+#include "doxmresource.h"
+#include "srmutility.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define TAG  PCF("SRM-ACL")
+
+OicSecAcl_t        *gAcl = NULL;
+static OCResourceHandle    gAclHandle = NULL;
+
+void DeleteACLList(OicSecAcl_t* acl)
+{
+    if (acl)
+    {
+        OicSecAcl_t *aclTmp1 = NULL, *aclTmp2 = NULL;
+        LL_FOREACH_SAFE(acl, aclTmp1, aclTmp2)
+        {
+            int i = 0;
+
+            LL_DELETE(acl, aclTmp1);
+
+            // Clean Resources
+            for (i = 0; i < aclTmp1->resourcesLen; i++)
+            {
+                OICFree(aclTmp1->resources[i]);
+            }
+            OICFree(aclTmp1->resources);
+
+            // Clean Owners
+            OICFree(aclTmp1->owners);
+
+            // Clean ACL node itself
+            OICFree(aclTmp1);
+        }
+    }
+}
+
+/*
+ * This internal method converts ACL data into JSON format.
+ *
+ * Note: Caller needs to invoke 'free' when finished done using
+ * return string.
+ */
+char * BinToAclJSON(const OicSecAcl_t * acl)
+{
+    cJSON *jsonRoot = NULL;
+    char *jsonStr = NULL;
+
+    if (acl)
+    {
+        jsonRoot = cJSON_CreateObject();
+        VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+        cJSON *jsonAclArray = NULL;
+        cJSON_AddItemToObject (jsonRoot, OIC_JSON_ACL_NAME, jsonAclArray = cJSON_CreateArray());
+        VERIFY_NON_NULL(TAG, jsonAclArray, ERROR);
+
+        while(acl)
+        {
+            char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
+            uint32_t outLen = 0;
+            size_t inLen = 0;
+            B64Result b64Ret = B64_OK;
+
+            cJSON *jsonAcl = cJSON_CreateObject();
+
+            // Subject -- Mandatory
+            outLen = 0;
+            if (memcmp(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)) == 0)
+            {
+                inLen = WILDCARD_SUBJECT_ID_LEN;
+            }
+            else
+            {
+                inLen =  sizeof(OicUuid_t);
+            }
+            b64Ret = b64Encode(acl->subject.id, inLen, base64Buff,
+                sizeof(base64Buff), &outLen);
+            VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+            cJSON_AddStringToObject(jsonAcl, OIC_JSON_SUBJECT_NAME, base64Buff );
+
+            // Resources -- Mandatory
+            cJSON *jsonRsrcArray = NULL;
+            cJSON_AddItemToObject (jsonAcl, OIC_JSON_RESOURCES_NAME, jsonRsrcArray = cJSON_CreateArray());
+            VERIFY_NON_NULL(TAG, jsonRsrcArray, ERROR);
+            for (int i = 0; i < acl->resourcesLen; i++)
+            {
+                cJSON_AddItemToArray (jsonRsrcArray, cJSON_CreateString(acl->resources[i]));
+            }
+
+            // Permissions -- Mandatory
+            cJSON_AddNumberToObject (jsonAcl, OIC_JSON_PERMISSION_NAME, acl->permission);
+
+            // Owners -- Mandatory
+            cJSON *jsonOwnrArray = NULL;
+            cJSON_AddItemToObject (jsonAcl, OIC_JSON_OWNERS_NAME, jsonOwnrArray = cJSON_CreateArray());
+            VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
+            for (int i = 0; i < acl->ownersLen; i++)
+            {
+                outLen = 0;
+
+                b64Ret = b64Encode(acl->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 acl node to Acl Array
+            cJSON_AddItemToArray(jsonAclArray, jsonAcl);
+            acl = acl->next;
+        }
+
+        jsonStr = cJSON_PrintUnformatted(jsonRoot);
+    }
+
+exit:
+    if (jsonRoot)
+    {
+        cJSON_Delete(jsonRoot);
+    }
+    return jsonStr;
+}
+
+/*
+ * This internal method converts JSON ACL into binary ACL.
+ */
+OicSecAcl_t * JSONToAclBin(const char * jsonStr)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    OicSecAcl_t * headAcl = NULL;
+    OicSecAcl_t * prevAcl = NULL;
+    cJSON *jsonRoot = NULL;
+    cJSON *jsonAclArray = NULL;
+
+    VERIFY_NON_NULL(TAG, jsonStr, ERROR);
+
+    jsonRoot = cJSON_Parse(jsonStr);
+    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+    jsonAclArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_ACL_NAME);
+    VERIFY_NON_NULL(TAG, jsonAclArray, ERROR);
+
+    if (cJSON_Array == jsonAclArray->type)
+    {
+        int numAcl = cJSON_GetArraySize(jsonAclArray);
+        int idx = 0;
+
+        VERIFY_SUCCESS(TAG, numAcl > 0, INFO);
+        do
+        {
+            cJSON *jsonAcl = cJSON_GetArrayItem(jsonAclArray, idx);
+            VERIFY_NON_NULL(TAG, jsonAcl, ERROR);
+
+            OicSecAcl_t *acl = (OicSecAcl_t*)OICCalloc(1, sizeof(OicSecAcl_t));
+            VERIFY_NON_NULL(TAG, acl, ERROR);
+
+            headAcl = (headAcl) ? headAcl : acl;
+            if (prevAcl)
+            {
+                prevAcl->next = acl;
+            }
+
+            size_t jsonObjLen = 0;
+            cJSON *jsonObj = NULL;
+
+            unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
+            uint32_t outLen = 0;
+            B64Result b64Ret = B64_OK;
+
+            // Subject -- Mandatory
+            jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_SUBJECT_NAME);
+            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(acl->subject.id)), ERROR);
+            memcpy(acl->subject.id, base64Buff, outLen);
+
+            // Resources -- Mandatory
+            jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_RESOURCES_NAME);
+            VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+            VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
+
+            acl->resourcesLen = cJSON_GetArraySize(jsonObj);
+            VERIFY_SUCCESS(TAG, acl->resourcesLen > 0, ERROR);
+            acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
+            VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
+
+            int idxx = 0;
+            do
+            {
+                cJSON *jsonRsrc = cJSON_GetArrayItem(jsonObj, idxx);
+                VERIFY_NON_NULL(TAG, jsonRsrc, ERROR);
+
+                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);
+            } while ( ++idxx < acl->resourcesLen);
+
+            // Permissions -- Mandatory
+            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;
+
+            // Owners -- Mandatory
+            jsonObj = cJSON_GetObjectItem(jsonAcl, OIC_JSON_OWNERS_NAME);
+            VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+            VERIFY_SUCCESS(TAG, cJSON_Array == jsonObj->type, ERROR);
+
+            acl->ownersLen = cJSON_GetArraySize(jsonObj);
+            VERIFY_SUCCESS(TAG, acl->ownersLen > 0, ERROR);
+            acl->owners = (OicUuid_t*)OICCalloc(acl->ownersLen, sizeof(OicUuid_t));
+            VERIFY_NON_NULL(TAG, (acl->owners), ERROR);
+
+            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(acl->owners[idxx].id)),
+                                    ERROR);
+                memcpy(acl->owners[idxx].id, base64Buff, outLen);
+            } while ( ++idxx < acl->ownersLen);
+
+            prevAcl = acl;
+        } while( ++idx < numAcl);
+    }
+
+    ret = OC_STACK_OK;
+
+exit:
+    cJSON_Delete(jsonRoot);
+    if (OC_STACK_OK != ret)
+    {
+        DeleteACLList(headAcl);
+        headAcl = NULL;
+    }
+    return headAcl;
+}
+
+static OCEntityHandlerResult HandleACLGetRequest (const OCEntityHandlerRequest * ehRequest)
+{
+    // Convert ACL data into JSON for transmission
+    char* jsonStr = BinToAclJSON(gAcl);
+
+    /*
+     * A device should 'always' have a default ACL. Therefore,
+     * jsonStr should never be NULL.
+     */
+    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 HandleACLPostRequest (const OCEntityHandlerRequest * ehRequest)
+{
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+    // Convert JSON ACL data into binary. This will also validate the ACL data received.
+    OicSecAcl_t* newAcl = JSONToAclBin((char *)(ehRequest->reqJSONPayload));
+
+    if (newAcl)
+    {
+        // 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)
+        {
+            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);
+        }
+    }
+
+    // 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 ACL resources and
+ * will handle REST request (GET/PUT/POST/DEL) for them.
+ */
+OCEntityHandlerResult ACLEntityHandler (OCEntityHandlerFlag flag,
+                                        OCEntityHandlerRequest * ehRequest)
+{
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+    if (!ehRequest)
+    {
+        return ehRet;
+    }
+
+    if (flag & OC_REQUEST_FLAG)
+    {
+        // TODO :  Handle PUT and DEL methods
+        OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+        switch (ehRequest->method)
+        {
+            case OC_REST_GET:
+                ehRet = HandleACLGetRequest(ehRequest);
+                break;
+
+            case OC_REST_POST:
+                ehRet = HandleACLPostRequest(ehRequest);
+                break;
+
+            default:
+                ehRet = OC_EH_ERROR;
+                SendSRMResponse(ehRequest, ehRet, NULL);
+        }
+    }
+
+    return ehRet;
+}
+
+/*
+ * This internal method is used to create '/oic/sec/acl' resource.
+ */
+OCStackResult CreateACLResource()
+{
+    OCStackResult ret;
+
+    ret = OCCreateResource(&gAclHandle,
+                           OIC_RSRC_TYPE_SEC_ACL,
+                           OIC_MI_DEF,
+                           OIC_RSRC_ACL_URI,
+                           ACLEntityHandler,
+                           OC_OBSERVABLE);
+
+    if (OC_STACK_OK != ret)
+    {
+        OC_LOG (FATAL, TAG, PCF("Unable to instantiate ACL resource"));
+        DeInitACLResource();
+    }
+    return ret;
+}
+
+/*
+ * This internal method is to retrieve the default ACL.
+ * If SVR database in persistent storage got corrupted or
+ * is not available for some reason, a default ACL is created
+ * which allows user to initiate ACL provisioning again.
+ */
+OCStackResult  GetDefaultACL(OicSecAcl_t** defaultAcl)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+
+    OicUuid_t ownerId = {};
+
+    /*
+     * TODO In future, when new virtual resources will be added in OIC
+     * specification, Iotivity stack should be able to add them in
+     * existing SVR database. To support this, we need to add 'versioning'
+     * mechanism in SVR database.
+     */
+
+    const char *rsrcs[] = {
+        OIC_RSRC_CORE_URI,
+        OIC_RSRC_CORE_D_URI,
+        OIC_RSRC_CORE_P_URI,
+        OIC_RSRC_TYPES_D_URI,
+        OIC_RSRC_PRESENCE_URI,
+        OIC_RSRC_ACL_URI,
+        OIC_RSRC_DOXM_URI,
+        OIC_RSRC_PSTAT_URI,
+    };
+
+    if (!defaultAcl)
+    {
+        return OC_STACK_INVALID_PARAM;
+    }
+
+    OicSecAcl_t *acl = (OicSecAcl_t *)OICCalloc(1, sizeof(OicSecAcl_t));
+    VERIFY_NON_NULL(TAG, acl, ERROR);
+
+    // Subject -- Mandatory
+    memcpy(&(acl->subject), &WILDCARD_SUBJECT_ID, sizeof(acl->subject));
+
+    // Resources -- Mandatory
+    acl->resourcesLen = sizeof(rsrcs)/sizeof(rsrcs[0]);
+
+    acl->resources = (char**)OICCalloc(acl->resourcesLen, sizeof(char*));
+    VERIFY_NON_NULL(TAG, (acl->resources), ERROR);
+
+    for (int i = 0; i <  acl->resourcesLen; i++)
+    {
+        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);
+    }
+
+    acl->permission = PERMISSION_READ;
+    acl->periodsLen = 0;
+    acl->periods = NULL;
+    acl->recurrences = NULL;
+
+    // Device ID is the owner of this default ACL
+    ret = GetDoxmDeviceID( &ownerId);
+    VERIFY_SUCCESS(TAG, OC_STACK_OK == ret, FATAL);
+
+    acl->ownersLen = 1;
+    acl->owners = (OicUuid_t*)OICMalloc(sizeof(OicUuid_t));
+    VERIFY_NON_NULL(TAG, (acl->owners), ERROR);
+    memcpy(acl->owners, &ownerId, sizeof(OicUuid_t));
+
+    acl->next = NULL;
+
+    *defaultAcl = acl;
+    ret = OC_STACK_OK;
+
+exit:
+
+    if (ret != OC_STACK_OK)
+    {
+        DeleteACLList(acl);
+        acl = NULL;
+    }
+
+    return ret;
+}
+
+/**
+ * Initialize ACL resource by loading data from persistent storage.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitACLResource()
+{
+    OCStackResult ret = OC_STACK_ERROR;
+
+    // Read ACL resource from PS
+    char* jsonSVRDatabase = GetSVRDatabase();
+
+    if (jsonSVRDatabase)
+    {
+        // Convert JSON ACL into binary format
+        gAcl = JSONToAclBin(jsonSVRDatabase);
+        OICFree(jsonSVRDatabase);
+    }
+    /*
+     * If SVR database in persistent storage got corrupted or
+     * is not available for some reason, a default ACL is created
+     * which allows user to initiate ACL provisioning again.
+     */
+    if (!jsonSVRDatabase || !gAcl)
+    {
+        GetDefaultACL(&gAcl);
+        // TODO Needs to update persistent storage
+    }
+    VERIFY_NON_NULL(TAG, gAcl, FATAL);
+
+    // Instantiate 'oic.sec.acl'
+    ret = CreateACLResource();
+
+exit:
+    if (OC_STACK_OK != ret)
+    {
+        DeInitACLResource();
+    }
+    return ret;
+}
+
+/**
+ * Perform cleanup for ACL resources.
+ *
+ * @retval  none
+ */
+void DeInitACLResource()
+{
+    OCDeleteResource(gAclHandle);
+    gAclHandle = NULL;
+
+    DeleteACLList(gAcl);
+    gAcl = NULL;
+}
+
+/**
+ * This method is used by PolicyEngine to retrieve ACL for a Subject.
+ *
+ * @param subjectId ID of the subject for which ACL is required.
+ * @param savePtr is used internally by @ref GetACLResourceData to maintain index between
+ *                successive calls for same subjectId.
+ *
+ * @retval  reference to @ref OicSecAcl_t if ACL is found, else NULL
+ *
+ * @note On the first call to @ref GetACLResourceData, savePtr should point to NULL
+ */
+const OicSecAcl_t* GetACLResourceData(const OicUuid_t* subjectId, OicSecAcl_t **savePtr)
+{
+    OicSecAcl_t *acl = NULL;
+    OicSecAcl_t *begin = NULL;
+
+    if ( NULL == subjectId)
+    {
+        return NULL;
+    }
+
+    /*
+     * savePtr MUST point to NULL if this is the 'first' call to retrieve ACL for
+     * subjectID.
+     */
+    if (NULL == *savePtr)
+    {
+        begin = gAcl;
+    }
+    else
+    {
+        /*
+         * If this is a 'successive' call, search for location pointed by
+         * savePtr and assign 'begin' to the next ACL after it in the linked
+         * list and start searching from there.
+         */
+        LL_FOREACH(gAcl, acl)
+        {
+            if (acl == *savePtr)
+            {
+                begin = acl->next;
+            }
+        }
+    }
+
+    // Find the next ACL corresponding to the 'subjectID' and return it.
+    LL_FOREACH(begin, acl)
+    {
+        if (memcmp(&(acl->subject), subjectId, sizeof(OicUuid_t)) == 0)
+        {
+            *savePtr = acl;
+            return acl;
+        }
+    }
+
+    // Cleanup in case no ACL is found
+    *savePtr = NULL;
+    return NULL;
+}
diff --git a/resource/csdk/security/src/base64.c b/resource/csdk/security/src/base64.c
new file mode 100644 (file)
index 0000000..3b20cf5
--- /dev/null
@@ -0,0 +1,255 @@
+/******************************************************************
+ *
+ * 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 "base64.h"
+
+/**< base character of Base64  */
+static const char g_b64TransTbl[] =
+                "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"\
+                "ghijklmnopqrstuvwxyz0123456789+/";
+
+/**
+ * base64 block encode function
+ *
+ * @param[in] in  octet stream, max 3 byte
+ * @param[out] out  base64 encoded stream, 4 byte
+ * @param[in] len  byte-length of in
+ *
+ * @return  B64_OK for Success, otherwise some error value
+ */
+static B64Result b64EncodeBlk(const uint8_t* in, char* out, uint32_t len)
+{
+    if (NULL == in || NULL ==  out || 0 == len )
+    {
+        return B64_INVALID_PARAM;
+    }
+
+    out[0] = g_b64TransTbl[in[0] >> 2];
+
+    if(1 == len)
+    {
+        out[1] = g_b64TransTbl[((in[0] & 0x03) << 4)];
+    }
+    else
+    {
+        out[1] = g_b64TransTbl[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)];
+    }
+
+    if(2 == len)
+    {
+        out[2] = g_b64TransTbl[((in[1] & 0x0f) << 2)];
+    }
+    else if (1 < len)
+    {
+        out[2] = g_b64TransTbl[((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)];
+    }
+    else
+    {
+        out[2] = '=';
+    }
+
+    if (2 < len)
+    {
+        out[3] = g_b64TransTbl[in[2] & 0x3f];
+    }
+    else
+    {
+        out[3] = '=';
+    }
+
+    return B64_OK;
+}
+
+/**
+ * Encode the plain message in base64.
+ *
+ * @param[in] in  Plain message
+ * @param[in] inLen  Byte length of 'in'
+ * @param[in,out] outBuf Output buffer
+ *                Base64 encoded message will be written into 'out'
+ *                NOTE : This method adds a NULL to the string configuration
+ * @param[in] outBufSize Size of output buffer
+ * @param[out] outLen  Byte length of encoded message
+ *
+ * @return  B64_OK for Success, otherwise some error value
+*/
+B64Result b64Encode(const uint8_t* in, const size_t inLen,
+               char* outBuf, const size_t outBufSize, uint32_t* outLen)
+{
+    uint32_t i;
+    uint32_t minBufSize;
+
+    if (NULL == in || 0 == inLen || NULL ==  outBuf || NULL == outLen )
+    {
+        return B64_INVALID_PARAM;
+    }
+
+    *outLen = ((inLen / 3) * 3 == inLen) ?
+              ((inLen / 3) * 4) :
+              (((inLen / 3) + 1) * 4);
+    minBufSize = (*outLen + 1);
+    if(outBufSize < minBufSize)
+    {
+        return B64_OUTPUT_BUFFER_TOO_SMALL;
+    }
+
+    for (i = 0; i < inLen / 3; i++)
+    {
+        if(B64_OK != b64EncodeBlk(in + i * 3, outBuf + i * 4, 3))
+        {
+            return B64_INVALID_PARAM;
+        }
+    }
+
+    if (i * 3 != inLen)
+    {
+        if(B64_OK != b64EncodeBlk(in + i * 3, outBuf + i * 4, inLen - i * 3))
+        {
+            return B64_INVALID_PARAM;
+        }
+    }
+
+    outBuf[*outLen] = '\0';
+
+    return B64_OK;
+}
+
+/**
+ * Get decoded value
+ *
+ * @param[in] c  Base64 encoded charactor
+ *
+ * @return decoded value, 6-bit
+ */
+static uint32_t b64GetVal(char c)
+{
+    if (('A' <= c) && ('Z' >= c))
+    {
+        return c - 'A';
+    }
+    else if (('a' <= c) && ('z' >= c))
+    {
+        return c - 'a' + 26;
+    }
+    else if (('0' <= c) && ('9' >= c))
+    {
+        return c - '0' + 52;
+    }
+    else if ('+' == c)
+    {
+        return 62;
+    }
+    else if ('/' == c)
+    {
+        return 63;
+    }
+    else if ('=' == c)
+    {
+        return 0;
+    }
+
+    return 0;
+}
+
+/**
+ * base64 block decode function
+ *
+ * @param[in] in  Base64 encoded stream, 4 bytes
+ * @param[out] out  Octet stream, 3 bytes
+ *
+ * @return  B64_OK for Success, otherwise some error value
+ */
+static B64Result b64DecodeBlk(const char* in, uint8_t* out)
+{
+    uint32_t val;
+
+    if(NULL == in || NULL == out)
+    {
+        return B64_INVALID_PARAM;
+    }
+
+    val = (b64GetVal(in[0]) << 18) | (b64GetVal(in[1]) << 12) |
+          (b64GetVal(in[2]) << 6) | (b64GetVal(in[3]));
+
+    out[0] = (val >> 16) & 0xff;
+
+    if ('=' != in[2])
+    {
+        out[1] = (val >> 8) & 0xff;
+    }
+    if ('=' != in[3])
+    {
+        out[2] = val & 0xff;
+    }
+
+    return B64_OK;
+}
+
+/**
+ * Decode the encoded message in base64.
+ *
+ * @param[in] in  Base64 encoded message
+ * @param[in] inLen  Byte lenth of 'in'
+ * @param[in, out] outBuf  Output buffer
+ *                 Base64 decoded message will be written into 'out'
+ * @param[in] outBufSize Size of output buffer
+ * @param[out] outLen  Byte length of decoded message
+ *
+ * @return  B64_OK for Success, otherwise some error value
+ */
+B64Result b64Decode(const char* in, const size_t inLen,
+               uint8_t* outBuf, size_t outBufSize, uint32_t* outLen)
+{
+    uint32_t i;
+    uint32_t minBufSize;
+
+    if (NULL == in || 0 == inLen || 0 != (inLen & 0x03) || NULL == outBuf || NULL == outLen)
+    {
+        return B64_INVALID_PARAM;
+    }
+
+    *outLen = (inLen / 4) * 3;
+    minBufSize = (inLen / 4) * 3;
+    if('=' == in[inLen - 1])
+    {
+        minBufSize--;
+        (*outLen)--;
+    }
+    if('=' == in[inLen - 2])
+    {
+        minBufSize--;
+        (*outLen)--;
+    }
+    if(outBufSize < minBufSize)
+    {
+        return B64_OUTPUT_BUFFER_TOO_SMALL;
+    }
+
+    for (i = 0; i < inLen / 4; i++)
+    {
+        if(B64_OK != b64DecodeBlk(in + i * 4, outBuf + i * 3))
+        {
+            return B64_INVALID_PARAM;
+        }
+    }
+
+    return B64_OK;
+}
+
diff --git a/resource/csdk/security/src/credresource.c b/resource/csdk/security/src/credresource.c
new file mode 100755 (executable)
index 0000000..53b286c
--- /dev/null
@@ -0,0 +1,673 @@
+//******************************************************************
+//
+// 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 "resourcemanager.h"
+#include "psinterface.h"
+#include "utlist.h"
+#include "srmresourcestrings.h"
+#include "credresource.h"
+#include "ocrandom.h"
+#include "doxmresource.h"
+#include "base64.h"
+#include "srmutility.h"
+#include "cainterface.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define TAG  PCF("SRM-CREDL")
+
+static OicSecCred_t        *gCred = NULL;
+static OCResourceHandle    gCredHandle = NULL;
+
+void DeleteCredList(OicSecCred_t* cred)
+{
+    if (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
+#if 0
+            //Clean roleIds
+            OICFree(credTmp1->roleIds);
+#endif
+
+            //Clean PublicData
+            OICFree(credTmp1->publicData.data);
+
+            //Clean PrivateData
+            OICFree(credTmp1->privateData.data);
+
+            //Clean Period
+            OICFree(credTmp1->period);
+
+            //Clean Owners
+            OICFree(credTmp1->owners);
+
+            //Clean Cred node itself
+            OICFree(credTmp1);
+        }
+    }
+}
+
+/**
+ * This function converts credential data into JSON format.
+ * Caller needs to invoke 'free' when done using
+ * returned string.
+ * @param cred  pointer to instance of OicSecCred_t structure.
+ *
+ * @retval
+ *      pointer to JSON credential representation - if credential for subjectId found
+ *      NULL                                      - if credential for subjectId not found
+ */
+char * BinToCredJSON(const OicSecCred_t * cred)
+{
+    cJSON *jsonRoot = NULL;
+    char *jsonStr = NULL;
+
+    if (cred)
+    {
+        char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
+        uint32_t outLen = 0;
+        B64Result b64Ret = B64_OK;
+
+        jsonRoot = cJSON_CreateObject();
+        VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+        cJSON *jsonCredArray = NULL;
+        cJSON_AddItemToObject(jsonRoot, OIC_JSON_CRED_NAME,
+                jsonCredArray = cJSON_CreateArray());
+        VERIFY_NON_NULL(TAG, jsonCredArray, ERROR);
+
+        while(cred)
+        {
+            cJSON *jsonCred = cJSON_CreateObject();
+            VERIFY_NON_NULL(TAG, jsonCred, ERROR);
+
+            //CredID -- Mandatory
+            cJSON_AddNumberToObject(jsonCred, OIC_JSON_CREDID_NAME, (int)cred->credId);
+
+            //Subject -- Mandatory
+            outLen = 0;
+            memset(base64Buff, 0, sizeof(base64Buff));
+            b64Ret = b64Encode(cred->subject.id, sizeof(cred->subject.id), base64Buff,
+                   sizeof(base64Buff), &outLen);
+            VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+            cJSON_AddStringToObject(jsonCred, OIC_JSON_SUBJECT_NAME, base64Buff);
+
+            //Note: Need further clarification on roleID data type
+#if 0
+            //RoleId -- Not Mandatory
+            if(cred->roleIdsLen > 0)
+            {
+                cJSON *jsonRoleIdsArray = NULL;
+                cJSON_AddItemToObject (jsonCred, OIC_JSON_ROLEIDS_NAME,
+                                         jsonRoleIdsArray = cJSON_CreateArray());
+                VERIFY_NON_NULL(TAG, jsonRoleIdsArray, ERROR);
+                for (size_t i = 0; i < cred->roleIdsLen; i++)
+                {
+                    cJSON_AddItemToArray (jsonRoleIdsArray,
+                            cJSON_CreateString((char *)cred->roleIds[i].id));
+                }
+            }
+#endif
+
+            //CredType -- Mandatory
+            cJSON_AddNumberToObject(jsonCred, OIC_JSON_CREDTYPE_NAME,(int)cred->credType);
+
+#if 0
+            //PublicData -- Not Mandatory
+            if(cred->publicData.data)
+            {
+                cJSON_AddStringToObject(jsonCred, OIC_JSON_PUBLICDATA_NAME, cred->publicData.data);
+            }
+#endif
+            //PrivateData -- Not Mandatory
+            if(cred->privateData.data)
+            {
+                cJSON_AddStringToObject(jsonCred, OIC_JSON_PRIVATEDATA_NAME, cred->privateData.data);
+            }
+
+            //Period -- Not Mandatory
+            if(cred->period)
+            {
+                cJSON_AddStringToObject(jsonCred, OIC_JSON_PERIOD_NAME,
+                                        cred->period);
+            }
+
+            //Owners -- Mandatory
+            cJSON *jsonOwnrArray = NULL;
+            cJSON_AddItemToObject (jsonCred, OIC_JSON_OWNERS_NAME,
+                                             jsonOwnrArray = cJSON_CreateArray());
+            VERIFY_NON_NULL(TAG, jsonOwnrArray, ERROR);
+            for (size_t i = 0; i < cred->ownersLen; i++)
+            {
+                outLen = 0;
+                memset(base64Buff, 0, sizeof(base64Buff));
+                b64Ret = b64Encode(cred->owners[i].id, sizeof(cred->owners[i].id),
+                        base64Buff, sizeof(base64Buff), &outLen);
+                VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+                cJSON_AddItemToArray (jsonOwnrArray,
+                                       cJSON_CreateString((char *)(base64Buff)));
+            }
+
+            /* Attach current cred node to cred Array */
+            cJSON_AddItemToArray(jsonCredArray, jsonCred);
+            cred = cred->next;
+        }
+
+        jsonStr = cJSON_PrintUnformatted(jsonRoot);
+    }
+
+exit:
+    if (jsonRoot)
+    {
+        cJSON_Delete(jsonRoot);
+    }
+    return jsonStr;
+}
+
+/*
+ * This internal method converts JSON cred into binary cred.
+ */
+OicSecCred_t * JSONToCredBin(const char * jsonStr)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    OicSecCred_t * headCred = NULL;
+    OicSecCred_t * prevCred = NULL;
+    cJSON *jsonCredArray = NULL;
+
+    cJSON *jsonRoot = cJSON_Parse(jsonStr);
+    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+    jsonCredArray = cJSON_GetObjectItem(jsonRoot, OIC_JSON_CRED_NAME);
+    VERIFY_NON_NULL(TAG, jsonCredArray, ERROR);
+    if (cJSON_Array == jsonCredArray->type)
+    {
+        int numCred = cJSON_GetArraySize(jsonCredArray);
+        int idx = 0;
+
+        unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
+        uint32_t outLen = 0;
+        B64Result b64Ret = B64_OK;
+
+        VERIFY_SUCCESS(TAG, numCred > 0, ERROR);
+        do
+        {
+            cJSON *jsonCred = cJSON_GetArrayItem(jsonCredArray, idx);
+            VERIFY_NON_NULL(TAG, jsonCred, ERROR);
+
+            OicSecCred_t *cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
+            VERIFY_NON_NULL(TAG, cred, ERROR);
+
+            headCred = (headCred) ? headCred : cred;
+            if (prevCred)
+            {
+                prevCred->next = cred;
+            }
+            size_t jsonObjLen = 0;
+            cJSON *jsonObj = NULL;
+
+            //CredId -- Mandatory
+            jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_CREDID_NAME);
+            VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+            VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR)
+            cred->credId = jsonObj->valueint;
+
+            //subject -- Mandatory
+            jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_SUBJECT_NAME);
+            VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+            VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR)
+            outLen = 0;
+            memset(base64Buff, 0, sizeof(base64Buff));
+            b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring),
+                    base64Buff, sizeof(base64Buff), &outLen);
+            VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(cred->subject.id)),
+                           ERROR);
+            memcpy(cred->subject.id, base64Buff, outLen);
+
+            //CredType -- Mandatory
+            jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_CREDTYPE_NAME);
+            VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+            VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR)
+            cred->credType = jsonObj->valueint;
+
+            //PrivateData is mandatory for some of the credential types listed below.
+            jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PRIVATEDATA_NAME);
+            if ((cred->credType & SYMMETRIC_PAIR_WISE_KEY) ||
+                (cred->credType & SYMMETRIC_GROUP_KEY) ||
+                (cred->credType & PIN_PASSWORD))
+            {
+                VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+                VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
+            }
+            if(jsonObj && cJSON_String == jsonObj->type)
+            {
+                jsonObjLen = strlen(jsonObj->valuestring) + 1;
+                cred->privateData.data = (char *)OICMalloc(jsonObjLen);
+                VERIFY_NON_NULL(TAG, (cred->privateData.data), ERROR);
+                strncpy((char *)cred->privateData.data, (char *)jsonObj->valuestring, jsonObjLen);
+            }
+
+            //Period -- Not Mandatory
+            jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_PERIOD_NAME);
+            if(jsonObj && cJSON_String == jsonObj->type)
+            {
+                jsonObjLen = strlen(jsonObj->valuestring) + 1;
+                cred->period = (char *)OICMalloc(jsonObjLen);
+                VERIFY_NON_NULL(TAG, cred->period, ERROR);
+                strncpy(cred->period, jsonObj->valuestring, jsonObjLen);
+            }
+
+            //Owners -- Mandatory
+            jsonObj = cJSON_GetObjectItem(jsonCred, OIC_JSON_OWNERS_NAME);
+            VERIFY_NON_NULL(TAG, jsonObj, 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));
+            VERIFY_NON_NULL(TAG, (cred->owners), ERROR);
+            for(size_t i = 0; i < cred->ownersLen; i++)
+            {
+                cJSON *jsonOwnr = cJSON_GetArrayItem(jsonObj, i);
+                VERIFY_NON_NULL(TAG, jsonOwnr, ERROR);
+                VERIFY_SUCCESS(TAG, cJSON_String == jsonOwnr->type, ERROR);
+                outLen = 0;
+                memset(base64Buff, 0, sizeof(base64Buff));
+                b64Ret = b64Decode(jsonOwnr->valuestring, strlen(jsonOwnr->valuestring),
+                         base64Buff, sizeof(base64Buff), &outLen);
+                VERIFY_SUCCESS(TAG, (b64Ret == B64_OK &&
+                               outLen <= sizeof(cred->owners[i].id)), ERROR);
+                memcpy(cred->owners[i].id, base64Buff, outLen);
+            }
+            prevCred = cred;
+        } while( ++idx < numCred);
+    }
+
+    ret = OC_STACK_OK;
+
+exit:
+    cJSON_Delete(jsonRoot);
+    if (OC_STACK_OK != ret)
+    {
+        DeleteCredList(headCred);
+        headCred = NULL;
+    }
+    return headCred;
+}
+
+/**
+ * This function generates the bin credential data.
+ *
+ * @param subject pointer to subject of this credential.
+ * @param credType credential type.
+ * @param publicData public data such as public key.
+ * @param privateData private data such as private key.
+ * @param ownersLen length of owners array
+ * @param owners array of owners.
+ *
+ * @retval
+ *      pointer to instance of OicSecCred_t  - success
+ *      NULL                                 - error
+ */
+OicSecCred_t * GenerateCredential(const OicUuid_t * subject, OicSecCredType_t credType,
+                                 const char * publicData, const char * privateData,
+                                 size_t ownersLen, const OicUuid_t * owners)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+
+    OicSecCred_t *cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
+    VERIFY_NON_NULL(TAG, cred, ERROR);
+
+    //TODO:Need more clarification on credId
+    OCFillRandomMem((uint8_t*)&cred->credId, sizeof(cred->credId));
+
+    VERIFY_NON_NULL(TAG, subject, ERROR);
+    memcpy(cred->subject.id, subject->id , sizeof(cred->subject.id));
+
+    //TODO: check credType has one of the values {0, 1, 2, 4, 6, 8, 16}
+    cred->credType = credType;
+
+#if 0
+    if(publicData)
+    {
+        cred->publicData.data = (char *)OICMalloc(strlen(publicData)+1);
+        VERIFY_NON_NULL(TAG, cred->publicData.data, ERROR);
+        strncpy((char *)cred->publicData.data, publicData, strlen(publicData)+1);
+    }
+#endif
+
+    if(privateData)
+    {
+        cred->privateData.data = (char *)OICMalloc(strlen(privateData)+1);
+        VERIFY_NON_NULL(TAG, cred->privateData.data, ERROR);
+        strncpy((char *)cred->privateData.data, privateData, strlen(privateData)+1);
+    }
+
+    VERIFY_SUCCESS(TAG, ownersLen > 0, ERROR);
+    cred->ownersLen = ownersLen;
+
+    cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
+    VERIFY_NON_NULL(TAG, cred->owners, ERROR);
+    for(size_t i = 0; i < cred->ownersLen; i++)
+    {
+        memcpy(cred->owners[i].id, owners[i].id, sizeof(cred->owners[i].id));
+    }
+
+    ret = OC_STACK_OK;
+exit:
+    if (OC_STACK_OK != ret)
+    {
+        DeleteCredList(cred);
+        cred = NULL;
+    }
+    return cred;
+}
+
+/**
+ * This function adds the new cred to the credential list.
+ *
+ * @param cred pointer to new credential.
+ *
+ * @retval
+ *      OC_STACK_OK     - cred not NULL and persistent storage gets updated
+ *      OC_STACK_ERROR  - cred is NULL or fails to update persistent storage
+ */
+OCStackResult AddCredential(OicSecCred_t * newCred)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+
+    if(NULL == newCred)
+    {
+        return OC_STACK_ERROR;
+    }
+
+    //Append the new Cred to existing list
+    LL_APPEND(gCred, newCred);
+
+    //Convert CredList to JSON and update the persistent Storage
+    char * jsonStr = BinToCredJSON(gCred);
+
+    if(jsonStr)
+    {
+        cJSON *jsonCred = cJSON_Parse(jsonStr);
+        OICFree(jsonStr);
+
+        if((jsonCred) && (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_CRED_NAME, jsonCred)))
+        {
+            ret = OC_STACK_OK;
+        }
+        cJSON_Delete(jsonCred);
+    }
+
+    return ret;
+}
+
+static OCEntityHandlerResult HandlePostRequest(const OCEntityHandlerRequest * ehRequest)
+{
+    OCEntityHandlerResult ret = OC_EH_ERROR;
+
+    //Get binary representation of json
+    OicSecCred_t * cred  = JSONToCredBin((char *)ehRequest->reqJSONPayload);
+
+    if(cred)
+    {
+        //Append the new Cred to existing list
+        ret = (OC_STACK_OK == AddCredential(cred))? OC_EH_RESOURCE_CREATED : OC_EH_ERROR;
+    }
+
+    return ret;
+}
+
+/*
+ * This internal method is the entity handler for Cred resources
+ * to handle REST request (PUT/POST/DEL)
+ */
+OCEntityHandlerResult CredEntityHandler (OCEntityHandlerFlag flag,
+                                        OCEntityHandlerRequest * ehRequest)
+{
+    OCEntityHandlerResult ret = OC_EH_ERROR;
+
+    if(!ehRequest)
+    {
+        return OC_EH_ERROR;
+    }
+    if (flag & OC_REQUEST_FLAG)
+    {
+        OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+        //TODO :  Handle PUT/DEL methods
+        switch(ehRequest->method)
+        {
+            case OC_REST_GET:
+                ret = OC_EH_FORBIDDEN;
+                break;
+            case OC_REST_POST:
+                ret = HandlePostRequest(ehRequest);
+                break;
+            default:
+                ret = OC_EH_ERROR;
+                break;
+        }
+    }
+
+    //Send payload to request originator
+    ret = (SendSRMResponse(ehRequest, ret, NULL) == OC_STACK_OK ?
+                       ret : OC_EH_ERROR);
+
+    return ret;
+}
+
+/*
+ * This internal method is used to create '/oic/sec/Cred' resource.
+ */
+OCStackResult CreateCredResource()
+{
+    OCStackResult ret;
+
+    ret = OCCreateResource(&gCredHandle,
+                           OIC_RSRC_TYPE_SEC_CRED,
+                           OIC_MI_DEF,
+                           OIC_RSRC_CRED_URI,
+                           CredEntityHandler,
+                           OC_RES_PROP_NONE);
+
+    if (OC_STACK_OK != ret)
+    {
+        OC_LOG (FATAL, TAG, PCF("Unable to instantiate Cred resource"));
+        DeInitCredResource();
+    }
+    return ret;
+}
+
+/**
+ * Get the default value
+ * @retval  NULL for now. Update it when we finalize the default info.
+ */
+static OicSecCred_t* GetCredDefault()
+{
+    return NULL;
+}
+
+/**
+ * Initialize Cred resource by loading data from persistent storage.
+ *
+ * @retval
+ *     OC_STACK_OK    - no errors
+ *     OC_STACK_ERROR - stack process error
+ */
+OCStackResult InitCredResource()
+{
+    OCStackResult ret = OC_STACK_ERROR;
+
+    //Read Cred resource from PS
+    char* jsonSVRDatabase = GetSVRDatabase();
+
+    if (jsonSVRDatabase)
+    {
+        //Convert JSON Cred into binary format
+        gCred = JSONToCredBin(jsonSVRDatabase);
+    }
+    /*
+     * If SVR database in persistent storage got corrupted or
+     * is not available for some reason, a default Cred is created
+     * which allows user to initiate Cred provisioning again.
+     */
+    if (!jsonSVRDatabase || !gCred)
+    {
+        gCred = GetCredDefault();
+    }
+    //Instantiate 'oic.sec.cred'
+    ret = CreateCredResource();
+    OICFree(jsonSVRDatabase);
+    return ret;
+}
+
+/**
+ * Perform cleanup for Cred resources.
+ *
+ * @return
+ *     OC_STACK_OK              - no errors
+ *     OC_STACK_ERROR           - stack process error
+ *     OC_STACK_NO_RESOURCE     - resource not found
+ *     OC_STACK_INVALID_PARAM   - invalid param
+ */
+OCStackResult DeInitCredResource()
+{
+    OCStackResult result = OCDeleteResource(gCredHandle);
+    DeleteCredList(gCred);
+    gCred = NULL;
+    return result;
+}
+
+/**
+ * This method is used by tinydtls/SRM to retrieve credential for given Subject.
+ *
+ * @param subject - subject for which credential is required.
+ *
+ * @retval
+ *     reference to OicSecCred_t - if credential is found
+ *     NULL                      - if credential not found
+ */
+const OicSecCred_t* GetCredResourceData(const OicUuid_t* subject)
+{
+    OicSecCred_t *cred = NULL;
+
+    if ( NULL == subject)
+    {
+        return NULL;
+    }
+
+    LL_FOREACH(gCred, cred)
+    {
+        if(memcmp(cred->subject.id, subject->id, sizeof(subject->id)) == 0)
+        {
+             return cred;
+        }
+    }
+    return NULL;
+}
+
+
+#if defined(__WITH_DTLS__)
+/**
+ * This internal callback is used by lower stack (i.e. CA layer) to
+ * retrieve PSK credentials from RI security layer.
+ *
+ * Note: When finished, caller should initialize memory to zeros and
+ * invoke OICFree to delete @p credInfo.
+ *
+ * @param credInfo
+ *     binary blob containing PSK credentials
+ *
+ * @retval none
+ */
+void GetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo)
+{
+    CADtlsPskCredsBlob_t * caBlob = NULL;
+    if(credInfo)
+    {
+        caBlob = (CADtlsPskCredsBlob_t *)OICCalloc(sizeof(CADtlsPskCredsBlob_t), 1);
+        if (caBlob)
+        {
+            OicUuid_t deviceID = {};
+
+            // Retrieve Device ID from doxm resource and copy in PSK creds blob
+            VERIFY_SUCCESS(TAG, GetDoxmDeviceID(&deviceID) == OC_STACK_OK, ERROR);
+            memcpy(caBlob->identity, deviceID.id, sizeof(caBlob->identity));
+
+            OicSecCred_t *cred = NULL;
+            size_t count = 0;
+            LL_FOREACH(gCred, cred)
+            {
+                // Currently, Iotivity supports only symmetric pair wise key credentials
+                if (cred->credType == SYMMETRIC_PAIR_WISE_KEY)
+                {
+                    ++count;
+                }
+            }
+            caBlob->num = count;
+            if (caBlob->num)
+            {
+                caBlob->creds =
+                    (OCDtlsPskCreds*) OICMalloc(caBlob->num * sizeof(OCDtlsPskCreds));
+                VERIFY_NON_NULL(TAG, caBlob->creds, ERROR);
+
+                unsigned int i = 0;
+                LL_FOREACH(gCred, cred)
+                {
+                    if ((cred->credType == SYMMETRIC_PAIR_WISE_KEY) &&
+                            (i < count))
+
+                    {
+                        // Copy subject ID
+                        memcpy(caBlob->creds[i].id, cred->subject.id,
+                                sizeof(caBlob->creds[i].id));
+
+                        // Convert PSK from JSON to binary before copying
+                        uint32_t outLen = 0;
+                        B64Result b64Ret = b64Decode(cred->privateData.data,
+                                strlen(cred->privateData.data), caBlob->creds[i].psk,
+                                sizeof(caBlob->creds[i].psk), &outLen);
+                        VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+                        i++;
+                    }
+                }
+            }
+        }
+        *credInfo = caBlob;
+        // Return from here after making the credential list
+        return;
+    }
+
+exit:
+    if (caBlob)
+    {
+        memset(caBlob->creds, 0, caBlob->num * sizeof(OCDtlsPskCreds));
+        OICFree(caBlob->creds);
+    }
+    OICFree(caBlob);
+}
+#endif /* __WITH_DTLS__ */
diff --git a/resource/csdk/security/src/doxmresource.c b/resource/csdk/security/src/doxmresource.c
new file mode 100755 (executable)
index 0000000..eb6df1b
--- /dev/null
@@ -0,0 +1,654 @@
+//******************************************************************
+//
+// 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 "resourcemanager.h"
+#include "doxmresource.h"
+#include "psinterface.h"
+#include "utlist.h"
+#include "srmresourcestrings.h"
+#include "securevirtualresourcetypes.h"
+#include "base64.h"
+#include "ocrandom.h"
+#include "cainterface.h"
+#include "credresource.h"
+#include "ocserverrequest.h"
+#include "srmutility.h"
+#include "uthash.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define TAG  PCF("SRM-DOXM")
+
+static OicSecDoxm_t        *gDoxm = NULL;
+static OCResourceHandle    gDoxmHandle = NULL;
+
+static OicSecOxm_t gOicSecDoxmJustWorks = OIC_JUST_WORKS;
+static OicSecDoxm_t gDefaultDoxm =
+{
+    NULL,                   /* OicUrn_t *oxmType */
+    0,                      /* size_t oxmTypeLen */
+    &gOicSecDoxmJustWorks,  /* uint16_t *oxm */
+    1,                      /* size_t oxmLen */
+    OIC_JUST_WORKS,         /* uint16_t oxmSel */
+    false,                  /* bool owned */
+    {},                     /* OicUuid_t deviceID */
+    {},                     /* OicUuid_t owner */
+};
+
+void DeleteDoxmBinData(OicSecDoxm_t* doxm)
+{
+    if (doxm)
+    {
+        //Clean oxmType
+        for(int i = 0; i < doxm->oxmTypeLen; i++)
+        {
+            OICFree(doxm->oxmType[i]);
+        }
+        OICFree(doxm->oxmType);
+
+        //clean oxm
+        OICFree(doxm->oxm);
+
+        //Clean doxm itself
+        OICFree(doxm);
+    }
+}
+
+char * BinToDoxmJSON(const OicSecDoxm_t * doxm)
+{
+    if (NULL == doxm)
+    {
+        return NULL;
+    }
+
+    char *jsonStr = NULL;
+    cJSON *jsonDoxm = NULL;
+    char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*)0)->id)) + 1] = {};
+    uint32_t outLen = 0;
+    B64Result b64Ret = B64_OK;
+
+    cJSON *jsonRoot = cJSON_CreateObject();
+    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+    jsonDoxm = cJSON_CreateObject();
+    VERIFY_NON_NULL(TAG, jsonDoxm, ERROR);
+    cJSON_AddItemToObject(jsonRoot, OIC_JSON_DOXM_NAME, jsonDoxm );
+
+    //OxmType -- Not Mandatory
+    if(doxm->oxmTypeLen > 0)
+    {
+        cJSON *jsonOxmTyArray = cJSON_CreateArray();
+        VERIFY_NON_NULL(TAG, jsonOxmTyArray, ERROR);
+        cJSON_AddItemToObject (jsonDoxm, OIC_JSON_OXM_TYPE_NAME, jsonOxmTyArray );
+        for (size_t i = 0; i < doxm->oxmTypeLen; i++)
+        {
+            cJSON_AddItemToArray (jsonOxmTyArray, cJSON_CreateString(doxm->oxmType[i]));
+        }
+    }
+
+    //Oxm -- Not Mandatory
+    if(doxm->oxmLen > 0)
+    {
+        cJSON *jsonOxmArray = cJSON_CreateArray();
+        VERIFY_NON_NULL(TAG, jsonOxmArray, ERROR);
+        cJSON_AddItemToObject (jsonDoxm, OIC_JSON_OXM_NAME,jsonOxmArray );
+        for (size_t i = 0; i < doxm->oxmLen; i++)
+        {
+            cJSON_AddItemToArray (jsonOxmArray, cJSON_CreateNumber(doxm->oxm[i]));
+        }
+    }
+
+    //OxmSel -- Mandatory
+    cJSON_AddNumberToObject(jsonDoxm, OIC_JSON_OXM_SEL_NAME, (int)doxm->oxmSel);
+
+    //Owned -- Mandatory
+    cJSON_AddBoolToObject(jsonDoxm, OIC_JSON_OWNED_NAME, doxm->owned);
+
+    //TODO: Need more clarification on deviceIDFormat field type.
+#if 0
+    //DeviceIdFormat -- Mandatory
+    cJSON_AddNumberToObject(jsonDoxm, OIC_JSON_DEVICE_ID_FORMAT_NAME, doxm->deviceIDFormat);
+#endif
+
+    //DeviceId -- Mandatory
+    outLen = 0;
+    b64Ret = b64Encode(doxm->deviceID.id, sizeof(doxm->deviceID.id), base64Buff,
+                    sizeof(base64Buff), &outLen);
+    VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+    cJSON_AddStringToObject(jsonDoxm, OIC_JSON_DEVICE_ID_NAME, base64Buff);
+
+    //Owner -- Mandatory
+    outLen = 0;
+    b64Ret = b64Encode(doxm->owner.id, sizeof(doxm->owner.id), base64Buff,
+                    sizeof(base64Buff), &outLen);
+    VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+    cJSON_AddStringToObject(jsonDoxm, OIC_JSON_OWNER_NAME, base64Buff);
+
+    jsonStr = cJSON_PrintUnformatted(jsonRoot);
+
+exit:
+    if (jsonRoot)
+    {
+        cJSON_Delete(jsonRoot);
+    }
+    return jsonStr;
+}
+
+OicSecDoxm_t * JSONToDoxmBin(const char * jsonStr)
+{
+
+    if (NULL == jsonStr)
+    {
+        return NULL;
+    }
+
+    OCStackResult ret = OC_STACK_ERROR;
+    OicSecDoxm_t *doxm =  NULL;
+    cJSON *jsonDoxm = NULL;
+    cJSON *jsonObj = NULL;
+
+    size_t jsonObjLen = 0;
+    unsigned char base64Buff[sizeof(((OicUuid_t*)0)->id)] = {};
+    uint32_t outLen = 0;
+    B64Result b64Ret = B64_OK;
+
+    cJSON *jsonRoot = cJSON_Parse(jsonStr);
+    VERIFY_NON_NULL(TAG, jsonRoot, ERROR);
+
+    jsonDoxm = cJSON_GetObjectItem(jsonRoot, OIC_JSON_DOXM_NAME);
+    VERIFY_NON_NULL(TAG, jsonDoxm, ERROR);
+
+    doxm = (OicSecDoxm_t*)OICCalloc(1, sizeof(OicSecDoxm_t));
+    VERIFY_NON_NULL(TAG, doxm, ERROR);
+
+    //OxmType -- not Mandatory
+    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_TYPE_NAME);
+    if ((jsonObj) && (cJSON_Array == jsonObj->type))
+    {
+        doxm->oxmTypeLen = cJSON_GetArraySize(jsonObj);
+        VERIFY_SUCCESS(TAG, doxm->oxmTypeLen > 0, ERROR);
+
+        doxm->oxmType = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(char *));
+        VERIFY_NON_NULL(TAG, (doxm->oxmType), ERROR);
+
+        for(int i  = 0; i < doxm->oxmTypeLen ; i++)
+        {
+            cJSON *jsonOxmTy = cJSON_GetArrayItem(jsonObj, i);
+            VERIFY_NON_NULL(TAG, jsonOxmTy, ERROR);
+
+            jsonObjLen = strlen(jsonOxmTy->valuestring) + 1;
+            doxm->oxmType[i] = (char*)OICMalloc(jsonObjLen);
+            VERIFY_NON_NULL(TAG, doxm->oxmType[i], ERROR);
+            strncpy((char *)doxm->oxmType[i], (char *)jsonOxmTy->valuestring, jsonObjLen);
+        }
+    }
+
+    //Oxm -- not Mandatory
+    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_NAME);
+    if (jsonObj && cJSON_Array == jsonObj->type)
+    {
+        doxm->oxmLen = cJSON_GetArraySize(jsonObj);
+        VERIFY_SUCCESS(TAG, doxm->oxmLen > 0, ERROR);
+
+        doxm->oxm = (OicSecOxm_t*)OICCalloc(doxm->oxmLen, sizeof(short));
+        VERIFY_NON_NULL(TAG, doxm->oxm, ERROR);
+
+        for(int i  = 0; i < doxm->oxmLen ; i++)
+        {
+            cJSON *jsonOxm = cJSON_GetArrayItem(jsonObj, i);
+            VERIFY_NON_NULL(TAG, jsonOxm, ERROR);
+            doxm->oxm[i] = (OicSecOxm_t)jsonOxm->valueint;
+        }
+    }
+
+    //OxmSel -- Mandatory
+    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OXM_SEL_NAME);
+    if(jsonObj)
+    {
+        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
+    {
+        VERIFY_NON_NULL(TAG, gDoxm, ERROR);
+        doxm->oxmSel = gDoxm->oxmSel;
+    }
+
+    //Owned -- Mandatory
+    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNED_NAME);
+    if(jsonObj)
+    {
+        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
+    {
+        VERIFY_NON_NULL(TAG, gDoxm, ERROR);
+        doxm->owned = gDoxm->owned;
+    }
+
+    //DeviceId -- Mandatory
+    jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_DEVICE_ID_NAME);
+    if(jsonObj)
+    {
+        VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
+        if(jsonObj && cJSON_String == jsonObj->type)
+        {
+            //Check for empty string, in case DeviceId field has not been set yet
+            if (jsonObj->valuestring[0])
+            {
+                outLen = 0;
+                b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
+                        sizeof(base64Buff), &outLen);
+                VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(doxm->deviceID.id)),
+                                ERROR);
+                memcpy(doxm->deviceID.id, base64Buff, outLen);
+            }
+        }
+    }
+    else // PUT/POST JSON will not have deviceID so set it to the gDoxm->deviceID.id
+    {
+        VERIFY_NON_NULL(TAG, gDoxm, ERROR);
+        VERIFY_SUCCESS(TAG, strcmp((char *)gDoxm->deviceID.id, "") != 0, ERROR);
+        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)
+    {
+        jsonObj = cJSON_GetObjectItem(jsonDoxm, OIC_JSON_OWNER_NAME);
+        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(doxm->owner.id)), ERROR);
+        memcpy(doxm->owner.id, base64Buff, outLen);
+    }
+
+    ret = OC_STACK_OK;
+
+exit:
+    cJSON_Delete(jsonRoot);
+    if (OC_STACK_OK != ret)
+    {
+        DeleteDoxmBinData(doxm);
+        doxm = NULL;
+    }
+
+    return doxm;
+}
+
+static bool UpdatePersistentStorage(OicSecDoxm_t * doxm)
+{
+    bool bRet = false;
+
+    if (NULL != doxm)
+    {
+        // Convert Doxm data into JSON for update to persistent storage
+        char *jsonStr = BinToDoxmJSON(doxm);
+        if (jsonStr)
+        {
+            cJSON *jsonDoxm = cJSON_Parse(jsonStr);
+            OICFree(jsonStr);
+
+            if (jsonDoxm &&
+                    (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_DOXM_NAME, jsonDoxm)))
+            {
+                bRet = true;
+            }
+            cJSON_Delete(jsonDoxm);
+        }
+    }
+
+    return bRet;
+}
+
+static OCEntityHandlerResult HandleDoxmGetRequest (const OCEntityHandlerRequest * ehRequest)
+{
+    // Convert Doxm data into JSON for transmission
+    char* jsonStr = BinToDoxmJSON(gDoxm);
+
+    /*
+     * A device should 'always' have a default Doxm. Therefore,
+     * jsonStr should never be NULL.
+     */
+    OCEntityHandlerResult ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
+
+    // Send response payload to request originator
+    if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, jsonStr))
+    {
+        OC_LOG (ERROR, TAG, PCF("SendSRMResponse failed in HandlePstatGetRequest"));
+    }
+
+    OICFree(jsonStr);
+
+    return ehRet;
+}
+
+
+static OCEntityHandlerResult HandleDoxmPutRequest (const OCEntityHandlerRequest * ehRequest)
+{
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+    OicUuid_t emptyOwner = {};
+
+    /*
+     * Convert JSON Doxm data into binary. This will also validate
+     * the Doxm data received.
+     */
+    OicSecDoxm_t* newDoxm = JSONToDoxmBin((char *)(ehRequest->reqJSONPayload));
+
+    if (newDoxm)
+    {
+        // Iotivity SRM ONLY supports OIC_JUST_WORKS now
+        if (OIC_JUST_WORKS == newDoxm->oxmSel)
+        {
+            /*
+             * If current state of the device is un-owned, enable
+             * anonymous ECDH cipher in tinyDTLS so that Provisioning
+             * tool can initiate JUST_WORKS ownership transfer process.
+             */
+            if ((false == gDoxm->owned) && (false == newDoxm->owned))
+            {
+#ifdef __WITH_DTLS__
+                ehRet = (CAEnableAnonECDHCipherSuite(true) == CA_STATUS_OK) ? OC_EH_OK : OC_EH_ERROR;
+#endif //__WITH_DTLS__
+                goto exit;
+            }
+
+            /*
+             * 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))
+            {
+                /*
+                 * Generate OwnerPSK and create credential for Provisioning
+                 * tool with the generated OwnerPSK.
+                 * Update persistent storage and disable anonymous ECDH cipher
+                 *
+                 */
+#ifdef __WITH_DTLS__
+                CAResult_t pskRet;
+
+                OCServerRequest * request = (OCServerRequest *)ehRequest->requestHandle;
+                uint8_t ownerPSK[OWNER_PSK_LENGTH_128] = {};
+
+                //Generating OwnerPSK
+                pskRet = CAGenerateOwnerPSK(&request->addressInfo,
+                        request->connectivityType,
+                        (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);
+
+                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));
+
+                // Update new state in persistent storage
+                if (true == UpdatePersistentStorage(gDoxm))
+                {
+                    ehRet = OC_EH_OK;
+                }
+                else
+                {
+                    ehRet = OC_EH_ERROR;
+
+                    /*
+                     * If persistent storage update failed, revert back the state
+                     * for global variable.
+                     */
+                    gDoxm->owned = false;
+                    memset(&(gDoxm->owner), 0, sizeof(OicUuid_t));
+                }
+
+                /*
+                 * Disable anonymous ECDH cipher in tinyDTLS since device is now
+                 * in owned state.
+                 */
+                CAEnableAnonECDHCipherSuite(false);
+#endif //__WITH_DTLS__
+            }
+        }
+    }
+
+exit:
+
+    //Send payload to request originator
+    if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL))
+    {
+        OC_LOG (ERROR, TAG, PCF("SendSRMResponse failed in HandlePstatPostRequest"));
+    }
+    DeleteDoxmBinData(newDoxm);
+
+    return ehRet;
+}
+
+/*
+ * This internal method is the entity handler for DOXM resources.
+ */
+OCEntityHandlerResult DoxmEntityHandler (OCEntityHandlerFlag flag,
+                                        OCEntityHandlerRequest * ehRequest)
+{
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+
+    if(NULL == 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 = HandleDoxmGetRequest(ehRequest);
+                break;
+
+            case OC_REST_PUT:
+                ehRet = HandleDoxmPutRequest(ehRequest);
+                break;
+
+            default:
+                ehRet = OC_EH_ERROR;
+                SendSRMResponse(ehRequest, ehRet, NULL);
+                break;
+        }
+    }
+
+    return ehRet;
+}
+
+/*
+ * This internal method is used to create '/oic/sec/doxm' resource.
+ */
+OCStackResult CreateDoxmResource()
+{
+    OCStackResult ret;
+
+    ret = OCCreateResource(&gDoxmHandle,
+                           OIC_RSRC_TYPE_SEC_DOXM,
+                           OIC_MI_DEF,
+                           OIC_RSRC_DOXM_URI,
+                           DoxmEntityHandler,
+                           OC_OBSERVABLE);
+
+    if (OC_STACK_OK != ret)
+    {
+        OC_LOG (FATAL, TAG, PCF("Unable to instantiate Doxm resource"));
+        DeInitDoxmResource();
+    }
+    return ret;
+}
+
+/**
+ * Checks if DeviceID is generated during provisioning for the new device.
+ * If DeviceID is NULL then generates the new DeviceID.
+ * Once DeviceID is assigned to the device it does not change for the lifetime of the device.
+ *
+ */
+void CheckDeviceID()
+{
+    //TODO: Save this deviceID at secure location so that we can retrieve it if the
+    //JSON gets corrupted.
+    if(strcmp((char *)gDoxm->deviceID.id, "") == 0 )
+    {
+        OCFillRandomMem(gDoxm->deviceID.id, sizeof(gDoxm->deviceID.id));
+    }
+}
+
+/**
+ * Get the default value.
+ * @retval  the gDefaultDoxm pointer;
+ */
+static OicSecDoxm_t* GetDoxmDefault()
+{
+    OC_LOG (INFO, TAG, PCF("GetDoxmToDefault"));
+    return &gDefaultDoxm;
+}
+
+/**
+ * This method is used by SRM to retrieve DOXM resource data.
+ *
+ * @retval  reference to @ref OicSecDoxm_t, binary format of Doxm resource data
+ */
+const OicSecDoxm_t* GetDoxmResourceData()
+{
+    return gDoxm;
+}
+
+/**
+ * Initialize DOXM resource by loading data from persistent storage.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitDoxmResource()
+{
+    OCStackResult ret = OC_STACK_ERROR;
+
+    //Read DOXM resource from PS
+    char* jsonSVRDatabase = GetSVRDatabase();
+    if(jsonSVRDatabase)
+    {
+        //Convert JSON DOXM into binary format
+        gDoxm = JSONToDoxmBin(jsonSVRDatabase);
+    }
+    /*
+     * If SVR database in persistent storage got corrupted or
+     * is not available for some reason, a default doxm is created
+     * which allows user to initiate doxm provisioning again.
+     */
+    if(!jsonSVRDatabase || !gDoxm)
+    {
+        gDoxm = GetDoxmDefault();
+    }
+    CheckDeviceID();
+    //Instantiate 'oic.sec.doxm'
+    ret = CreateDoxmResource();
+    OICFree(jsonSVRDatabase);
+    return ret;
+}
+
+/**
+ * Perform cleanup for DOXM resources.
+ *
+ * @return
+ * OC_STACK_OK    - no error
+ * OC_STACK_ERROR - stack process error
+ *
+ */
+OCStackResult DeInitDoxmResource()
+{
+    OCStackResult ret = OCDeleteResource(gDoxmHandle);
+    if(gDoxm  != &gDefaultDoxm)
+    {
+        DeleteDoxmBinData(gDoxm);
+    }
+    gDoxm = NULL;
+
+    if(OC_STACK_OK == ret)
+    {
+        return OC_STACK_OK;
+    }
+    else
+    {
+        return OC_STACK_ERROR;
+    }
+}
+
+
+/**
+ * This method returns the SRM device ID for this device.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult GetDoxmDeviceID(OicUuid_t *deviceID)
+{
+    if(deviceID && gDoxm)
+    {
+       *deviceID = gDoxm->deviceID;
+        return OC_STACK_OK;
+    }
+    return OC_STACK_ERROR;
+}
+
+/**
+ * @brief Gets the OicUuid_t value for the owner of this device.
+ *
+ * @return OC_STACK_OK if devOwner is a valid UUID, otherwise OC_STACK_ERROR.
+ */
+OCStackResult GetDoxmDevOwnerId(OicUuid_t *devOwner)
+{
+    OCStackResult retVal = OC_STACK_ERROR;
+    if(gDoxm)
+    {
+        if(gDoxm->owned) {
+            *devOwner = gDoxm->owner; // TODO change to devOwner when available
+            retVal = OC_STACK_OK;
+        }
+    }
+    return retVal;
+}
diff --git a/resource/csdk/security/src/ocsecurity.c b/resource/csdk/security/src/ocsecurity.c
deleted file mode 100644 (file)
index 27e5b79..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-//******************************************************************
-//
-// Copyright 2014 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 "oic_malloc.h"
-#include "ocsecurity.h"
-#include "ocsecurityconfig.h"
-#include "cainterface.h"
-#include <string.h>
-
-static OCSecConfigData* secConfigData;
-static int secConfigDataLen;
-
-
-/**
- * This internal API removes/clears the global variable holding the security
- * config data. This needs to be invoked when OIC stack is shutting down.
- *
- * @retval none
- */
-void DeinitOCSecurityInfo()
-{
-    if (secConfigData)
-    {
-        // Initialize sensitive data to zeroes before freeing.
-        memset(secConfigData, 0, secConfigDataLen);
-
-        OICFree(secConfigData);
-        secConfigData = NULL;
-    }
-}
-
-/**
- * This internal callback is used by lower stack (i.e. CA layer) to
- * retrieve PSK credentials from RI security layer.
- *
- * Note: When finished, caller should initialize memory to zeroes and
- * invoke OICFree to delete @p credInfo.
- *
- * @param credInfo
- *     binary blob containing PSK credentials
- *
- * @retval none
- */
-#ifdef __WITH_DTLS__
-void GetDtlsPskCredentials(CADtlsPskCredsBlob_t **credInfo)
-{
-    // CA layer interface publishes security data structures ONLY if
-    // stack is compiled in SECURED mode
-    CADtlsPskCredsBlob_t * caBlob = NULL;
-    if(secConfigData && credInfo)
-    {
-        unsigned int i = 0;
-        OCSecBlob * osb = (OCSecBlob*)secConfigData->blob;
-        for ( ;(i<secConfigData->numBlob) && osb; i++)
-        {
-            if (osb->type == OC_BLOB_TYPE_PSK)
-            {
-                caBlob = (CADtlsPskCredsBlob_t *)OICCalloc(sizeof(CADtlsPskCredsBlob_t), 1);
-                if (caBlob)
-                {
-                    OCDtlsPskCredsBlob * ocBlob = (OCDtlsPskCredsBlob *)osb->val;
-
-                    memcpy(caBlob->identity, ocBlob->identity, sizeof(caBlob->identity));
-                    caBlob->num = ocBlob->num;
-                    caBlob->creds =
-                        (OCDtlsPskCreds*) OICMalloc(caBlob->num * sizeof(OCDtlsPskCreds));
-                    if (caBlob->creds)
-                    {
-                        memcpy(caBlob->creds, ocBlob->creds,
-                                caBlob->num * sizeof(OCDtlsPskCreds));
-                        *credInfo = caBlob;
-                        // We copied the credential blob in the CA data structure.
-                        // Let's get out of here.
-                        return;
-                    }
-                }
-                break;
-            }
-            osb = config_data_next_blob(osb);
-        }
-    }
-
-    // Clear memory if any memory allocation failed above
-    if(caBlob)
-    {
-        OICFree(caBlob->creds);
-        OICFree(caBlob);
-    }
-}
-#endif //__WITH_DTLS__
-
-
-/**
- * This method validates the sanctity of OCDtlsPskCredsBlob.
- *
- * @param secBlob
- *     binary blob containing PSK credentials
- *
- * @retval OC_STACK_OK for Success, otherwise some error value
- */
-static
-OCStackResult ValidateBlobTypePSK(const OCSecBlob *secBlob)
-{
-    OCDtlsPskCredsBlob *pskCredsBlob;
-    uint16_t validLen;
-
-    if(!secBlob || secBlob->len == 0)
-    {
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    pskCredsBlob = (OCDtlsPskCredsBlob *)secBlob->val;
-
-    //calculate the expected length of PSKCredsBlob
-    if(pskCredsBlob->num >= 1)
-    {
-        validLen = sizeof(OCDtlsPskCredsBlob) +
-            (pskCredsBlob->num - 1) * sizeof(OCDtlsPskCredsBlob);
-    }
-    else
-    {
-        validLen = sizeof(OCDtlsPskCredsBlob);
-    }
-
-    if(secBlob->len != validLen)
-        return OC_STACK_INVALID_PARAM;
-
-    return OC_STACK_OK;
-}
-
-
-/**
- * This method validates the sanctity of configuration data provided
- * by application to OC stack.
- *
- * @param cfgdata
- *     binary blob containing credentials and other config data
- * @param len
- *     length of binary blob
- *
- * @retval OC_STACK_OK for Success, otherwise some error value
- */
-static
-OCStackResult ValidateSecConfigData(const OCSecConfigData *cfgData,
-                size_t len)
-{
-    OCStackResult ret = OC_STACK_OK;
-    unsigned int i = 0;
-    OCSecBlob * osb = NULL;
-
-    if (!cfgData || (len == 0))
-    {
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    if (cfgData->version != OCSecConfigVer_CurrentVersion)
-    {
-        return OC_STACK_INVALID_PARAM;
-    }
-
-    osb = (OCSecBlob*)cfgData->blob;
-    for ( ;(i<cfgData->numBlob) && osb; i++)
-    {
-        if (osb->type == OC_BLOB_TYPE_PSK)
-        {
-            ret = ValidateBlobTypePSK(osb);
-        }
-        else
-        {
-            return OC_STACK_INVALID_PARAM;
-        }
-
-        if (ret != OC_STACK_OK)
-        {
-            return ret;
-        }
-        osb = config_data_next_blob(osb);
-    }
-
-    return ret;
-}
-
-
-
-/**
- * Provides the Security configuration data to OC stack.
- *
- * @param cfgdata
- *     binary blob containing credentials and other config data
- * @param len
- *     length of binary blob
- *
- * @retval OC_STACK_OK for Success, otherwise some error value
- */
-OCStackResult OCSecSetConfigData(const OCSecConfigData *cfgData,
-                size_t len)
-{
-    // Validate the data inside blob before consuming
-    if (cfgData && ValidateSecConfigData(cfgData, len) == OC_STACK_OK)
-    {
-        // Remove existing blob
-        DeinitOCSecurityInfo();
-        // Allocate storage for new blob
-        secConfigData = (OCSecConfigData*)OICMalloc(len);
-        if (secConfigData)
-        {
-            memcpy(secConfigData, cfgData, len);
-            secConfigDataLen = len;
-            return OC_STACK_OK;
-        }
-
-        return OC_STACK_NO_MEMORY;
-    }
-
-    return OC_STACK_INVALID_PARAM;
-}
-
-
-
diff --git a/resource/csdk/security/src/policyengine.c b/resource/csdk/security/src/policyengine.c
new file mode 100644 (file)
index 0000000..28ece4a
--- /dev/null
@@ -0,0 +1,368 @@
+//******************************************************************
+//
+// 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 "oic_malloc.h"
+#include "policyengine.h"
+#include "resourcemanager.h"
+#include "securevirtualresourcetypes.h"
+#include "srmresourcestrings.h"
+#include "logger.h"
+#include "aclresource.h"
+#include "srmutility.h"
+#include "doxmresource.h"
+#include <string.h>
+
+#define TAG PCF("SRM-PE")
+
+/**
+ * Return the uint16_t CRUDN permission corresponding to passed CAMethod_t.
+ */
+uint16_t GetPermissionFromCAMethod_t(const CAMethod_t method)
+{
+    uint16_t perm = 0;
+    switch(method)
+    {
+        case CA_GET:
+            perm = (uint16_t)PERMISSION_READ;
+            break;
+        case CA_POST: // For now we treat all PUT & POST as Write
+        case CA_PUT:  // because we don't know if resource exists yet.
+            perm = (uint16_t)PERMISSION_WRITE;
+            break;
+        case CA_DELETE:
+            perm = (uint16_t)PERMISSION_DELETE;
+            break;
+        default: // if not recognized, must assume requesting full control
+            perm = (uint16_t)PERMISSION_FULL_CONTROL;
+            break;
+    }
+    return perm;
+}
+
+/**
+ * @brief Compares two OicUuid_t structs.
+ * @return true if the two OicUuid_t structs are equal, else false.
+ */
+bool UuidCmp(OicUuid_t *firstId, OicUuid_t *secondId)
+{
+    // TODO use VERIFY macros to check for null when they are merged.
+    if(NULL == firstId || NULL == secondId)
+    {
+        return false;
+    }
+    for(int i = 0; i < UUID_LENGTH; i++)
+    {
+        if(firstId->id[i] != secondId->id[i])
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+
+/**
+ * Set the state and clear other stateful context vars.
+ */
+void SetPolicyEngineState(PEContext_t *context, const PEState_t state)
+{
+    // Clear stateful context variables.
+    OICFree(context->subject);
+    context->subject = NULL;
+    OICFree(context->resource);
+    context->resource = NULL;
+    context->permission = 0x0;
+    context->matchingAclFound = false;
+    context->retVal = ACCESS_DENIED_POLICY_ENGINE_ERROR;
+
+    // Set state.
+    context->state = state;
+}
+
+/**
+ * @brief Compare the request's subject to DevOwner.
+ *
+ * @return true if context->subjectId == GetDoxmDevOwner(), else false
+ */
+bool IsRequestFromDevOwner(PEContext_t *context)
+{
+    bool retVal = false;
+    OicUuid_t owner;
+
+    if(OC_STACK_OK == GetDoxmDevOwnerId(&owner))
+    {
+        retVal = UuidCmp(context->subject, &owner);
+    }
+
+    return retVal;
+}
+
+/**
+ * Bitwise check to see if 'permission' contains 'request'.
+ * @param   permission  The allowed CRUDN permission.
+ * @param   request     The CRUDN permission being requested.
+ * @return true if 'permission' bits include all 'request' bits.
+ */
+static inline bool IsPermissionAllowingRequest(const uint16_t permission,
+    const uint16_t request)
+{
+    if(request == (request & permission))
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+/**
+ * Compare the passed subject to the wildcard (aka anonymous) subjectId.
+ * @return true if 'subject' is the wildcard, false if it is not.
+ */
+static inline bool IsWildCardSubject(OicUuid_t *subject)
+{
+    // Because always comparing to string literal, use strcmp()
+    if(0 == memcmp(subject, &WILDCARD_SUBJECT_ID, sizeof(OicUuid_t)))
+    {
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+/**
+ * Copy the subject, resource and permission into the context fields.
+ */
+void CopyParamsToContext(
+    PEContext_t     *context,
+    const OicUuid_t *subjectId,
+    const char      *resource,
+    const uint16_t  requestedPermission)
+{
+    size_t length = 0;
+
+    // Free any existing subject.
+    OICFree(context->subject);
+    // Copy the subjectId into context.
+    context->subject = (OicUuid_t*)OICMalloc(sizeof(OicUuid_t));
+    VERIFY_NON_NULL(TAG, context->subject, ERROR);
+    memcpy(context->subject, subjectId, sizeof(OicUuid_t));
+
+    // Copy the resource string into context.
+    length = strlen(resource) + 1;
+    if(0 < length)
+    {
+        OICFree(context->resource);
+        context->resource = (char*)OICMalloc(length);
+        VERIFY_NON_NULL(TAG, context->resource, ERROR);
+        strncpy(context->resource, resource, length);
+        context->resource[length - 1] = '\0';
+    }
+
+    // Assign the permission field.
+    context->permission = requestedPermission;
+
+exit:
+    return;
+}
+
+/**
+ * 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?
+        {
+            return true;
+        }
+    }
+    return false;
+ }
+
+/**
+ * Find ACLs containing context->subject.
+ * Search each ACL for requested resource.
+ * If resource found, check for context->permission.
+ * Set context->retVal to result from first ACL found which contains
+ * correct subject AND resource.
+ *
+ * @retval void
+ */
+void ProcessAccessRequest(PEContext_t *context)
+{
+    OC_LOG(INFO, TAG, PCF("Entering ProcessAccessRequest()"));
+    if(NULL != context)
+    {
+        const OicSecAcl_t *currentAcl = NULL;
+        OicSecAcl_t *savePtr = NULL;
+
+        // Start out assuming subject not found.
+        context->retVal = ACCESS_DENIED_SUBJECT_NOT_FOUND;
+        do
+        {
+            OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): getting ACL..."));
+            currentAcl = GetACLResourceData(context->subject, &savePtr);
+            char *tmp = (char*)OICMalloc(sizeof(OicUuid_t) +1);
+            memcpy(tmp, context->subject, sizeof(OicUuid_t));
+            tmp[sizeof(OicUuid_t) + 1] = '\0';
+            if(NULL != currentAcl)
+            {
+                // Found the subject, so how about resource?
+                OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
+                    found ACL matching subject."));
+                context->retVal = ACCESS_DENIED_RESOURCE_NOT_FOUND;
+                OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
+                    Searching for resource..."));
+                if(IsResourceInAcl(context->resource, currentAcl))
+                {
+                    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))
+                    {
+                        context->retVal = ACCESS_GRANTED;
+                    }
+                }
+            }
+            else
+            {
+                OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
+                    no ACL found matching subject ."));
+            }
+        }
+        while((NULL != currentAcl) && (false == context->matchingAclFound));
+    }
+    if(IsAccessGranted(context->retVal))
+    {
+        OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
+            Leaving ProcessAccessRequest(ACCESS_GRANTED)"));
+    }
+    else
+    {
+        OC_LOG(INFO, TAG, PCF("ProcessAccessRequest(): \
+            Leaving ProcessAccessRequest(ACCESS_DENIED)"));
+    }
+}
+
+/**
+ * Check whether a request should be allowed.
+ * @param   context     Pointer to (Initialized) Policy Engine context to use.
+ * @param   subjectId   Pointer to Id of the requesting entity.
+ * @param   resource    Pointer to URI of Resource being requested.
+ * @param   permission  Requested permission.
+ * @return  ACCESS_GRANTED if request should go through,
+ *          otherwise some flavor of ACCESS_DENIED
+ */
+SRMAccessResponse_t CheckPermission(
+    PEContext_t     *context,
+    const OicUuid_t *subjectId,
+    const char      *resource,
+    const uint16_t  requestedPermission)
+{
+    SRMAccessResponse_t retVal = ACCESS_DENIED_POLICY_ENGINE_ERROR;
+
+    VERIFY_NON_NULL(TAG, context, ERROR);
+    VERIFY_NON_NULL(TAG, subjectId, ERROR);
+    VERIFY_NON_NULL(TAG, resource, ERROR);
+
+    // Each state machine context can only be processing one request at a time.
+    // Therefore if the context is not in AWAITING_REQUEST state, return error.
+    // Otherwise, change to BUSY state and begin processing request.
+    if(AWAITING_REQUEST == context->state)
+    {
+        SetPolicyEngineState(context, BUSY);
+        CopyParamsToContext(context, subjectId, resource, requestedPermission);
+        // Before doing any processing, check if request coming
+        // from DevOwner and if so, always GRANT.
+        if(IsRequestFromDevOwner(context))
+        {
+            context->retVal = ACCESS_GRANTED;
+        }
+        else
+        {
+            ProcessAccessRequest(context);
+            // If matching ACL not found, and subject != wildcard, try wildcard.
+            if((false == context->matchingAclFound) && \
+                (false == IsWildCardSubject(context->subject)))
+            {
+                OICFree(context->subject);
+                context->subject = (OicUuid_t*)OICMalloc(sizeof(OicUuid_t));
+                VERIFY_NON_NULL(TAG, context->subject, ERROR);
+                memcpy(context->subject, &WILDCARD_SUBJECT_ID,
+                    sizeof(OicUuid_t));
+                ProcessAccessRequest(context); // TODO anonymous subj can result
+                                               // in confusing err code return.
+            }
+        }
+    }
+    else
+    {
+        context->retVal = ACCESS_DENIED_POLICY_ENGINE_ERROR;
+    }
+
+    // Capture retVal before resetting state for next request.
+    retVal = context->retVal;
+    SetPolicyEngineState(context, AWAITING_REQUEST);
+
+exit:
+    return retVal;
+}
+
+/**
+ * Initialize the Policy Engine. Call this before calling CheckPermission().
+ * @param   context     Pointer to Policy Engine context to initialize.
+ * @return  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitPolicyEngine(PEContext_t *context)
+{
+    if(NULL != context)
+    {
+        SetPolicyEngineState(context, AWAITING_REQUEST);
+    }
+
+    return OC_STACK_OK;
+}
+
+/**
+ * De-Initialize the Policy Engine.  Call this before exiting to allow Policy
+ * Engine to do cleanup on context.
+ * @param   context     Pointer to Policy Engine context to de-initialize.
+ * @return  none
+ */
+void DeInitPolicyEngine(PEContext_t *context)
+{
+    if(NULL != context)
+    {
+        SetPolicyEngineState(context, STOPPED);
+    }
+
+    return;
+}
diff --git a/resource/csdk/security/src/psinterface.c b/resource/csdk/security/src/psinterface.c
new file mode 100644 (file)
index 0000000..f295fce
--- /dev/null
@@ -0,0 +1,200 @@
+//******************************************************************
+//
+// 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 "cainterface.h"
+#include "secureresourcemanager.h"
+#include "resourcemanager.h"
+#include "srmresourcestrings.h"
+#include "srmutility.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define TAG  PCF("SRM-PSI")
+
+//SVR database buffer block size
+const size_t DB_FILE_SIZE_BLOCK = 1023;
+
+/**
+ * Gets the Secure Virtual Database size.
+ *
+ * @param ps  pointer of OCPersistentStorage for the SVR name ("acl", "cred", "pstat" etc).
+ *
+ * @retval  total size of the SVR database.
+ */
+size_t GetSVRDatabaseSize(OCPersistentStorage* ps)
+{
+    size_t size = 0;
+    if (!ps)
+    {
+        return size;
+    }
+    size_t bytesRead  = 0;
+    char buffer[DB_FILE_SIZE_BLOCK];
+    FILE* fp = ps->open(SVR_DB_FILE_NAME, "r");
+    if (fp)
+    {
+        do
+        {
+            bytesRead = ps->read(buffer, 1, DB_FILE_SIZE_BLOCK, fp);
+            size += bytesRead;
+        } while (bytesRead > 0);
+        ps->close(fp);
+    }
+    return size;
+}
+
+/**
+ * Reads the Secure Virtual Database from PS into dynamically allocated
+ * memory buffer.
+ *
+ * @note Caller of this method MUST use OICFree() method to release memory
+ *       referenced by return value.
+ *
+ * @retval  reference to memory buffer containing SVR database.
+ */
+char * GetSVRDatabase()
+{
+    char * jsonStr = NULL;
+    FILE * fp = NULL;
+    OCPersistentStorage* ps = SRMGetPersistentStorageHandler();
+    int size = GetSVRDatabaseSize(ps);
+    if (0 == size)
+    {
+        OC_LOG (ERROR, TAG, PCF("FindSVRDatabaseSize failed"));
+        return NULL;
+    }
+
+    if (ps && ps->open)
+    {
+        // Open default SRM database file. An app could change the path for its server.
+        fp = ps->open(SVR_DB_FILE_NAME, "r");
+        if (fp)
+        {
+            jsonStr = (char*)OICMalloc(size + 1);
+            VERIFY_NON_NULL(TAG, jsonStr, FATAL);
+            size_t bytesRead = ps->read(jsonStr, 1, size, fp);
+            jsonStr[bytesRead] = '\0';
+
+            OC_LOG_V(INFO, TAG, PCF("Read %d bytes from SVR database file"), bytesRead);
+            ps->close(fp);
+            fp = NULL;
+        }
+        else
+        {
+            OC_LOG (ERROR, TAG, PCF("Unable to open SVR database file!!"));
+        }
+    }
+
+exit:
+    if (ps && fp)
+    {
+        ps->close(fp);
+    }
+    return jsonStr;
+}
+
+
+/**
+ * This method is used by a entity handlers of SVR's to update
+ * SVR database.
+ *
+ * @param rsrcName string denoting the SVR name ("acl", "cred", "pstat" etc).
+ * @param jsonObj JSON object containing the SVR contents.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult UpdateSVRDatabase(const char* rsrcName, cJSON* jsonObj)
+{
+    OCStackResult ret = OC_STACK_ERROR;
+    cJSON *jsonSVRDb = NULL;
+
+    // Read SVR database from PS
+    char* jsonSVRDbStr = GetSVRDatabase();
+    VERIFY_NON_NULL(TAG,jsonSVRDbStr, ERROR);
+
+    // Use cJSON_Parse to parse the existing SVR database
+    jsonSVRDb = cJSON_Parse(jsonSVRDbStr);
+    VERIFY_NON_NULL(TAG,jsonSVRDb, ERROR);
+
+    OICFree(jsonSVRDbStr);
+    jsonSVRDbStr = NULL;
+
+    if (jsonObj->child )
+    {
+        // Create a duplicate of the JSON object which was passed.
+        cJSON* jsonDuplicateObj = cJSON_Duplicate(jsonObj, 1);
+        VERIFY_NON_NULL(TAG,jsonDuplicateObj, ERROR);
+
+        cJSON* jsonObj = cJSON_GetObjectItem(jsonSVRDb, rsrcName);
+
+        /*
+         ACL, PStat & Doxm resources at least have default entries in the database but
+         Cred resource may have no entries. The first cred resource entry (for provisioning tool)
+         is created when the device is owned by provisioning tool and it's ownerpsk is generated.*/
+        if((strcmp(rsrcName, OIC_JSON_CRED_NAME) == 0) && (!jsonObj))
+        {
+            // Add the fist cred object in existing SVR database json
+            cJSON_AddItemToObject(jsonSVRDb, rsrcName, jsonDuplicateObj->child);
+        }
+        else
+        {
+            VERIFY_NON_NULL(TAG,jsonObj, ERROR);
+
+            // 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);
+
+        // Update the persistent storage with new SVR database
+        OCPersistentStorage* ps = SRMGetPersistentStorageHandler();
+        if (ps && ps->open)
+        {
+            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))
+                {
+                    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!! "));
+            }
+        }
+    }
+
+exit:
+    OICFree(jsonSVRDbStr);
+    cJSON_Delete(jsonSVRDb);
+
+    return ret;
+}
diff --git a/resource/csdk/security/src/pstatresource.c b/resource/csdk/security/src/pstatresource.c
new file mode 100644 (file)
index 0000000..19702a7
--- /dev/null
@@ -0,0 +1,399 @@
+//******************************************************************
+//
+// 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 "resourcemanager.h"
+#include "pstatresource.h"
+#include "psinterface.h"
+#include "utlist.h"
+#include "base64.h"
+#include "srmresourcestrings.h"
+#include "srmutility.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define TAG  PCF("SRM-PSTAT")
+
+static OicSecDpom_t gSm = SINGLE_SERVICE_CLIENT_DRIVEN;
+static OicSecPstat_t gDefaultPstat =
+{
+    false,                                    // bool isOwned
+    (OicSecDpm_t)(TAKE_OWNER | BOOTSTRAP_SERVICE | SECURITY_MANAGEMENT_SERVICES |
+    PROVISION_CREDENTIALS | PROVISION_ACLS),   // OicSecDpm_t cm
+    (OicSecDpm_t)(TAKE_OWNER | BOOTSTRAP_SERVICE | SECURITY_MANAGEMENT_SERVICES |
+    PROVISION_CREDENTIALS | PROVISION_ACLS),   // OicSecDpm_t tm
+    {},                                       // OicUuid_t deviceID
+    SINGLE_SERVICE_CLIENT_DRIVEN,             // OicSecDpom_t om */
+    1,                                        // the number of elts in Sms
+    &gSm,                                     // OicSecDpom_t *sm
+    0,                                        // uint16_t commitHash
+};
+static OicSecPstat_t    *gPstat = NULL;
+static OCResourceHandle gPstatHandle = NULL;
+
+void DeletePstatBinData(OicSecPstat_t* pstat)
+{
+    if (pstat)
+    {
+        //Clean 'supported modes' field
+        OICFree(pstat->sm);
+
+        //Clean pstat itself
+        OICFree(pstat);
+    }
+}
+
+char * BinToPstatJSON(const OicSecPstat_t * pstat)
+{
+    if(NULL == pstat)
+    {
+        return NULL;
+    }
+
+    cJSON *jsonPstat = NULL;
+    char *jsonStr = NULL;
+    cJSON *jsonSmArray = NULL;
+    char base64Buff[B64ENCODE_OUT_SAFESIZE(sizeof(((OicUuid_t*) 0)->id)) + 1] = {};
+    uint32_t outLen = 0;
+    B64Result b64Ret = B64_OK;
+
+    cJSON *jsonRoot = cJSON_CreateObject();
+    VERIFY_NON_NULL(TAG, jsonRoot, INFO);
+
+    cJSON_AddItemToObject(jsonRoot, OIC_JSON_PSTAT_NAME, jsonPstat=cJSON_CreateObject());
+    cJSON_AddBoolToObject(jsonPstat, OIC_JSON_ISOP_NAME, pstat->isOp);
+
+    b64Ret = b64Encode(pstat->deviceID.id,
+            sizeof(pstat->deviceID.id), base64Buff, sizeof(base64Buff), &outLen);
+    VERIFY_SUCCESS(TAG, b64Ret == B64_OK, ERROR);
+
+    cJSON_AddStringToObject(jsonPstat, OIC_JSON_DEVICE_ID_NAME, base64Buff);
+    cJSON_AddNumberToObject(jsonPstat, OIC_JSON_COMMIT_HASH_NAME, pstat->commitHash);
+    cJSON_AddNumberToObject(jsonPstat, OIC_JSON_CM_NAME, (int)pstat->cm);
+    cJSON_AddNumberToObject(jsonPstat, OIC_JSON_TM_NAME, (int)pstat->tm);
+    cJSON_AddNumberToObject(jsonPstat, OIC_JSON_OM_NAME, (int)pstat->om);
+
+    cJSON_AddItemToObject(jsonPstat, OIC_JSON_SM_NAME, jsonSmArray = cJSON_CreateArray());
+    VERIFY_NON_NULL(TAG, jsonSmArray, INFO);
+    for (int i = 0; i < pstat->smLen; i++)
+    {
+        cJSON_AddItemToArray(jsonSmArray, cJSON_CreateNumber((int )pstat->sm[i]));
+    }
+    jsonStr = cJSON_Print(jsonRoot);
+
+exit:
+    if (jsonRoot)
+    {
+        cJSON_Delete(jsonRoot);
+    }
+    return jsonStr;
+}
+
+OicSecPstat_t * JSONToPstatBin(const char * jsonStr)
+{
+    if(NULL == jsonStr)
+    {
+        return NULL;
+    }
+
+    OCStackResult ret = OC_STACK_ERROR;
+    OicSecPstat_t *pstat = NULL;
+    cJSON *jsonPstat = NULL;
+    cJSON *jsonObj = NULL;
+
+    unsigned char base64Buff[sizeof(((OicUuid_t*) 0)->id)] = {};
+    uint32_t outLen = 0;
+    B64Result b64Ret = B64_OK;
+
+    cJSON *jsonRoot = cJSON_Parse(jsonStr);
+    VERIFY_NON_NULL(TAG, jsonRoot, INFO);
+
+    jsonPstat = cJSON_GetObjectItem(jsonRoot, OIC_JSON_PSTAT_NAME);
+    VERIFY_NON_NULL(TAG, jsonPstat, INFO);
+
+    pstat = (OicSecPstat_t*)OICCalloc(1, sizeof(OicSecPstat_t));
+    VERIFY_NON_NULL(TAG, pstat, INFO);
+    jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_ISOP_NAME);
+    VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+    VERIFY_SUCCESS(TAG, (cJSON_True == jsonObj->type || cJSON_False == jsonObj->type) , ERROR);
+    pstat->isOp = jsonObj->valueint;
+
+    jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_DEVICE_ID_NAME);
+    VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+    VERIFY_SUCCESS(TAG, cJSON_String == jsonObj->type, ERROR);
+    b64Ret = b64Decode(jsonObj->valuestring, strlen(jsonObj->valuestring), base64Buff,
+                sizeof(base64Buff), &outLen);
+    VERIFY_SUCCESS(TAG, (b64Ret == B64_OK && outLen <= sizeof(pstat->deviceID.id)), ERROR);
+    memcpy(pstat->deviceID.id, base64Buff, outLen);
+
+    jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_COMMIT_HASH_NAME);
+    VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+    VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
+    pstat->commitHash  = jsonObj->valueint;
+
+    jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_CM_NAME);
+    VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+    VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
+    pstat->cm  = (OicSecDpm_t)jsonObj->valueint;
+
+    jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_OM_NAME);
+    VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+    VERIFY_SUCCESS(TAG, cJSON_Number == jsonObj->type, ERROR);
+    pstat->om  = (OicSecDpom_t)jsonObj->valueint;
+
+    jsonObj = cJSON_GetObjectItem(jsonPstat, OIC_JSON_SM_NAME);
+    VERIFY_NON_NULL(TAG, jsonObj, ERROR);
+    if (cJSON_Array == jsonObj->type)
+    {
+        pstat->smLen = cJSON_GetArraySize(jsonObj);
+        int idxx = 0;
+        VERIFY_SUCCESS(TAG, pstat->smLen != 0, ERROR);
+        pstat->sm = (OicSecDpom_t*)OICCalloc(pstat->smLen, sizeof(OicSecDpom_t));
+        VERIFY_NON_NULL(TAG, pstat->sm, ERROR);
+        do
+        {
+            cJSON *jsonSm = cJSON_GetArrayItem(jsonObj, idxx);
+            VERIFY_NON_NULL(TAG, jsonSm, ERROR);
+            pstat->sm[idxx] = (OicSecDpom_t)jsonSm->valueint;
+        }while ( ++idxx < pstat->smLen);
+    }
+    ret = OC_STACK_OK;
+
+exit:
+    cJSON_Delete(jsonRoot);
+    if (OC_STACK_OK != ret)
+    {
+        OC_LOG (ERROR, TAG, PCF("JSONToPstatBin failed"));
+        DeletePstatBinData(pstat);
+        pstat = NULL;
+    }
+    return pstat;
+}
+
+/**
+ * The entity handler determines how to process a GET request.
+ */
+static OCEntityHandlerResult HandlePstatGetRequest (const OCEntityHandlerRequest * ehRequest)
+{
+    // Convert ACL data into JSON for transmission
+    char* jsonStr = BinToPstatJSON(gPstat);
+
+    // A device should always have a default pstat. Therefore, jsonStr should never be NULL.
+    OCEntityHandlerResult ehRet = (jsonStr ? OC_EH_OK : OC_EH_ERROR);
+
+    // Send response payload to request originator
+    SendSRMResponse(ehRequest, ehRet, jsonStr);
+    OICFree(jsonStr);
+    return ehRet;
+}
+
+/**
+ * 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.
+ * For pstat, it updates only tm and om.
+ */
+static OCEntityHandlerResult HandlePstatPutRequest(const OCEntityHandlerRequest *ehRequest)
+{
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+    cJSON *postJson = NULL;
+
+    if (ehRequest->resource)
+    {
+        postJson = cJSON_Parse((char *) ehRequest->reqJSONPayload);
+        VERIFY_NON_NULL(TAG, postJson, INFO);
+        cJSON *jsonPstat = cJSON_GetObjectItem(postJson, OIC_JSON_PSTAT_NAME);
+        VERIFY_NON_NULL(TAG, jsonPstat, INFO);
+        cJSON *commitHashJson = cJSON_GetObjectItem(jsonPstat, OIC_JSON_COMMIT_HASH_NAME);
+        uint16_t commitHash = 0;
+        if (commitHashJson)
+        {
+            commitHash = commitHashJson->valueint;
+        }
+        cJSON *tmJson = cJSON_GetObjectItem(jsonPstat, OIC_JSON_TM_NAME);
+        if (tmJson && gPstat)
+        {
+            gPstat->tm = (OicSecDpm_t)tmJson->valueint;
+            if(0 == tmJson->valueint && gPstat->commitHash == commitHash)
+            {
+                gPstat->isOp = true;
+                gPstat->cm = NORMAL;
+                OC_LOG (INFO, TAG, PCF("CommitHash is valid and isOp is TRUE"));
+            }
+            else
+            {
+                OC_LOG (INFO, TAG, PCF("CommitHash is not valid"));
+            }
+        }
+        cJSON *omJson = cJSON_GetObjectItem(jsonPstat, OIC_JSON_OM_NAME);
+        if (omJson && gPstat)
+        {
+            /*
+             * Check if the operation mode is in the supported provisioning services
+             * operation mode list.
+             */
+            for(size_t i=0; i< gPstat->smLen; i++)
+            {
+                if(gPstat->sm[i] == omJson->valueint)
+                {
+                    gPstat->om = (OicSecDpom_t)omJson->valueint;
+                    break;
+                }
+            }
+        }
+        // Convert pstat data into JSON for update to persistent storage
+        char *jsonStr = BinToPstatJSON(gPstat);
+        if (jsonStr)
+        {
+            cJSON *jsonPstat = cJSON_Parse(jsonStr);
+            OICFree(jsonStr);
+            if (OC_STACK_OK == UpdateSVRDatabase(OIC_JSON_PSTAT_NAME, jsonPstat))
+            {
+                ehRet = OC_EH_OK;
+            }
+        }
+    }
+ exit:
+    //Send payload to request originator
+    if(OC_STACK_OK != SendSRMResponse(ehRequest, ehRet, NULL))
+    {
+        OC_LOG (ERROR, TAG, PCF("SendSRMResponse failed in HandlePstatPostRequest"));
+    }
+    cJSON_Delete(postJson);
+    return ehRet;
+}
+
+/**
+ * This internal method is the entity handler for pstat resources.
+ */
+OCEntityHandlerResult PstatEntityHandler(OCEntityHandlerFlag flag,
+        OCEntityHandlerRequest * ehRequest)
+{
+    OCEntityHandlerResult ehRet = OC_EH_ERROR;
+    // This method will handle REST request (GET/POST) for /oic/sec/pstat
+    if (flag & OC_REQUEST_FLAG)
+    {
+        OC_LOG (INFO, TAG, PCF("Flag includes OC_REQUEST_FLAG"));
+        switch (ehRequest->method)
+        {
+            case OC_REST_GET:
+                ehRet = HandlePstatGetRequest(ehRequest);
+                break;
+            case OC_REST_PUT:
+                ehRet = HandlePstatPutRequest(ehRequest);
+                break;
+            default:
+                ehRet = OC_EH_ERROR;
+                SendSRMResponse(ehRequest, ehRet, NULL);
+                break;
+        }
+    }
+    return ehRet;
+}
+
+/**
+ * This internal method is used to create '/oic/sec/pstat' resource.
+ */
+OCStackResult CreatePstatResource()
+{
+    OCStackResult ret;
+
+    ret = OCCreateResource(&gPstatHandle,
+                           OIC_RSRC_TYPE_SEC_PSTAT,
+                           OIC_MI_DEF,
+                           OIC_RSRC_PSTAT_URI,
+                           PstatEntityHandler,
+                           OC_RES_PROP_NONE);
+
+    if (ret != OC_STACK_OK)
+    {
+        OC_LOG (FATAL, TAG, PCF("Unable to instantiate pstat resource"));
+        DeInitPstatResource();
+    }
+    return ret;
+}
+
+/**
+ * Post ACL hander update the commitHash during ACL provisioning.
+ */
+void SetCommitHash(uint16_t commitHash)
+{
+    gPstat->commitHash = commitHash;
+}
+
+/**
+ * Get the default value
+ * @retval  the gDefaultPstat pointer
+ */
+static OicSecPstat_t* GetPstatDefault()
+{
+    return &gDefaultPstat;
+}
+
+/**
+ * Initialize pstat resource by loading data from persistent storage.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitPstatResource()
+{
+    OCStackResult ret = OC_STACK_ERROR;
+
+    // Read Pstat resource from PS
+    char* jsonSVRDatabase = GetSVRDatabase();
+    if (jsonSVRDatabase)
+    {
+        // Convert JSON Pstat into binary format
+        gPstat = JSONToPstatBin(jsonSVRDatabase);
+    }
+    /*
+     * If SVR database in persistent storage got corrupted or
+     * is not available for some reason, a default pstat is created
+     * which allows user to initiate pstat provisioning again.
+     */
+    if(!jsonSVRDatabase || !gPstat)
+    {
+        gPstat = GetPstatDefault();
+    }
+    // Instantiate 'oic.sec.pstat'
+    ret = CreatePstatResource();
+
+    OICFree(jsonSVRDatabase);
+    return ret;
+}
+
+/**
+ * Perform cleanup for pstat resources.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult DeInitPstatResource()
+{
+    if(gPstat != &gDefaultPstat)
+    {
+        DeletePstatBinData(gPstat);
+        gPstat = NULL;
+    }
+    return OCDeleteResource(gPstatHandle);
+}
+
diff --git a/resource/csdk/security/src/resourcemanager.c b/resource/csdk/security/src/resourcemanager.c
new file mode 100644 (file)
index 0000000..5a41bb9
--- /dev/null
@@ -0,0 +1,110 @@
+//******************************************************************
+//
+// 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 "resourcemanager.h"
+#include "securevirtualresourcetypes.h"
+#include "aclresource.h"
+#include "pstatresource.h"
+#include "doxmresource.h"
+#include "credresource.h"
+#include "oic_malloc.h"
+#include "logger.h"
+#include "utlist.h"
+#include <string.h>
+
+#define TAG PCF("SRM-RM")
+
+/**
+ * This method is used by all secure resource modules to send responses to REST queries.
+ *
+ * @param ehRequest pointer to entity handler request data structure.
+ * @param ehRet result code from entity handler.
+ * @param rspPayload response payload in JSON.
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult SendSRMResponse(const OCEntityHandlerRequest *ehRequest,
+        OCEntityHandlerResult ehRet, const char *rspPayload)
+{
+    OCEntityHandlerResponse response = {};
+    if (ehRequest)
+    {
+        response.requestHandle = ehRequest->requestHandle;
+        response.resourceHandle = ehRequest->resource;
+        response.ehResult = ehRet;
+        response.payload = (char *)rspPayload;
+        response.payloadSize = (rspPayload ? strlen(rspPayload) : 0);
+        response.persistentBufferFlag = 0;
+
+        return OCDoResponse(&response);
+    }
+    return OC_STACK_ERROR;
+}
+
+/**
+ * Initialize all secure resources ( /oic/sec/cred, /oic/sec/acl, /oic/sec/pstat etc).
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult InitSecureResources( )
+{
+    OCStackResult ret;
+
+    /*
+     * doxm resource should be initialized first as it contains the DeviceID
+     * which MAY be used during initialization of other resources.
+     */
+
+    ret = InitDoxmResource();
+
+    if(OC_STACK_OK == ret)
+    {
+        ret = InitPstatResource();
+    }
+    if(OC_STACK_OK == ret)
+    {
+        ret = InitACLResource();
+    }
+    if(OC_STACK_OK == ret)
+    {
+        ret = InitCredResource();
+    }
+    if(OC_STACK_OK != ret)
+    {
+        //TODO: Update the default behavior if one of the SVR fails
+        DestroySecureResources();
+    }
+    return ret;
+}
+
+/**
+ * Perform cleanup for secure resources ( /oic/sec/cred, /oic/sec/acl, /oic/sec/pstat etc).
+ *
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult DestroySecureResources( )
+{
+    DeInitACLResource();
+    DeInitCredResource();
+    DeInitDoxmResource();
+    DeInitPstatResource();
+
+    return OC_STACK_OK;
+}
diff --git a/resource/csdk/security/src/secureresourcemanager.c b/resource/csdk/security/src/secureresourcemanager.c
new file mode 100644 (file)
index 0000000..e3fd498
--- /dev/null
@@ -0,0 +1,263 @@
+//******************************************************************
+//
+// 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 "cainterface.h"
+#include "secureresourcemanager.h"
+#include "resourcemanager.h"
+#include "credresource.h"
+#include "policyengine.h"
+#include <string.h>
+
+#define TAG  PCF("SRM")
+
+//Request Callback handler
+static CARequestCallback gRequestHandler = NULL;
+//Response Callback handler
+static CAResponseCallback gResponseHandler = NULL;
+//Error Callback handler
+static CAErrorCallback gErrorHandler = NULL;
+//Persistent Storage callback handler for open/read/write/close/unlink
+static OCPersistentStorage *gPersistentStorageHandler =  NULL;
+
+/**
+ * A single global Policy Engine context will suffice as long
+ * as SRM is single-threaded.
+ */
+PEContext_t g_policyEngineContext;
+
+/**
+ * @brief   Handle the request from the SRM.
+ * @param   endPoint       [IN] Endpoint object from which the response is received.
+ * @param   requestInfo    [IN] Information for the request.
+ * @return  NONE
+ */
+void SRMRequestHandler(const CARemoteEndpoint_t *endPoint, const CARequestInfo_t *requestInfo)
+{
+    OC_LOG(INFO, TAG, PCF("Received request from remote device"));
+
+    if (!endPoint || !requestInfo)
+    {
+        OC_LOG(ERROR, TAG, PCF("Invalid arguments"));
+        return;
+    }
+
+    // Copy the subjectID
+    OicUuid_t subjectId = {};
+    memcpy(subjectId.id, endPoint->identity.id, sizeof(subjectId.id));
+
+    //Check the URI has the query and skip it before checking the permission
+    char *uri = strstr(endPoint->resourceUri, "?");
+    int position = 0;
+    if (uri)
+    {
+        position = uri - endPoint->resourceUri;
+    }
+    if (position > MAX_URI_LENGTH)
+    {
+        OC_LOG(ERROR, TAG, PCF("URI length is too long"));
+        return;
+    }
+    SRMAccessResponse_t response = ACCESS_DENIED;
+    if (position > 0)
+    {
+        char newUri[MAX_URI_LENGTH + 1];
+        strncpy(newUri, endPoint->resourceUri, (position));
+        newUri[position] = '\0';
+        //Skip query and pass the newUri.
+        response = CheckPermission(&g_policyEngineContext, &subjectId, newUri,
+                GetPermissionFromCAMethod_t(requestInfo->method));
+
+    }
+    else
+    {
+        //Pass endPoint->resourceUri if there is no query info.
+        response = CheckPermission(&g_policyEngineContext, &subjectId, endPoint->resourceUri,
+                GetPermissionFromCAMethod_t(requestInfo->method));
+    }
+    if (IsAccessGranted(response) && gRequestHandler)
+    {
+        return (gRequestHandler(endPoint, requestInfo));
+    }
+
+    // Form a 'access deny' or 'Error' response and send to peer
+    CAResponseInfo_t responseInfo = {};
+    memcpy(&responseInfo.info, &(requestInfo->info), sizeof(responseInfo.info));
+    responseInfo.info.payload = NULL;
+    if (!gRequestHandler)
+    {
+        responseInfo.result = CA_INTERNAL_SERVER_ERROR;
+    }
+    else
+    {
+        /*
+         * TODO Enhance this logic more to decide between
+         * CA_UNAUTHORIZED_REQ or CA_FORBIDDEN_REQ depending
+         * upon SRMAccessResponseReasonCode_t
+         */
+        responseInfo.result = CA_UNAUTHORIZED_REQ;
+    }
+
+    if (CA_STATUS_OK != CASendResponse(endPoint, &responseInfo))
+    {
+        OC_LOG(ERROR, TAG, PCF("Failed in sending response to a unauthorized request!"));
+    }
+}
+
+/**
+ * @brief   Handle the response from the SRM.
+ * @param   endPoint     [IN] The remote endpoint.
+ * @param   responseInfo [IN] Response information from the endpoint.
+ * @return  NONE
+ */
+void SRMResponseHandler(const CARemoteEndpoint_t *endPoint, const CAResponseInfo_t *responseInfo)
+{
+    OC_LOG(INFO, TAG, PCF("Received response from remote device"));
+    if (gResponseHandler)
+    {
+        gResponseHandler(endPoint, responseInfo);
+    }
+}
+
+
+/**
+ * @brief   Handle the error from the SRM.
+ * @param   endPoint  [IN] The remote endpoint.
+ * @param   errorInfo [IN] Error information from the endpoint.
+ * @return  NONE
+ */
+void SRMErrorHandler(const CARemoteEndpoint_t *endPoint, const CAErrorInfo_t *errorInfo)
+{
+    OC_LOG(INFO, TAG, PCF("Received error from remote device"));
+    if (gErrorHandler)
+    {
+        gErrorHandler(endPoint, errorInfo);
+    }
+}
+
+
+/**
+ * @brief   Register request and response callbacks.
+ *          Requests and responses are delivered in these callbacks.
+ * @param   reqHandler   [IN] Request handler callback ( for GET,PUT ..etc)
+ * @param   respHandler  [IN] Response handler callback.
+ * @return
+ *     OC_STACK_OK    - No errors; Success
+ *     OC_STACK_INVALID_PARAM - invalid parameter
+ */
+OCStackResult SRMRegisterHandler(CARequestCallback reqHandler,
+                                 CAResponseCallback respHandler,
+                                 CAErrorCallback errHandler)
+{
+    OC_LOG(INFO, TAG, PCF("SRMRegisterHandler !!"));
+    if( !reqHandler || !respHandler || !errHandler)
+    {
+        OC_LOG(ERROR, TAG, PCF("Callback handlers are invalid"));
+        return OC_STACK_INVALID_PARAM;
+    }
+    gRequestHandler = reqHandler;
+    gResponseHandler = respHandler;
+    gErrorHandler = errHandler;
+
+
+#if defined(__WITH_DTLS__)
+    CARegisterHandler(SRMRequestHandler, SRMResponseHandler, SRMErrorHandler);
+#else
+    CARegisterHandler(reqHandler, respHandler, errHandler);
+#endif /* __WITH_DTLS__ */
+    return OC_STACK_OK;
+}
+
+/**
+ * @brief   Register Persistent storage callback.
+ * @param   persistentStorageHandler [IN] Pointers to open, read, write, close & unlink handlers.
+ * @return
+ *     OC_STACK_OK    - No errors; Success
+ *     OC_STACK_INVALID_PARAM - Invalid parameter
+ */
+OCStackResult SRMRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler)
+{
+    OC_LOG(INFO, TAG, PCF("SRMRegisterPersistentStorageHandler !!"));
+    if(!persistentStorageHandler)
+    {
+        OC_LOG(ERROR, TAG, PCF("The persistent storage handler is invalid"));
+        return OC_STACK_INVALID_PARAM;
+    }
+    gPersistentStorageHandler = persistentStorageHandler;
+    return OC_STACK_OK;
+}
+
+/**
+ * @brief   Get Persistent storage handler pointer.
+ * @return
+ *     The pointer to Persistent Storage callback handler
+ */
+
+OCPersistentStorage* SRMGetPersistentStorageHandler()
+{
+    OC_LOG(INFO, TAG, PCF("SRMGetPersistentStorageHandler !!"));
+    return gPersistentStorageHandler;
+}
+
+
+/**
+ * @brief   Initialize all secure resources ( /oic/sec/cred, /oic/sec/acl, /oic/sec/pstat etc).
+ * @retval  OC_STACK_OK for Success, otherwise some error value
+ */
+OCStackResult SRMInitSecureResources()
+{
+    // TODO: temporarily returning OC_STACK_OK every time until default
+    // behavior (for when SVR DB is missing) is settled.
+    InitSecureResources();
+
+#if defined(__WITH_DTLS__)
+    CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials);
+#endif // (__WITH_DTLS__)
+
+    return OC_STACK_OK;
+}
+
+/**
+ * @brief   Perform cleanup for secure resources ( /oic/sec/cred, /oic/sec/acl, /oic/sec/pstat etc).
+ * @retval  none
+ */
+void SRMDeInitSecureResources()
+{
+    DestroySecureResources();
+}
+
+/**
+ * @brief   Initialize Policy Engine.
+ * @return  OC_STACK_OK for Success, otherwise some error value.
+ */
+OCStackResult SRMInitPolicyEngine()
+{
+    return InitPolicyEngine(&g_policyEngineContext);
+}
+
+/**
+ * @brief   Cleanup Policy Engine.
+ * @return  none
+ */
+void SRMDeInitPolicyEngine()
+{
+    return DeInitPolicyEngine(&g_policyEngineContext);
+}
diff --git a/resource/csdk/security/src/srmresourcestrings.c b/resource/csdk/security/src/srmresourcestrings.c
new file mode 100644 (file)
index 0000000..0a26ecc
--- /dev/null
@@ -0,0 +1,87 @@
+//******************************************************************
+//
+// 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 "securevirtualresourcetypes.h"
+
+const char * SVR_DB_FILE_NAME = "oic_svr_db.json";
+const char * OIC_MI_DEF = "oic.mi.def";
+
+const char * OIC_RSRC_CORE_URI =  "/oic/res";
+const char * OIC_RSRC_CORE_D_URI =  "/oic/res/d";
+const char * OIC_RSRC_CORE_P_URI =  "/oic/p";
+const char * OIC_RSRC_PRESENCE_URI =  "/oic/ad";
+const char * OIC_RSRC_TYPES_D_URI =  "/oic/res/types/d";
+
+//ACL
+const char * OIC_RSRC_TYPE_SEC_ACL = "oic.sec.acl";
+const char * OIC_RSRC_ACL_URI =  "/oic/sec/acl";
+const char * OIC_JSON_ACL_NAME = "acl";
+
+//Pstat
+const char * OIC_RSRC_TYPE_SEC_PSTAT = "oic.sec.pstat";
+const char * OIC_RSRC_PSTAT_URI =  "/oic/sec/pstat";
+const char * OIC_JSON_PSTAT_NAME = "pstat";
+
+//doxm
+const char * OIC_RSRC_TYPE_SEC_DOXM = "oic.sec.doxm";
+const char * OIC_RSRC_DOXM_URI =  "/oic/sec/doxm";
+const char * OIC_JSON_DOXM_NAME = "doxm";
+
+//cred
+const char * OIC_RSRC_TYPE_SEC_CRED = "oic.sec.cred";
+const char * OIC_RSRC_CRED_URI =  "/oic/sec/cred";
+const char * OIC_JSON_CRED_NAME = "cred";
+
+const char * OIC_JSON_SUBJECT_NAME = "sub";
+const char * OIC_JSON_RESOURCES_NAME = "rsrc";
+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_OWNED_NAME = "owned";
+const char * OIC_JSON_OXM_NAME = "oxm";
+const char * OIC_JSON_OXM_TYPE_NAME = "oxmtype";
+const char * OIC_JSON_OXM_SEL_NAME = "oxmsel";
+const char * OIC_JSON_DEVICE_ID_FORMAT_NAME = "dvcidfrmt";
+const char * OIC_JSON_ISOP_NAME = "isop";
+const char * OIC_JSON_COMMIT_HASH_NAME = "commithash";
+const char * OIC_JSON_DEVICE_ID_NAME = "deviceid";
+const char * OIC_JSON_CM_NAME = "cm";
+const char * OIC_JSON_TM_NAME = "tm";
+const char * OIC_JSON_OM_NAME = "om";
+const char * OIC_JSON_SM_NAME = "sm";
+const char * OIC_JSON_CREDID_NAME = "credid";
+const char * OIC_JSON_SUBJECTID_NAME = "subid";
+const char * OIC_JSON_ROLEIDS_NAME = "roleid";
+const char * OIC_JSON_CREDTYPE_NAME = "credtyp";
+const char * OIC_JSON_PUBLICDATA_NAME = "pbdata";
+const char * OIC_JSON_PRIVATEDATA_NAME = "pvdata";
+const char * OIC_JSON_PERIOD_NAME = "period";
+
+OicUuid_t WILDCARD_SUBJECT_ID = {"*"};
+size_t WILDCARD_SUBJECT_ID_LEN = 1 ;
+
+//Ownership Transfer Methods
+const char * OXM_JUST_WORKS = "oic.sec.doxm.jw";
+const char * OXM_MODE_SWITCH = "oic.sec.doxm.ms";
+const char * OXM_RANDOM_DEVICE_PIN = "oic.sec.doxm.rdp";
+const char * OXM_PRE_PROVISIONED_DEVICE_PIN = "oic.sec.doxm.ppdp";
+const char * OXM_PRE_PROVISIONED_STRONG_CREDENTIAL = "oic.sec.doxm.ppsc";
+
diff --git a/resource/csdk/security/unittest/SConscript b/resource/csdk/security/unittest/SConscript
new file mode 100644 (file)
index 0000000..7aea344
--- /dev/null
@@ -0,0 +1,102 @@
+# //******************************************************************
+# //
+# // 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.
+# //
+# //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+#
+
+Import('env')
+import os
+import os.path
+srmtest_env = env.Clone()
+
+src_dir = srmtest_env.get('SRC_DIR')
+
+######################################################################
+# Build flags
+######################################################################
+srmtest_env.PrependUnique(CPPPATH = [
+        '../../ocmalloc/include',
+               '../../connectivity/inc',
+               '../../connectivity/api',
+               '../../connectivity/external/inc',
+               '../include',
+               '../include/internal',
+               '../../logger/include',
+               '../../ocmalloc/include',
+               '../../stack/include',
+               '../../stack/include/internal',
+               '../../../oc_logger/include',
+               '../../../../extlibs/gtest/gtest-1.7.0/include',
+               '../../../../extlibs/cjson/',
+               '../include'
+               ])
+srmtest_env.AppendUnique(CXXFLAGS = ['-std=c++0x', '-Wall', '-pthread'])
+srmtest_env.AppendUnique(LIBS = ['-lpthread'])
+srmtest_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
+srmtest_env.AppendUnique(LIBPATH = [src_dir + '/extlibs/gtest/gtest-1.7.0/lib/.libs'])
+srmtest_env.PrependUnique(LIBS = ['ocsrm',
+                                    'octbstack',
+                                    'oc_logger',
+                                    'connectivity_abstraction',
+                                    'coap',
+                                    'gtest',
+                                    'gtest_main'])
+
+if env.get('SECURED') == '1':
+    srmtest_env.AppendUnique(LIBS = ['tinydtls'])
+
+if not env.get('RELEASE'):
+       srmtest_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+
+######################################################################
+# Source files and Targets
+######################################################################
+unittest = srmtest_env.Program('unittest', ['aclresourcetest.cpp',
+                                            'pstatresource.cpp',
+                                            'doxmresource.cpp',
+                                            'policyengine.cpp',
+                                            'securityresourcemanager.cpp',
+                                            'credentialresource.cpp',
+                                            'base64tests.cpp'])
+
+Alias("test", [unittest])
+
+unittest_src_dir = src_dir + '/resource/csdk/security/unittest/'
+unittest_build_dir = env.get('BUILD_DIR') +'/resource/csdk/security/unittest'
+
+srmtest_env.Alias("install", srmtest_env.Install( unittest_build_dir,
+    unittest_src_dir + 'oic_unittest.json'))
+srmtest_env.Alias("install", srmtest_env.Install( unittest_build_dir,
+    unittest_src_dir + 'oic_unittest_acl1.json'))
+srmtest_env.Alias("install", srmtest_env.Install( unittest_build_dir,
+    unittest_src_dir + 'oic_unittest_default_acl.json'))
+
+env.AppendTarget('test')
+if env.get('TEST') == '1':
+       target_os = env.get('TARGET_OS')
+       if target_os == 'linux':
+               out_dir = env.get('BUILD_DIR')
+               result_dir = env.get('BUILD_DIR') + '/test_out/'
+               if not os.path.isdir(result_dir):
+                       os.makedirs(result_dir)
+               srmtest_env.AppendENVPath('GTEST_OUTPUT', ['xml:'+ result_dir])
+               srmtest_env.AppendENVPath('LD_LIBRARY_PATH', [out_dir])
+               srmtest_env.AppendENVPath('LD_LIBRARY_PATH', ['./extlibs/gtest/gtest-1.7.0/lib/.libs'])
+               ut = srmtest_env.Command ('ut', None, out_dir + '/resource/csdk/security/unittest/unittest')
+               AlwaysBuild ('ut')
+
diff --git a/resource/csdk/security/unittest/aclresourcetest.cpp b/resource/csdk/security/unittest/aclresourcetest.cpp
new file mode 100644 (file)
index 0000000..0e6f5b7
--- /dev/null
@@ -0,0 +1,253 @@
+//******************************************************************
+//
+// 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 "aclresource.h"
+
+using namespace std;
+
+#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,
+                                        OCEntityHandlerRequest * ehRequest);
+#ifdef __cplusplus
+}
+#endif
+
+const char* JSON_FILE_NAME = "oic_unittest.json";
+const char* DEFAULT_ACL_JSON_FILE_NAME = "oic_unittest_default_acl.json";
+const char* ACL1_JSON_FILE_NAME = "oic_unittest_acl1.json";
+
+#define NUM_ACE_FOR_WILDCARD_IN_ACL1_JSON (2)
+
+char* ReadFile(const char* filename)
+{
+
+    FILE *fp = NULL;
+    char *data = NULL;
+    struct stat st;
+    // TODO: Find the location of the executable and concatenate the SVR file name
+    // before opening it.
+    fp = fopen(filename, "r");
+    if (fp)
+    {
+        if (stat(filename, &st) == 0)
+        {
+            data = (char*)OICMalloc(st.st_size);
+            if (data)
+            {
+                if (fread(data, 1, st.st_size, fp) != (size_t)st.st_size)
+                {
+                    printf("Error in reading file %s", filename);
+                }
+            }
+        }
+        fclose(fp);
+    }
+    else
+    {
+        printf("Unable to open %s file", filename);
+    }
+
+    return data;
+}
+
+void SetPersistentHandler(OCPersistentStorage *ps, bool set)
+{
+    if (set)
+    {
+        ps->open = fopen;
+        ps->read = fread;
+        ps->write = fwrite;
+        ps->close = fclose;
+        ps->unlink = unlink;
+    }
+    else
+    {
+        memset(ps, 0, sizeof(OCPersistentStorage));
+    }
+    EXPECT_EQ(OC_STACK_OK,
+            OCRegisterPersistentStorageHandler(ps));
+}
+
+// JSON Marshalling Tests
+TEST(ACLResourceTest, JSONMarshallingTests)
+{
+    char *jsonStr1 = ReadFile(ACL1_JSON_FILE_NAME);
+    if (jsonStr1)
+    {
+        cJSON_Minify(jsonStr1);
+        /* Workaround : cJSON_Minify does not remove all the unwanted characters
+         from the end. Here is an attempt to remove those characters */
+        int len = strlen(jsonStr1);
+        while (len > 0)
+        {
+            if (jsonStr1[--len] == '}')
+            {
+                break;
+            }
+        }
+        jsonStr1[len + 1] = 0;
+
+        OicSecAcl_t * acl = JSONToAclBin(jsonStr1);
+        EXPECT_TRUE(NULL != acl);
+
+        char * jsonStr2 = BinToAclJSON(acl);
+        EXPECT_TRUE(NULL != jsonStr2);
+
+        if (jsonStr1 && jsonStr2)
+        {
+            EXPECT_STREQ(jsonStr1, jsonStr2);
+        }
+
+        OICFree(jsonStr1);
+        OICFree(jsonStr2);
+        DeleteACLList(acl);
+    }
+}
+
+// Default ACL tests
+TEST(ACLResourceTest, GetDefaultACLTests)
+{
+    // Read default ACL from the file
+    char *jsonStr = ReadFile(DEFAULT_ACL_JSON_FILE_NAME);
+    if (jsonStr)
+    {
+        OicSecAcl_t * acl = JSONToAclBin(jsonStr);
+        EXPECT_TRUE(NULL != acl);
+
+        // Invoke API to generate default ACL
+        OicSecAcl_t * defaultAcl = NULL;
+        OCStackResult ret = GetDefaultACL(&defaultAcl);
+        EXPECT_TRUE(NULL == defaultAcl);
+
+        EXPECT_TRUE(OC_STACK_ERROR == ret);
+
+        // Verify if the SRM generated default ACL matches with unit test default
+        if (acl && defaultAcl)
+        {
+            EXPECT_TRUE(memcmp(&(acl->subject), &(defaultAcl->subject), sizeof(OicUuid_t)) == 0);
+            EXPECT_EQ(acl->resourcesLen, defaultAcl->resourcesLen);
+            for (size_t i = 0; i < acl->resourcesLen; i++)
+            {
+                EXPECT_EQ(strlen(acl->resources[i]), strlen(defaultAcl->resources[i]));
+                EXPECT_TRUE(
+                        memcmp(acl->resources[i], defaultAcl->resources[i],
+                                strlen(acl->resources[i])) == 0);
+            }
+            EXPECT_EQ(acl->permission, defaultAcl->permission);
+        }
+
+        // Perform cleanup
+        DeleteACLList(acl);
+        DeleteACLList(defaultAcl);
+        OICFree(jsonStr);
+    }
+}
+
+
+// 'POST' ACL tests
+TEST(ACLResourceTest, ACLPostTest)
+{
+    OCEntityHandlerRequest ehReq = {};
+
+    // Read an ACL from the file
+    char *jsonStr = ReadFile(ACL1_JSON_FILE_NAME);
+    if (jsonStr)
+    {
+        static OCPersistentStorage ps =
+        { };
+        SetPersistentHandler(&ps, true);
+
+        // Create Entity Handler POST request payload
+        ehReq.method = OC_REST_POST;
+        ehReq.reqJSONPayload = jsonStr;
+
+        OCEntityHandlerResult ehRet = ACLEntityHandler(OC_REQUEST_FLAG, &ehReq);
+        EXPECT_TRUE(OC_EH_ERROR == ehRet);
+
+        // Convert JSON into OicSecAcl_t for verification
+        OicSecAcl_t * acl = JSONToAclBin(jsonStr);
+        EXPECT_TRUE(NULL != acl);
+
+        // Verify if SRM contains ACL for the subject
+        OicSecAcl_t* savePtr = NULL;
+        const OicSecAcl_t* subjectAcl = GetACLResourceData(&(acl->subject), &savePtr);
+        EXPECT_TRUE(NULL != subjectAcl);
+
+        // Perform cleanup
+        DeleteACLList(acl);
+        DeInitACLResource();
+        OICFree(jsonStr);
+    }
+}
+
+
+// GetACLResource tests
+TEST(ACLResourceTest, GetACLResourceTests)
+{
+    // gAcl is a pointer to the the global ACL used by SRM
+    extern OicSecAcl_t  *gAcl;
+
+    // Read an ACL from the file
+    char *jsonStr = ReadFile(ACL1_JSON_FILE_NAME);
+    if (jsonStr)
+    {
+        gAcl = JSONToAclBin(jsonStr);
+        EXPECT_TRUE(NULL != gAcl);
+
+        // Verify that ACL file contains 2 ACE entries for 'WILDCARD' subject
+        const OicSecAcl_t* acl = NULL;
+        OicSecAcl_t* savePtr = NULL;
+        OicUuid_t subject = WILDCARD_SUBJECT_ID;
+        int count = 0;
+
+        do
+        {
+            acl = GetACLResourceData(&subject, &savePtr);
+            count = (NULL != acl) ? count + 1 : count;
+        } while (acl != NULL);
+
+        EXPECT_EQ(count, NUM_ACE_FOR_WILDCARD_IN_ACL1_JSON);
+
+        /* Perform cleanup */
+        DeleteACLList(gAcl);
+        gAcl = NULL;
+        OICFree(jsonStr);
+    }
+}
+
diff --git a/resource/csdk/security/unittest/base64tests.cpp b/resource/csdk/security/unittest/base64tests.cpp
new file mode 100644 (file)
index 0000000..4cce483
--- /dev/null
@@ -0,0 +1,260 @@
+ /******************************************************************
+  *
+  * 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 "base64.h"
+#include <stdlib.h>
+#include <stdint.h>
+
+// Tests for base64 encode function
+TEST(B64EncodeTest, ValidInputForEncoding)
+{
+    char buf[128];
+    uint32_t outputLength;
+    uint32_t expectedLength;
+    uint32_t i=0;
+    B64Result res = B64_OK;
+
+    const char* input = "IoTivity base64~!@#$%^&*()-=0123456789<>?;:'[]{},.\"\\|";
+
+    /**< expected output is generated from
+             "http://www.convertstring.com/EncodeDecode/Base64Encode" */
+    const char* expectedOutput[53] = {
+        "SQ==",
+        "SW8=",
+        "SW9U",
+        "SW9UaQ==",
+        "SW9UaXY=",
+        "SW9UaXZp",
+        "SW9UaXZpdA==",
+        "SW9UaXZpdHk=",
+        "SW9UaXZpdHkg",
+        "SW9UaXZpdHkgYg==",
+        "SW9UaXZpdHkgYmE=",
+        "SW9UaXZpdHkgYmFz",
+        "SW9UaXZpdHkgYmFzZQ==",
+        "SW9UaXZpdHkgYmFzZTY=",
+        "SW9UaXZpdHkgYmFzZTY0",
+        "SW9UaXZpdHkgYmFzZTY0fg==",
+        "SW9UaXZpdHkgYmFzZTY0fiE=",
+        "SW9UaXZpdHkgYmFzZTY0fiFA",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIw==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQ=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQl",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXg==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiY=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYq",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKA==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCk=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCkt",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPQ==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTA=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAx",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMg==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NQ==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3OA==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pg==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj8=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87Og==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87Oic=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87Oidb",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXQ==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXs=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LA==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LC4=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LC4i",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LC4iXA==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LC4iXHw="
+    };
+
+    for(i=0; i< strlen(input); i++)
+    {
+        memset(buf, 0, sizeof(buf));
+
+        expectedLength = strlen(expectedOutput[i]);
+
+        res = b64Encode((uint8_t*)input, i + 1, buf, 128, &outputLength);
+
+        EXPECT_EQ(B64_OK, res);
+        EXPECT_EQ(expectedLength, outputLength);
+        EXPECT_EQ(0, strcmp(expectedOutput[i], buf));
+    }
+}
+
+// Tests for base64 decode function
+TEST(B64DeodeTest, ValidInputForDecoding)
+{
+    uint8_t buf[128];
+    uint32_t outputLength;
+    uint32_t i=0;
+    B64Result res = B64_OK;
+
+    const char* input[53] = {
+        "SQ==",
+        "SW8=",
+        "SW9U",
+        "SW9UaQ==",
+        "SW9UaXY=",
+        "SW9UaXZp",
+        "SW9UaXZpdA==",
+        "SW9UaXZpdHk=",
+        "SW9UaXZpdHkg",
+        "SW9UaXZpdHkgYg==",
+        "SW9UaXZpdHkgYmE=",
+        "SW9UaXZpdHkgYmFz",
+        "SW9UaXZpdHkgYmFzZQ==",
+        "SW9UaXZpdHkgYmFzZTY=",
+        "SW9UaXZpdHkgYmFzZTY0",
+        "SW9UaXZpdHkgYmFzZTY0fg==",
+        "SW9UaXZpdHkgYmFzZTY0fiE=",
+        "SW9UaXZpdHkgYmFzZTY0fiFA",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIw==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQ=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQl",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXg==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiY=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYq",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKA==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCk=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCkt",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPQ==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTA=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAx",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMg==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NQ==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3OA==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pg==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj8=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87Og==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87Oic=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87Oidb",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXQ==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXs=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LA==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LC4=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LC4i",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LC4iXA==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LC4iXHw="
+    };
+    const char* expectedOutput = "IoTivity base64~!@#$%^&*()-=0123456789<>?;:'[]{},.\"\\|";
+
+    for(i=0; i< (sizeof(input)/sizeof(char*)); i++)
+    {
+        memset(buf, 0, sizeof(buf));
+
+        res = b64Decode(input[i], strlen(input[i]), buf, 128, &outputLength);
+
+        EXPECT_EQ(B64_OK, res);
+        EXPECT_EQ(i + 1, outputLength);
+        EXPECT_EQ(0, memcmp(expectedOutput, buf, i + 1));
+    }
+}
+
+// Tests for base64 decode function
+TEST(B64DeodeTest, InvalidInputForDecoding)
+{
+    uint8_t buf[128];
+    uint32_t outputLength;
+    uint32_t i=0;
+
+    const char* input[53] = {
+        "SQ=",
+        "Sw8=",
+        "SW1U",
+        "SW9Uaq==",
+        "SW9uaXY=",
+        "SW91UaXZp",
+        "SW9UaXZpdA.==",
+        "Sw9UAXZpdHk=",
+        "SW9UAXZpdHkg",
+        "SW9UaXZpdhkgYg==",
+        "SW9UaXZpd5kgYmE=",
+        "SW9UaXZ1dHkgYmFz",
+        "SW9UaXZpdHkgymFzZQ==",
+        "SW9UaXZpdHkgYmFzZTY==",
+        "SW9UaXZpdHkgYmFzZTY0=",
+        "SW9UaXZpdHkgYmFzZTY0fg=",
+        "SW9UaXZpdHkgYmFzZTY0fiE==",
+        "SW8UaXZpdHkgYmFzZTY0fiFA",
+        "SW9UaxzPDHkgYmFzZTY0fiFAIw==",
+        "SW9UaXZpdHKGYmFzZTY0fiFAIyQ=",
+        "SW9UaXZpdHkgYmFZztY0fiFAIyQl=",
+        "SW8UaXZpdHkgYmFzZTY0fiFAIyQlXg=",
+        "#SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiY=",
+        "SSW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYq",
+        "SW9UaXZpdHkgYmFzZTY0fiFAiyQlXiYqKA==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCk===",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKckt",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKcktpQ==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQiXiYqKCktPTA=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAx=",
+        "SW9UaXZpdHkgYmFzZTY0fifAIyQlXiYqKCktPTAxmg=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM#1=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM1",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0Nq==",
+        "sw9uaxzpdhkgymfzzty0fifaiyqlxiyqKcktptaxmjm0nty=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0nTY3",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3Ok==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3OA==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pg",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pg=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjm0NTY3ODk8Pj9=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXqKCktPTAxMjM0NTY3ODk8Pj87=",
+        "SW9UaXZpdHkgYmFzZTY0fiFaIyiYqKCktPTAxMjM0NTY3ODk8Pj87Og==",
+        "W9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87Oic1=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCkTAxMjM0NTY3ODk8Pj87Oidb==",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYCktPTAxMjM0NTY3ODk8Pj87Oidbxq==",
+        "SW9UaXZpdHkgYmzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87Oidbxxs=",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCkPTAxMjM0NTY3ODk8Pj87OidbXXT9",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9la==",
+        "SW9UaXZpdHkgYzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9Lc4=",
+        "SW9UaXZpdHkgYmFzZ0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9lC4i",
+        "SW9UaXZpdHkgYmFzZTY0fiFAIyQlXiYqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9lc4iXA==",
+        "SW9UaXZpdHkgYmFzZTY0fiFqKCktPTAxMjM0NTY3ODk8Pj87OidbXXt9LC4ixHw="
+    };
+    const char* expectedOutput = "IoTivity base64~!@#$%^&*()-=0123456789<>?;:'[]{},.\"\\|";
+
+    for(i=0; i< (sizeof(input)/sizeof(char*)); i++)
+    {
+        memset(buf, 0, sizeof(buf));
+
+        if( B64_OK == b64Decode(input[i], strlen(input[i]), buf, 128, &outputLength) )
+        {
+            EXPECT_NE(0, memcmp(expectedOutput, buf, i + 1));
+        }
+    }
+}
+
diff --git a/resource/csdk/security/unittest/credentialresource.cpp b/resource/csdk/security/unittest/credentialresource.cpp
new file mode 100644 (file)
index 0000000..31c5b55
--- /dev/null
@@ -0,0 +1,216 @@
+// 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 "ocstack.h"
+#include "resourcemanager.h"
+#include "securevirtualresourcetypes.h"
+#include "credresource.h"
+#include "oic_malloc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//Declare Cred resource methods for testing
+OCStackResult CreateCredResource();
+OCEntityHandlerResult CredEntityHandler (OCEntityHandlerFlag flag,
+                OCEntityHandlerRequest * ehRequest);
+char * BinToCredJSON(const OicSecCred_t * pstat);
+OicSecCred_t * JSONToCredBin(const char * jsonStr);
+void InitSecCredInstance(OicSecCred_t * cred);
+void DeleteCredList(OicSecCred_t* cred);
+#ifdef __cplusplus
+}
+#endif
+
+OicSecCred_t * getCredList()
+{
+    OicSecCred_t * cred = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
+    cred->credId = 1234;
+    strcpy((char *)cred->subject.id, "subject1");
+
+#if 0
+    cred->roleIdsLen = 2;
+    cred->roleIds = (OicSecRole_t *)OICCalloc(cred->roleIdsLen, sizeof(OicSecRole_t));
+    strcpy((char *)cred->roleIds[0].id, "role11");
+    strcpy((char *)cred->roleIds[1].id, "role12");
+#endif
+
+    cred->credType = 1;
+    cred->ownersLen = 1;
+    cred->owners = (OicUuid_t*)OICCalloc(cred->ownersLen, sizeof(OicUuid_t));
+    strcpy((char *)cred->owners[0].id, "ownersId11");
+
+    cred->next = (OicSecCred_t*)OICCalloc(1, sizeof(OicSecCred_t));
+    cred->next->credId = 5678;
+    strcpy((char *)cred->next->subject.id, "subject2");
+#if 0
+    cred->next->roleIdsLen = 0;
+#endif
+    cred->next->credType = 1;
+    cred->next->privateData.data = (char *)OICCalloc(1, strlen("My private Key21") + 1);
+    strcpy(cred->next->privateData.data, "My private Key21");
+#if 0
+    cred->next->publicData.data = (char *)OICCalloc(1, strlen("My Public Key123") + 1);
+    strcpy(cred->next->publicData.data, "My Public Key123");
+#endif
+    cred->next->ownersLen = 2;
+    cred->next->owners = (OicUuid_t*)OICCalloc(cred->next->ownersLen, sizeof(OicUuid_t));
+    strcpy((char *)cred->next->owners[0].id, "ownersId21");
+    strcpy((char *)cred->next->owners[1].id, "ownersId22");
+    return cred;
+}
+
+ //InitCredResource Tests
+TEST(InitCredResourceTest, InitCredResource)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, InitCredResource());
+}
+
+//DeInitCredResource Tests
+TEST(DeInitCredResourceTest, DeInitCredResource)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, DeInitCredResource());
+}
+
+//CreateCredResource Tests
+TEST(CreateCredResourceTest, CreateCredResource)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, CreateCredResource());
+}
+
+ //CredEntityHandler Tests
+TEST(CredEntityHandlerTest, CredEntityHandlerWithDummyRequest)
+{
+    OCEntityHandlerRequest 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));
+}
+
+TEST(CredEntityHandlerTest, CredEntityHandlerInvalidFlag)
+{
+    OCEntityHandlerRequest req;
+    EXPECT_EQ(OC_EH_ERROR, CredEntityHandler(OCEntityHandlerFlag::OC_OBSERVE_FLAG, &req));
+}
+
+//BinToCredJSON Tests
+TEST(BinToCredJSONTest, BinToCredJSONNullCred)
+{
+    char* value = BinToCredJSON(NULL);
+    EXPECT_TRUE(value == NULL);
+}
+
+TEST(BinToCredJSONTest, BinToCredJSONValidCred)
+{
+    char* json = NULL;
+    OicSecCred_t * cred = getCredList();
+
+    json = BinToCredJSON(cred);
+
+    printf("BinToCredJSON:%s\n", json);
+    EXPECT_TRUE(json != NULL);
+    DeleteCredList(cred);
+    OICFree(json);
+}
+
+//JSONToCredBin Tests
+TEST(JSONToCredBinTest, JSONToCredBinValidJSON)
+{
+    OicSecCred_t* cred1 = getCredList();
+    char* json = BinToCredJSON(cred1);
+
+    EXPECT_TRUE(json != NULL);
+    OicSecCred_t *cred2 = JSONToCredBin(json);
+    EXPECT_TRUE(cred2 == NULL);
+    DeleteCredList(cred1);
+    DeleteCredList(cred2);
+    OICFree(json);
+}
+
+TEST(JSONToCredBinTest, JSONToCredBinNullJSON)
+{
+    OicSecCred_t *cred = JSONToCredBin(NULL);
+    EXPECT_TRUE(cred == NULL);
+}
+
+//GetCredResourceData Test
+TEST(CredGetResourceDataTest, GetCredResourceDataNULLSubject)
+{
+    EXPECT_TRUE(NULL == GetCredResourceData(NULL));
+}
+
+TEST(CredGenerateCredentialTest, GenerateCredentialValidInput)
+{
+    OicUuid_t owners[1];
+   strcpy((char *)owners[0].id, "ownersId21");
+
+    OicUuid_t subject = {};
+    strcpy((char *)subject.id, "subject11");
+
+    char privateKey[] = "My private Key11";
+
+    OicSecCred_t * cred  = NULL;
+
+    cred = GenerateCredential(&subject, SYMMETRIC_PAIR_WISE_KEY, NULL,
+                             privateKey, 1, owners);
+    printf("cred->credId = %d\n", cred->credId);
+    printf("cred->subject.id = %s\n", cred->subject.id);
+    printf("cred->credType = %d\n", cred->credType);
+    printf("cred->privateData.data = %s\n", cred->privateData.data);
+    printf("cred->ownersLen = %zd\n", cred->ownersLen);
+    printf("cred->owners[0].id = %s\n", cred->owners[0].id);
+
+    EXPECT_TRUE(NULL != cred);
+    DeleteCredList(cred);
+}
+
+TEST(CredAddCredentialTest, GenerateCredentialValidInput)
+{
+    OicUuid_t owners[1];
+    strcpy((char *)owners[0].id, "ownersId21");
+
+    OicUuid_t subject = {};
+    strcpy((char *)subject.id, "subject11");
+
+    char privateKey[] = "My private Key11";
+
+    OicSecCred_t * cred  = NULL;
+
+    cred = GenerateCredential(&subject, SYMMETRIC_PAIR_WISE_KEY, NULL,
+                                 privateKey, 1, owners);
+    EXPECT_TRUE(NULL != cred);
+
+    EXPECT_EQ(OC_STACK_ERROR, AddCredential(cred));
+
+    DeleteCredList(cred);
+
+}
+#if 0
+TEST(CredGetResourceDataTest, GetCredResourceDataValidSubject)
+{
+    OicSecCred_t* cred = getCredList();
+    EXPECT_TRUE(NULL != GetCredResourceData(cred->subject));
+}
+#endif
+
+
diff --git a/resource/csdk/security/unittest/doxmresource.cpp b/resource/csdk/security/unittest/doxmresource.cpp
new file mode 100644 (file)
index 0000000..13e03b7
--- /dev/null
@@ -0,0 +1,163 @@
+// 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 "ocstack.h"
+#include "resourcemanager.h"
+#include "securevirtualresourcetypes.h"
+#include "srmresourcestrings.h"
+#include "doxmresource.h"
+#include "ocserverrequest.h"
+#include "oic_malloc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//Declare Doxm resource methods for testing
+OCStackResult CreateDoxmResource();
+OCEntityHandlerResult DoxmEntityHandler (OCEntityHandlerFlag flag,
+                OCEntityHandlerRequest * ehRequest);
+char * BinToDoxmJSON(const OicSecDoxm_t * doxm);
+OicSecDoxm_t * JSONToDoxmBin(const char * jsonStr);
+void InitSecDoxmInstance(OicSecDoxm_t * doxm);
+OCEntityHandlerResult HandleDoxmPostRequest (const OCEntityHandlerRequest * ehRequest);
+void DeleteDoxmBinData(OicSecDoxm_t* doxm);
+#ifdef __cplusplus
+}
+#endif
+
+OicSecDoxm_t * getBinDoxm()
+{
+    OicSecDoxm_t * doxm = (OicSecDoxm_t*)OICCalloc(1, sizeof(OicSecDoxm_t));
+    doxm->oxmTypeLen =  1;
+    doxm->oxmType    = (OicUrn_t *)OICCalloc(doxm->oxmTypeLen, sizeof(char *));
+    doxm->oxmType[0] = (char*)OICMalloc(strlen(OXM_JUST_WORKS) + 1);
+    strcpy(doxm->oxmType[0], OXM_JUST_WORKS);
+    doxm->oxmLen     = 1;
+    doxm->oxm        = (OicSecOxm_t *)OICCalloc(doxm->oxmLen, sizeof(short));
+    doxm->oxm[0]     = OIC_JUST_WORKS;
+    doxm->oxmSel     = OIC_JUST_WORKS;
+    doxm->owned      = true;
+    //TODO: Need more clarification on deviceIDFormat field type.
+    //doxm.deviceIDFormat = URN;
+    strcpy((char *) doxm->deviceID.id, "deviceId");
+    strcpy((char *)doxm->owner.id, "ownersId");
+    return doxm;
+}
+
+ //InitDoxmResource Tests
+TEST(InitDoxmResourceTest, InitDoxmResource)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, InitDoxmResource());
+}
+
+//DeInitDoxmResource Tests
+TEST(DeInitDoxmResourceTest, DeInitDoxmResource)
+{
+    EXPECT_EQ(OC_STACK_ERROR, DeInitDoxmResource());
+}
+
+//CreateDoxmResource Tests
+TEST(CreateDoxmResourceTest, CreateDoxmResource)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, CreateDoxmResource());
+}
+
+ //DoxmEntityHandler Tests
+TEST(DoxmEntityHandlerTest, DoxmEntityHandlerWithDummyRequest)
+{
+    OCEntityHandlerRequest req;
+    EXPECT_EQ(OC_EH_ERROR, DoxmEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, &req));
+}
+
+TEST(DoxmEntityHandlerTest, DoxmEntityHandlerWithNULLRequest)
+{
+    EXPECT_EQ(OC_EH_ERROR, DoxmEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, NULL));
+}
+
+TEST(DoxmEntityHandlerTest, DoxmEntityHandlerInvalidFlag)
+{
+    OCEntityHandlerRequest req;
+    EXPECT_EQ(OC_EH_ERROR, DoxmEntityHandler(OCEntityHandlerFlag::OC_OBSERVE_FLAG, &req));
+}
+
+//BinToDoxmJSON Tests
+TEST(BinToDoxmJSONTest, BinToDoxmJSONNullDoxm)
+{
+    char* value = BinToDoxmJSON(NULL);
+    EXPECT_TRUE(value == NULL);
+}
+
+TEST(BinToDoxmJSONTest, BinToDoxmJSONValidDoxm)
+{
+    OicSecDoxm_t * doxm =  getBinDoxm();
+
+    char * json = BinToDoxmJSON(doxm);
+    printf("BinToDoxmJSON:%s\n", json);
+    EXPECT_TRUE(json != NULL);
+
+    DeleteDoxmBinData(doxm);
+    OICFree(json);
+}
+
+//JSONToDoxmBin Tests
+TEST(JSONToDoxmBinTest, JSONToDoxmBinValidJSON)
+{
+    OicSecDoxm_t * doxm1 =  getBinDoxm();
+    char * json = BinToDoxmJSON(doxm1);
+    EXPECT_TRUE(json != NULL);
+
+    OicSecDoxm_t *doxm2 = JSONToDoxmBin(json);
+    EXPECT_TRUE(doxm2 != NULL);
+
+    DeleteDoxmBinData(doxm1);
+    OICFree(json);
+}
+
+TEST(JSONToDoxmBinTest, JSONToDoxmBinNullJSON)
+{
+    OicSecDoxm_t *doxm = JSONToDoxmBin(NULL);
+    EXPECT_TRUE(doxm == NULL);
+}
+
+//GetDoxmResourceData Test
+TEST(DoxmGetResourceDataTest, GetDoxmResourceData)
+{
+    EXPECT_TRUE(NULL == GetDoxmResourceData());
+}
+#if 0
+TEST(HandleDoxmPostRequestTest, HandleDoxmPostRequestValidInput)
+{
+    OCEntityHandlerRequest ehRequest = {};
+    OCServerRequest svRequest = {};
+
+    OicSecDoxm_t * doxm =  getBinDoxm();
+
+    strcpy(svRequest.addressInfo.IP.ipAddress, "10.10.10.10");
+    svRequest.addressInfo.IP.port = 2345;
+    svRequest.connectivityType = CA_ETHERNET;
+
+    ehRequest.reqJSONPayload = (unsigned char *) BinToDoxmJSON(doxm);
+    ehRequest.requestHandle = (OCRequestHandle) &svRequest;
+
+    EXPECT_EQ(OC_EH_ERROR, HandleDoxmPostRequest(&ehRequest));
+    DeleteDoxmBinData(doxm);
+    OICFree(ehRequest.reqJSONPayload);
+}
+#endif
diff --git a/resource/csdk/security/unittest/oic_svr_db.json b/resource/csdk/security/unittest/oic_svr_db.json
new file mode 100644 (file)
index 0000000..721a8bf
--- /dev/null
@@ -0,0 +1,45 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/d",
+                "/oic/p",
+                "/oic/res/types/d",
+                "/oic/ad"
+                       ],
+                       "perms": 2,
+                       "ownrs" : [
+                               "MjIyMjIyMjIyMjIyMjIyMg=="
+                       ]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat",
+                "/oic/sec/acl"
+           ],
+             "perms": 6,
+             "ownrs" : [
+                 "MjIyMjIyMjIyMjIyMjIyMg=="
+             ]
+        }
+       ],
+       "pstat":        {
+               "isop": false,
+               "deviceid":     "ZGV2aWNlaWQAAAAAABhanw==",
+               "commithash": 0,
+               "cm":   0,
+               "tm":   0,
+               "om":   3,
+               "sm":   [3]
+       },
+       "doxm": {
+               "oxm":  [0],
+               "oxmsel": 0,
+               "owned": false,
+               "deviceid":     "MjIyMjIyMjIyMjIyMjIyMg=="
+       }
+}
diff --git a/resource/csdk/security/unittest/oic_unittest.json b/resource/csdk/security/unittest/oic_unittest.json
new file mode 100644 (file)
index 0000000..7663880
--- /dev/null
@@ -0,0 +1,37 @@
+{
+    "acl": [
+        {
+            "sub": "MTExMTExMTExMTExMTExMQ==",
+            "rsrc": [
+                               "/oic/light",
+                               "/oic/fan"
+                       ],
+                       "perms": 255,
+                       "ownrs" : [
+                               "MjIyMjIyMjIyMjIyMjIyMg=="
+                       ]
+               },
+               {
+            "sub": "MzMzMzMzMzMzMzMzMzMzMw==",
+            "rsrc": [
+                               "/oic/light",
+                               "/oic/garage"
+                       ],
+                       "perms": 255,
+                       "ownrs" : [
+                               "MjIyMjIyMjIyMjIyMjIyMg==",
+                "NDQ0NDQ0NDQ0NDQ0NDQ0NA=="
+                       ]
+               }
+       ],
+
+       "pstat":        {
+               "isop": false,
+               "deviceid":     "ZGV2aWNlaWQAAAAAABhanw==",
+               "commithash":   1234,
+               "cm":   63,
+               "tm":   48,
+               "om":   0,
+               "sm":   [3, 1]
+       }
+}
diff --git a/resource/csdk/security/unittest/oic_unittest_acl1.json b/resource/csdk/security/unittest/oic_unittest_acl1.json
new file mode 100644 (file)
index 0000000..a179c2c
--- /dev/null
@@ -0,0 +1,53 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/d",
+                "/oic/p",
+                "/oic/res/types/d",
+                "/oic/ad",
+                "/oic/sec/acl"
+                       ],
+                       "perms": 2,
+                       "ownrs" : [
+                               "MjIyMjIyMjIyMjIyMjIyMg=="
+                       ]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat"
+                       ],
+                       "perms": 6,
+                       "ownrs" : [
+                               "MjIyMjIyMjIyMjIyMjIyMg=="
+                       ]
+               },
+        {
+            "sub": "MTExMTExMTExMTExMTExMQ==",
+            "rsrc": [
+                               "/oic/light",
+                               "/oic/fan"
+                       ],
+                       "perms": 255,
+                       "ownrs" : [
+                               "MjIyMjIyMjIyMjIyMjIyMg=="
+                       ]
+               },
+               {
+            "sub": "MzMzMzMzMzMzMzMzMzMzMw==",
+            "rsrc": [
+                               "/oic/light",
+                               "/oic/garage"
+                       ],
+                       "perms": 255,
+                       "ownrs" : [
+                               "MjIyMjIyMjIyMjIyMjIyMg==",
+                "NDQ0NDQ0NDQ0NDQ0NDQ0NA=="
+                       ]
+               }
+       ]
+}
diff --git a/resource/csdk/security/unittest/oic_unittest_default_acl.json b/resource/csdk/security/unittest/oic_unittest_default_acl.json
new file mode 100644 (file)
index 0000000..7f3d449
--- /dev/null
@@ -0,0 +1,21 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/d",
+                "/oic/p",
+                "/oic/res/types/d",
+                "/oic/ad",
+                "/oic/sec/acl",
+                "/oic/sec/doxm",
+                "/oic/sec/pstat"
+                       ],
+                       "perms": 2,
+                       "ownrs" : [
+                               "MjIyMjIyMjIyMjIyMjIyMg=="
+                       ]
+               }
+       ]
+}
diff --git a/resource/csdk/security/unittest/policyengine.cpp b/resource/csdk/security/unittest/policyengine.cpp
new file mode 100644 (file)
index 0000000..8ad43a8
--- /dev/null
@@ -0,0 +1,110 @@
+//******************************************************************
+//
+// 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 "ocstack.h"
+#include "cainterface.h"
+#include "srmresourcestrings.h"
+
+using namespace std;
+
+#define PE_UT_TAG "\tPE-UT-message: "
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "policyengine.h"
+#include "doxmresource.h"
+
+// test parameters
+PEContext_t g_peContext;
+
+#ifdef __cplusplus
+}
+#endif
+
+OicUuid_t g_subjectIdA = {"SubjectA"};
+OicUuid_t g_subjectIdB = {"SubjectB"};
+OicUuid_t g_devOwner;
+char g_resource1[] = "Resource1";
+char g_resource2[] = "Resource2";
+
+//Policy Engine Core Tests
+TEST(PolicyEngineCore, InitPolicyEngine)
+{
+    EXPECT_EQ(OC_STACK_OK, InitPolicyEngine(&g_peContext));
+}
+
+TEST(PolicyEngineCore, CheckPermissionNoAcls)
+{
+    EXPECT_EQ(ACCESS_DENIED_SUBJECT_NOT_FOUND,
+        CheckPermission(&g_peContext,
+                        &g_subjectIdA,
+                        g_resource1,
+                        PERMISSION_READ));
+}
+
+//TODO This won't work until we figure out how to OcInit() or equivalent.
+TEST(PolicyEngineCore, CheckDevOwnerRequest)
+{
+    if(OC_STACK_OK == InitDoxmResource())
+    {
+        if(OC_STACK_OK == GetDoxmDevOwnerId(&g_devOwner))
+        {
+            printf("%s", PE_UT_TAG);
+            for(int i = 0; i < UUID_LENGTH; i++)
+            {
+                printf("%d", g_devOwner.id[i]);
+            }
+            printf("\n");
+                EXPECT_EQ(ACCESS_GRANTED,
+                    CheckPermission(&g_peContext,
+                        &g_devOwner,
+                        g_resource1,
+                        PERMISSION_FULL_CONTROL));
+        }
+        else
+        {
+            printf("%s WARNING: InitDoxmResource() returned ERROR!\n", \
+                PE_UT_TAG);
+        }
+    }
+    else
+    {
+        printf("%s WARNING: GetDoxmDevOwnerId() returned ERROR!\n", PE_UT_TAG);
+    }
+
+
+}
+
+TEST(PolicyEngineCore, DeInitPolicyEngine)
+{
+    DeInitPolicyEngine(&g_peContext);
+    EXPECT_EQ(STOPPED, g_peContext.state);
+    EXPECT_EQ(NULL, g_peContext.subject);
+    EXPECT_EQ(NULL, g_peContext.resource);
+    EXPECT_EQ((uint16_t)0, g_peContext.permission);
+    EXPECT_FALSE(g_peContext.matchingAclFound);
+    EXPECT_EQ(ACCESS_DENIED_POLICY_ENGINE_ERROR, g_peContext.retVal);
+}
diff --git a/resource/csdk/security/unittest/pstatresource.cpp b/resource/csdk/security/unittest/pstatresource.cpp
new file mode 100644 (file)
index 0000000..dcdac77
--- /dev/null
@@ -0,0 +1,159 @@
+//******************************************************************
+//
+// 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 "ocstack.h"
+#include "resourcemanager.h"
+#include "pstatresource.h"
+#include "oic_malloc.h"
+#include "cJSON.h"
+#include "base64.h"
+#include "cainterface.h"
+#include "secureresourcemanager.h"
+#include <unistd.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+//Declare Provision status resource methods for testing
+OCStackResult CreatePstatResource();
+OCEntityHandlerResult PstatEntityHandler (OCEntityHandlerFlag flag,
+                                        OCEntityHandlerRequest * ehRequest);
+char * BinToPstatJSON(const OicSecPstat_t * pstat);
+OicSecPstat_t * JSONToPstatBin(const char * jsonStr);
+char* ReadFile(const char* filename);
+extern char* JSON_FILE_NAME;
+#ifdef __cplusplus
+}
+#endif
+
+//InitPstatResource Tests
+TEST(InitPstatResourceTest, InitPstatResource)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM,  InitPstatResource());
+}
+
+
+//DeInitPstatResource Tests
+TEST(DeInitPstatResourceTest, DeInitPstatResource)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, DeInitPstatResource());
+}
+
+//CreatePstatResource Tests
+TEST(CreatePstatResourceTest, CreatePstatResource)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM,  CreatePstatResource());
+}
+
+//PstatEntityHandler Tests
+TEST(PstatEntityHandlerTest, PstatEntityHandlerWithDummyRequest)
+{
+    OCEntityHandlerRequest req;
+    EXPECT_EQ(OC_EH_ERROR, PstatEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, &req));
+}
+
+TEST(PstatEntityHandlerTest, PstatEntityHandlerWithPostRequest)
+{
+    OCEntityHandlerRequest req;
+    req.method = OC_REST_POST;
+    req.reqJSONPayload = (char*)"{ \"pstat\": { \"tm\": 0, \"om\": 3 }}";
+    EXPECT_EQ(OC_EH_ERROR, PstatEntityHandler(OCEntityHandlerFlag::OC_REQUEST_FLAG, &req));
+}
+
+TEST(PstatEntityHandlerTest, PstatEntityHandlerInvalidRequest)
+{
+    EXPECT_EQ(OC_EH_ERROR, PstatEntityHandler(OCEntityHandlerFlag::OC_OBSERVE_FLAG, NULL));
+}
+
+//BinToJSON Tests
+TEST(BinToJSONTest, BinToNullJSON)
+{
+    char* value = BinToPstatJSON(NULL);
+    EXPECT_TRUE(value == NULL);
+}
+
+TEST(JSONToBinTest, NullJSONToBin)
+{
+    OicSecPstat_t *pstat1 = JSONToPstatBin(NULL);
+    EXPECT_TRUE(pstat1 == NULL);
+}
+
+TEST(MarshalingAndUnMarshalingTest, BinToPstatJSONAndJSONToPstatBin)
+{
+    const char* id = "ZGV2aWNlaWQAAAAAABhanw==";
+    OicSecPstat_t pstat;
+    pstat.cm = NORMAL;
+    pstat.commitHash = 0;
+    uint32_t outLen = 0;
+    unsigned char base64Buff[sizeof(((OicUuid_t*) 0)->id)] = {};
+    EXPECT_EQ(B64_OK, b64Decode(id, strlen(id), base64Buff, sizeof(base64Buff), &outLen));
+    memcpy(pstat.deviceID.id, base64Buff, outLen);
+    pstat.isOp = true;
+    pstat.tm = NORMAL;
+    pstat.om = SINGLE_SERVICE_CLIENT_DRIVEN;
+    pstat.smLen = 2;
+    pstat.sm = (OicSecDpom_t*)OICCalloc(pstat.smLen, sizeof(OicSecDpom_t));
+    pstat.sm[0] = SINGLE_SERVICE_CLIENT_DRIVEN;
+    pstat.sm[1] = SINGLE_SERVICE_SERVER_DRIVEN;
+    char* jsonPstat = BinToPstatJSON(&pstat);
+    printf("BinToJSON Dump:\n%s\n\n", jsonPstat);
+    EXPECT_TRUE(jsonPstat != NULL);
+    OicSecPstat_t *pstat1 = JSONToPstatBin(jsonPstat);
+    EXPECT_TRUE(pstat1 != NULL);
+    OICFree(pstat1->sm);
+    OICFree(pstat1);
+    OICFree(jsonPstat);
+    OICFree(pstat.sm);
+}
+
+TEST(PstatTests, JSONMarshalliingTests)
+{
+    char *jsonStr1 = ReadFile(JSON_FILE_NAME);
+    if (NULL != jsonStr1)
+    {
+        cJSON_Minify(jsonStr1);
+        /* Workaround : cJSON_Minify does not remove all the unwanted characters
+         from the end. Here is an attempt to remove those characters */
+        int len = strlen(jsonStr1);
+        while (len > 0)
+        {
+            if (jsonStr1[--len] == '}')
+            {
+                break;
+            }
+        }
+        jsonStr1[len + 1] = 0;
+
+        OicSecPstat_t* pstat = JSONToPstatBin(jsonStr1);
+        EXPECT_TRUE(NULL != pstat);
+
+        char* jsonStr2 = BinToPstatJSON(pstat);
+        printf("BinToPstatJSON Dump:\n%s\n\n", jsonStr2);
+        EXPECT_STRNE(jsonStr1, jsonStr2);
+
+        OICFree(jsonStr1);
+        OICFree(jsonStr2);
+        OICFree(pstat);
+   }
+    else
+    {
+        printf("Please copy %s into unittest folder\n", JSON_FILE_NAME);
+    }
+}
diff --git a/resource/csdk/security/unittest/securityresourcemanager.cpp b/resource/csdk/security/unittest/securityresourcemanager.cpp
new file mode 100644 (file)
index 0000000..2259e41
--- /dev/null
@@ -0,0 +1,156 @@
+//******************************************************************
+//
+// 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 "ocstack.h"
+#include "cainterface.h"
+#include "secureresourcemanager.h"
+
+using namespace std;
+
+// Helper Methods
+void UTRequestHandler(const CARemoteEndpoint_t *endPoint, const CARequestInfo_t *requestInfo)
+{
+    EXPECT_TRUE(true) << "UTRequestHandler\n";
+}
+
+void UTResponseHandler(const CARemoteEndpoint_t *endPoint, const CAResponseInfo_t *responseInfo)
+{
+     EXPECT_TRUE(true) << "UTResponseHandler\n";
+}
+
+void UTErrorHandler(const CARemoteEndpoint_t *endPoint, const CAErrorInfo_t *errorInfo)
+{
+     EXPECT_TRUE(true) << "UTErrorHandler\n";
+}
+
+FILE *utopen(const char *path, const char *mode)
+{
+    EXPECT_TRUE((path != NULL)) << "utopen\n";
+    FILE *stream = fopen(path, mode);
+    return stream;
+
+}
+
+size_t utread(void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+    return fread(ptr, size, nmemb, stream);
+}
+
+size_t utwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+    return fwrite(ptr, size, nmemb, stream);
+}
+
+int utclose(FILE *fp)
+{
+    EXPECT_TRUE((fp != NULL)) << "utclose\n";
+    return fclose(fp);
+}
+int utunlink(const char *path)
+{
+    EXPECT_TRUE((path != NULL)) << "utunlink\n";
+    return unlink(path);
+}
+static OCPersistentStorage gpsi;
+
+//RegisterHandler Tests
+TEST(RegisterHandlerTest, RegisterNullRequestHandler)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, SRMRegisterHandler(NULL, UTResponseHandler, NULL));
+}
+
+TEST(RegisterHandlerTest, RegisterNullResponseHandler)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, SRMRegisterHandler(UTRequestHandler, NULL, NULL));
+}
+
+TEST(RegisterHandlerTest, RegisterNullHandler)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM, SRMRegisterHandler(NULL, NULL, NULL));
+}
+
+TEST(RegisterHandlerTest, RegisterValidHandler)
+{
+    EXPECT_EQ(OC_STACK_OK, SRMRegisterHandler(UTRequestHandler, UTResponseHandler, UTErrorHandler));
+}
+
+// PersistentStorageHandler Tests
+TEST(PersistentStorageHandlerTest, RegisterNullHandler)
+{
+    EXPECT_EQ(OC_STACK_INVALID_PARAM,
+            SRMRegisterPersistentStorageHandler(NULL));
+}
+
+TEST(PersistentStorageHandlerTest, RegisterValidHandler)
+{
+    gpsi.open = utopen;
+    gpsi.read = utread;
+    gpsi.write = utwrite;
+    gpsi.close = utclose;
+    gpsi.unlink = utunlink;
+
+    EXPECT_EQ(OC_STACK_OK,
+            SRMRegisterPersistentStorageHandler(&gpsi));
+    OCPersistentStorage *ps = SRMGetPersistentStorageHandler();
+    EXPECT_TRUE(&gpsi == ps);
+}
+
+TEST(PersistentStorageHandlerTest, PersistentStorageValidHandlers)
+{
+    OCPersistentStorage *psi = SRMGetPersistentStorageHandler();
+    EXPECT_TRUE(psi != NULL);
+
+    unsigned char buf[PATH_MAX];
+    FILE* streamIn = NULL;
+    FILE* streamOut = NULL;
+    struct passwd *pw = getpwuid(getuid());
+    const char *homeDir = pw->pw_dir;
+    char inFilePath [PATH_MAX];
+    char outFilePath [PATH_MAX];
+    snprintf(inFilePath, PATH_MAX, "%s/iotivity/Readme.scons.txt", homeDir );
+    snprintf(outFilePath, PATH_MAX, "%s/Downloads/Readme.scons.out.txt", homeDir );
+
+    streamIn = psi->open(inFilePath, "r");
+    streamOut = psi->open(outFilePath, "w");
+
+    if (streamIn && streamOut)
+    {
+        size_t value = 1;
+        while (value)
+        {
+            value = psi->read(buf, 1, sizeof(buf), streamIn);
+            psi->write(buf, 1, value, streamOut);
+        }
+    }
+
+    if (streamIn)
+    {
+        psi->close(streamIn);
+    }
+    if (streamOut)
+    {
+        psi->close(streamOut);
+    }
+    psi->unlink(outFilePath);
+}
index 28ecba8..ae30a0a 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef OCSTACK_H_
 #define OCSTACK_H_
 
+#include <stdio.h>
 #include <stdint.h>
 #include "octypes.h"
 
@@ -118,6 +119,15 @@ OCStackResult OCDoResource(OCDoHandle *handle, OCMethod method, const char *requ
 OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption * options,
         uint8_t numOptions);
 
+/**
+ * @brief   Register Persistent storage callback.
+ * @param   persistentStorageHandler [IN] Pointers to open, read, write, close & unlink handlers.
+ * @return
+ *     OC_STACK_OK    - No errors; Success
+ *     OC_STACK_INVALID_PARAM - Invalid parameter
+ */
+OCStackResult OCRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler);
+
 #ifdef WITH_PRESENCE
 /**
  * When operating in @ref OCServer or @ref OCClientServer mode, this API will start sending out
index b6d35d3..76c4ccf 100644 (file)
@@ -202,23 +202,26 @@ typedef enum
 /**
  * Resource Properties.
  *
- * ::OC_ACTIVE       When this bit is set, the resource is initialized, otherwise the resource
- *                   is 'inactive'. 'inactive' signifies that the resource has been marked for
- *                   deletion or is already deleted.
- * ::OC_DISCOVERABLE When this bit is set, the resource is allowed to be discovered by clients.
- * ::OC_OBSERVABLE   When this bit is set, the resource is allowed to be observed by clients.
- * ::OC_SLOW         When this bit is set, the resource has been marked as 'slow'. 'slow' signifies
- *                   that responses from this resource can expect delays in processing its
- *                   requests from clients.
- * ::OC_SECURE       When this bit is set, the resource is a secure resource.
+ * ::OC_RES_PROP_NONE When none of the bits are set, the resource is non-discoverable &
+ *                    non-observable by the client.
+ * ::OC_ACTIVE        When this bit is set, the resource is initialized, otherwise the resource
+ *                    is 'inactive'. 'inactive' signifies that the resource has been marked for
+ *                    deletion or is already deleted.
+ * ::OC_DISCOVERABLE  When this bit is set, the resource is allowed to be discovered by clients.
+ * ::OC_OBSERVABLE    When this bit is set, the resource is allowed to be observed by clients.
+ * ::OC_SLOW          When this bit is set, the resource has been marked as 'slow'. 'slow'
+ *                    signifies that responses from this resource can expect delays in
+ *                    processing its requests from clients.
+ * ::OC_SECURE        When this bit is set, the resource is a secure resource.
  */
 typedef enum
 {
-    OC_ACTIVE       = (1 << 0),
-    OC_DISCOVERABLE = (1 << 1),
-    OC_OBSERVABLE   = (1 << 2),
-    OC_SLOW         = (1 << 3),
-    OC_SECURE       = (1 << 4)
+    OC_RES_PROP_NONE = (0),
+    OC_ACTIVE        = (1 << 0),
+    OC_DISCOVERABLE  = (1 << 1),
+    OC_OBSERVABLE    = (1 << 2),
+    OC_SLOW          = (1 << 3),
+    OC_SECURE        = (1 << 4)
 } OCResourceProperty;
 
 /**
@@ -320,6 +323,27 @@ typedef enum
     OC_OBSERVE_NO_OPTION = 2
 } OCObserveAction;
 
+
+/**
+ * Persistent storage handlers. An app must provide OCPersistentStorage handler pointers when it
+ * calls OCRegisterPersistentStorageHandler.
+ */
+typedef struct {
+    /*
+     *  Persistent storage open handler points to default file path.
+     *  Application can point to appropriate SVR database path for its Iotivity Server.
+     */
+    FILE* (* open)(const char *path, const char *mode);
+    // Persistent storage read handler
+    size_t (* read)(void *ptr, size_t size, size_t nmemb, FILE *stream);
+    // Persistent storage write handler
+    size_t (* write)(const void *ptr, size_t size, size_t nmemb, FILE *stream);
+    // Persistent storage close handler
+    int (* close)(FILE *fp);
+    // Persistent storage unlink handler
+    int (* unlink)(const char *path);
+} OCPersistentStorage;
+
 typedef struct
 {
     // Action associated with observation request
index 6f03453..d3e39c2 100644 (file)
@@ -33,7 +33,7 @@ arduino_simplecs_env.PrependUnique(CPPPATH = [
 arduino_simplecs_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
 arduino_simplecs_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
 
-arduino_simplecs_env.PrependUnique(LIBS = ['octbstack', 'connectivity_abstraction','coap'])
+arduino_simplecs_env.PrependUnique(LIBS = ['octbstack', 'ocsrm', 'connectivity_abstraction','coap'])
 
 arduino_simplecs = arduino_simplecs_env.Program('SimpleClientServer', 'ocserver.cpp')
 env.CreateBin('SimpleClientServer')
index ab43795..6f9a37e 100644 (file)
@@ -38,9 +38,9 @@ samples_env.AppendUnique(LIBS = ['-lpthread' ])
 samples_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
 
 if target_os in ['darwin', 'ios']:
-       samples_env.PrependUnique(LIBS = ['m','octbstack', 'connectivity_abstraction','coap' ])
+       samples_env.PrependUnique(LIBS = ['m','octbstack', 'ocsrm', 'connectivity_abstraction','coap' ])
 elif target_os not in ['arduino']:
-       samples_env.PrependUnique(LIBS = ['m', 'octbstack', 'oc_logger', 'connectivity_abstraction', 'coap'])
+       samples_env.PrependUnique(LIBS = ['m', 'octbstack', 'ocsrm', 'oc_logger', 'connectivity_abstraction', 'coap'])
        samples_env.AppendUnique(LIBS = ['rt'])
 
 if env.get('SECURED') == '1':
index e2f6a61..961a917 100644 (file)
@@ -39,7 +39,7 @@ static int UNICAST_DISCOVERY = 0;
 static int TEST_CASE = 0;
 
 static const char UNICAST_DISCOVERY_QUERY[] = "coap://%s:6298/oic/res";
-static std::string putPayload = "{\"state\":\"off\",\"power\":10}";
+static std::string putPayload = "{\"oic\":[{\"rep\":{\"power\":15,\"state\":true}}]}";
 
 //The following variable determines the interface protocol (IPv4, IPv6, etc)
 //to be used for sending unicast messages. Default set to IPv4.
index 43b913f..e053160 100644 (file)
@@ -57,7 +57,8 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
     }
 
     cJSON *format;
-    char *jsonResponse;
+    cJSON *putJson = NULL;
+    char *jsonResponse = NULL;
     LEDResource *currLEDResource = &LED;
 
     if (ehRequest->resource == gLedInstance[0].handle)
@@ -73,18 +74,37 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
 
     if(OC_REST_PUT == ehRequest->method)
     {
-        cJSON *putJson = cJSON_Parse((char *)ehRequest->reqJSONPayload);
+        cJSON* jsonObj = NULL;
+        putJson = cJSON_Parse(ehRequest->reqJSONPayload);
+        if(putJson)
+        {
+            jsonObj = cJSON_GetObjectItem(putJson,"oic");
+            if (jsonObj)
+            {
+                jsonObj = cJSON_GetArrayItem(jsonObj, 0);
+                if (jsonObj)
+                {
+                    jsonObj = cJSON_GetObjectItem(jsonObj, "rep");
+                }
+            }
+        }
+        if (NULL == jsonObj)
+        {
+            OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload);
+            goto exit;
+        }
 
-        if(!putJson)
+        cJSON* prop = cJSON_GetObjectItem(jsonObj,"power");
+        if (prop)
         {
-            OC_LOG (ERROR, TAG, "putJson object not created properly");
-            cJSON_Delete(json);
-            return NULL;
+            currLEDResource->power =prop->valueint;
+        }
+
+        prop = cJSON_GetObjectItem(jsonObj,"state");
+        if (prop)
+        {
+            currLEDResource->state = prop->valueint;
         }
-        currLEDResource->state = ( !strcmp(cJSON_GetObjectItem(putJson,"state")->valuestring ,
-                "on") ? true:false);
-        currLEDResource->power = cJSON_GetObjectItem(putJson,"power")->valuedouble;
-        cJSON_Delete(putJson);
     }
 
     cJSON_AddStringToObject(json,"href",gResourceUri);
@@ -93,8 +113,7 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
     if(!format)
     {
         OC_LOG (ERROR, TAG, "format object not created properly");
-        cJSON_Delete(json);
-        return NULL;
+        goto exit;
     }
 
     cJSON_AddItemToObject(json, "rep", format);
@@ -102,6 +121,9 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
     cJSON_AddNumberToObject(format, "power", currLEDResource->power);
 
     jsonResponse = cJSON_Print(json);
+
+exit:
+    cJSON_Delete(putJson);
     cJSON_Delete(json);
     return jsonResponse;
 }
index 71e298f..b6dd32c 100644 (file)
@@ -65,10 +65,17 @@ samples_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
 ######################################################################
 ocserverbasicops = samples_env.Program('ocserverbasicops', ['common.cpp', 'ocserverbasicops.cpp'])
 occlientbasicops = samples_env.Program('occlientbasicops', ['common.cpp', 'occlientbasicops.cpp'])
-gen_sec_bin = samples_env.Program('gen_sec_bin', ['gen_sec_bin.cpp'])
-
 
 Alias("samples", [ocserverbasicops, occlientbasicops])
 
 env.AppendTarget('samples')
 
+src_dir = samples_env.get('SRC_DIR')
+sec_samples_src_dir = src_dir + '/resource/csdk/stack/samples/linux/secure/'
+sec_samples_build_dir = env.get('BUILD_DIR') +'/resource/csdk/stack/samples/linux/secure'
+
+samples_env.Alias("install", samples_env.Install( sec_samples_build_dir, 
+    sec_samples_src_dir + 'oic_svr_db_server.json'))
+samples_env.Alias("install", samples_env.Install( sec_samples_build_dir, 
+    sec_samples_src_dir + 'oic_svr_db_client.json'))
+
index 7c04494..8137da0 100644 (file)
@@ -19,7 +19,7 @@
 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 #include "common.h"
 
-#include "ocsecurity.h"
+#include "ocstack.h"
 #include "logger.h"
 #include <stdio.h>
 #include <stdlib.h>
 
 #define TAG "sample-common"
 
-OCStackResult SetCredentials(const char* filename) {
-
-    FILE *fp = NULL;
-    uint8_t *data = NULL;
-    struct stat st;
-    OCStackResult ret = OC_STACK_ERROR;
-
-    fp = fopen(filename, "rb");
-    if (fp)
-    {
-        if (stat(filename, &st) == 0)
-        {
-            data = (uint8_t*)malloc(st.st_size);
-            if (data)
-            {
-                if (fread(data, 1, st.st_size, fp) == (size_t)st.st_size)
-                {
-                    // Provide credentials to OC Stack
-                    ret = OCSecSetConfigData((OCSecConfigData *)data,
-                            st.st_size);
-                }
-                else
-                {
-                    OC_LOG_V(FATAL, TAG, "Error in reading file %s", filename);
-                }
-            }
-        }
-        fclose(fp);
-    }
-    else
-    {
-        OC_LOG_V(FATAL, TAG, "Unable to open %s file", filename);
-    }
-
-    free(data);
-
-    return ret;
-}
-
 const char *getResult(OCStackResult result) {
     switch (result) {
     case OC_STACK_OK:
index ac73c1d..ea899c3 100644 (file)
@@ -26,9 +26,6 @@
 /* Get the result in string format. */
 const char *getResult(OCStackResult result);
 
-/* Read the credentials from persistent storage and provide to OC stack. */
-OCStackResult SetCredentials(const char* filename);
-
 /* Removes the new line character from a NULL terminated C string. */
 void StripNewLineChar(char* str);
 
diff --git a/resource/csdk/stack/samples/linux/secure/gen_sec_bin.cpp b/resource/csdk/stack/samples/linux/secure/gen_sec_bin.cpp
deleted file mode 100644 (file)
index c30aada..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-//******************************************************************
-//
-// Copyright 2014 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 "ocsecurityconfig.h"
-#include "logger.h"
-#include <stdio.h>
-#include <time.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#define TAG "gen_sec_bin"
-
-//scratch buffer
-const int WORK_BUF_LEN = 512;
-
-const char SERVER_CRED_FILE[] = "server_cred.bin";
-const char CLIENT_CRED_FILE[] = "client_cred.bin";
-
-static void printStruct(const char * device, OCSecConfigData* s)
-{
-    if (device && s)
-    {
-        OC_LOG(INFO, TAG, device);
-        OC_LOG_V(INFO, TAG, "Version - %d", s->version);
-        OC_LOG_V(INFO, TAG, "Number of blobs - %d", s->numBlob);
-
-        OCSecBlob* osb = (OCSecBlob*)(s->blob);
-        OC_LOG_V(INFO, TAG, "Blob Type - %d", osb->type);
-        OC_LOG_V(INFO, TAG, "Blob Data Length - %d", osb->len);
-
-        OCDtlsPskCredsBlob* odpcb = (OCDtlsPskCredsBlob*)(osb->val);
-        OC_LOG(INFO, TAG, "My Identity :");
-        OC_LOG_BUFFER(INFO, TAG, odpcb->identity, DTLS_PSK_ID_LEN);
-
-        OC_LOG_V(INFO, TAG, "Number of trusted Peers  - %d", odpcb->num);
-        OC_LOG(INFO, TAG, "Peer Identity :");
-        OC_LOG_BUFFER(INFO, TAG, odpcb->creds[0].id, DTLS_PSK_ID_LEN);
-        OC_LOG(INFO, TAG, "Peer Psk :");
-        OC_LOG_BUFFER(INFO, TAG, odpcb->creds[0].psk, DTLS_PSK_PSK_LEN);
-    }
-}
-
-
-static int SizeOfOCConfigData (OCSecConfigData *oscd)
-{
-    int len = 0;
-    if(oscd)
-    {
-        int i = 0;
-        OCSecBlob * osb;
-        len = len + sizeof(OCSecConfigData) - sizeof(uint8_t);
-
-        //go to first blob
-        osb = (OCSecBlob*)(oscd->blob);
-        for( i =0; i < oscd->numBlob; i++)
-        {
-            len += (sizeof(OCSecBlob) - sizeof(uint8_t) + osb->len);
-            osb = config_data_next_blob(osb);
-        }
-    }
-    return len;
-}
-
-int main()
-{
-    unsigned char buf_s[WORK_BUF_LEN];
-    unsigned char buf_c[WORK_BUF_LEN];
-
-    srand(time(NULL));
-
-    OCSecConfigData * oscd_s = (OCSecConfigData*)buf_s;
-    OCSecConfigData * oscd_c = (OCSecConfigData*)buf_c;
-    oscd_s->version = oscd_c->version = OCSecConfigVer_CurrentVersion;
-
-    //Only storing 1 blob of type 'OC_BLOB_TYPE_PSK'
-    oscd_s->numBlob = oscd_c->numBlob = 1;
-
-    OCSecBlob * osb_s = (OCSecBlob*)oscd_s->blob;
-    OCSecBlob * osb_c = (OCSecBlob*)oscd_c->blob;
-    osb_s->type = osb_c->type = OC_BLOB_TYPE_PSK;
-    //length of this blob will be the length to contain PSK credentials
-    // for '1' peer device
-    osb_s->len = osb_c->len = sizeof(OCDtlsPskCredsBlob);
-
-    OCDtlsPskCredsBlob * odpcb_s = (OCDtlsPskCredsBlob*)(osb_s->val);
-    OCDtlsPskCredsBlob * odpcb_c = (OCDtlsPskCredsBlob*)(osb_c->val);
-
-    odpcb_s->num = odpcb_c->num = 1;
-
-    for(int i = 0; i < DTLS_PSK_ID_LEN; i++)
-    {
-        odpcb_c->creds[0].id[i] = odpcb_s->identity[i] = rand() % (2^8);
-
-        odpcb_s->creds[0].id[i] = odpcb_c->identity[i] = rand() % (2^8);
-
-        odpcb_c->creds[0].psk[i] = odpcb_s->creds[0].psk[i] = rand() % (2^8);
-    }
-
-    // Print Credentials
-    printStruct("Server", oscd_s);
-    printStruct("Client", oscd_c);
-
-    // Write to files
-    FILE* fps, *fpc;
-    if ((fps = (FILE*) fopen("server_cred.bin", "wb")) != NULL)
-    {
-        fwrite(oscd_s, SizeOfOCConfigData(oscd_s), 1, fps);
-        fclose(fps);
-    }
-
-
-    if ((fpc = (FILE*) fopen("client_cred.bin", "wb")) != NULL)
-    {
-        fwrite(oscd_c, SizeOfOCConfigData(oscd_c), 1, fpc);
-        fclose(fpc);
-    }
-
-    struct stat st;
-    memset(buf_s, 0, sizeof(buf_s));
-    memset(buf_c, 0, sizeof(buf_c));
-    // Read from files; print and verify manually
-    if ((fps = (FILE*) fopen(SERVER_CRED_FILE, "rb")) != NULL)
-    {
-        stat(SERVER_CRED_FILE, &st);
-        if ((sizeof(buf_s) < (unsigned int)st.st_size) ||
-            (fread(buf_s, 1, st.st_size, fps) != (unsigned int)st.st_size))
-        {
-            OC_LOG(INFO, TAG, PCF("Reading from the file failed."));
-        }
-        fclose(fps);
-    }
-
-
-    if ((fpc = (FILE*) fopen(CLIENT_CRED_FILE, "rb")) != NULL)
-    {
-        stat(CLIENT_CRED_FILE, &st);
-        if ((sizeof(buf_c) < (unsigned int)st.st_size) ||
-            (fread(buf_c, 1, st.st_size, fpc) != (unsigned int)st.st_size))
-        {
-            OC_LOG(INFO, TAG, PCF("Reading from the file failed."));
-        }
-        fclose(fpc);
-    }
-
-    printf("\n\n");
-    OC_LOG(INFO, TAG, PCF("Reading from file and printing again to verify manually"));
-    printStruct("Server", (OCSecConfigData*)buf_s);
-    printStruct("Client", (OCSecConfigData*)buf_c);
-
-    return 1;
-}
-
-
index 5088121..e791a28 100644 (file)
@@ -47,10 +47,10 @@ static int coapSecureResource;
 static OCConnectivityType ocConnType;
 
 
-//File containing Client's Identity and the PSK credentials
+//Secure Virtual Resource database for Iotivity Client application
+//It contains Client's Identity and the PSK credentials
 //of other devices which the client trusts
-//This can be generated using 'gen_sec_bin' application
-static char CRED_FILE[] = "client_cred.bin";
+static char CRED_FILE[] = "oic_svr_db_client.json";
 
 
 int gQuitFlag = 0;
@@ -286,6 +286,12 @@ int InitDiscovery()
     return ret;
 }
 
+FILE* client_fopen(const char *path, const char *mode)
+{
+    (void)path;
+    return fopen(CRED_FILE, mode);
+}
+
 int main(int argc, char* argv[])
 {
     int opt;
@@ -314,23 +320,22 @@ int main(int argc, char* argv[])
         return -1;
     }
 
+    // Initialize Persistent Storage for SVR database
+    OCPersistentStorage ps = {};
+    ps.open = client_fopen;
+    ps.read = fread;
+    ps.write = fwrite;
+    ps.close = fclose;
+    ps.unlink = unlink;
+    OCRegisterPersistentStorageHandler(&ps);
+
     /* Initialize OCStack*/
-    if (OCInit(NULL, 0, OC_CLIENT) != OC_STACK_OK)
+    if (OCInit(NULL, 0, OC_CLIENT_SERVER) != OC_STACK_OK)
     {
         OC_LOG(ERROR, TAG, "OCStack init error");
         return 0;
     }
 
-    /*
-     * Read DTLS PSK credentials from persistent storage and
-     * set in the OC stack.
-     */
-    if (SetCredentials(CRED_FILE) != OC_STACK_OK)
-    {
-        OC_LOG(ERROR, TAG, "SetCredentials failed");
-        return 0;
-    }
-
     InitDiscovery();
 
     timeout.tv_sec  = 0;
@@ -410,9 +415,10 @@ int parseClientResponse(OCClientResponse * clientResponse)
 
     if (oc->type == cJSON_Array)
     {
-        if (cJSON_GetArraySize(oc) > 0)
+        int numRsrcs =  cJSON_GetArraySize(oc);
+        for(int i = 0; i < numRsrcs; i++)
         {
-            cJSON * resource = cJSON_GetArrayItem(oc, 0);
+            cJSON * resource = cJSON_GetArrayItem(oc, i);
             if (cJSON_GetObjectItem(resource, "href"))
             {
                 coapServerResource.assign(cJSON_GetObjectItem(resource, "href")->valuestring);
@@ -446,6 +452,12 @@ int parseClientResponse(OCClientResponse * clientResponse)
                     coapServerPort = ss.str();
                 }
             }
+
+            // If we discovered a secure resource, exit from here
+            if (coapSecureResource)
+            {
+                break;
+            }
         }
     }
     cJSON_Delete(root);
index 440b667..a6ec6af 100644 (file)
@@ -41,18 +41,19 @@ static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
 
 char *gResourceUri= (char *)"/a/led";
 
-//File containing Server's Identity and the PSK credentials
+//Secure Virtual Resource database for Iotivity Server
+//It contains Server's Identity and the PSK credentials
 //of other devices which the server trusts
-//This can be generated using 'gen_sec_bin' application
-static char CRED_FILE[] = "server_cred.bin";
+static char CRED_FILE[] = "oic_svr_db_server.json";
 
 //This function takes the request as an input and returns the response
 //in JSON format.
 char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
 {
     cJSON *json = cJSON_CreateObject();
+    cJSON *putJson = NULL;
     cJSON *format;
-    char *jsonResponse;
+    char *jsonResponse = NULL;
     LEDResource *currLEDResource = &LED;
 
     if (ehRequest->resource == gLedInstance[0].handle)
@@ -68,17 +69,29 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
 
     if(OC_REST_PUT == ehRequest->method)
     {
-        cJSON *putJson = cJSON_Parse(ehRequest->reqJSONPayload);
-        if(!putJson)
+        cJSON* jsonObj = NULL;
+        putJson = cJSON_Parse(ehRequest->reqJSONPayload);
+        if(putJson)
+        {
+            jsonObj = cJSON_GetObjectItem(putJson,"oic");
+            if (jsonObj)
+            {
+                jsonObj = cJSON_GetArrayItem(jsonObj, 0);
+                if (jsonObj)
+                {
+                    jsonObj = cJSON_GetObjectItem(jsonObj, "rep");
+                }
+            }
+        }
+        if (NULL == jsonObj)
         {
             OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload);
-            return NULL;
+            goto exit;
         }
 
-        currLEDResource->state = ( !strcmp(cJSON_GetObjectItem(putJson,"state")->valuestring ,
-                "on") ? true:false);
-        currLEDResource->power = cJSON_GetObjectItem(putJson,"power")->valuedouble;
-        cJSON_Delete(putJson);
+        currLEDResource->state = ( !strcmp(cJSON_GetObjectItem(jsonObj,"state")->valuestring ,
+                    "on") ? true:false);
+        currLEDResource->power = cJSON_GetObjectItem(jsonObj,"power")->valuedouble;
     }
 
     cJSON_AddStringToObject(json,"href",gResourceUri);
@@ -87,6 +100,9 @@ char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
     cJSON_AddNumberToObject(format, "power", currLEDResource->power);
 
     jsonResponse = cJSON_Print(json);
+
+exit:
+    cJSON_Delete(putJson);
     cJSON_Delete(json);
     return jsonResponse;
 }
@@ -310,12 +326,27 @@ void handleSigInt(int signum)
     }
 }
 
+FILE* server_fopen(const char *path, const char *mode)
+{
+    (void)path;
+    return fopen(CRED_FILE, mode);
+}
+
 int main(int argc, char* argv[])
 {
     struct timespec timeout;
 
     OC_LOG(DEBUG, TAG, "OCServer is starting...");
 
+    // Initialize Persistent Storage for SVR database
+    OCPersistentStorage ps = {};
+    ps.open = server_fopen;
+    ps.read = fread;
+    ps.write = fwrite;
+    ps.close = fclose;
+    ps.unlink = unlink;
+    OCRegisterPersistentStorageHandler(&ps);
+
     if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
     {
         OC_LOG(ERROR, TAG, "OCStack init error");
@@ -323,15 +354,6 @@ int main(int argc, char* argv[])
     }
 
     /*
-     * Read DTLS PSK credentials from persistent storage and
-     * set in the OC stack.
-     */
-    if (SetCredentials(CRED_FILE) != OC_STACK_OK)
-    {
-        OC_LOG(ERROR, TAG, "SetCredentials failed");
-        return 0;
-    }
-    /*
      * Declare and create the example resource: LED
      */
     createLEDResource(gResourceUri, &LED, false, 0);
diff --git a/resource/csdk/stack/samples/linux/secure/oic_svr_db_client.json b/resource/csdk/stack/samples/linux/secure/oic_svr_db_client.json
new file mode 100644 (file)
index 0000000..aba0590
--- /dev/null
@@ -0,0 +1,49 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/d",
+                "/oic/p",
+                "/oic/res/types/d",
+                "/oic/ad",
+                "/oic/sec/acl"
+                       ],
+                       "perms": 2,
+                       "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat"
+             ],
+             "perms": 2,
+             "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+        }
+       ],
+       "pstat":        {
+               "isop": true,
+               "deviceid":     "ZGV2aWNlaWQAAAAAABhanw==",
+               "commithash": 0,
+               "cm":   0,
+               "tm":   0,
+               "om":   3,
+               "sm":   [3]
+       },
+       "doxm": {
+               "oxm":  [0],
+               "oxmsel": 0,
+               "owned": true,
+               "deviceid":     "MjIyMjIyMjIyMjIyMjIyMg==",
+               "ownr": "MjIyMjIyMjIyMjIyMjIyMg=="
+       },
+    "cred":    [{
+               "credid": 1,
+               "sub": "MTExMTExMTExMTExMTExMQ==",
+               "credtyp": 1,
+               "pvdata": "QUFBQUFBQUFBQUFBQUFBQQ==",
+        "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+       }]
+}
diff --git a/resource/csdk/stack/samples/linux/secure/oic_svr_db_server.json b/resource/csdk/stack/samples/linux/secure/oic_svr_db_server.json
new file mode 100644 (file)
index 0000000..a23287d
--- /dev/null
@@ -0,0 +1,55 @@
+{
+    "acl": [
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/res",
+                "/oic/d",
+                "/oic/p",
+                "/oic/res/types/d",
+                "/oic/ad",
+                "/oic/sec/acl"
+                       ],
+                       "perms": 2,
+                       "ownrs" : ["MTExMTExMTExMTExMTExMQ=="]
+               },
+        {
+            "sub": "Kg==",
+            "rsrc": [
+                "/oic/sec/doxm",
+                "/oic/sec/pstat"
+             ],
+             "perms": 2,
+             "ownrs" : ["MTExMTExMTExMTExMTExMQ=="]
+        },
+        {
+            "sub": "MjIyMjIyMjIyMjIyMjIyMg==",
+            "rsrc": ["/a/led"],
+            "perms": 6,
+            "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+        }
+       ],
+       "pstat":        {
+               "isop": true,
+               "deviceid":     "ZGV2aWNlaWQAAAAAABhanw==",
+               "commithash": 0,
+               "cm":   0,
+               "tm":   0,
+               "om":   3,
+               "sm":   [3]
+       },
+       "doxm": {
+               "oxm":  [0],
+               "oxmsel": 0,
+               "owned": true,
+               "deviceid":     "MTExMTExMTExMTExMTExMQ==",
+               "ownr": "MjIyMjIyMjIyMjIyMjIyMg=="
+       },
+    "cred":    [{
+               "credid": 1,
+               "sub": "MjIyMjIyMjIyMjIyMjIyMg==",
+               "credtyp": 1,
+               "pvdata": "QUFBQUFBQUFBQUFBQUFBQQ==",
+        "ownrs" : ["MjIyMjIyMjIyMjIyMjIyMg=="]
+       }]
+}
index d0a018f..5a3bfc0 100644 (file)
@@ -420,7 +420,7 @@ CAResponseResult_t ConvertEHResultToCAResult (OCEntityHandlerResult result)
             caResult = CA_SUCCESS;
             break;
         case OC_EH_FORBIDDEN:
-            caResult = CA_BAD_REQ;
+            caResult = CA_UNAUTHORIZED_REQ;
             break;
         case OC_EH_RESOURCE_NOT_FOUND:
             caResult = CA_NOT_FOUND;
@@ -557,11 +557,16 @@ OCStackResult HandleSingleResponse(OCEntityHandlerResponse * ehResponse)
         responseInfo.info.options = NULL;
     }
 
-    char payload[MAX_RESPONSE_LENGTH + OC_JSON_PREFIX_LEN + OC_JSON_SUFFIX_LEN] = {};
+    char payload[MAX_RESPONSE_LENGTH + OC_JSON_PREFIX_LEN + OC_JSON_SUFFIX_LEN + 1] = {};
 
     // Put the JSON prefix and suffix around the payload
     strcpy(payload, (const char *)OC_JSON_PREFIX);
-    strncat(payload, (const char *)ehResponse->payload, ehResponse->payloadSize);
+    if(ehResponse->payloadSize)
+    {
+        strncat(payload, (const char *)ehResponse->payload,
+                       ehResponse->payloadSize < MAX_RESPONSE_LENGTH ?
+                       ehResponse->payloadSize : MAX_RESPONSE_LENGTH);
+    }
     strcat(payload, (const char *)OC_JSON_SUFFIX);
     responseInfo.info.payload = (CAPayload_t)payload;
 
index 73dacb9..c17b752 100644 (file)
@@ -41,8 +41,7 @@
 #include "ocrandom.h"
 #include "oic_malloc.h"
 #include "ocserverrequest.h"
-#include "ocsecurityinternal.h"
-
+#include "secureresourcemanager.h"
 #include "cacommon.h"
 #include "cainterface.h"
 
@@ -1865,18 +1864,20 @@ OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
     result = CAResultToOCResult(OCSelectNetwork());
     VERIFY_SUCCESS(result, OC_STACK_OK);
 
-    CARegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
     switch (myStackMode)
     {
         case OC_CLIENT:
+                       CARegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
             result = CAResultToOCResult(CAStartDiscoveryServer());
             OC_LOG(INFO, TAG, PCF("Client mode: CAStartDiscoveryServer"));
             break;
         case OC_SERVER:
+                       SRMRegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
             result = CAResultToOCResult(CAStartListeningServer());
             OC_LOG(INFO, TAG, PCF("Server mode: CAStartListeningServer"));
             break;
         case OC_CLIENT_SERVER:
+                       SRMRegisterHandler(HandleCARequests, HandleCAResponses, HandleCAErrorResponse);
             result = CAResultToOCResult(CAStartListeningServer());
             if(result == OC_STACK_OK)
             {
@@ -1886,12 +1887,6 @@ OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
     }
     VERIFY_SUCCESS(result, OC_STACK_OK);
 
-#if defined(__WITH_DTLS__)
-    result = (CARegisterDTLSCredentialsHandler(GetDtlsPskCredentials) == CA_STATUS_OK) ?
-        OC_STACK_OK : OC_STACK_ERROR;
-    VERIFY_SUCCESS(result, OC_STACK_OK);
-#endif // (__WITH_DTLS__)
-
 #ifdef WITH_PRESENCE
     PresenceTimeOutSize = sizeof(PresenceTimeOut)/sizeof(PresenceTimeOut[0]) - 1;
 #endif // WITH_PRESENCE
@@ -1905,6 +1900,13 @@ OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode)
         result = initResources();
     }
 
+    // Initialize the SRM Policy Engine
+    if(result == OC_STACK_OK)
+    {
+        result = SRMInitPolicyEngine();
+        // TODO after BeachHead delivery: consolidate into single SRMInit()
+    }
+
 exit:
     if(result != OC_STACK_OK)
     {
@@ -1948,8 +1950,11 @@ OCStackResult OCStop()
     DeleteObserverList();
     // Remove all the client callbacks
     DeleteClientCBList();
-    // Deinit security blob
-    DeinitOCSecurityInfo();
+
+       // De-init the SRM Policy Engine
+    // TODO after BeachHead delivery: consolidate into single SRMDeInit()
+    SRMDeInitPolicyEngine();
+
     stackState = OC_STACK_UNINITIALIZED;
     return OC_STACK_OK;
 }
@@ -2362,6 +2367,36 @@ OCStackResult OCCancel(OCDoHandle handle, OCQualityOfService qos, OCHeaderOption
     return ret;
 }
 
+/**
+ * @brief   Register Persistent storage callback.
+ * @param   persistentStorageHandler [IN] Pointers to open, read, write, close & unlink handlers.
+ * @return
+ *     OC_STACK_OK    - No errors; Success
+ *     OC_STACK_INVALID_PARAM - Invalid parameter
+ */
+OCStackResult OCRegisterPersistentStorageHandler(OCPersistentStorage* persistentStorageHandler)
+{
+    OC_LOG(INFO, TAG, PCF("RegisterPersistentStorageHandler !!"));
+    if(!persistentStorageHandler)
+    {
+        OC_LOG(ERROR, TAG, PCF("The persistent storage handler is invalid"));
+        return OC_STACK_INVALID_PARAM;
+    }
+    else
+    {
+        if( !persistentStorageHandler->open ||
+                !persistentStorageHandler->close ||
+                !persistentStorageHandler->read ||
+                !persistentStorageHandler->unlink ||
+                !persistentStorageHandler->write)
+        {
+            OC_LOG(ERROR, TAG, PCF("The persistent storage handler is invalid"));
+            return OC_STACK_INVALID_PARAM;
+        }
+    }
+    return SRMRegisterPersistentStorageHandler(persistentStorageHandler);
+}
+
 #ifdef WITH_PRESENCE
 OCStackResult OCProcessPresence()
 {
@@ -3471,6 +3506,12 @@ OCStackResult initResources()
             &(((OCResource *) presenceResource.handle)->resourceProperties),
             OC_ACTIVE, 0);
     #endif
+
+    if (result == OC_STACK_OK)
+    {
+        result = SRMInitSecureResources();
+    }
+
     return result;
 }
 
@@ -3523,6 +3564,8 @@ void deleteAllResources()
         pointer = temp;
     }
 
+    SRMDeInitSecureResources();
+
     #ifdef WITH_PRESENCE
     // Ensure that the last resource to be deleted is the presence resource. This allows for all
     // presence notification attributed to their deletion to be processed.
index 1fe5464..27f9905 100644 (file)
@@ -36,6 +36,7 @@ stacktest_env.PrependUnique(CPPPATH = [
                '../../stack/include',
                '../../stack/include/internal',
                '../../connectivity/api',
+               '../../connectivity/external/inc',
                '../../extlibs/cjson',
                '../../../oc_logger/include',
                '../../../../extlibs/gtest/gtest-1.7.0/include'
@@ -47,6 +48,7 @@ stacktest_env.AppendUnique(LIBPATH = [env.get('BUILD_DIR')])
 stacktest_env.AppendUnique(LIBPATH = [src_dir + '/extlibs/gtest/gtest-1.7.0/lib/.libs'])
 stacktest_env.PrependUnique(LIBS = ['m',
                                     'octbstack',
+                                    'ocsrm',
                                     'connectivity_abstraction',
                                     'coap',
                                     'gtest',
index 1e3d93f..590bda3 100644 (file)
@@ -713,6 +713,8 @@ TEST(StackResource, StackTestResourceDiscoverOneResourceBad)
     itst::DeadmanTimer killSwitch(SHORT_TEST_TIMEOUT);
     OC_LOG(INFO, TAG, "Starting StackTestResourceDiscoverOneResourceBad test");
     InitStack(OC_SERVER);
+    uint8_t numResources = 0;
+    EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
 
     OCResourceHandle handle;
     EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
@@ -726,10 +728,9 @@ TEST(StackResource, StackTestResourceDiscoverOneResourceBad)
 
     //EXPECT_EQ(OC_STACK_INVALID_URI, OCHandleServerRequest(&res, uri, query, req, rsp));
     EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle));
-    uint8_t numResources = 0;
-    uint8_t numExpectedResources = InitNumExpectedResources();
+    uint8_t numExpectedResources = 0;
 
-    EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+    EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numExpectedResources));
     EXPECT_EQ(numExpectedResources, numResources);
 
     EXPECT_EQ(OC_STACK_OK, OCStop());
@@ -1048,10 +1049,9 @@ TEST(StackBind, BindContainedResourceGood)
     InitStack(OC_SERVER);
 
     uint8_t numResources = 0;
-    uint8_t numExpectedResources = InitNumExpectedResources();
+    uint8_t numExpectedResources = 0;
 
-    EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
-    EXPECT_EQ(numExpectedResources, numResources);
+    EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numExpectedResources));
 
     OCResourceHandle containerHandle;
     EXPECT_EQ(OC_STACK_OK, OCCreateResource(&containerHandle,
@@ -1192,12 +1192,11 @@ TEST(StackResourceAccess, GetResourceByIndex)
     InitStack(OC_SERVER);
 
     uint8_t numResources = 0;
-    uint8_t numExpectedResources = InitNumExpectedResources();
-    uint8_t resourceIndex = InitResourceIndex();
-
-    EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
-    EXPECT_EQ(numExpectedResources, numResources);
-
+    uint8_t numExpectedResources = 0;
+    uint8_t resourceIndex = 0;
+    uint8_t prevResources = 0;
+    EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numExpectedResources));
+    prevResources = numExpectedResources;
     OCResourceHandle containerHandle;
     EXPECT_EQ(OC_STACK_OK, OCCreateResource(&containerHandle,
                                             "core.led",
@@ -1267,7 +1266,7 @@ TEST(StackResourceAccess, GetResourceByIndex)
                                             OC_DISCOVERABLE|OC_OBSERVABLE));
     EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
     EXPECT_EQ(++numExpectedResources, numResources);
-
+    resourceIndex += prevResources;
     EXPECT_EQ(containerHandle, OCGetResourceHandle(resourceIndex));
     EXPECT_EQ(handle0, OCGetResourceHandle(++resourceIndex));
     EXPECT_EQ(handle1, OCGetResourceHandle(++resourceIndex));
@@ -1286,10 +1285,9 @@ TEST(StackResourceAccess, DeleteHeadResource)
     InitStack(OC_SERVER);
 
     uint8_t numResources = 0;
-    uint8_t numExpectedResources = InitNumExpectedResources();
+    uint8_t numExpectedResources = 0;
 
-    EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
-    EXPECT_EQ(numExpectedResources, numResources);
+    EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numExpectedResources));
 
     OCResourceHandle handle0;
     EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0,
@@ -1315,12 +1313,9 @@ TEST(StackResourceAccess, DeleteHeadResource2)
     InitStack(OC_SERVER);
 
     uint8_t numResources = 0;
-    uint8_t numExpectedResources = InitNumExpectedResources();
-    uint8_t resourceIndex = InitResourceIndex();
-
-    EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
-    EXPECT_EQ(numExpectedResources, numResources);
+    uint8_t numExpectedResources = 0;
 
+    EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numExpectedResources));
     OCResourceHandle handle0;
     EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0,
                                             "core.led",
@@ -1345,7 +1340,7 @@ TEST(StackResourceAccess, DeleteHeadResource2)
     EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
     EXPECT_EQ(--numExpectedResources, numResources);
 
-    EXPECT_EQ(handle1, OCGetResourceHandle(resourceIndex));
+    EXPECT_EQ(handle1, OCGetResourceHandle(numResources - 1));
 
     EXPECT_EQ(OC_STACK_OK, OCStop());
 }
@@ -1358,12 +1353,10 @@ TEST(StackResourceAccess, DeleteLastResource)
     InitStack(OC_SERVER);
 
     uint8_t numResources = 0;
-    uint8_t numExpectedResources = InitNumExpectedResources();
-    uint8_t resourceIndex = InitResourceIndex();
-
-    EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
-    EXPECT_EQ(numExpectedResources, numResources);
+    uint8_t numExpectedResources = 0;
 
+    EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numExpectedResources));
     OCResourceHandle handle0;
     EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0,
                                             "core.led",
@@ -1388,7 +1381,7 @@ TEST(StackResourceAccess, DeleteLastResource)
     EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
     EXPECT_EQ(--numExpectedResources, numResources);
 
-    EXPECT_EQ(handle0, OCGetResourceHandle(resourceIndex));
+    EXPECT_EQ(handle0, OCGetResourceHandle(numResources - 1));
 
     OCResourceHandle handle2;
     EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle2,
@@ -1410,12 +1403,11 @@ TEST(StackResourceAccess, DeleteMiddleResource)
     InitStack(OC_SERVER);
 
     uint8_t numResources = 0;
-    uint8_t numExpectedResources = InitNumExpectedResources();
+    uint8_t numExpectedResources = 0;
     uint8_t resourceIndex = InitResourceIndex();
 
-    EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
-    EXPECT_EQ(numExpectedResources, numResources);
-
+    EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numExpectedResources));
+    resourceIndex = numExpectedResources;
     OCResourceHandle handle0;
     EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0,
                                             "core.led",
index a5f1368..14b13e2 100644 (file)
@@ -48,9 +48,16 @@ if target_os == 'linux':
 
        SConscript('csdk/connectivity/test/SConscript')
 
+       # Build Security Resource Manager unit tests
+       SConscript('csdk/security/unittest/SConscript')
+
        # Build C++ unit tests
        SConscript('unittests/SConscript')
 
+       # Build Provisioning API unit test
+       if env.get('SECURED') == '1':
+               SConscript('csdk/security/provisioning/unittest/SConscript')
+
 elif target_os == 'darwin':
        # Verify that 'google unit test' library is installed.  If not,
        # get it and install it
@@ -60,3 +67,4 @@ elif target_os == 'darwin':
        SConscript('csdk/stack/test/SConscript')
        SConscript('csdk/connectivity/test/SConscript')
 
+
index cdb9ca7..3050b78 100644 (file)
@@ -34,6 +34,7 @@ unittests_env.PrependUnique(CPPPATH = [
                '../csdk/security/include',
                '../csdk/stack/include/internal',
                '../csdk/connectivity/api',
+               '../csdk/connectivity/external/inc',
                '../csdk/ocsocket/include',
                '../csdk/ocrandom/include',
                '../csdk/logger/include',