Merging security-M3 to master 71/1071/17
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)
@@ -74,6 +74,11 @@ extern "C"
 #define COAP_MAX_PDU_SIZE           1400 /* maximum size of a CoAP PDU for big platforms*/
 #endif
 
+/**
+ *@brief Maximum length of the remoteEndpoint identity
+ */
+#define CA_MAX_ENDPOINT_IDENTITY_LEN   (32)
+
 /**
  * @brief option types - the highest option number 63
  */
@@ -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.
@@ -152,6 +156,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.");
+            }
+        }
+    }
+}